1use idents::symbol;
2use nom::{
3 branch::alt,
4 bytes::complete::tag,
5 combinator::map,
6 multi::{fold_many0, separated_list0},
7 sequence::{delimited, pair},
8 IResult,
9};
10use numbers::number;
11use whitespace::opt_space;
12
13#[derive(Debug, PartialEq, Clone)]
14pub enum UnaryOperator {
15 LogicNot,
16 Minus,
17 BitwiseNot,
18}
19
20#[derive(Debug, PartialEq, Clone)]
21pub enum BinaryOperator {
22 LogicOr,
23 LogicAnd,
24 BitwiseOr,
25 BitwiseAnd,
26 Equals,
27 NotEquals,
28 Lesser,
29 Greater,
30 LesserOrEquals,
31 GreaterOrEquals,
32 ShiftRight,
33 ShiftLeft,
34 Plus,
35 Minus,
36 Multiply,
37 Divide,
38 Remainder,
39}
40
41#[derive(Debug, PartialEq, Clone)]
42pub enum Expression {
43 Ident(String),
44 Number(u64),
45 Call {
46 function: String,
47 arguments: Vec<Expression>,
48 },
49 UnaryOp {
50 operator: UnaryOperator,
51 right: Box<Expression>,
52 },
53 BinaryOp {
54 left: Box<Expression>,
55 operator: BinaryOperator,
56 right: Box<Expression>,
57 },
58 TernaryOp {
59 condition: Box<Expression>,
60 left: Box<Expression>,
61 right: Box<Expression>,
62 },
63}
64
65fn value_ident(input: &str) -> IResult<&str, Expression> {
66 map(symbol, |x: &str| Expression::Ident(x.into()))(input)
67}
68
69fn value_number(input: &str) -> IResult<&str, Expression> {
70 map(number, |x| Expression::Number(x))(input)
71}
72
73fn value_nested(input: &str) -> IResult<&str, Expression> {
74 delimited(tag("("), wsc!(expression), tag(")"))(input)
75}
76
77fn value_call(input: &str) -> IResult<&str, Expression> {
78 let (input, func) = symbol(input)?;
79 let (input, _) = wsc!(tag("("))(input)?;
80 let (input, args) = separated_list0(wsc!(tag(",")), expression)(input)?;
81 let (input, _) = pair(opt_space, tag(")"))(input)?;
82 Ok((
83 input,
84 Expression::Call {
85 function: func.into(),
86 arguments: args,
87 },
88 ))
89}
90
91pub fn value(input: &str) -> IResult<&str, Expression> {
92 alt((value_nested, value_call, value_number, value_ident))(input)
93}
94
95fn expr_unary_op(input: &str) -> IResult<&str, Expression> {
96 let (input, op) = alt((tag("-"), tag("!"), tag("~")))(input)?;
97 let (input, _) = opt_space(input)?;
98 let (input, right) = expr_level_1(input)?;
99 Ok((
100 input,
101 Expression::UnaryOp {
102 operator: match op {
103 "-" => UnaryOperator::Minus,
104 "!" => UnaryOperator::LogicNot,
105 "~" => UnaryOperator::BitwiseNot,
106 _ => panic!("Invalid operator"),
107 },
108 right: Box::new(right),
109 },
110 ))
111}
112
113fn expr_level_1(input: &str) -> IResult<&str, Expression> {
114 alt((expr_unary_op, value))(input)
115}
116
117fn expr_level_2(input: &str) -> IResult<&str, Expression> {
118 let (input, first) = expr_level_1(input)?;
119 let (input, fold) = fold_many0(
120 pair(wsc!(alt((tag("*"), tag("/"), tag("%")))), expr_level_1),
121 || first.clone(),
122 |prev, new: (&str, Expression)| Expression::BinaryOp {
123 left: Box::new(prev),
124 operator: match new.0 {
125 "*" => BinaryOperator::Multiply,
126 "/" => BinaryOperator::Divide,
127 "%" => BinaryOperator::Remainder,
128 _ => panic!("Invalid operator"),
129 },
130 right: Box::new(new.1),
131 },
132 )(input)?;
133 Ok((input, fold))
134}
135
136fn expr_level_3(input: &str) -> IResult<&str, Expression> {
137 let (input, first) = expr_level_2(input)?;
138 let (input, fold) = fold_many0(
139 pair(wsc!(alt((tag("+"), tag("-")))), expr_level_2),
140 || first.clone(),
141 |prev, new: (&str, Expression)| Expression::BinaryOp {
142 left: Box::new(prev),
143 operator: match new.0 {
144 "+" => BinaryOperator::Plus,
145 "-" => BinaryOperator::Minus,
146 _ => panic!("Invalid operator"),
147 },
148 right: Box::new(new.1),
149 },
150 )(input)?;
151 Ok((input, fold))
152}
153
154fn expr_level_4(input: &str) -> IResult<&str, Expression> {
155 let (input, first) = expr_level_3(input)?;
156 let (input, fold) = fold_many0(
157 pair(wsc!(alt((tag("<<"), tag(">>")))), expr_level_3),
158 || first.clone(),
159 |prev, new: (&str, Expression)| Expression::BinaryOp {
160 left: Box::new(prev),
161 operator: match new.0 {
162 "<<" => BinaryOperator::ShiftLeft,
163 ">>" => BinaryOperator::ShiftRight,
164 _ => panic!("Invalid operator"),
165 },
166 right: Box::new(new.1),
167 },
168 )(input)?;
169 Ok((input, fold))
170}
171
172fn expr_level_5(input: &str) -> IResult<&str, Expression> {
173 let (input, first) = expr_level_4(input)?;
174 let (input, fold) = fold_many0(
175 pair(
176 wsc!(alt((
177 tag("=="),
178 tag("!="),
179 tag("<="),
180 tag(">="),
181 tag("<"),
182 tag(">")
183 ))),
184 expr_level_4,
185 ),
186 || first.clone(),
187 |prev, new: (&str, Expression)| Expression::BinaryOp {
188 left: Box::new(prev),
189 operator: match new.0 {
190 "==" => BinaryOperator::Equals,
191 "!=" => BinaryOperator::NotEquals,
192 "<=" => BinaryOperator::LesserOrEquals,
193 ">=" => BinaryOperator::GreaterOrEquals,
194 "<" => BinaryOperator::Lesser,
195 ">" => BinaryOperator::Greater,
196 _ => panic!("Invalid operator"),
197 },
198 right: Box::new(new.1),
199 },
200 )(input)?;
201 Ok((input, fold))
202}
203
204fn expr_level_6(input: &str) -> IResult<&str, Expression> {
205 let (input, first) = expr_level_5(input)?;
206 let (input, fold) = fold_many0(
207 pair(wsc!(tag("&")), expr_level_5),
208 || first.clone(),
209 |prev, new: (&str, Expression)| Expression::BinaryOp {
210 left: Box::new(prev),
211 operator: BinaryOperator::BitwiseAnd,
212 right: Box::new(new.1),
213 },
214 )(input)?;
215 Ok((input, fold))
216}
217
218fn expr_level_7(input: &str) -> IResult<&str, Expression> {
219 let (input, first) = expr_level_6(input)?;
220 let (input, fold) = fold_many0(
221 pair(wsc!(tag("|")), expr_level_6),
222 || first.clone(),
223 |prev, new: (&str, Expression)| Expression::BinaryOp {
224 left: Box::new(prev),
225 operator: BinaryOperator::BitwiseOr,
226 right: Box::new(new.1),
227 },
228 )(input)?;
229 Ok((input, fold))
230}
231
232fn expr_level_8(input: &str) -> IResult<&str, Expression> {
233 let (input, first) = expr_level_7(input)?;
234 let (input, fold) = fold_many0(
235 pair(wsc!(tag("&&")), expr_level_7),
236 || first.clone(),
237 |prev, new: (&str, Expression)| Expression::BinaryOp {
238 left: Box::new(prev),
239 operator: BinaryOperator::LogicAnd,
240 right: Box::new(new.1),
241 },
242 )(input)?;
243 Ok((input, fold))
244}
245
246fn expr_level_9(input: &str) -> IResult<&str, Expression> {
247 let (input, first) = expr_level_8(input)?;
248 let (input, fold) = fold_many0(
249 pair(wsc!(tag("||")), expr_level_8),
250 || first.clone(),
251 |prev, new: (&str, Expression)| Expression::BinaryOp {
252 left: Box::new(prev),
253 operator: BinaryOperator::LogicOr,
254 right: Box::new(new.1),
255 },
256 )(input)?;
257 Ok((input, fold))
258}
259
260fn expr_ternary_op(input: &str) -> IResult<&str, Expression> {
261 let (input, cond) = expr_level_9(input)?;
262 let (input, _) = wsc!(tag("?"))(input)?;
263 let (input, left) = expression(input)?;
264 let (input, _) = wsc!(tag(":"))(input)?;
265 let (input, right) = expression(input)?;
266 Ok((
267 input,
268 Expression::TernaryOp {
269 condition: Box::new(cond),
270 left: Box::new(left),
271 right: Box::new(right),
272 },
273 ))
274}
275
276pub fn expression(input: &str) -> IResult<&str, Expression> {
277 alt((expr_ternary_op, expr_level_9))(input)
278}
279
280#[cfg(test)]
281mod tests {
282 use expressions::*;
283
284 #[test]
285 fn test_ws() {
286 let x = "a ( b ( d , ( 0 ) ) , c )";
287 assert_done!(expression(x));
288 let y = "a(b(d,(0)),c)";
289 assert_eq!(expression(x), expression(y));
290 }
291
292 #[test]
293 fn test_expression() {
294 assert_done!(expression("a ( .b ) ? c ( d ) : e"));
295
296 assert_done!(expression("A-B"), Expression::Ident("A-B".into()));
297
298 assert_done!(
299 expression("A - B"),
300 Expression::BinaryOp {
301 left: Box::new(Expression::Ident("A".into())),
302 operator: BinaryOperator::Minus,
303 right: Box::new(Expression::Ident("B".into())),
304 }
305 );
306 }
307}