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
9pub 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 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)), Some(Err(e)) => return Err(e),
35 };
36
37 let mut lhs = match lhs {
38 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 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 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 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 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#[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#[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#[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
726fn infix_binding_power(op: Op) -> Option<(u8, u8)> {
739 let res = match op {
740 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}