blob: 145729d19977149171634618bd77eea4fd675195 [file] [log] [blame]
David Tolnay3cb23a92016-10-07 23:02:21 -07001use super::*;
2
David Tolnay9bf4af82017-01-07 11:17:46 -08003#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnay3cb23a92016-10-07 23:02:21 -07004pub 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"))]
David Tolnay9bf4af82017-01-07 11:17:46 -080031#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayfe2cc9a2016-10-30 12:47:36 -070032pub 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 Tolnay514f1292017-02-27 12:30:57 -080056 // Cannot handle ConstExpr::Other here because for example
57 // `[u32; n!()]` would end up successfully parsing `n` as
58 // ConstExpr::Path and then fail to parse `!()`. Instead, callers
59 // are required to handle Other. See ty::parsing::array_len and
60 // data::parsing::discriminant.
David Tolnay3cb23a92016-10-07 23:02:21 -070061 ) >>
62 many0!(alt!(
63 tap!(args: and_call => {
64 e = ConstExpr::Call(Box::new(e), args);
65 })
66 |
67 tap!(more: and_binary => {
68 let (op, other) = more;
69 e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
70 })
71 |
72 tap!(ty: and_cast => {
73 e = ConstExpr::Cast(Box::new(e), Box::new(ty));
74 })
David Tolnay67588752016-10-30 12:23:10 -070075 |
76 tap!(i: and_index => {
77 e = ConstExpr::Index(Box::new(e), Box::new(i));
78 })
David Tolnay3cb23a92016-10-07 23:02:21 -070079 )) >>
80 (e)
81 ));
82
83 named!(and_call -> Vec<ConstExpr>, do_parse!(
84 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -070085 args: terminated_list!(punct!(","), const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -070086 punct!(")") >>
87 (args)
88 ));
89
90 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
91
92 named!(expr_unary -> ConstExpr, do_parse!(
93 operator: unop >>
94 operand: const_expr >>
95 (ConstExpr::Unary(operator, Box::new(operand)))
96 ));
97
98 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
99
David Tolnayf43ba802016-10-30 10:20:47 -0700100 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
101
David Tolnay67588752016-10-30 12:23:10 -0700102 named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
103
David Tolnayf43ba802016-10-30 10:20:47 -0700104 named!(expr_paren -> ConstExpr, do_parse!(
105 punct!("(") >>
106 e: const_expr >>
107 punct!(")") >>
108 (ConstExpr::Paren(Box::new(e)))
109 ));
110
David Tolnay3cb23a92016-10-07 23:02:21 -0700111 named!(and_cast -> Ty, do_parse!(
112 keyword!("as") >>
113 ty: ty >>
114 (ty)
115 ));
116}
117
118#[cfg(feature = "printing")]
119mod printing {
120 use super::*;
121 use quote::{Tokens, ToTokens};
122
123 impl ToTokens for ConstExpr {
124 fn to_tokens(&self, tokens: &mut Tokens) {
125 match *self {
126 ConstExpr::Call(ref func, ref args) => {
127 func.to_tokens(tokens);
128 tokens.append("(");
129 tokens.append_separated(args, ",");
130 tokens.append(")");
131 }
132 ConstExpr::Binary(op, ref left, ref right) => {
133 left.to_tokens(tokens);
134 op.to_tokens(tokens);
135 right.to_tokens(tokens);
136 }
137 ConstExpr::Unary(op, ref expr) => {
138 op.to_tokens(tokens);
139 expr.to_tokens(tokens);
140 }
141 ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
142 ConstExpr::Cast(ref expr, ref ty) => {
143 expr.to_tokens(tokens);
144 tokens.append("as");
145 ty.to_tokens(tokens);
146 }
147 ConstExpr::Path(ref path) => path.to_tokens(tokens),
David Tolnay67588752016-10-30 12:23:10 -0700148 ConstExpr::Index(ref expr, ref index) => {
149 expr.to_tokens(tokens);
150 tokens.append("[");
151 index.to_tokens(tokens);
152 tokens.append("]");
153 }
David Tolnayf43ba802016-10-30 10:20:47 -0700154 ConstExpr::Paren(ref expr) => {
155 tokens.append("(");
156 expr.to_tokens(tokens);
157 tokens.append(")");
158 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700159 ConstExpr::Other(ref other) => {
160 other.to_tokens(tokens);
161 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700162 }
163 }
164 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700165
166 #[cfg(not(feature = "full"))]
167 impl ToTokens for Other {
168 fn to_tokens(&self, _tokens: &mut Tokens) {
169 unreachable!()
170 }
171 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700172}