1use super::{CompletedMarker, EXPR_RECOVERY, Parser};
23use crate::syntax_kind::{SyntaxKind, SyntaxKind::*};
24
25fn infix_binding_power(op: SyntaxKind) -> Option<(u8, u8)> {
38 let bp = match op {
39 PIPE2 => (4, 5),
42 AMP2 => (6, 7),
44 EQ2 | BANG_EQ => (8, 8),
46 LT | LT_EQ | GT | GT_EQ => (10, 10),
48 PIPE => (12, 13),
50 CARET => (14, 15),
52 AMP => (16, 17),
54 SHL | SHR => (18, 19),
56 PLUS | MINUS => (20, 21),
58 STAR | SLASH | PERCENT => (22, 23),
60 STAR2 => (25, 24),
62 KW_AS => (26, 27),
64 _ => return None,
65 };
66 Some(bp)
67}
68
69fn is_comparison_op(op: SyntaxKind) -> bool {
71 matches!(op, EQ2 | BANG_EQ | LT | LT_EQ | GT | GT_EQ)
72}
73
74fn expected_after_comparison(bp: u8) -> &'static [&'static str] {
77 match bp {
78 8 => &["'&&'", "'||'", "'?'"], 10 => &["'&&'", "'||'", "'=='", "'!='", "'?'"], _ => &["an operator"],
81 }
82}
83
84fn prefix_binding_power(op: SyntaxKind) -> Option<u8> {
86 match op {
87 BANG | MINUS => Some(30),
89 _ => None,
90 }
91}
92
93fn postfix_binding_power(op: SyntaxKind) -> Option<u8> {
95 match op {
96 DOT | L_BRACKET | L_PAREN => Some(32),
98 _ => None,
99 }
100}
101
102#[derive(Default, Clone, Copy)]
108pub struct ExprOpts {
109 pub no_struct: bool,
112}
113
114impl ExprOpts {
115 pub fn no_struct() -> Self {
117 Self { no_struct: true }
118 }
119}
120
121impl Parser<'_, '_> {
126 pub const EXPR_CONTINUATION: &'static [SyntaxKind] = &[
128 AMP2,
129 PIPE2,
130 AMP,
131 PIPE,
132 CARET,
133 EQ2,
134 BANG_EQ,
135 LT,
136 LT_EQ,
137 GT,
138 GT_EQ,
139 PLUS,
140 MINUS,
141 STAR,
142 SLASH,
143 STAR2,
144 PERCENT,
145 SHL,
146 SHR,
147 L_PAREN,
148 L_BRACKET,
149 L_BRACE,
150 DOT,
151 COLON_COLON,
152 QUESTION,
153 KW_AS,
154 ];
155
156 pub fn parse_expr(&mut self) -> Option<CompletedMarker> {
158 self.parse_expr_with_opts(ExprOpts::default())
159 }
160
161 pub fn parse_expr_with_opts(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
163 self.parse_expr_bp(0, opts)
164 }
165
166 fn parse_expr_bp(&mut self, min_bp: u8, opts: ExprOpts) -> Option<CompletedMarker> {
168 let mut lhs = self.parse_prefix_expr(opts)?;
170
171 loop {
172 if let Some(bp) = self.current_postfix_bp() {
174 if bp < min_bp {
175 break;
176 }
177 lhs = self.parse_postfix_expr(lhs)?;
178 continue;
179 }
180
181 if self.at(QUESTION) && min_bp <= 2 {
183 lhs = self.parse_ternary_expr(lhs)?;
184 continue;
185 }
186
187 let op = self.current();
189 if let Some((l_bp, r_bp)) = infix_binding_power(op) {
190 if l_bp < min_bp {
191 break;
192 }
193
194 if l_bp == r_bp && l_bp == min_bp && is_comparison_op(op) {
199 let expected_tokens = expected_after_comparison(l_bp);
200 self.error_unexpected(op, expected_tokens);
201 break;
202 }
203
204 lhs = self.parse_infix_expr(lhs, op, r_bp, opts)?;
205 continue;
206 }
207
208 break;
209 }
210
211 Some(lhs)
212 }
213
214 fn current_postfix_bp(&self) -> Option<u8> {
216 postfix_binding_power(self.current())
217 }
218
219 fn parse_prefix_expr(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
221 self.skip_trivia();
222
223 if let Some(bp) = prefix_binding_power(self.current()) {
225 let m = self.start();
226 self.bump_any(); if self.parse_expr_bp(bp, opts).is_none() {
231 self.error("expected expression after unary operator");
232 }
233
234 return Some(m.complete(self, UNARY_EXPR));
235 }
236
237 self.parse_primary_expr(opts)
239 }
240
241 fn parse_postfix_expr(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
243 match self.current() {
244 DOT => self.parse_member_access(lhs),
245 L_BRACKET => self.parse_index_expr(lhs),
246 L_PAREN => self.parse_call_expr(lhs),
247 _ => Some(lhs),
248 }
249 }
250
251 fn parse_infix_expr(
253 &mut self,
254 lhs: CompletedMarker,
255 op: SyntaxKind,
256 r_bp: u8,
257 opts: ExprOpts,
258 ) -> Option<CompletedMarker> {
259 let m = lhs.precede(self);
260 self.bump_any(); if op == KW_AS {
264 if self.parse_cast_type().is_none() {
265 let expected: Vec<&str> = Self::PRIMITIVE_TYPE_KINDS.iter().map(|k| k.user_friendly_name()).collect();
266 self.error_unexpected(self.current(), &expected);
267 }
268 return Some(m.complete(self, CAST_EXPR));
269 }
270
271 if self.parse_expr_bp(r_bp, opts).is_none() {
274 self.error("expected expression after operator");
275 }
276
277 Some(m.complete(self, BINARY_EXPR))
278 }
279
280 fn parse_ternary_expr(&mut self, condition: CompletedMarker) -> Option<CompletedMarker> {
282 let m = condition.precede(self);
283 self.bump_any(); if self.parse_expr().is_none() {
287 self.error("expected expression after '?'");
288 }
289
290 self.expect(COLON);
291
292 if self.parse_expr_bp(2, ExprOpts::default()).is_none() {
294 self.error("expected expression after ':'");
295 }
296
297 Some(m.complete(self, TERNARY_EXPR))
298 }
299
300 fn parse_member_access(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
302 let m = lhs.precede(self);
303 self.bump_any(); self.skip_trivia();
306
307 if self.at(INTEGER) {
310 self.bump_any();
311 return Some(m.complete(self, TUPLE_ACCESS_EXPR));
312 }
313
314 if self.at(IDENT) || self.current().is_keyword() {
315 self.bump_any();
316 } else {
317 self.error("expected field name or tuple index");
318 return Some(m.complete(self, FIELD_EXPR));
319 }
320
321 if self.at(L_PAREN) {
323 self.bump_any(); if !self.at(R_PAREN) {
325 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
326 self.error_recover("expected argument expression", EXPR_RECOVERY);
327 }
328 while self.eat(COMMA) {
329 if self.at(R_PAREN) {
330 break;
331 }
332 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
333 self.error_recover("expected argument expression", EXPR_RECOVERY);
334 }
335 }
336 }
337 self.expect(R_PAREN);
338 return Some(m.complete(self, METHOD_CALL_EXPR));
339 }
340
341 Some(m.complete(self, FIELD_EXPR))
342 }
343
344 fn parse_index_expr(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
346 let m = lhs.precede(self);
347 self.bump_any(); if self.parse_expr().is_none() {
350 self.error("expected index expression");
351 }
352
353 self.expect(R_BRACKET);
354
355 Some(m.complete(self, INDEX_EXPR))
356 }
357
358 fn parse_dynamic_call_expr(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
360 let m = lhs.precede(self);
361
362 self.bump_any(); self.expect(L_PAREN);
364 self.parse_expr(); if self.eat(COMMA) {
367 self.parse_expr(); }
369 self.expect(R_PAREN);
370 self.expect(COLON_COLON);
371 if self.at(IDENT) {
372 self.bump_any(); }
374 self.expect(L_PAREN);
376 if !self.at(R_PAREN) {
377 self.parse_expr();
378 while self.eat(COMMA) {
379 if self.at(R_PAREN) {
380 break;
381 }
382 self.parse_expr();
383 }
384 }
385 self.expect(R_PAREN);
386 Some(m.complete(self, DYNAMIC_CALL_EXPR))
387 }
388
389 fn parse_call_expr(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
391 let m = lhs.precede(self);
392 self.bump_any(); if !self.at(R_PAREN) {
396 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
397 self.error_recover("expected argument expression", EXPR_RECOVERY);
399 }
400 while self.eat(COMMA) {
401 if self.at(R_PAREN) {
402 break;
403 }
404 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
405 self.error_recover("expected argument expression", EXPR_RECOVERY);
406 }
407 }
408 }
409
410 self.expect(R_PAREN);
411
412 Some(m.complete(self, CALL_EXPR))
413 }
414
415 fn parse_primary_expr(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
421 self.skip_trivia();
422
423 match self.current() {
424 INTEGER => self.parse_integer_literal(),
426 STRING => self.parse_string_literal(),
427 ADDRESS_LIT => self.parse_address_literal(),
428 IDENT_LIT => self.parse_identifier_literal(),
429 KW_TRUE | KW_FALSE => self.parse_bool_literal(),
430 KW_NONE => self.parse_none_literal(),
431
432 L_PAREN => self.parse_paren_or_tuple_expr(),
434
435 L_BRACKET => self.parse_array_expr(),
437
438 IDENT | KW_FINAL_UPPER => self.parse_ident_expr(opts),
440
441 KW_SELF => self.parse_self_expr(),
443
444 KW_BLOCK => self.parse_block_access(),
446 KW_NETWORK => self.parse_network_access(),
447
448 KW_FINAL => self.parse_final_block_expr(),
450
451 _ => {
452 self.error_unexpected(self.current(), &[
453 "an identifier",
454 "a program id",
455 "an address literal",
456 "an integer literal",
457 "a static string",
458 "'!'",
459 "'-'",
460 "'('",
461 "'['",
462 "'true'",
463 "'false'",
464 "'final'",
465 "'block'",
466 "'network'",
467 "'self'",
468 ]);
469 None
470 }
471 }
472 }
473
474 fn parse_integer_literal(&mut self) -> Option<CompletedMarker> {
479 let m = self.start();
480 let text = self.current_text();
481 let kind = if text.ends_with("field") {
482 LITERAL_FIELD
483 } else if text.ends_with("group") {
484 LITERAL_GROUP
485 } else if text.ends_with("scalar") {
486 LITERAL_SCALAR
487 } else {
488 LITERAL_INT
489 };
490 self.bump_any();
491 Some(m.complete(self, kind))
492 }
493
494 fn parse_string_literal(&mut self) -> Option<CompletedMarker> {
496 let m = self.start();
497 self.bump_any();
498 Some(m.complete(self, LITERAL_STRING))
499 }
500
501 fn parse_identifier_literal(&mut self) -> Option<CompletedMarker> {
503 let m = self.start();
504 self.bump_any();
505 Some(m.complete(self, LITERAL_IDENT))
506 }
507
508 fn parse_address_literal(&mut self) -> Option<CompletedMarker> {
510 let m = self.start();
511 self.bump_any();
512 Some(m.complete(self, LITERAL_ADDRESS))
513 }
514
515 fn parse_bool_literal(&mut self) -> Option<CompletedMarker> {
517 let m = self.start();
518 self.bump_any();
519 Some(m.complete(self, LITERAL_BOOL))
520 }
521
522 fn parse_none_literal(&mut self) -> Option<CompletedMarker> {
524 let m = self.start();
525 self.bump_any();
526 Some(m.complete(self, LITERAL_NONE))
527 }
528
529 fn parse_paren_or_tuple_expr(&mut self) -> Option<CompletedMarker> {
531 let m = self.start();
532 self.bump_any(); if self.eat(R_PAREN) {
536 return Some(m.complete(self, TUPLE_EXPR));
537 }
538
539 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
541 self.error_recover("expected expression", EXPR_RECOVERY);
542 }
543
544 if self.eat(COMMA) {
546 if !self.at(R_PAREN) {
548 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
549 self.error_recover("expected tuple element", EXPR_RECOVERY);
550 }
551 while self.eat(COMMA) {
552 if self.at(R_PAREN) {
553 break;
554 }
555 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
556 self.error_recover("expected tuple element", EXPR_RECOVERY);
557 }
558 }
559 }
560 self.expect(R_PAREN);
561 return Some(m.complete(self, TUPLE_EXPR));
562 }
563
564 self.expect(R_PAREN);
566 Some(m.complete(self, PAREN_EXPR))
567 }
568
569 fn parse_array_expr(&mut self) -> Option<CompletedMarker> {
571 let m = self.start();
572 self.bump_any(); if self.eat(R_BRACKET) {
576 return Some(m.complete(self, ARRAY_EXPR));
577 }
578
579 if self.parse_expr().is_none() && !self.at(R_BRACKET) && !self.at(COMMA) && !self.at(SEMICOLON) {
581 self.error_recover("expected array element", EXPR_RECOVERY);
582 }
583
584 if self.eat(SEMICOLON) {
586 if self.parse_expr().is_none() && !self.at(R_BRACKET) {
587 self.error("expected repeat count");
588 }
589 self.expect(R_BRACKET);
590 return Some(m.complete(self, REPEAT_EXPR));
591 }
592
593 while self.eat(COMMA) {
595 if self.at(R_BRACKET) {
596 break;
597 }
598 if self.parse_expr().is_none() && !self.at(R_BRACKET) && !self.at(COMMA) {
599 self.error_recover("expected array element", EXPR_RECOVERY);
600 }
601 }
602
603 self.expect(R_BRACKET);
604 Some(m.complete(self, ARRAY_EXPR))
605 }
606
607 fn parse_ident_expr(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
609 let m = self.start();
610 self.bump_any(); if self.at(DOT) && self.nth(1) == KW_ALEO {
614 self.bump_any(); self.bump_any(); let is_locator = if self.eat(COLON_COLON) {
618 if self.at(IDENT) {
620 self.bump_any();
621 while self.at(COLON_COLON) && self.nth(1) == IDENT {
623 self.bump_any(); self.bump_any(); }
626 }
627 true
628 } else {
629 false
630 };
631
632 if self.at(COLON_COLON) && self.nth(1) == L_BRACKET {
634 self.bump_any(); self.parse_const_generic_args_bracket();
636 }
637
638 if !opts.no_struct && self.at(L_BRACE) {
640 self.bump_any(); if !self.at(R_BRACE) {
642 self.parse_struct_field();
643 while self.eat(COMMA) {
644 if self.at(R_BRACE) {
645 break;
646 }
647 self.parse_struct_field();
648 }
649 }
650 self.expect(R_BRACE);
651 let kind = if is_locator { STRUCT_LOCATOR_EXPR } else { STRUCT_EXPR };
652 return Some(m.complete(self, kind));
653 }
654
655 if self.at(L_PAREN) {
657 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
658 let cm = m.complete(self, kind);
659 return self.parse_call_expr(cm);
660 }
661
662 if self.at(AT) {
664 let cm = m.complete(self, TYPE_LOCATOR);
665 return self.parse_dynamic_call_expr(cm);
666 }
667
668 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
669 return Some(m.complete(self, kind));
670 }
671
672 while self.eat(COLON_COLON) {
674 if self.at(L_BRACKET) {
675 self.parse_const_generic_args_bracket();
677 break;
678 } else if self.at(LT) {
679 self.parse_const_generic_args_angle();
682 break;
683 } else if self.at(IDENT) {
684 self.bump_any();
685 } else {
686 self.error("expected identifier after ::");
687 break;
688 }
689 }
690
691 if !opts.no_struct && self.at(L_BRACE) {
693 self.bump_any(); if !self.at(R_BRACE) {
697 self.parse_struct_field();
698 while self.eat(COMMA) {
699 if self.at(R_BRACE) {
700 break;
701 }
702 self.parse_struct_field();
703 }
704 }
705
706 self.expect(R_BRACE);
707 return Some(m.complete(self, STRUCT_EXPR));
708 }
709
710 if self.at(L_PAREN) {
712 let cm = m.complete(self, PATH_EXPR);
713 return self.parse_call_expr(cm);
714 }
715
716 if self.at(AT) {
718 let cm = m.complete(self, TYPE_PATH);
719 return self.parse_dynamic_call_expr(cm);
720 }
721
722 Some(m.complete(self, PATH_EXPR))
723 }
724
725 fn parse_struct_field(&mut self) {
727 let m = self.start();
728 self.skip_trivia();
729
730 if self.at(IDENT) {
731 self.bump_any(); if self.eat(COLON) {
734 if self.parse_expr().is_none() && !self.at(R_BRACE) && !self.at(COMMA) {
736 self.error("expected field value");
737 }
738 m.complete(self, STRUCT_FIELD_INIT);
739 } else {
740 m.complete(self, STRUCT_FIELD_SHORTHAND);
742 }
743 } else {
744 self.error("expected field name");
745 m.complete(self, STRUCT_FIELD_INIT);
746 }
747 }
748
749 fn parse_self_expr(&mut self) -> Option<CompletedMarker> {
751 let m = self.start();
752 self.bump_any(); if self.at(COLON_COLON) {
756 self.error("expected '.' -- found '::'");
757 }
758
759 Some(m.complete(self, SELF_EXPR))
760 }
761
762 fn parse_block_access(&mut self) -> Option<CompletedMarker> {
764 let m = self.start();
765 self.bump_any(); Some(m.complete(self, BLOCK_KW_EXPR))
767 }
768
769 fn parse_network_access(&mut self) -> Option<CompletedMarker> {
771 let m = self.start();
772 self.bump_any(); Some(m.complete(self, NETWORK_KW_EXPR))
774 }
775
776 fn parse_final_block_expr(&mut self) -> Option<CompletedMarker> {
778 let m = self.start();
779 self.bump_any(); self.skip_trivia();
781 if self.parse_block().is_none() {
782 self.error("expected block after 'final'");
783 }
784 Some(m.complete(self, FINAL_EXPR))
785 }
786}
787
788#[cfg(test)]
789mod tests {
790 use super::*;
791 use crate::{lexer::lex, parser::Parse};
792 use expect_test::{Expect, expect};
793
794 fn check_expr(input: &str, expect: Expect) {
795 let (tokens, _) = lex(input);
796 let mut parser = Parser::new(input, &tokens);
797 let root = parser.start();
798 parser.parse_expr();
799 parser.skip_trivia();
800 root.complete(&mut parser, ROOT);
801 let parse: Parse = parser.finish(vec![]);
802 let output = format!("{:#?}", parse.syntax());
803 expect.assert_eq(&output);
804 }
805
806 #[test]
811 fn parse_expr_integer() {
812 check_expr("42", expect![[r#"
813 ROOT@0..2
814 LITERAL_INT@0..2
815 INTEGER@0..2 "42"
816 "#]]);
817 }
818
819 #[test]
820 fn parse_expr_bool_true() {
821 check_expr("true", expect![[r#"
822 ROOT@0..4
823 LITERAL_BOOL@0..4
824 KW_TRUE@0..4 "true"
825 "#]]);
826 }
827
828 #[test]
829 fn parse_expr_bool_false() {
830 check_expr("false", expect![[r#"
831 ROOT@0..5
832 LITERAL_BOOL@0..5
833 KW_FALSE@0..5 "false"
834 "#]]);
835 }
836
837 #[test]
838 fn parse_expr_none() {
839 check_expr("none", expect![[r#"
840 ROOT@0..4
841 LITERAL_NONE@0..4
842 KW_NONE@0..4 "none"
843 "#]]);
844 }
845
846 #[test]
847 fn parse_expr_identifier_literal() {
848 check_expr("'foo'", expect![[r#"
849 ROOT@0..5
850 LITERAL_IDENT@0..5
851 IDENT_LIT@0..5 "'foo'"
852 "#]]);
853 }
854
855 #[test]
860 fn parse_expr_dynamic_call_basic() {
861 check_expr("Adder@(target)::sum(x, y)", expect![[r#"
862 ROOT@0..25
863 DYNAMIC_CALL_EXPR@0..25
864 TYPE_PATH@0..5
865 IDENT@0..5 "Adder"
866 AT@5..6 "@"
867 L_PAREN@6..7 "("
868 PATH_EXPR@7..13
869 IDENT@7..13 "target"
870 R_PAREN@13..14 ")"
871 COLON_COLON@14..16 "::"
872 IDENT@16..19 "sum"
873 L_PAREN@19..20 "("
874 PATH_EXPR@20..21
875 IDENT@20..21 "x"
876 COMMA@21..22 ","
877 WHITESPACE@22..23 " "
878 PATH_EXPR@23..24
879 IDENT@23..24 "y"
880 R_PAREN@24..25 ")"
881 "#]]);
882 }
883
884 #[test]
885 fn parse_expr_dynamic_call_identifier_target() {
886 check_expr("Adder@('foo')::sum(x, y)", expect![[r#"
887 ROOT@0..24
888 DYNAMIC_CALL_EXPR@0..24
889 TYPE_PATH@0..5
890 IDENT@0..5 "Adder"
891 AT@5..6 "@"
892 L_PAREN@6..7 "("
893 LITERAL_IDENT@7..12
894 IDENT_LIT@7..12 "'foo'"
895 R_PAREN@12..13 ")"
896 COLON_COLON@13..15 "::"
897 IDENT@15..18 "sum"
898 L_PAREN@18..19 "("
899 PATH_EXPR@19..20
900 IDENT@19..20 "x"
901 COMMA@20..21 ","
902 WHITESPACE@21..22 " "
903 PATH_EXPR@22..23
904 IDENT@22..23 "y"
905 R_PAREN@23..24 ")"
906 "#]]);
907 }
908
909 #[test]
910 fn parse_expr_dynamic_call_with_network() {
911 check_expr("Adder@('foo', 'aleo')::sum(x, y)", expect![[r#"
912 ROOT@0..32
913 DYNAMIC_CALL_EXPR@0..32
914 TYPE_PATH@0..5
915 IDENT@0..5 "Adder"
916 AT@5..6 "@"
917 L_PAREN@6..7 "("
918 LITERAL_IDENT@7..12
919 IDENT_LIT@7..12 "'foo'"
920 COMMA@12..13 ","
921 WHITESPACE@13..14 " "
922 LITERAL_IDENT@14..20
923 IDENT_LIT@14..20 "'aleo'"
924 R_PAREN@20..21 ")"
925 COLON_COLON@21..23 "::"
926 IDENT@23..26 "sum"
927 L_PAREN@26..27 "("
928 PATH_EXPR@27..28
929 IDENT@27..28 "x"
930 COMMA@28..29 ","
931 WHITESPACE@29..30 " "
932 PATH_EXPR@30..31
933 IDENT@30..31 "y"
934 R_PAREN@31..32 ")"
935 "#]]);
936 }
937
938 #[test]
939 fn parse_expr_dynamic_call_no_args() {
940 check_expr("Adder@(target)::sum()", expect![[r#"
941 ROOT@0..21
942 DYNAMIC_CALL_EXPR@0..21
943 TYPE_PATH@0..5
944 IDENT@0..5 "Adder"
945 AT@5..6 "@"
946 L_PAREN@6..7 "("
947 PATH_EXPR@7..13
948 IDENT@7..13 "target"
949 R_PAREN@13..14 ")"
950 COLON_COLON@14..16 "::"
951 IDENT@16..19 "sum"
952 L_PAREN@19..20 "("
953 R_PAREN@20..21 ")"
954 "#]]);
955 }
956
957 #[test]
962 fn parse_expr_ident() {
963 check_expr("foo", expect![[r#"
964 ROOT@0..3
965 PATH_EXPR@0..3
966 IDENT@0..3 "foo"
967 "#]]);
968 }
969
970 #[test]
971 fn parse_expr_path() {
972 check_expr("Foo::bar", expect![[r#"
973 ROOT@0..8
974 PATH_EXPR@0..8
975 IDENT@0..3 "Foo"
976 COLON_COLON@3..5 "::"
977 IDENT@5..8 "bar"
978 "#]]);
979 }
980
981 #[test]
982 fn parse_expr_self() {
983 check_expr("self", expect![[r#"
984 ROOT@0..4
985 SELF_EXPR@0..4
986 KW_SELF@0..4 "self"
987 "#]]);
988 }
989
990 #[test]
991 fn parse_expr_self_colon_colon_is_error() {
992 let (tokens, _) = lex("self::y");
994 let mut parser = Parser::new("self::y", &tokens);
995 let root = parser.start();
996 parser.parse_expr();
997 parser.skip_trivia();
998 root.complete(&mut parser, ROOT);
999 let parse: Parse = parser.finish(vec![]);
1000 assert!(!parse.errors().is_empty(), "expected error for self::");
1001 assert!(
1002 parse.errors().iter().any(|e| e.message.contains("expected '.'")),
1003 "expected error message to mention expected '.', got: {:?}",
1004 parse.errors()
1005 );
1006 }
1007
1008 #[test]
1013 fn parse_expr_add() {
1014 check_expr("1 + 2", expect![[r#"
1015 ROOT@0..5
1016 BINARY_EXPR@0..5
1017 LITERAL_INT@0..1
1018 INTEGER@0..1 "1"
1019 WHITESPACE@1..2 " "
1020 PLUS@2..3 "+"
1021 WHITESPACE@3..4 " "
1022 LITERAL_INT@4..5
1023 INTEGER@4..5 "2"
1024 "#]]);
1025 }
1026
1027 #[test]
1028 fn parse_expr_mul() {
1029 check_expr("a * b", expect![[r#"
1030 ROOT@0..5
1031 BINARY_EXPR@0..5
1032 PATH_EXPR@0..2
1033 IDENT@0..1 "a"
1034 WHITESPACE@1..2 " "
1035 STAR@2..3 "*"
1036 WHITESPACE@3..4 " "
1037 PATH_EXPR@4..5
1038 IDENT@4..5 "b"
1039 "#]]);
1040 }
1041
1042 #[test]
1043 fn parse_expr_precedence() {
1044 check_expr("1 + 2 * 3", expect![[r#"
1046 ROOT@0..9
1047 BINARY_EXPR@0..9
1048 LITERAL_INT@0..1
1049 INTEGER@0..1 "1"
1050 WHITESPACE@1..2 " "
1051 PLUS@2..3 "+"
1052 WHITESPACE@3..4 " "
1053 BINARY_EXPR@4..9
1054 LITERAL_INT@4..5
1055 INTEGER@4..5 "2"
1056 WHITESPACE@5..6 " "
1057 STAR@6..7 "*"
1058 WHITESPACE@7..8 " "
1059 LITERAL_INT@8..9
1060 INTEGER@8..9 "3"
1061 "#]]);
1062 }
1063
1064 #[test]
1065 fn parse_expr_power_right_assoc() {
1066 check_expr("a ** b ** c", expect![[r#"
1068 ROOT@0..11
1069 BINARY_EXPR@0..11
1070 PATH_EXPR@0..2
1071 IDENT@0..1 "a"
1072 WHITESPACE@1..2 " "
1073 STAR2@2..4 "**"
1074 WHITESPACE@4..5 " "
1075 BINARY_EXPR@5..11
1076 PATH_EXPR@5..7
1077 IDENT@5..6 "b"
1078 WHITESPACE@6..7 " "
1079 STAR2@7..9 "**"
1080 WHITESPACE@9..10 " "
1081 PATH_EXPR@10..11
1082 IDENT@10..11 "c"
1083 "#]]);
1084 }
1085
1086 #[test]
1091 fn parse_expr_unary_neg() {
1092 check_expr("-x", expect![[r#"
1093 ROOT@0..2
1094 UNARY_EXPR@0..2
1095 MINUS@0..1 "-"
1096 PATH_EXPR@1..2
1097 IDENT@1..2 "x"
1098 "#]]);
1099 }
1100
1101 #[test]
1102 fn parse_expr_unary_not() {
1103 check_expr("!flag", expect![[r#"
1104 ROOT@0..5
1105 UNARY_EXPR@0..5
1106 BANG@0..1 "!"
1107 PATH_EXPR@1..5
1108 IDENT@1..5 "flag"
1109 "#]]);
1110 }
1111
1112 #[test]
1117 fn parse_expr_comparison() {
1118 check_expr("a < b", expect![[r#"
1119 ROOT@0..5
1120 BINARY_EXPR@0..5
1121 PATH_EXPR@0..2
1122 IDENT@0..1 "a"
1123 WHITESPACE@1..2 " "
1124 LT@2..3 "<"
1125 WHITESPACE@3..4 " "
1126 PATH_EXPR@4..5
1127 IDENT@4..5 "b"
1128 "#]]);
1129 }
1130
1131 #[test]
1132 fn parse_expr_logical_and() {
1133 check_expr("a && b", expect![[r#"
1134 ROOT@0..6
1135 BINARY_EXPR@0..6
1136 PATH_EXPR@0..2
1137 IDENT@0..1 "a"
1138 WHITESPACE@1..2 " "
1139 AMP2@2..4 "&&"
1140 WHITESPACE@4..5 " "
1141 PATH_EXPR@5..6
1142 IDENT@5..6 "b"
1143 "#]]);
1144 }
1145
1146 #[test]
1147 fn parse_expr_logical_or() {
1148 check_expr("a || b", expect![[r#"
1149 ROOT@0..6
1150 BINARY_EXPR@0..6
1151 PATH_EXPR@0..2
1152 IDENT@0..1 "a"
1153 WHITESPACE@1..2 " "
1154 PIPE2@2..4 "||"
1155 WHITESPACE@4..5 " "
1156 PATH_EXPR@5..6
1157 IDENT@5..6 "b"
1158 "#]]);
1159 }
1160
1161 #[test]
1166 fn parse_expr_ternary() {
1167 check_expr("a ? b : c", expect![[r#"
1168 ROOT@0..9
1169 TERNARY_EXPR@0..9
1170 PATH_EXPR@0..2
1171 IDENT@0..1 "a"
1172 WHITESPACE@1..2 " "
1173 QUESTION@2..3 "?"
1174 WHITESPACE@3..4 " "
1175 PATH_EXPR@4..6
1176 IDENT@4..5 "b"
1177 WHITESPACE@5..6 " "
1178 COLON@6..7 ":"
1179 WHITESPACE@7..8 " "
1180 PATH_EXPR@8..9
1181 IDENT@8..9 "c"
1182 "#]]);
1183 }
1184
1185 #[test]
1190 fn parse_expr_member_access() {
1191 check_expr("foo.bar", expect![[r#"
1192 ROOT@0..7
1193 FIELD_EXPR@0..7
1194 PATH_EXPR@0..3
1195 IDENT@0..3 "foo"
1196 DOT@3..4 "."
1197 IDENT@4..7 "bar"
1198 "#]]);
1199 }
1200
1201 #[test]
1202 fn parse_expr_tuple_access() {
1203 check_expr("tuple.0", expect![[r#"
1204 ROOT@0..7
1205 TUPLE_ACCESS_EXPR@0..7
1206 PATH_EXPR@0..5
1207 IDENT@0..5 "tuple"
1208 DOT@5..6 "."
1209 INTEGER@6..7 "0"
1210 "#]]);
1211 }
1212
1213 #[test]
1214 fn parse_expr_index() {
1215 check_expr("arr[0]", expect![[r#"
1216 ROOT@0..6
1217 INDEX_EXPR@0..6
1218 PATH_EXPR@0..3
1219 IDENT@0..3 "arr"
1220 L_BRACKET@3..4 "["
1221 LITERAL_INT@4..5
1222 INTEGER@4..5 "0"
1223 R_BRACKET@5..6 "]"
1224 "#]]);
1225 }
1226
1227 #[test]
1228 fn parse_expr_call() {
1229 check_expr("foo(a, b)", expect![[r#"
1230 ROOT@0..9
1231 CALL_EXPR@0..9
1232 PATH_EXPR@0..3
1233 IDENT@0..3 "foo"
1234 L_PAREN@3..4 "("
1235 PATH_EXPR@4..5
1236 IDENT@4..5 "a"
1237 COMMA@5..6 ","
1238 WHITESPACE@6..7 " "
1239 PATH_EXPR@7..8
1240 IDENT@7..8 "b"
1241 R_PAREN@8..9 ")"
1242 "#]]);
1243 }
1244
1245 #[test]
1246 fn parse_expr_method_call() {
1247 check_expr("x.foo()", expect![[r#"
1248 ROOT@0..7
1249 METHOD_CALL_EXPR@0..7
1250 PATH_EXPR@0..1
1251 IDENT@0..1 "x"
1252 DOT@1..2 "."
1253 IDENT@2..5 "foo"
1254 L_PAREN@5..6 "("
1255 R_PAREN@6..7 ")"
1256 "#]]);
1257 }
1258
1259 #[test]
1264 fn parse_expr_cast() {
1265 check_expr("x as u64", expect![[r#"
1266 ROOT@0..8
1267 CAST_EXPR@0..8
1268 PATH_EXPR@0..2
1269 IDENT@0..1 "x"
1270 WHITESPACE@1..2 " "
1271 KW_AS@2..4 "as"
1272 WHITESPACE@4..5 " "
1273 TYPE_PRIMITIVE@5..8
1274 KW_U64@5..8 "u64"
1275 "#]]);
1276 }
1277
1278 #[test]
1283 fn parse_expr_paren() {
1284 check_expr("(a + b)", expect![[r#"
1285 ROOT@0..7
1286 PAREN_EXPR@0..7
1287 L_PAREN@0..1 "("
1288 BINARY_EXPR@1..6
1289 PATH_EXPR@1..3
1290 IDENT@1..2 "a"
1291 WHITESPACE@2..3 " "
1292 PLUS@3..4 "+"
1293 WHITESPACE@4..5 " "
1294 PATH_EXPR@5..6
1295 IDENT@5..6 "b"
1296 R_PAREN@6..7 ")"
1297 "#]]);
1298 }
1299
1300 #[test]
1301 fn parse_expr_tuple() {
1302 check_expr("(a, b)", expect![[r#"
1303 ROOT@0..6
1304 TUPLE_EXPR@0..6
1305 L_PAREN@0..1 "("
1306 PATH_EXPR@1..2
1307 IDENT@1..2 "a"
1308 COMMA@2..3 ","
1309 WHITESPACE@3..4 " "
1310 PATH_EXPR@4..5
1311 IDENT@4..5 "b"
1312 R_PAREN@5..6 ")"
1313 "#]]);
1314 }
1315
1316 #[test]
1317 fn parse_expr_unit() {
1318 check_expr("()", expect![[r#"
1319 ROOT@0..2
1320 TUPLE_EXPR@0..2
1321 L_PAREN@0..1 "("
1322 R_PAREN@1..2 ")"
1323 "#]]);
1324 }
1325
1326 #[test]
1331 fn parse_expr_array() {
1332 check_expr("[1, 2, 3]", expect![[r#"
1333 ROOT@0..9
1334 ARRAY_EXPR@0..9
1335 L_BRACKET@0..1 "["
1336 LITERAL_INT@1..2
1337 INTEGER@1..2 "1"
1338 COMMA@2..3 ","
1339 WHITESPACE@3..4 " "
1340 LITERAL_INT@4..5
1341 INTEGER@4..5 "2"
1342 COMMA@5..6 ","
1343 WHITESPACE@6..7 " "
1344 LITERAL_INT@7..8
1345 INTEGER@7..8 "3"
1346 R_BRACKET@8..9 "]"
1347 "#]]);
1348 }
1349
1350 #[test]
1351 fn parse_expr_array_repeat() {
1352 check_expr("[0; 10]", expect![[r#"
1353 ROOT@0..7
1354 REPEAT_EXPR@0..7
1355 L_BRACKET@0..1 "["
1356 LITERAL_INT@1..2
1357 INTEGER@1..2 "0"
1358 SEMICOLON@2..3 ";"
1359 WHITESPACE@3..4 " "
1360 LITERAL_INT@4..6
1361 INTEGER@4..6 "10"
1362 R_BRACKET@6..7 "]"
1363 "#]]);
1364 }
1365
1366 #[test]
1371 fn parse_expr_struct_init() {
1372 check_expr("Point { x: 1, y: 2 }", expect![[r#"
1373 ROOT@0..20
1374 STRUCT_EXPR@0..20
1375 IDENT@0..5 "Point"
1376 WHITESPACE@5..6 " "
1377 L_BRACE@6..7 "{"
1378 STRUCT_FIELD_INIT@7..12
1379 WHITESPACE@7..8 " "
1380 IDENT@8..9 "x"
1381 COLON@9..10 ":"
1382 WHITESPACE@10..11 " "
1383 LITERAL_INT@11..12
1384 INTEGER@11..12 "1"
1385 COMMA@12..13 ","
1386 STRUCT_FIELD_INIT@13..18
1387 WHITESPACE@13..14 " "
1388 IDENT@14..15 "y"
1389 COLON@15..16 ":"
1390 WHITESPACE@16..17 " "
1391 LITERAL_INT@17..18
1392 INTEGER@17..18 "2"
1393 WHITESPACE@18..19 " "
1394 R_BRACE@19..20 "}"
1395 "#]]);
1396 }
1397
1398 #[test]
1399 fn parse_expr_struct_shorthand() {
1400 check_expr("Point { x, y }", expect![[r#"
1401 ROOT@0..14
1402 STRUCT_EXPR@0..14
1403 IDENT@0..5 "Point"
1404 WHITESPACE@5..6 " "
1405 L_BRACE@6..7 "{"
1406 STRUCT_FIELD_SHORTHAND@7..9
1407 WHITESPACE@7..8 " "
1408 IDENT@8..9 "x"
1409 COMMA@9..10 ","
1410 STRUCT_FIELD_SHORTHAND@10..13
1411 WHITESPACE@10..11 " "
1412 IDENT@11..12 "y"
1413 WHITESPACE@12..13 " "
1414 R_BRACE@13..14 "}"
1415 "#]]);
1416 }
1417
1418 fn check_expr_no_errors(input: &str) {
1427 let (tokens, _) = lex(input);
1428 let mut parser = Parser::new(input, &tokens);
1429 let root = parser.start();
1430 parser.parse_expr();
1431 parser.skip_trivia();
1432 root.complete(&mut parser, ROOT);
1433 let parse: Parse = parser.finish(vec![]);
1434 if !parse.errors().is_empty() {
1435 for err in parse.errors() {
1436 eprintln!("error at {:?}: {}", err.range, err.message);
1437 }
1438 eprintln!("tree:\n{:#?}", parse.syntax());
1439 panic!("expression parse had {} error(s)", parse.errors().len());
1440 }
1441 }
1442
1443 #[test]
1444 fn parse_expr_call_const_generic_simple() {
1445 check_expr("foo::[5]()", expect![[r#"
1447 ROOT@0..10
1448 CALL_EXPR@0..10
1449 PATH_EXPR@0..8
1450 IDENT@0..3 "foo"
1451 COLON_COLON@3..5 "::"
1452 CONST_ARG_LIST@5..8
1453 L_BRACKET@5..6 "["
1454 LITERAL_INT@6..7
1455 INTEGER@6..7 "5"
1456 R_BRACKET@7..8 "]"
1457 L_PAREN@8..9 "("
1458 R_PAREN@9..10 ")"
1459 "#]]);
1460 }
1461
1462 #[test]
1463 fn parse_expr_call_const_generic_expr() {
1464 check_expr_no_errors("foo::[N + 1]()");
1466 }
1467
1468 #[test]
1469 fn parse_expr_call_const_generic_multi() {
1470 check_expr_no_errors("bar::[M, K, N]()");
1472 }
1473
1474 #[test]
1475 fn parse_expr_struct_lit_const_generic() {
1476 check_expr("Foo::[8u32] { arr: x }", expect![[r#"
1478 ROOT@0..22
1479 STRUCT_EXPR@0..22
1480 IDENT@0..3 "Foo"
1481 COLON_COLON@3..5 "::"
1482 CONST_ARG_LIST@5..11
1483 L_BRACKET@5..6 "["
1484 LITERAL_INT@6..10
1485 INTEGER@6..10 "8u32"
1486 R_BRACKET@10..11 "]"
1487 WHITESPACE@11..12 " "
1488 L_BRACE@12..13 "{"
1489 STRUCT_FIELD_INIT@13..21
1490 WHITESPACE@13..14 " "
1491 IDENT@14..17 "arr"
1492 COLON@17..18 ":"
1493 WHITESPACE@18..19 " "
1494 PATH_EXPR@19..21
1495 IDENT@19..20 "x"
1496 WHITESPACE@20..21 " "
1497 R_BRACE@21..22 "}"
1498 "#]]);
1499 }
1500
1501 #[test]
1502 fn parse_expr_locator_call_const_generic() {
1503 check_expr_no_errors("child.aleo::foo::[3]()");
1505 }
1506
1507 #[test]
1508 fn parse_expr_assoc_fn_const_generic() {
1509 check_expr_no_errors("Foo::bar::[N]()");
1511 }
1512
1513 #[test]
1518 fn parse_expr_complex() {
1519 check_expr("a.b[c](d) + e", expect![[r#"
1520 ROOT@0..13
1521 BINARY_EXPR@0..13
1522 CALL_EXPR@0..9
1523 INDEX_EXPR@0..6
1524 FIELD_EXPR@0..3
1525 PATH_EXPR@0..1
1526 IDENT@0..1 "a"
1527 DOT@1..2 "."
1528 IDENT@2..3 "b"
1529 L_BRACKET@3..4 "["
1530 PATH_EXPR@4..5
1531 IDENT@4..5 "c"
1532 R_BRACKET@5..6 "]"
1533 L_PAREN@6..7 "("
1534 PATH_EXPR@7..8
1535 IDENT@7..8 "d"
1536 R_PAREN@8..9 ")"
1537 WHITESPACE@9..10 " "
1538 PLUS@10..11 "+"
1539 WHITESPACE@11..12 " "
1540 PATH_EXPR@12..13
1541 IDENT@12..13 "e"
1542 "#]]);
1543 }
1544
1545 fn parse_expr_for_test(input: &str) -> Parse {
1550 let (tokens, _) = lex(input);
1551 let mut parser = Parser::new(input, &tokens);
1552 let root = parser.start();
1553 parser.parse_expr();
1554 parser.skip_trivia();
1555 root.complete(&mut parser, ROOT);
1556 parser.finish(vec![])
1557 }
1558
1559 #[test]
1560 fn parse_expr_chained_eq_is_error() {
1561 let parse = parse_expr_for_test("1 == 2 == 3");
1563 assert!(!parse.errors().is_empty(), "expected error for chained ==, got none");
1564 assert!(
1565 parse.errors().iter().any(|e| e.message.contains("'&&'") || e.message.contains("expected")),
1566 "expected error message about valid operators, got: {:?}",
1567 parse.errors()
1568 );
1569 }
1570
1571 #[test]
1572 fn parse_expr_chained_neq_is_error() {
1573 let parse = parse_expr_for_test("1 != 2 != 3");
1575 assert!(!parse.errors().is_empty(), "expected error for chained !=, got none");
1576 }
1577
1578 #[test]
1579 fn parse_expr_chained_lt_is_error() {
1580 let parse = parse_expr_for_test("1 < 2 < 3");
1582 assert!(!parse.errors().is_empty(), "expected error for chained <, got none");
1583 }
1584
1585 #[test]
1586 fn parse_expr_chained_gt_is_error() {
1587 let parse = parse_expr_for_test("1 > 2 > 3");
1589 assert!(!parse.errors().is_empty(), "expected error for chained >, got none");
1590 }
1591
1592 #[test]
1593 fn parse_expr_comparison_with_logical_is_ok() {
1594 check_expr_no_errors("1 == 2 && 3 == 4");
1596 check_expr_no_errors("1 < 2 || 3 > 4");
1597 }
1598
1599 #[test]
1604 fn parse_expr_group_associated_fn() {
1605 check_expr("group::to_x_coordinate(a)", expect![[r#"
1608 ROOT@0..25
1609 CALL_EXPR@0..25
1610 PATH_EXPR@0..22
1611 IDENT@0..22 "group::to_x_coordinate"
1612 L_PAREN@22..23 "("
1613 PATH_EXPR@23..24
1614 IDENT@23..24 "a"
1615 R_PAREN@24..25 ")"
1616 "#]]);
1617 }
1618
1619 #[test]
1620 fn parse_expr_signature_associated_fn() {
1621 check_expr("signature::verify(s, a, v)", expect![[r#"
1624 ROOT@0..26
1625 CALL_EXPR@0..26
1626 PATH_EXPR@0..17
1627 IDENT@0..17 "signature::verify"
1628 L_PAREN@17..18 "("
1629 PATH_EXPR@18..19
1630 IDENT@18..19 "s"
1631 COMMA@19..20 ","
1632 WHITESPACE@20..21 " "
1633 PATH_EXPR@21..22
1634 IDENT@21..22 "a"
1635 COMMA@22..23 ","
1636 WHITESPACE@23..24 " "
1637 PATH_EXPR@24..25
1638 IDENT@24..25 "v"
1639 R_PAREN@25..26 ")"
1640 "#]]);
1641 }
1642
1643 #[test]
1648 fn parse_expr_chained_le_is_error() {
1649 let parse = parse_expr_for_test("1 <= 2 <= 3");
1650 assert!(!parse.errors().is_empty(), "expected error for chained <=, got none");
1651 }
1652
1653 #[test]
1654 fn parse_expr_chained_ge_is_error() {
1655 let parse = parse_expr_for_test("1 >= 2 >= 3");
1656 assert!(!parse.errors().is_empty(), "expected error for chained >=, got none");
1657 }
1658
1659 #[test]
1660 fn parse_expr_chained_mixed_cmp_is_error() {
1661 let parse = parse_expr_for_test("1 < 2 > 3");
1662 assert!(!parse.errors().is_empty(), "expected error for mixed chained comparisons, got none");
1663 }
1664
1665 #[test]
1670 fn parse_expr_ternary_nested() {
1671 check_expr("a ? b ? c : d : e", expect![[r#"
1672 ROOT@0..17
1673 TERNARY_EXPR@0..17
1674 PATH_EXPR@0..2
1675 IDENT@0..1 "a"
1676 WHITESPACE@1..2 " "
1677 QUESTION@2..3 "?"
1678 WHITESPACE@3..4 " "
1679 TERNARY_EXPR@4..14
1680 PATH_EXPR@4..6
1681 IDENT@4..5 "b"
1682 WHITESPACE@5..6 " "
1683 QUESTION@6..7 "?"
1684 WHITESPACE@7..8 " "
1685 PATH_EXPR@8..10
1686 IDENT@8..9 "c"
1687 WHITESPACE@9..10 " "
1688 COLON@10..11 ":"
1689 WHITESPACE@11..12 " "
1690 PATH_EXPR@12..14
1691 IDENT@12..13 "d"
1692 WHITESPACE@13..14 " "
1693 COLON@14..15 ":"
1694 WHITESPACE@15..16 " "
1695 PATH_EXPR@16..17
1696 IDENT@16..17 "e"
1697 "#]]);
1698 }
1699
1700 #[test]
1705 fn parse_expr_cast_chained() {
1706 check_expr("x as u32 as u64", expect![[r#"
1707 ROOT@0..15
1708 CAST_EXPR@0..15
1709 CAST_EXPR@0..8
1710 PATH_EXPR@0..2
1711 IDENT@0..1 "x"
1712 WHITESPACE@1..2 " "
1713 KW_AS@2..4 "as"
1714 WHITESPACE@4..5 " "
1715 TYPE_PRIMITIVE@5..8
1716 KW_U32@5..8 "u32"
1717 WHITESPACE@8..9 " "
1718 KW_AS@9..11 "as"
1719 WHITESPACE@11..12 " "
1720 TYPE_PRIMITIVE@12..15
1721 KW_U64@12..15 "u64"
1722 "#]]);
1723 }
1724
1725 #[test]
1730 fn parse_expr_array_trailing_comma() {
1731 check_expr("[1, 2, 3,]", expect![[r#"
1732 ROOT@0..10
1733 ARRAY_EXPR@0..10
1734 L_BRACKET@0..1 "["
1735 LITERAL_INT@1..2
1736 INTEGER@1..2 "1"
1737 COMMA@2..3 ","
1738 WHITESPACE@3..4 " "
1739 LITERAL_INT@4..5
1740 INTEGER@4..5 "2"
1741 COMMA@5..6 ","
1742 WHITESPACE@6..7 " "
1743 LITERAL_INT@7..8
1744 INTEGER@7..8 "3"
1745 COMMA@8..9 ","
1746 R_BRACKET@9..10 "]"
1747 "#]]);
1748 }
1749
1750 #[test]
1751 fn parse_expr_array_empty() {
1752 check_expr("[]", expect![[r#"
1753 ROOT@0..2
1754 ARRAY_EXPR@0..2
1755 L_BRACKET@0..1 "["
1756 R_BRACKET@1..2 "]"
1757 "#]]);
1758 }
1759
1760 #[test]
1761 fn parse_expr_tuple_single() {
1762 check_expr("(a,)", expect![[r#"
1763 ROOT@0..4
1764 TUPLE_EXPR@0..4
1765 L_PAREN@0..1 "("
1766 PATH_EXPR@1..2
1767 IDENT@1..2 "a"
1768 COMMA@2..3 ","
1769 R_PAREN@3..4 ")"
1770 "#]]);
1771 }
1772
1773 #[test]
1774 fn parse_expr_tuple_trailing_comma() {
1775 check_expr("(1, 2,)", expect![[r#"
1776 ROOT@0..7
1777 TUPLE_EXPR@0..7
1778 L_PAREN@0..1 "("
1779 LITERAL_INT@1..2
1780 INTEGER@1..2 "1"
1781 COMMA@2..3 ","
1782 WHITESPACE@3..4 " "
1783 LITERAL_INT@4..5
1784 INTEGER@4..5 "2"
1785 COMMA@5..6 ","
1786 R_PAREN@6..7 ")"
1787 "#]]);
1788 }
1789
1790 #[test]
1795 fn parse_expr_struct_empty() {
1796 check_expr("Point { }", expect![[r#"
1797 ROOT@0..9
1798 STRUCT_EXPR@0..9
1799 IDENT@0..5 "Point"
1800 WHITESPACE@5..6 " "
1801 L_BRACE@6..7 "{"
1802 WHITESPACE@7..8 " "
1803 R_BRACE@8..9 "}"
1804 "#]]);
1805 }
1806
1807 #[test]
1808 fn parse_expr_struct_trailing_comma() {
1809 check_expr("Point { x: 1, }", expect![[r#"
1810 ROOT@0..15
1811 STRUCT_EXPR@0..15
1812 IDENT@0..5 "Point"
1813 WHITESPACE@5..6 " "
1814 L_BRACE@6..7 "{"
1815 STRUCT_FIELD_INIT@7..12
1816 WHITESPACE@7..8 " "
1817 IDENT@8..9 "x"
1818 COLON@9..10 ":"
1819 WHITESPACE@10..11 " "
1820 LITERAL_INT@11..12
1821 INTEGER@11..12 "1"
1822 COMMA@12..13 ","
1823 WHITESPACE@13..14 " "
1824 R_BRACE@14..15 "}"
1825 "#]]);
1826 }
1827
1828 #[test]
1829 fn parse_expr_struct_mixed_fields() {
1830 check_expr("Point { x, y: 2 }", expect![[r#"
1831 ROOT@0..17
1832 STRUCT_EXPR@0..17
1833 IDENT@0..5 "Point"
1834 WHITESPACE@5..6 " "
1835 L_BRACE@6..7 "{"
1836 STRUCT_FIELD_SHORTHAND@7..9
1837 WHITESPACE@7..8 " "
1838 IDENT@8..9 "x"
1839 COMMA@9..10 ","
1840 STRUCT_FIELD_INIT@10..15
1841 WHITESPACE@10..11 " "
1842 IDENT@11..12 "y"
1843 COLON@12..13 ":"
1844 WHITESPACE@13..14 " "
1845 LITERAL_INT@14..15
1846 INTEGER@14..15 "2"
1847 WHITESPACE@15..16 " "
1848 R_BRACE@16..17 "}"
1849 "#]]);
1850 }
1851
1852 #[test]
1857 fn parse_expr_string() {
1858 check_expr("\"hello\"", expect![[r#"
1859 ROOT@0..7
1860 LITERAL_STRING@0..7
1861 STRING@0..7 "\"hello\""
1862 "#]]);
1863 }
1864
1865 #[test]
1866 fn parse_expr_address() {
1867 check_expr("aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9", expect![[r#"
1868 ROOT@0..63
1869 LITERAL_ADDRESS@0..63
1870 ADDRESS_LIT@0..63 "aleo1qnr4dkkvkgfqph0v ..."
1871 "#]]);
1872 }
1873
1874 #[test]
1879 fn parse_expr_deep_postfix() {
1880 check_expr("a[0].b.c(x)[1]", expect![[r#"
1881 ROOT@0..14
1882 INDEX_EXPR@0..14
1883 METHOD_CALL_EXPR@0..11
1884 FIELD_EXPR@0..6
1885 INDEX_EXPR@0..4
1886 PATH_EXPR@0..1
1887 IDENT@0..1 "a"
1888 L_BRACKET@1..2 "["
1889 LITERAL_INT@2..3
1890 INTEGER@2..3 "0"
1891 R_BRACKET@3..4 "]"
1892 DOT@4..5 "."
1893 IDENT@5..6 "b"
1894 DOT@6..7 "."
1895 IDENT@7..8 "c"
1896 L_PAREN@8..9 "("
1897 PATH_EXPR@9..10
1898 IDENT@9..10 "x"
1899 R_PAREN@10..11 ")"
1900 L_BRACKET@11..12 "["
1901 LITERAL_INT@12..13
1902 INTEGER@12..13 "1"
1903 R_BRACKET@13..14 "]"
1904 "#]]);
1905 }
1906
1907 #[test]
1912 fn parse_expr_final() {
1913 check_expr("final { foo() }", expect![[r#"
1914 ROOT@0..15
1915 FINAL_EXPR@0..15
1916 KW_FINAL@0..5 "final"
1917 WHITESPACE@5..6 " "
1918 BLOCK@6..15
1919 L_BRACE@6..7 "{"
1920 WHITESPACE@7..8 " "
1921 EXPR_STMT@8..14
1922 CALL_EXPR@8..13
1923 PATH_EXPR@8..11
1924 IDENT@8..11 "foo"
1925 L_PAREN@11..12 "("
1926 R_PAREN@12..13 ")"
1927 WHITESPACE@13..14 " "
1928 ERROR@14..14
1929 R_BRACE@14..15 "}"
1930 "#]]);
1931 }
1932
1933 #[test]
1938 fn parse_expr_mixed_arithmetic() {
1939 check_expr("a + b * c / d - e", expect![[r#"
1941 ROOT@0..17
1942 BINARY_EXPR@0..17
1943 BINARY_EXPR@0..14
1944 PATH_EXPR@0..2
1945 IDENT@0..1 "a"
1946 WHITESPACE@1..2 " "
1947 PLUS@2..3 "+"
1948 WHITESPACE@3..4 " "
1949 BINARY_EXPR@4..14
1950 BINARY_EXPR@4..10
1951 PATH_EXPR@4..6
1952 IDENT@4..5 "b"
1953 WHITESPACE@5..6 " "
1954 STAR@6..7 "*"
1955 WHITESPACE@7..8 " "
1956 PATH_EXPR@8..10
1957 IDENT@8..9 "c"
1958 WHITESPACE@9..10 " "
1959 SLASH@10..11 "/"
1960 WHITESPACE@11..12 " "
1961 PATH_EXPR@12..14
1962 IDENT@12..13 "d"
1963 WHITESPACE@13..14 " "
1964 MINUS@14..15 "-"
1965 WHITESPACE@15..16 " "
1966 PATH_EXPR@16..17
1967 IDENT@16..17 "e"
1968 "#]]);
1969 }
1970
1971 #[test]
1972 fn parse_expr_bitwise_precedence() {
1973 check_expr("a | b & c ^ d", expect![[r#"
1977 ROOT@0..13
1978 BINARY_EXPR@0..13
1979 PATH_EXPR@0..2
1980 IDENT@0..1 "a"
1981 WHITESPACE@1..2 " "
1982 PIPE@2..3 "|"
1983 WHITESPACE@3..4 " "
1984 BINARY_EXPR@4..13
1985 BINARY_EXPR@4..10
1986 PATH_EXPR@4..6
1987 IDENT@4..5 "b"
1988 WHITESPACE@5..6 " "
1989 AMP@6..7 "&"
1990 WHITESPACE@7..8 " "
1991 PATH_EXPR@8..10
1992 IDENT@8..9 "c"
1993 WHITESPACE@9..10 " "
1994 CARET@10..11 "^"
1995 WHITESPACE@11..12 " "
1996 PATH_EXPR@12..13
1997 IDENT@12..13 "d"
1998 "#]]);
1999 }
2000
2001 #[test]
2002 fn parse_expr_shift_chain() {
2003 check_expr("x << 1 >> 2", expect![[r#"
2006 ROOT@0..11
2007 BINARY_EXPR@0..11
2008 BINARY_EXPR@0..6
2009 PATH_EXPR@0..2
2010 IDENT@0..1 "x"
2011 WHITESPACE@1..2 " "
2012 SHL@2..4 "<<"
2013 WHITESPACE@4..5 " "
2014 LITERAL_INT@5..6
2015 INTEGER@5..6 "1"
2016 WHITESPACE@6..7 " "
2017 SHR@7..9 ">>"
2018 WHITESPACE@9..10 " "
2019 LITERAL_INT@10..11
2020 INTEGER@10..11 "2"
2021 "#]]);
2022 }
2023}