1use super::token::{Literal, Operator, StringLiteral, Token};
2use crate::token::{get_lexer, Bracket};
3use crate::Error;
4
5use chumsky::prelude::*;
6use chumsky::primitive::FilterMap;
7
8#[derive(Clone, Debug, PartialEq)]
9pub enum Expr {
10 Integer(u128),
11 Float(String), String(String),
13 Bool(bool),
14 Ident(String),
15 Array(Vec<Expr>),
16 UnaryExpr {
17 operator: Operator,
18 value: Box<Expr>,
19 },
20 BinaryExpr {
21 operator: Operator,
22 lhs: Box<Expr>,
23 rhs: Box<Expr>,
24 },
25 Attr(Box<Expr>, String),
26 Call {
27 value: Box<Expr>,
28 args: Vec<Expr>,
29 kwargs: Vec<(String, Expr)>,
30 },
31}
32
33impl Expr {
34 pub fn from_tokens(tokens: Vec<Token>) -> (Self, Vec<Error>) {
35 let (expr, errors) = get_expr_parser().parse_recovery(tokens);
36
37 (expr.unwrap(), errors)
38 }
39
40 pub fn from_string(s: String) -> (Self, Vec<Error>) {
41 Self::from_tokens(get_lexer().parse(s.as_str()).unwrap())
42 }
43}
44
45#[derive(Clone, Debug, PartialEq)]
46pub enum Target {
47 Ident(String),
49 Array(Vec<Target>),
50 Attr(Box<Target>, String), }
52
53#[derive(Clone, Debug, PartialEq)]
54pub enum Node {
55 Module(Vec<Node>),
56 Func {
57 name: String,
58 params: Vec<Node>,
59 body: Vec<Node>,
60 },
61 Expr(Expr),
62 Assign {
64 target: Target,
65 value: Expr,
66 r#let: bool,
67 immut: bool,
68 },
69 Return(Option<Expr>),
70}
71
72pub trait CommonParser<T> = Parser<Token, T, Error = Error> + Clone;
73
74pub fn get_expr_parser() -> impl CommonParser<Expr> {
75 recursive(|e: Recursive<Token, Expr, Error>| {
76 let literal: FilterMap<_, Error> = select! {
77 Token::Literal(lit) => match lit {
78 Literal::Integer(i) => Expr::Integer(i),
79 Literal::Float(f) => Expr::Float(f),
80 Literal::String(s) => match s {
81 StringLiteral::String(s) => Expr::String(s),
82 _ => unreachable!(),
83 },
84 }
85 };
86
87 let ident = select! {
88 Token::Identifier(s) => match s.as_str() {
89 "true" => Expr::Bool(true),
90 "false" => Expr::Bool(false),
91 _ => Expr::Ident(s),
92 }
93 };
94
95 let array = e
96 .clone()
97 .separated_by(just::<_, Token, _>(Token::Comma))
98 .allow_trailing()
99 .delimited_by(
100 just(Token::StartBracket(Bracket::Bracket)),
101 just(Token::EndBracket(Bracket::Bracket)),
102 )
103 .map(Expr::Array);
104
105 let atom = choice((
106 literal,
107 ident,
108 e.clone()
109 .delimited_by(
110 just(Token::StartBracket(Bracket::Paren)),
111 just(Token::EndBracket(Bracket::Paren)),
112 )
113 .boxed(),
114 array,
115 ))
116 .boxed();
117
118 let attr = atom
119 .clone()
120 .then(
121 just::<_, Token, _>(Token::Dot)
122 .ignore_then(ident)
123 .repeated(),
124 )
125 .foldl(|a, b| {
126 Expr::Attr(
127 Box::new(a),
128 match b {
129 Expr::Ident(s) => s,
130 Expr::Bool(b) => b.to_string(),
131 _ => unreachable!(),
132 },
133 )
134 })
135 .boxed();
136
137 let call = attr
138 .clone()
139 .then(
140 e.clone()
141 .separated_by(just::<_, Token, _>(Token::Comma))
142 .allow_trailing()
143 .delimited_by(
144 just(Token::StartBracket(Bracket::Paren)),
145 just(Token::EndBracket(Bracket::Paren)),
146 )
147 .or_not(),
148 )
149 .map(|(expr, args)| match args {
150 Some(args) => Expr::Call {
151 value: Box::new(expr),
152 args,
153 kwargs: vec![],
154 },
155 None => expr,
156 })
157 .boxed();
158
159 let unary = just(Token::Operator(Operator::Sub))
160 .or(just(Token::Operator(Operator::Add)))
161 .or(just(Token::Operator(Operator::Not)))
162 .or(just(Token::Operator(Operator::BitNot)))
163 .repeated()
164 .then(call.clone())
165 .foldr(|operator, expr| match operator {
166 Token::Operator(operator) => Expr::UnaryExpr {
167 operator,
168 value: Box::new(expr),
169 },
170 _ => unreachable!(),
171 })
172 .boxed();
173
174 let binary_pow = unary
175 .clone()
176 .then(
177 just(Token::Operator(Operator::Pow))
178 .map(|o| match o {
179 Token::Operator(op) => op,
180 _ => unreachable!(),
181 })
182 .then(unary)
183 .repeated(),
184 )
185 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
186 operator,
187 lhs: Box::new(lhs),
188 rhs: Box::new(rhs),
189 })
190 .boxed();
191
192 let op = just(Token::Operator(Operator::Mul))
193 .or(just(Token::Operator(Operator::Div)))
194 .or(just(Token::Operator(Operator::Mod)))
195 .map(|o| match o {
196 Token::Operator(op) => op,
197 _ => unreachable!(),
198 });
199 let binary_product = binary_pow
200 .clone()
201 .then(op.then(binary_pow).repeated())
202 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
203 operator,
204 lhs: Box::new(lhs),
205 rhs: Box::new(rhs),
206 })
207 .boxed();
208
209 let op = just(Token::Operator(Operator::Add))
210 .or(just(Token::Operator(Operator::Sub)))
211 .map(|o| match o {
212 Token::Operator(op) => op,
213 _ => unreachable!(),
214 });
215 let binary_sum = binary_product
216 .clone()
217 .then(op.then(binary_product).repeated())
218 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
219 operator,
220 lhs: Box::new(lhs),
221 rhs: Box::new(rhs),
222 })
223 .boxed();
224
225 let op = just(Token::Operator(Operator::Eq))
226 .or(just(Token::Operator(Operator::Ne)))
227 .or(just(Token::Operator(Operator::Lt)))
228 .or(just(Token::Operator(Operator::Gt)))
229 .or(just(Token::Operator(Operator::Le)))
230 .or(just(Token::Operator(Operator::Ge)))
231 .map(|o| match o {
232 Token::Operator(op) => op,
233 _ => unreachable!(),
234 });
235 let binary_cmp = binary_sum
236 .clone()
237 .then(op.then(binary_sum).repeated())
238 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
239 operator,
240 lhs: Box::new(lhs),
241 rhs: Box::new(rhs),
242 })
243 .boxed();
244
245 let binary_logical_and = binary_cmp
246 .clone()
247 .then(
248 just(Token::Operator(Operator::And))
249 .map(|o| match o {
250 Token::Operator(op) => op,
251 _ => unreachable!(),
252 })
253 .then(binary_cmp)
254 .repeated(),
255 )
256 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
257 operator,
258 lhs: Box::new(lhs),
259 rhs: Box::new(rhs),
260 })
261 .boxed();
262
263 let binary_logical_or = binary_logical_and
264 .clone()
265 .then(
266 just(Token::Operator(Operator::Or))
267 .map(|o| match o {
268 Token::Operator(op) => op,
269 _ => unreachable!(),
270 })
271 .then(binary_logical_and)
272 .repeated(),
273 )
274 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
275 operator,
276 lhs: Box::new(lhs),
277 rhs: Box::new(rhs),
278 })
279 .boxed();
280
281 let op = just(Token::Operator(Operator::BitAnd))
282 .or(just(Token::Operator(Operator::BitOr)))
283 .or(just(Token::Operator(Operator::BitXor)))
284 .map(|o| match o {
285 Token::Operator(op) => op,
286 _ => unreachable!(),
287 });
288 binary_logical_or
289 .clone()
290 .then(op.then(binary_logical_or).repeated())
291 .foldl(|lhs, (operator, rhs)| Expr::BinaryExpr {
292 operator,
293 lhs: Box::new(lhs),
294 rhs: Box::new(rhs),
295 })
296 .boxed()
297 })
298}
299
300#[cfg(test)]
301mod tests {
302 use super::*;
303 use crate::ast::Expr::*;
304
305 #[test]
306 fn test_expr_parser() {
307 let code = "-1 + 2 * (5 - [2, a.b() - (c + -d), e(5, f())])";
308 let (tree, errors) = Expr::from_string(code.to_string());
309
310 assert_eq!(
311 tree,
312 BinaryExpr {
313 operator: Operator::Add,
314 lhs: Box::new(UnaryExpr {
315 operator: Operator::Sub,
316 value: Box::new(Integer(1)),
317 }),
318 rhs: Box::new(BinaryExpr {
319 operator: Operator::Mul,
320 lhs: Box::new(Integer(2)),
321 rhs: Box::new(BinaryExpr {
322 operator: Operator::Sub,
323 lhs: Box::new(Integer(5)),
324 rhs: Box::new(Array(vec![
325 Integer(2),
326 BinaryExpr {
327 operator: Operator::Sub,
328 lhs: Box::new(Call {
329 value: Box::new(Attr(
330 Box::new(Ident("a".to_string())),
331 "b".to_string()
332 )),
333 args: vec![],
334 kwargs: vec![],
335 }),
336 rhs: Box::new(BinaryExpr {
337 operator: Operator::Add,
338 lhs: Box::new(Ident("c".to_string())),
339 rhs: Box::new(UnaryExpr {
340 operator: Operator::Sub,
341 value: Box::new(Ident("d".to_string())),
342 }),
343 }),
344 },
345 Call {
346 value: Box::new(Ident("e".to_string())),
347 args: vec![
348 Integer(5),
349 Call {
350 value: Box::new(Ident("f".to_string())),
351 args: vec![],
352 kwargs: vec![],
353 },
354 ],
355 kwargs: vec![],
356 },
357 ])),
358 }),
359 }),
360 }
361 );
362 assert_eq!(errors.len(), 0);
363 }
364}