blob: d0f11b5cf75fcfc38f7ead31731a406d6ad0813f [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};
Simon Sapinec3cb0d2017-02-27 12:28:47 +010046 #[cfg(feature = "full")] use expr::parsing::expr;
47 #[cfg(not(feature = "full"))] use synom::IResult;
David Tolnay3cb23a92016-10-07 23:02:21 -070048
49 named!(pub const_expr -> ConstExpr, do_parse!(
50 mut e: alt!(
David Tolnay3cb23a92016-10-07 23:02:21 -070051 expr_unary
52 |
David Tolnayf43ba802016-10-30 10:20:47 -070053 expr_lit
54 |
55 expr_path
56 |
57 expr_paren
Simon Sapinec3cb0d2017-02-27 12:28:47 +010058 |
59 expr_other
David Tolnay3cb23a92016-10-07 23:02:21 -070060 ) >>
61 many0!(alt!(
62 tap!(args: and_call => {
63 e = ConstExpr::Call(Box::new(e), args);
64 })
65 |
66 tap!(more: and_binary => {
67 let (op, other) = more;
68 e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
69 })
70 |
71 tap!(ty: and_cast => {
72 e = ConstExpr::Cast(Box::new(e), Box::new(ty));
73 })
David Tolnay67588752016-10-30 12:23:10 -070074 |
75 tap!(i: and_index => {
76 e = ConstExpr::Index(Box::new(e), Box::new(i));
77 })
David Tolnay3cb23a92016-10-07 23:02:21 -070078 )) >>
79 (e)
80 ));
81
82 named!(and_call -> Vec<ConstExpr>, do_parse!(
83 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -070084 args: terminated_list!(punct!(","), const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -070085 punct!(")") >>
86 (args)
87 ));
88
89 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
90
91 named!(expr_unary -> ConstExpr, do_parse!(
92 operator: unop >>
93 operand: const_expr >>
94 (ConstExpr::Unary(operator, Box::new(operand)))
95 ));
96
97 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
98
David Tolnayf43ba802016-10-30 10:20:47 -070099 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
100
Simon Sapinec3cb0d2017-02-27 12:28:47 +0100101 #[cfg(feature = "full")]
102 named!(expr_other -> ConstExpr, map!(expr, ConstExpr::Other));
103
104 #[cfg(not(feature = "full"))]
105 fn expr_other(_: &str) -> IResult<&str, ConstExpr> {
106 IResult::Error
107 }
108
David Tolnay67588752016-10-30 12:23:10 -0700109 named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
110
David Tolnayf43ba802016-10-30 10:20:47 -0700111 named!(expr_paren -> ConstExpr, do_parse!(
112 punct!("(") >>
113 e: const_expr >>
114 punct!(")") >>
115 (ConstExpr::Paren(Box::new(e)))
116 ));
117
David Tolnay3cb23a92016-10-07 23:02:21 -0700118 named!(and_cast -> Ty, do_parse!(
119 keyword!("as") >>
120 ty: ty >>
121 (ty)
122 ));
123}
124
125#[cfg(feature = "printing")]
126mod printing {
127 use super::*;
128 use quote::{Tokens, ToTokens};
129
130 impl ToTokens for ConstExpr {
131 fn to_tokens(&self, tokens: &mut Tokens) {
132 match *self {
133 ConstExpr::Call(ref func, ref args) => {
134 func.to_tokens(tokens);
135 tokens.append("(");
136 tokens.append_separated(args, ",");
137 tokens.append(")");
138 }
139 ConstExpr::Binary(op, ref left, ref right) => {
140 left.to_tokens(tokens);
141 op.to_tokens(tokens);
142 right.to_tokens(tokens);
143 }
144 ConstExpr::Unary(op, ref expr) => {
145 op.to_tokens(tokens);
146 expr.to_tokens(tokens);
147 }
148 ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
149 ConstExpr::Cast(ref expr, ref ty) => {
150 expr.to_tokens(tokens);
151 tokens.append("as");
152 ty.to_tokens(tokens);
153 }
154 ConstExpr::Path(ref path) => path.to_tokens(tokens),
David Tolnay67588752016-10-30 12:23:10 -0700155 ConstExpr::Index(ref expr, ref index) => {
156 expr.to_tokens(tokens);
157 tokens.append("[");
158 index.to_tokens(tokens);
159 tokens.append("]");
160 }
David Tolnayf43ba802016-10-30 10:20:47 -0700161 ConstExpr::Paren(ref expr) => {
162 tokens.append("(");
163 expr.to_tokens(tokens);
164 tokens.append(")");
165 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700166 ConstExpr::Other(ref other) => {
167 other.to_tokens(tokens);
168 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700169 }
170 }
171 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700172
173 #[cfg(not(feature = "full"))]
174 impl ToTokens for Other {
175 fn to_tokens(&self, _tokens: &mut Tokens) {
176 unreachable!()
177 }
178 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700179}