cellang/
parser.rs

1use crate::Lexer;
2use crate::lexer::{Token, TokenType};
3use miette::{Context, Error, LabeledSpan};
4use serde::Serialize;
5use serde::ser::SerializeStruct;
6use std::borrow::Cow;
7use std::fmt;
8
9/// A parser for the language.
10/// This parser is a Pratt parser, which is a top-down operator precedence parser.
11/// Produces TokenTree (AST) from the input by using the lexer.
12pub struct Parser<'src> {
13    input: &'src str,
14    lexer: Lexer<'src>,
15}
16
17impl<'src> Parser<'src> {
18    pub fn new(input: &'src str) -> Self {
19        Self {
20            input,
21            lexer: Lexer::new(input),
22        }
23    }
24
25    /// Parses the whole input and returns the AST.
26    pub fn parse(&mut self) -> Result<TokenTree<'src>, Error> {
27        self.parse_expr(0)
28    }
29
30    fn parse_expr(&mut self, min_bp: u8) -> Result<TokenTree<'src>, Error> {
31        let lhs = match self.lexer.next() {
32            Some(Ok(token)) => token,
33            None => return Ok(TokenTree::Atom(Atom::Null)), // todo: figure out this
34            Some(Err(e)) => return Err(e),
35        };
36
37        let mut lhs = match lhs {
38            // atoms
39            Token {
40                ty: TokenType::Ident,
41                origin,
42                ..
43            } => TokenTree::Atom(Atom::Ident(origin)),
44            Token {
45                ty: TokenType::Int(n),
46                ..
47            } => TokenTree::Atom(Atom::Int(n)),
48            Token {
49                ty: TokenType::Uint(n),
50                ..
51            } => TokenTree::Atom(Atom::Uint(n)),
52            Token {
53                ty: TokenType::Double(n),
54                ..
55            } => TokenTree::Atom(Atom::Double(n)),
56            Token {
57                ty: TokenType::Null,
58                ..
59            } => TokenTree::Atom(Atom::Null),
60            Token {
61                ty: TokenType::String | TokenType::RawString,
62                origin,
63                ..
64            } => TokenTree::Atom(Atom::String(Token::unescape(origin))),
65            Token {
66                ty: TokenType::Bytes | TokenType::RawBytes,
67                origin,
68                ..
69            } => TokenTree::Atom(Atom::Bytes(Token::unescape_bytes(origin))),
70            Token {
71                ty: TokenType::True,
72                ..
73            } => TokenTree::Atom(Atom::Bool(true)),
74            Token {
75                ty: TokenType::False,
76                ..
77            } => TokenTree::Atom(Atom::Bool(false)),
78
79            // dyn
80            Token {
81                ty: TokenType::Dyn, ..
82            } => {
83                self.lexer.expect(
84                    TokenType::LeftParen,
85                    "Expected opening parenthesis after dyn",
86                )?;
87                let expr = self.parse_expr(0)?;
88                self.lexer.expect(
89                    TokenType::RightParen,
90                    "Expected closing parenthesis after dyn",
91                )?;
92                TokenTree::Cons(Op::Dyn, vec![expr])
93            }
94
95            // groups
96            Token {
97                ty: TokenType::LeftParen,
98                ..
99            } => {
100                let lhs = self.parse_expr(0)?;
101                self.lexer.expect(
102                    TokenType::RightParen,
103                    "Expected closing parenthesis",
104                )?;
105                TokenTree::Cons(Op::Group, vec![lhs])
106            }
107
108            // unary operators
109            Token {
110                ty: TokenType::Not | TokenType::Minus,
111                ..
112            } => {
113                let op = match lhs.ty {
114                    TokenType::Not => Op::Not,
115                    TokenType::Minus => Op::Minus,
116                    _ => unreachable!(),
117                };
118                let ((), r_bp) = prefix_binding_power(op);
119                let rhs = self.parse_expr(r_bp)?;
120                TokenTree::Cons(op, vec![rhs])
121            }
122
123            // aggregate types
124            Token {
125                ty: TokenType::LeftBrace,
126                ..
127            } => self.parse_map()?,
128
129            Token {
130                ty: TokenType::LeftBracket,
131                ..
132            } => self.parse_list()?,
133
134            token => {
135                return Err(miette::miette! {
136                    labels = vec![
137                        LabeledSpan::at(
138                            token.offset..token.offset + token.origin.len(),
139                            "here",
140                        ),
141                    ],
142                        help = format!("Unexpected token: {:?}", token.ty),
143                        "Unexpected token"
144                });
145            }
146        };
147
148        loop {
149            let op = self.lexer.peek();
150            if op.is_some_and(|op| op.is_err()) {
151                return Err(self
152                    .lexer
153                    .next()
154                    .expect("checked Some above")
155                    .expect_err("checked Err above"))
156                .wrap_err("in place of expected operator");
157            }
158
159            let op = match op.map(|res| res.as_ref().expect("handled Err above")) {
160                None | Some(Token {
161                    ty:
162                        TokenType::RightParen
163                        | TokenType::RightBracket
164                        | TokenType::RightBrace
165                        | TokenType::Comma
166                        | TokenType::Colon
167                        | TokenType::Semicolon,
168                    ..
169                }) => break,
170                Some(Token {
171                    ty: TokenType::LeftParen,
172                    ..
173                }) => Op::Call,
174                Some(Token {
175                    ty: TokenType::LeftBracket,
176                    ..
177                }) => Op::Index,
178                Some(Token {
179                    ty: TokenType::Dot,
180                    ..
181                }) => Op::Field,
182                Some(Token {
183                    ty: TokenType::Minus,
184                    ..
185                }) => Op::Minus,
186                Some(Token {
187                    ty: TokenType::Plus,
188                    ..
189                }) => Op::Plus,
190                Some(Token {
191                    ty: TokenType::Star,
192                    ..
193                }) => Op::Multiply,
194                Some(Token {
195                    ty: TokenType::Percent,
196                    ..
197                }) => Op::Mod,
198                Some(Token {
199                    ty: TokenType::NotEqual,
200                    ..
201                }) => Op::NotEqual,
202                Some(Token {
203                    ty: TokenType::In,
204                    ..
205                }) => Op::In,
206                Some(Token {
207                    ty: TokenType::EqualEqual,
208                    ..
209                }) => Op::EqualEqual,
210                Some(Token {
211                    ty: TokenType::LessEqual,
212                    ..
213                }) => Op::LessEqual,
214                Some(Token {
215                    ty: TokenType::GreaterEqual,
216                    ..
217                }) => Op::GreaterEqual,
218                Some(Token {
219                    ty: TokenType::Less,
220                    ..
221                }) => Op::Less,
222                Some(Token {
223                    ty: TokenType::Greater,
224                    ..
225                }) => Op::Greater,
226                Some(Token {
227                    ty: TokenType::Slash,
228                    ..
229                }) => Op::Devide,
230                Some(Token {
231                    ty: TokenType::And,
232                    ..
233                }) => Op::And,
234                Some(Token {
235                    ty: TokenType::Or,
236                    ..
237                }) => Op::Or,
238                Some(Token {
239                    ty: TokenType::QuestionMark,
240                    ..
241                }) => Op::IfTernary,
242
243                Some(token) => return Err(miette::miette! {
244                    labels = vec![
245                        LabeledSpan::at(token.offset..token.offset + token.origin.len(), "here"),
246                    ],
247                    help = format!("Unexpected {token:?}"),
248                    "Expected an infix operator",
249                }
250                .with_source_code(self.input.to_string())),
251            };
252
253            if let Some((l_bp, ())) = postfix_binding_power(op) {
254                if l_bp < min_bp {
255                    break;
256                }
257                self.lexer.next();
258
259                lhs = match op {
260                    Op::Call => TokenTree::Call {
261                        func: Box::new(lhs),
262                        args: self
263                            .parse_fn_call_args()
264                            .wrap_err("in function call arguments")?,
265                        is_method: false,
266                    },
267                    Op::Index => {
268                        let index = self
269                            .parse_expr(0)
270                            .wrap_err("in index expression")?;
271                        self.lexer.expect(
272                            TokenType::RightBracket,
273                            "Expected closing bracket",
274                        )?;
275                        TokenTree::Cons(op, vec![lhs, index])
276                    }
277                    _ => TokenTree::Cons(op, vec![lhs]),
278                };
279                continue;
280            }
281
282            if let Some((l_bp, r_bp)) = infix_binding_power(op) {
283                if l_bp < min_bp {
284                    break;
285                }
286                self.lexer.next();
287
288                lhs = match op {
289                    Op::IfTernary => {
290                        let mhs = self.parse_expr(0)?;
291                        self.lexer.expect(
292                            TokenType::Colon,
293                            "Expected colon after the condition",
294                        )?;
295                        let rhs = self.parse_expr(r_bp)?;
296                        TokenTree::Cons(op, vec![lhs, mhs, rhs])
297                    }
298                    Op::Field => {
299                        let rhs = self.parse_expr(r_bp)?;
300                        match rhs {
301                            TokenTree::Call {
302                                func,
303                                mut args,
304                                is_method,
305                            } => {
306                                if !is_method {
307                                    TokenTree::Call {
308                                        func,
309                                        args: vec![lhs]
310                                            .into_iter()
311                                            .chain(args)
312                                            .collect(),
313                                        is_method: true,
314                                    }
315                                } else {
316                                    let access = args.remove(0);
317                                    args.insert(
318                                        0,
319                                        TokenTree::Cons(
320                                            Op::Field,
321                                            vec![lhs, access],
322                                        ),
323                                    );
324                                    TokenTree::Call {
325                                        func,
326                                        args,
327                                        is_method,
328                                    }
329                                }
330                            }
331                            rhs => TokenTree::Cons(op, vec![lhs, rhs]),
332                        }
333                    }
334                    _ => {
335                        let rhs = self.parse_expr(r_bp)?;
336                        TokenTree::Cons(op, vec![lhs, rhs])
337                    }
338                };
339
340                continue;
341            }
342
343            break;
344        }
345
346        Ok(lhs)
347    }
348
349    fn parse_map(&mut self) -> Result<TokenTree<'src>, Error> {
350        let mut items = Vec::new();
351        if matches!(
352            self.lexer.peek(),
353            Some(Ok(Token {
354                ty: TokenType::RightBrace,
355                ..
356            }))
357        ) {
358            self.lexer.next();
359            return Ok(TokenTree::Cons(Op::Map, items));
360        }
361        loop {
362            let key = self.parse_expr(0).wrap_err("in map key")?;
363            self.lexer.expect(
364                TokenType::Colon,
365                "Expected colon between map key and value",
366            )?;
367            let value = self.parse_expr(0).wrap_err("in map value")?;
368            items.push(key);
369            items.push(value);
370
371            let token = self
372                .lexer
373                .expect_where(
374                    |token| {
375                        matches!(
376                            token.ty,
377                            TokenType::Comma | TokenType::RightBrace
378                        )
379                    },
380                    "continuing map",
381                )
382                .wrap_err("in map")?;
383
384            if token.ty == TokenType::RightBrace {
385                break;
386            }
387        }
388        Ok(TokenTree::Cons(Op::Map, items))
389    }
390
391    fn parse_list(&mut self) -> Result<TokenTree<'src>, Error> {
392        let mut items = Vec::new();
393        if matches!(
394            self.lexer.peek(),
395            Some(Ok(Token {
396                ty: TokenType::RightBracket,
397                ..
398            }))
399        ) {
400            self.lexer.next();
401            return Ok(TokenTree::Cons(Op::List, items));
402        }
403        loop {
404            let item = self.parse_expr(0).wrap_err("in list item")?;
405            items.push(item);
406            let token = self
407                .lexer
408                .expect_where(
409                    |token| {
410                        matches!(
411                            token.ty,
412                            TokenType::Comma | TokenType::RightBracket
413                        )
414                    },
415                    "continuing list",
416                )
417                .wrap_err("in list")?;
418
419            if token.ty == TokenType::RightBracket {
420                break;
421            }
422        }
423        Ok(TokenTree::Cons(Op::List, items))
424    }
425
426    fn parse_fn_call_args(&mut self) -> Result<Vec<TokenTree<'src>>, Error> {
427        let mut args = Vec::new();
428
429        if !matches!(
430            self.lexer.peek(),
431            Some(Ok(Token {
432                ty: TokenType::RightParen,
433                ..
434            }))
435        ) {
436            loop {
437                let arg = self.parse_expr(0).wrap_err_with(|| {
438                    format!("in argument #{} of function call", args.len() + 1)
439                })?;
440                args.push(arg);
441                let token = self
442                    .lexer
443                    .expect_where(
444                        |token| {
445                            matches!(
446                                token.ty,
447                                TokenType::Comma | TokenType::RightParen
448                            )
449                        },
450                        "continuing argument list",
451                    )
452                    .wrap_err("in argument list of function call")?;
453
454                if token.ty == TokenType::RightParen {
455                    break;
456                }
457            }
458        } else {
459            self.lexer.next();
460        }
461        Ok(args)
462    }
463}
464
465/// An atomic value in the AST.
466/// This is the smallest unit of the AST.
467#[derive(Debug, Clone, PartialEq)]
468pub enum Atom<'src> {
469    Bool(bool),
470    Int(i64),
471    Uint(u64),
472    Double(f64),
473    String(Cow<'src, str>),
474    Bytes(Cow<'src, [u8]>),
475    Ident(&'src str),
476    Null,
477}
478
479impl Serialize for Atom<'_> {
480    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
481    where
482        S: serde::Serializer,
483    {
484        match self {
485            Atom::Bool(b) => {
486                let mut s = serializer.serialize_struct("Bool", 2)?;
487                s.serialize_field("kind", "bool")?;
488                s.serialize_field("value", b)?;
489                s.end()
490            }
491            Atom::Int(i) => {
492                let mut s = serializer.serialize_struct("Int", 2)?;
493                s.serialize_field("kind", "int")?;
494                s.serialize_field("value", i)?;
495                s.end()
496            }
497            Atom::Uint(u) => {
498                let mut s = serializer.serialize_struct("Uint", 2)?;
499                s.serialize_field("kind", "uint")?;
500                s.serialize_field("value", u)?;
501                s.end()
502            }
503            Atom::Double(d) => {
504                let mut s = serializer.serialize_struct("Double", 2)?;
505                s.serialize_field("kind", "double")?;
506                s.serialize_field("value", d)?;
507                s.end()
508            }
509            Atom::String(s) => {
510                let mut srl = serializer.serialize_struct("String", 2)?;
511                srl.serialize_field("kind", "string")?;
512                srl.serialize_field("value", s)?;
513                srl.end()
514            }
515            Atom::Bytes(b) => {
516                let mut srl = serializer.serialize_struct("Bytes", 2)?;
517                srl.serialize_field("kind", "bytes")?;
518                srl.serialize_field("value", b)?;
519                srl.end()
520            }
521            Atom::Ident(i) => {
522                let mut s = serializer.serialize_struct("Ident", 2)?;
523                s.serialize_field("kind", "ident")?;
524                s.serialize_field("value", i)?;
525                s.end()
526            }
527            Atom::Null => {
528                let mut s = serializer.serialize_struct("Null", 1)?;
529                s.serialize_field("kind", "null")?;
530                s.end()
531            }
532        }
533    }
534}
535
536impl fmt::Display for Atom<'_> {
537    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
538        match self {
539            Atom::Bool(b) => write!(f, "{b:?}"),
540            Atom::Int(i) => write!(f, "{}", i),
541            Atom::Uint(u) => write!(f, "{}", u),
542            Atom::Double(d) => write!(f, "{}", d),
543            Atom::String(s) => write!(f, "{:?}", s),
544            Atom::Bytes(b) => write!(f, "{:?}", b),
545            Atom::Ident(i) => write!(f, "{}", i),
546            Atom::Null => write!(f, "null"),
547        }
548    }
549}
550
551/// An operator in the AST.
552#[derive(Debug, Clone, Copy, PartialEq)]
553pub enum Op {
554    Minus,
555    Plus,
556    Multiply,
557    Devide,
558    Mod,
559    NotEqual,
560    EqualEqual,
561    Less,
562    LessEqual,
563    Greater,
564    GreaterEqual,
565    Not,
566    And,
567    Or,
568    IfTernary,
569    In,
570    Call,
571    Index,
572    For,
573    Field,
574    While,
575    Var,
576    Group,
577    Map,
578    List,
579    Dyn,
580}
581
582impl Serialize for Op {
583    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
584    where
585        S: serde::Serializer,
586    {
587        let mut s = serializer.serialize_struct("Op", 1)?;
588        s.serialize_field("op", &self.to_string())?;
589        s.end()
590    }
591}
592
593impl fmt::Display for Op {
594    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
595        let s = match self {
596            Op::IfTernary => "?:",
597            Op::Minus => "-",
598            Op::Plus => "+",
599            Op::Multiply => "*",
600            Op::NotEqual => "!=",
601            Op::EqualEqual => "==",
602            Op::LessEqual => "<=",
603            Op::GreaterEqual => ">=",
604            Op::Less => "<",
605            Op::Greater => ">",
606            Op::Index => "[]",
607            Op::Var => "var",
608            Op::In => "in",
609            Op::Devide => "/",
610            Op::Not => "!",
611            Op::And => "&&",
612            Op::Or => "||",
613            Op::Call => "(args)",
614            Op::For => "for",
615            Op::Field => ".",
616            Op::While => "while",
617            Op::Group => "(",
618            Op::Map => "{map}",
619            Op::List => "[list]",
620            Op::Mod => "%",
621            Op::Dyn => "dyn",
622        };
623        write!(f, "{}", s)
624    }
625}
626
627/// A node in the AST.
628#[derive(Debug, Clone, PartialEq)]
629pub enum TokenTree<'src> {
630    Atom(Atom<'src>),
631    Cons(Op, Vec<TokenTree<'src>>),
632    Call {
633        func: Box<TokenTree<'src>>,
634        args: Vec<TokenTree<'src>>,
635        is_method: bool,
636    },
637}
638
639impl Serialize for TokenTree<'_> {
640    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
641    where
642        S: serde::Serializer,
643    {
644        match self {
645            TokenTree::Atom(atom) => atom.serialize(serializer),
646            TokenTree::Cons(op, args) => {
647                let mut state = serializer.serialize_struct("Cons", 2)?;
648                state.serialize_field("op", op)?;
649                state.serialize_field("args", args)?;
650                state.end()
651            }
652            TokenTree::Call {
653                func,
654                args,
655                is_method,
656            } => {
657                let mut state = serializer.serialize_struct("Call", 3)?;
658                state.serialize_field("func", func)?;
659                state.serialize_field("args", args)?;
660                state.serialize_field("is_method", is_method)?;
661                state.end()
662            }
663        }
664    }
665}
666
667impl fmt::Display for TokenTree<'_> {
668    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
669        match self {
670            TokenTree::Atom(atom) => write!(f, "{}", atom),
671            TokenTree::Cons(op, args) => {
672                write!(f, "{}", op)?;
673                for arg in args {
674                    write!(f, " {}", arg)?;
675                }
676                Ok(())
677            }
678            TokenTree::Call {
679                func,
680                args,
681                is_method,
682            } => {
683                if *is_method {
684                    write!(
685                        f,
686                        "{}.{}({})",
687                        args[0],
688                        func,
689                        args[1..]
690                            .iter()
691                            .map(|arg| arg.to_string())
692                            .collect::<Vec<_>>()
693                            .join(", ")
694                    )
695                } else {
696                    write!(
697                        f,
698                        "{}({})",
699                        func,
700                        args.iter()
701                            .map(|arg| arg.to_string())
702                            .collect::<Vec<_>>()
703                            .join(", ")
704                    )
705                }
706            }
707        }
708    }
709}
710
711fn prefix_binding_power(op: Op) -> ((), u8) {
712    match op {
713        Op::Minus | Op::Not => ((), 13),
714        _ => panic!("Unexpected operator: {:?}", op),
715    }
716}
717
718fn postfix_binding_power(op: Op) -> Option<(u8, ())> {
719    match op {
720        Op::Index => Some((15, ())),
721        Op::Call => Some((17, ())),
722        _ => None,
723    }
724}
725
726// Precedence levels for infix operators.
727// ?: - 1,2
728// || - 3,4
729// && - 5,6
730// in - 7,8
731// == != <><=>= - 7,8
732// -(binary) +(binary) - 9,10
733// * / % - 11,12
734// ! -(unary) - 13,14
735// () . [] {} - 15,16
736
737/// Returns the binding powers for the given infix operator.
738fn infix_binding_power(op: Op) -> Option<(u8, u8)> {
739    let res = match op {
740        // '=' => (2, 1),
741        Op::IfTernary => (2, 1),
742        Op::Or => (3, 4),
743        Op::And => (5, 6),
744        Op::In
745        | Op::NotEqual
746        | Op::EqualEqual
747        | Op::Less
748        | Op::LessEqual
749        | Op::Greater
750        | Op::GreaterEqual => (7, 8),
751        Op::Plus | Op::Minus => (9, 10),
752        Op::Multiply | Op::Devide | Op::Mod => (11, 12),
753        Op::Field | Op::Call => (18, 17),
754        _ => return None,
755    };
756    Some(res)
757}
758
759#[cfg(test)]
760mod tests {
761    use super::*;
762
763    #[test]
764    fn test_add_and_multiply() {
765        let input = "1 + 2 * 3";
766        let mut parser = Parser::new(input);
767        let tree = parser.parse().unwrap();
768        assert_eq!(
769            tree,
770            TokenTree::Cons(
771                Op::Plus,
772                vec![
773                    TokenTree::Atom(Atom::Int(1)),
774                    TokenTree::Cons(
775                        Op::Multiply,
776                        vec![
777                            TokenTree::Atom(Atom::Int(2)),
778                            TokenTree::Atom(Atom::Int(3)),
779                        ]
780                    )
781                ]
782            )
783        );
784    }
785
786    #[test]
787    fn test_field_access() {
788        let input = "foo.bar.baz";
789        let mut parser = Parser::new(input);
790        let tree = parser.parse().unwrap();
791        assert_eq!(
792            tree,
793            TokenTree::Cons(
794                Op::Field,
795                vec![
796                    TokenTree::Atom(Atom::Ident("foo")),
797                    TokenTree::Cons(
798                        Op::Field,
799                        vec![
800                            TokenTree::Atom(Atom::Ident("bar")),
801                            TokenTree::Atom(Atom::Ident("baz")),
802                        ]
803                    )
804                ]
805            )
806        );
807
808        let input = "foo.check[0].baz";
809        let mut parser = Parser::new(input);
810        let tree = parser.parse().unwrap();
811        assert_eq!(
812            tree,
813            TokenTree::Cons(
814                Op::Field,
815                vec![
816                    TokenTree::Cons(
817                        Op::Index,
818                        vec![
819                            TokenTree::Cons(
820                                Op::Field,
821                                vec![
822                                    TokenTree::Atom(Atom::Ident("foo")),
823                                    TokenTree::Atom(Atom::Ident("check")),
824                                ],
825                            ),
826                            TokenTree::Atom(Atom::Int(0)),
827                        ]
828                    ),
829                    TokenTree::Atom(Atom::Ident("baz")),
830                ]
831            )
832        );
833    }
834
835    #[test]
836    fn test_function_call() {
837        let input = "foo(bar, baz)";
838        let mut parser = Parser::new(input);
839        let tree = parser.parse().unwrap();
840        assert_eq!(
841            tree,
842            TokenTree::Call {
843                func: Box::new(TokenTree::Atom(Atom::Ident("foo"))),
844                args: vec![
845                    TokenTree::Atom(Atom::Ident("bar")),
846                    TokenTree::Atom(Atom::Ident("baz")),
847                ],
848                is_method: false,
849            }
850        );
851
852        let input = "foo([])";
853        let mut parser = Parser::new(input);
854        let tree = parser.parse().unwrap();
855        assert_eq!(
856            tree,
857            TokenTree::Call {
858                func: Box::new(TokenTree::Atom(Atom::Ident("foo"))),
859                args: vec![TokenTree::Cons(Op::List, vec![])],
860                is_method: false,
861            }
862        );
863
864        let input = "foo({})";
865        let mut parser = Parser::new(input);
866        let tree = parser.parse().unwrap();
867        assert_eq!(
868            tree,
869            TokenTree::Call {
870                func: Box::new(TokenTree::Atom(Atom::Ident("foo"))),
871                args: vec![TokenTree::Cons(Op::Map, vec![])],
872                is_method: false,
873            }
874        );
875    }
876
877    #[test]
878    fn test_method_call() {
879        let input = "foo.bar(baz)";
880        let mut parser = Parser::new(input);
881        let tree = parser.parse().unwrap();
882        assert_eq!(
883            tree,
884            TokenTree::Call {
885                func: Box::new(TokenTree::Atom(Atom::Ident("bar"))),
886                args: vec![
887                    TokenTree::Atom(Atom::Ident("foo")),
888                    TokenTree::Atom(Atom::Ident("baz")),
889                ],
890                is_method: true,
891            }
892        );
893    }
894
895    #[test]
896    fn test_nested_method_call() {
897        let input = "foo.all(test, test.size() > 4)";
898        let mut parser = Parser::new(input);
899        let tree = parser.parse().unwrap();
900        let want = TokenTree::Call {
901            func: Box::new(TokenTree::Atom(Atom::Ident("all"))),
902            args: vec![
903                TokenTree::Atom(Atom::Ident("foo")),
904                TokenTree::Atom(Atom::Ident("test")),
905                TokenTree::Cons(
906                    Op::Greater,
907                    vec![
908                        TokenTree::Call {
909                            func: Box::new(TokenTree::Atom(Atom::Ident(
910                                "size",
911                            ))),
912                            args: vec![TokenTree::Atom(Atom::Ident("test"))],
913                            is_method: true,
914                        },
915                        TokenTree::Atom(Atom::Int(4)),
916                    ],
917                ),
918            ],
919            is_method: true,
920        };
921        assert_eq!(tree, want, "expected {want:?}, got {tree:?}");
922    }
923
924    #[test]
925    fn test_list_definition() {
926        let input = "[1, 2, 3]";
927        let mut parser = Parser::new(input);
928        let tree = parser.parse();
929        assert!(tree.is_ok(), "{:?}", tree);
930        let tree = tree.unwrap();
931        assert_eq!(
932            tree,
933            TokenTree::Cons(
934                Op::List,
935                vec![
936                    TokenTree::Atom(Atom::Int(1)),
937                    TokenTree::Atom(Atom::Int(2)),
938                    TokenTree::Atom(Atom::Int(3)),
939                ]
940            )
941        );
942
943        let input = "[]";
944        let mut parser = Parser::new(input);
945        let tree = parser.parse().unwrap();
946        assert_eq!(tree, TokenTree::Cons(Op::List, vec![]));
947    }
948
949    #[test]
950    fn test_map_definition() {
951        let input = "{foo: 1, bar: 2}";
952        let mut parser = Parser::new(input);
953        let tree = parser.parse();
954        assert!(tree.is_ok(), "{:?}", tree);
955        let tree = tree.unwrap();
956        assert_eq!(
957            tree,
958            TokenTree::Cons(
959                Op::Map,
960                vec![
961                    TokenTree::Atom(Atom::Ident("foo")),
962                    TokenTree::Atom(Atom::Int(1)),
963                    TokenTree::Atom(Atom::Ident("bar")),
964                    TokenTree::Atom(Atom::Int(2)),
965                ]
966            )
967        );
968
969        let input = "{}";
970        let mut parser = Parser::new(input);
971        let tree = parser.parse().unwrap();
972        assert_eq!(tree, TokenTree::Cons(Op::Map, vec![]));
973    }
974
975    #[test]
976    fn test_grouping() {
977        let input = "(1 + 2) * 3 % 4";
978        let mut parser = Parser::new(input);
979        let tree = parser.parse().unwrap();
980        assert_eq!(
981            tree,
982            TokenTree::Cons(
983                Op::Mod,
984                vec![
985                    TokenTree::Cons(
986                        Op::Multiply,
987                        vec![
988                            TokenTree::Cons(
989                                Op::Group,
990                                vec![TokenTree::Cons(
991                                    Op::Plus,
992                                    vec![
993                                        TokenTree::Atom(Atom::Int(1)),
994                                        TokenTree::Atom(Atom::Int(2)),
995                                    ]
996                                ),]
997                            ),
998                            TokenTree::Atom(Atom::Int(3)),
999                        ]
1000                    ),
1001                    TokenTree::Atom(Atom::Int(4)),
1002                ]
1003            )
1004        );
1005    }
1006
1007    #[test]
1008    fn test_unary_minus() {
1009        let input = "-1";
1010        let mut parser = Parser::new(input);
1011        let tree = parser.parse().unwrap();
1012        assert_eq!(
1013            tree,
1014            TokenTree::Cons(Op::Minus, vec![TokenTree::Atom(Atom::Int(1))])
1015        );
1016    }
1017
1018    #[test]
1019    fn test_unary_not() {
1020        let input = "!true";
1021        let mut parser = Parser::new(input);
1022        let tree = parser.parse().unwrap();
1023        assert_eq!(
1024            tree,
1025            TokenTree::Cons(Op::Not, vec![TokenTree::Atom(Atom::Bool(true))])
1026        );
1027    }
1028
1029    #[test]
1030    fn test_relations() {
1031        let input = "1 < 2 && 3 >= 4 || 5 == 6 && 5 in 6";
1032        let mut parser = Parser::new(input);
1033        let tree = parser.parse().unwrap();
1034        assert_eq!(
1035            tree,
1036            TokenTree::Cons(
1037                Op::Or,
1038                vec![
1039                    TokenTree::Cons(
1040                        Op::And,
1041                        vec![
1042                            TokenTree::Cons(
1043                                Op::Less,
1044                                vec![
1045                                    TokenTree::Atom(Atom::Int(1)),
1046                                    TokenTree::Atom(Atom::Int(2)),
1047                                ]
1048                            ),
1049                            TokenTree::Cons(
1050                                Op::GreaterEqual,
1051                                vec![
1052                                    TokenTree::Atom(Atom::Int(3)),
1053                                    TokenTree::Atom(Atom::Int(4)),
1054                                ]
1055                            ),
1056                        ]
1057                    ),
1058                    TokenTree::Cons(
1059                        Op::And,
1060                        vec![
1061                            TokenTree::Cons(
1062                                Op::EqualEqual,
1063                                vec![
1064                                    TokenTree::Atom(Atom::Int(5)),
1065                                    TokenTree::Atom(Atom::Int(6)),
1066                                ]
1067                            ),
1068                            TokenTree::Cons(
1069                                Op::In,
1070                                vec![
1071                                    TokenTree::Atom(Atom::Int(5)),
1072                                    TokenTree::Atom(Atom::Int(6)),
1073                                ]
1074                            ),
1075                        ]
1076                    ),
1077                ]
1078            )
1079        );
1080    }
1081
1082    #[test]
1083    fn test_singuler_expression() {
1084        let tt = vec![
1085            ("identifier", TokenTree::Atom(Atom::Ident("identifier"))),
1086            ("123", TokenTree::Atom(Atom::Int(123))),
1087            ("123u", TokenTree::Atom(Atom::Uint(123))),
1088            ("123.456", TokenTree::Atom(Atom::Double(123.456))),
1089            ("true", TokenTree::Atom(Atom::Bool(true))),
1090            ("false", TokenTree::Atom(Atom::Bool(false))),
1091            (
1092                "\"string\"",
1093                TokenTree::Atom(Atom::String(Cow::Borrowed("string"))),
1094            ),
1095            ("null", TokenTree::Atom(Atom::Null)),
1096        ]
1097        .into_iter();
1098
1099        for (input, expected) in tt {
1100            let mut parser = Parser::new(input);
1101            let tree = parser.parse();
1102            assert!(tree.is_ok(), "input={:?}, out={:?}", input, tree);
1103            let tree = tree.unwrap();
1104            assert_eq!(tree, expected);
1105        }
1106    }
1107
1108    #[test]
1109    fn test_indexing() {
1110        let input = "foo[1]";
1111        let mut parser = Parser::new(input);
1112        let tree = parser.parse().unwrap();
1113        assert_eq!(
1114            tree,
1115            TokenTree::Cons(
1116                Op::Index,
1117                vec![
1118                    TokenTree::Atom(Atom::Ident("foo")),
1119                    TokenTree::Atom(Atom::Int(1)),
1120                ]
1121            )
1122        );
1123
1124        let input = "foo[1][2]";
1125        let mut parser = Parser::new(input);
1126        let tree = parser.parse().unwrap();
1127        assert_eq!(
1128            tree,
1129            TokenTree::Cons(
1130                Op::Index,
1131                vec![
1132                    TokenTree::Cons(
1133                        Op::Index,
1134                        vec![
1135                            TokenTree::Atom(Atom::Ident("foo")),
1136                            TokenTree::Atom(Atom::Int(1)),
1137                        ]
1138                    ),
1139                    TokenTree::Atom(Atom::Int(2)),
1140                ]
1141            )
1142        );
1143    }
1144
1145    #[test]
1146    fn test_ternary_if() {
1147        let input = "true ? 1 : 2";
1148        let mut parser = Parser::new(input);
1149        let tree = parser.parse().unwrap();
1150        assert_eq!(
1151            tree,
1152            TokenTree::Cons(
1153                Op::IfTernary,
1154                vec![
1155                    TokenTree::Atom(Atom::Bool(true)),
1156                    TokenTree::Atom(Atom::Int(1)),
1157                    TokenTree::Atom(Atom::Int(2)),
1158                ]
1159            )
1160        );
1161
1162        let input = "true ? 1 : false ? 2 : 3";
1163        let mut parser = Parser::new(input);
1164        let tree = parser.parse().unwrap();
1165        assert_eq!(
1166            tree,
1167            TokenTree::Cons(
1168                Op::IfTernary,
1169                vec![
1170                    TokenTree::Atom(Atom::Bool(true)),
1171                    TokenTree::Atom(Atom::Int(1)),
1172                    TokenTree::Cons(
1173                        Op::IfTernary,
1174                        vec![
1175                            TokenTree::Atom(Atom::Bool(false)),
1176                            TokenTree::Atom(Atom::Int(2)),
1177                            TokenTree::Atom(Atom::Int(3)),
1178                        ]
1179                    ),
1180                ]
1181            )
1182        );
1183    }
1184
1185    #[test]
1186    fn test_method_relation() {
1187        let input = "foo.bar() < 4";
1188        let mut parser = Parser::new(input);
1189        let tree = parser.parse().unwrap();
1190        assert_eq!(
1191            tree,
1192            TokenTree::Cons(
1193                Op::Less,
1194                vec![
1195                    TokenTree::Call {
1196                        func: Box::new(TokenTree::Atom(Atom::Ident("bar"))),
1197                        args: vec![TokenTree::Atom(Atom::Ident("foo"))],
1198                        is_method: true,
1199                    },
1200                    TokenTree::Atom(Atom::Int(4)),
1201                ]
1202            )
1203        );
1204    }
1205
1206    #[test]
1207    fn test_inline_function_call() {
1208        let input = "1 + size(2u)";
1209        let mut parser = Parser::new(input);
1210        let tree = parser.parse().unwrap();
1211        assert_eq!(
1212            tree,
1213            TokenTree::Cons(
1214                Op::Plus,
1215                vec![
1216                    TokenTree::Atom(Atom::Int(1)),
1217                    TokenTree::Call {
1218                        func: Box::new(TokenTree::Atom(Atom::Ident("size"))),
1219                        args: vec![TokenTree::Atom(Atom::Uint(2))],
1220                        is_method: false,
1221                    },
1222                ]
1223            )
1224        );
1225    }
1226
1227    #[test]
1228    fn test_inline_dyn_call() {
1229        let input = "1 + dyn(2u)";
1230        let mut parser = Parser::new(input);
1231        let tree = parser.parse().unwrap();
1232        assert_eq!(
1233            tree,
1234            TokenTree::Cons(
1235                Op::Plus,
1236                vec![
1237                    TokenTree::Atom(Atom::Int(1)),
1238                    TokenTree::Cons(
1239                        Op::Dyn,
1240                        vec![TokenTree::Atom(Atom::Uint(2))],
1241                    ),
1242                ]
1243            )
1244        );
1245    }
1246
1247    #[test]
1248    fn test_nested_list_with_map() {
1249        let input = "[{foo: 1}, {bar: 2}]";
1250        let mut parser = Parser::new(input);
1251        let tree = parser.parse().unwrap();
1252        assert_eq!(
1253            tree,
1254            TokenTree::Cons(
1255                Op::List,
1256                vec![
1257                    TokenTree::Cons(
1258                        Op::Map,
1259                        vec![
1260                            TokenTree::Atom(Atom::Ident("foo")),
1261                            TokenTree::Atom(Atom::Int(1)),
1262                        ]
1263                    ),
1264                    TokenTree::Cons(
1265                        Op::Map,
1266                        vec![
1267                            TokenTree::Atom(Atom::Ident("bar")),
1268                            TokenTree::Atom(Atom::Int(2)),
1269                        ]
1270                    ),
1271                ]
1272            )
1273        );
1274    }
1275
1276    #[test]
1277    fn test_method_call_with_indexing() {
1278        let input = "foo.bar(x, t[x] > 10)";
1279        let mut parser = Parser::new(input);
1280        let tree = parser.parse().unwrap();
1281
1282        let want = TokenTree::Call {
1283            func: Box::new(TokenTree::Atom(Atom::Ident("bar"))),
1284            args: vec![
1285                TokenTree::Atom(Atom::Ident("foo")),
1286                TokenTree::Atom(Atom::Ident("x")),
1287                TokenTree::Cons(
1288                    Op::Greater,
1289                    vec![
1290                        TokenTree::Cons(
1291                            Op::Index,
1292                            vec![
1293                                TokenTree::Atom(Atom::Ident("t")),
1294                                TokenTree::Atom(Atom::Ident("x")),
1295                            ],
1296                        ),
1297                        TokenTree::Atom(Atom::Int(10)),
1298                    ],
1299                ),
1300            ],
1301            is_method: true,
1302        };
1303
1304        assert_eq!(tree, want);
1305    }
1306
1307    #[test]
1308    fn test_nested_fields() {
1309        let input = "foo.bar.baz";
1310        let mut parser = Parser::new(input);
1311        let tree = parser.parse().unwrap();
1312
1313        let want = TokenTree::Cons(
1314            Op::Field,
1315            vec![
1316                TokenTree::Atom(Atom::Ident("foo")),
1317                TokenTree::Cons(
1318                    Op::Field,
1319                    vec![
1320                        TokenTree::Atom(Atom::Ident("bar")),
1321                        TokenTree::Atom(Atom::Ident("baz")),
1322                    ],
1323                ),
1324            ],
1325        );
1326
1327        assert_eq!(tree, want);
1328    }
1329
1330    #[test]
1331    fn test_nested_fields_method_call() {
1332        let input = "foo.bar.foo.baz()";
1333        let mut parser = Parser::new(input);
1334        let tree = parser.parse().unwrap();
1335
1336        let want = TokenTree::Call {
1337            func: Box::new(TokenTree::Atom(Atom::Ident("baz"))),
1338            args: vec![TokenTree::Cons(
1339                Op::Field,
1340                vec![
1341                    TokenTree::Atom(Atom::Ident("foo")),
1342                    TokenTree::Cons(
1343                        Op::Field,
1344                        vec![
1345                            TokenTree::Atom(Atom::Ident("bar")),
1346                            TokenTree::Atom(Atom::Ident("foo")),
1347                        ],
1348                    ),
1349                ],
1350            )],
1351            is_method: true,
1352        };
1353
1354        assert_eq!(tree, want);
1355    }
1356
1357    #[test]
1358    fn test_nested_method_call_with_indexing() {
1359        let input = "foo.bar.filter(x, x > 10)[0].id";
1360        let mut parser = Parser::new(input);
1361        let tree = parser.parse().unwrap();
1362
1363        let want = TokenTree::Cons(
1364            Op::Field,
1365            vec![
1366                TokenTree::Cons(
1367                    Op::Index,
1368                    vec![
1369                        TokenTree::Call {
1370                            func: Box::new(TokenTree::Atom(Atom::Ident(
1371                                "filter",
1372                            ))),
1373                            args: vec![
1374                                TokenTree::Cons(
1375                                    Op::Field,
1376                                    vec![
1377                                        TokenTree::Atom(Atom::Ident("foo")),
1378                                        TokenTree::Atom(Atom::Ident("bar")),
1379                                    ],
1380                                ),
1381                                TokenTree::Atom(Atom::Ident("x")),
1382                                TokenTree::Cons(
1383                                    Op::Greater,
1384                                    vec![
1385                                        TokenTree::Atom(Atom::Ident("x")),
1386                                        TokenTree::Atom(Atom::Int(10)),
1387                                    ],
1388                                ),
1389                            ],
1390                            is_method: true,
1391                        },
1392                        TokenTree::Atom(Atom::Int(0)),
1393                    ],
1394                ),
1395                TokenTree::Atom(Atom::Ident("id")),
1396            ],
1397        );
1398
1399        assert_eq!(tree, want);
1400    }
1401}