blob: b2420c0a0ae503ae379c3a113090768edd5e1b4e [file] [log] [blame]
David Tolnay3cb23a92016-10-07 23:02:21 -07001use super::*;
2
3#[derive(Debug, Clone, Eq, PartialEq)]
4pub enum ConstExpr {
5 /// A function call
6 ///
7 /// The first field resolves to the function itself,
8 /// and the second field is the list of arguments
9 Call(Box<ConstExpr>, Vec<ConstExpr>),
10 /// A binary operation (For example: `a + b`, `a * b`)
11 Binary(BinOp, Box<ConstExpr>, Box<ConstExpr>),
12 /// A unary operation (For example: `!x`, `*x`)
13 Unary(UnOp, Box<ConstExpr>),
14 /// A literal (For example: `1`, `"foo"`)
15 Lit(Lit),
16 /// A cast (`foo as f64`)
17 Cast(Box<ConstExpr>, Box<Ty>),
18 /// Variable reference, possibly containing `::` and/or type
19 /// parameters, e.g. foo::bar::<baz>.
20 Path(Path),
David Tolnay67588752016-10-30 12:23:10 -070021 /// An indexing operation (`foo[2]`)
22 Index(Box<ConstExpr>, Box<ConstExpr>),
David Tolnayf43ba802016-10-30 10:20:47 -070023 /// No-op: used solely so we can pretty-print faithfully
24 Paren(Box<ConstExpr>),
David Tolnayfe2cc9a2016-10-30 12:47:36 -070025 /// If compiling with full support for expression syntax, any expression is
26 /// allowed
27 Other(Other),
David Tolnay3cb23a92016-10-07 23:02:21 -070028}
29
David Tolnayfe2cc9a2016-10-30 12:47:36 -070030#[cfg(not(feature = "full"))]
31#[derive(Debug, Clone, Eq, PartialEq)]
32pub struct Other {
33 _private: (),
34}
35
36#[cfg(feature = "full")]
37pub type Other = Expr;
38
David Tolnay3cb23a92016-10-07 23:02:21 -070039#[cfg(feature = "parsing")]
40pub mod parsing {
41 use super::*;
42 use {BinOp, Ty};
43 use lit::parsing::lit;
44 use op::parsing::{binop, unop};
45 use ty::parsing::{path, ty};
46
47 named!(pub const_expr -> ConstExpr, do_parse!(
48 mut e: alt!(
David Tolnay3cb23a92016-10-07 23:02:21 -070049 expr_unary
50 |
David Tolnayf43ba802016-10-30 10:20:47 -070051 expr_lit
52 |
53 expr_path
54 |
55 expr_paren
David Tolnay3cb23a92016-10-07 23:02:21 -070056 ) >>
57 many0!(alt!(
58 tap!(args: and_call => {
59 e = ConstExpr::Call(Box::new(e), args);
60 })
61 |
62 tap!(more: and_binary => {
63 let (op, other) = more;
64 e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
65 })
66 |
67 tap!(ty: and_cast => {
68 e = ConstExpr::Cast(Box::new(e), Box::new(ty));
69 })
David Tolnay67588752016-10-30 12:23:10 -070070 |
71 tap!(i: and_index => {
72 e = ConstExpr::Index(Box::new(e), Box::new(i));
73 })
David Tolnay3cb23a92016-10-07 23:02:21 -070074 )) >>
75 (e)
76 ));
77
78 named!(and_call -> Vec<ConstExpr>, do_parse!(
79 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -070080 args: terminated_list!(punct!(","), const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -070081 punct!(")") >>
82 (args)
83 ));
84
85 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
86
87 named!(expr_unary -> ConstExpr, do_parse!(
88 operator: unop >>
89 operand: const_expr >>
90 (ConstExpr::Unary(operator, Box::new(operand)))
91 ));
92
93 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
94
David Tolnayf43ba802016-10-30 10:20:47 -070095 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
96
David Tolnay67588752016-10-30 12:23:10 -070097 named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
98
David Tolnayf43ba802016-10-30 10:20:47 -070099 named!(expr_paren -> ConstExpr, do_parse!(
100 punct!("(") >>
101 e: const_expr >>
102 punct!(")") >>
103 (ConstExpr::Paren(Box::new(e)))
104 ));
105
David Tolnay3cb23a92016-10-07 23:02:21 -0700106 named!(and_cast -> Ty, do_parse!(
107 keyword!("as") >>
108 ty: ty >>
109 (ty)
110 ));
111}
112
113#[cfg(feature = "printing")]
114mod printing {
115 use super::*;
116 use quote::{Tokens, ToTokens};
117
118 impl ToTokens for ConstExpr {
119 fn to_tokens(&self, tokens: &mut Tokens) {
120 match *self {
121 ConstExpr::Call(ref func, ref args) => {
122 func.to_tokens(tokens);
123 tokens.append("(");
124 tokens.append_separated(args, ",");
125 tokens.append(")");
126 }
127 ConstExpr::Binary(op, ref left, ref right) => {
128 left.to_tokens(tokens);
129 op.to_tokens(tokens);
130 right.to_tokens(tokens);
131 }
132 ConstExpr::Unary(op, ref expr) => {
133 op.to_tokens(tokens);
134 expr.to_tokens(tokens);
135 }
136 ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
137 ConstExpr::Cast(ref expr, ref ty) => {
138 expr.to_tokens(tokens);
139 tokens.append("as");
140 ty.to_tokens(tokens);
141 }
142 ConstExpr::Path(ref path) => path.to_tokens(tokens),
David Tolnay67588752016-10-30 12:23:10 -0700143 ConstExpr::Index(ref expr, ref index) => {
144 expr.to_tokens(tokens);
145 tokens.append("[");
146 index.to_tokens(tokens);
147 tokens.append("]");
148 }
David Tolnayf43ba802016-10-30 10:20:47 -0700149 ConstExpr::Paren(ref expr) => {
150 tokens.append("(");
151 expr.to_tokens(tokens);
152 tokens.append(")");
153 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700154 ConstExpr::Other(ref other) => {
155 other.to_tokens(tokens);
156 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700157 }
158 }
159 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700160
161 #[cfg(not(feature = "full"))]
162 impl ToTokens for Other {
163 fn to_tokens(&self, _tokens: &mut Tokens) {
164 unreachable!()
165 }
166 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700167}