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 }
622 true
623 } else {
624 false
625 };
626
627 if self.at(COLON_COLON) && self.nth(1) == L_BRACKET {
629 self.bump_any(); self.parse_const_generic_args_bracket();
631 }
632
633 if !opts.no_struct && self.at(L_BRACE) {
635 self.bump_any(); if !self.at(R_BRACE) {
637 self.parse_struct_field();
638 while self.eat(COMMA) {
639 if self.at(R_BRACE) {
640 break;
641 }
642 self.parse_struct_field();
643 }
644 }
645 self.expect(R_BRACE);
646 let kind = if is_locator { STRUCT_LOCATOR_EXPR } else { STRUCT_EXPR };
647 return Some(m.complete(self, kind));
648 }
649
650 if self.at(L_PAREN) {
652 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
653 let cm = m.complete(self, kind);
654 return self.parse_call_expr(cm);
655 }
656
657 if self.at(AT) {
659 let cm = m.complete(self, TYPE_LOCATOR);
660 return self.parse_dynamic_call_expr(cm);
661 }
662
663 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
664 return Some(m.complete(self, kind));
665 }
666
667 while self.eat(COLON_COLON) {
669 if self.at(L_BRACKET) {
670 self.parse_const_generic_args_bracket();
672 break;
673 } else if self.at(LT) {
674 self.parse_const_generic_args_angle();
677 break;
678 } else if self.at(IDENT) {
679 self.bump_any();
680 } else {
681 self.error("expected identifier after ::");
682 break;
683 }
684 }
685
686 if !opts.no_struct && self.at(L_BRACE) {
688 self.bump_any(); if !self.at(R_BRACE) {
692 self.parse_struct_field();
693 while self.eat(COMMA) {
694 if self.at(R_BRACE) {
695 break;
696 }
697 self.parse_struct_field();
698 }
699 }
700
701 self.expect(R_BRACE);
702 return Some(m.complete(self, STRUCT_EXPR));
703 }
704
705 if self.at(L_PAREN) {
707 let cm = m.complete(self, PATH_EXPR);
708 return self.parse_call_expr(cm);
709 }
710
711 if self.at(AT) {
713 let cm = m.complete(self, TYPE_PATH);
714 return self.parse_dynamic_call_expr(cm);
715 }
716
717 Some(m.complete(self, PATH_EXPR))
718 }
719
720 fn parse_struct_field(&mut self) {
722 let m = self.start();
723 self.skip_trivia();
724
725 if self.at(IDENT) {
726 self.bump_any(); if self.eat(COLON) {
729 if self.parse_expr().is_none() && !self.at(R_BRACE) && !self.at(COMMA) {
731 self.error("expected field value");
732 }
733 m.complete(self, STRUCT_FIELD_INIT);
734 } else {
735 m.complete(self, STRUCT_FIELD_SHORTHAND);
737 }
738 } else {
739 self.error("expected field name");
740 m.complete(self, STRUCT_FIELD_INIT);
741 }
742 }
743
744 fn parse_self_expr(&mut self) -> Option<CompletedMarker> {
746 let m = self.start();
747 self.bump_any(); if self.at(COLON_COLON) {
751 self.error("expected '.' -- found '::'");
752 }
753
754 Some(m.complete(self, SELF_EXPR))
755 }
756
757 fn parse_block_access(&mut self) -> Option<CompletedMarker> {
759 let m = self.start();
760 self.bump_any(); Some(m.complete(self, BLOCK_KW_EXPR))
762 }
763
764 fn parse_network_access(&mut self) -> Option<CompletedMarker> {
766 let m = self.start();
767 self.bump_any(); Some(m.complete(self, NETWORK_KW_EXPR))
769 }
770
771 fn parse_final_block_expr(&mut self) -> Option<CompletedMarker> {
773 let m = self.start();
774 self.bump_any(); self.skip_trivia();
776 if self.parse_block().is_none() {
777 self.error("expected block after 'final'");
778 }
779 Some(m.complete(self, FINAL_EXPR))
780 }
781}
782
783#[cfg(test)]
784mod tests {
785 use super::*;
786 use crate::{lexer::lex, parser::Parse};
787 use expect_test::{Expect, expect};
788
789 fn check_expr(input: &str, expect: Expect) {
790 let (tokens, _) = lex(input);
791 let mut parser = Parser::new(input, &tokens);
792 let root = parser.start();
793 parser.parse_expr();
794 parser.skip_trivia();
795 root.complete(&mut parser, ROOT);
796 let parse: Parse = parser.finish(vec![]);
797 let output = format!("{:#?}", parse.syntax());
798 expect.assert_eq(&output);
799 }
800
801 #[test]
806 fn parse_expr_integer() {
807 check_expr("42", expect![[r#"
808 ROOT@0..2
809 LITERAL_INT@0..2
810 INTEGER@0..2 "42"
811 "#]]);
812 }
813
814 #[test]
815 fn parse_expr_bool_true() {
816 check_expr("true", expect![[r#"
817 ROOT@0..4
818 LITERAL_BOOL@0..4
819 KW_TRUE@0..4 "true"
820 "#]]);
821 }
822
823 #[test]
824 fn parse_expr_bool_false() {
825 check_expr("false", expect![[r#"
826 ROOT@0..5
827 LITERAL_BOOL@0..5
828 KW_FALSE@0..5 "false"
829 "#]]);
830 }
831
832 #[test]
833 fn parse_expr_none() {
834 check_expr("none", expect![[r#"
835 ROOT@0..4
836 LITERAL_NONE@0..4
837 KW_NONE@0..4 "none"
838 "#]]);
839 }
840
841 #[test]
842 fn parse_expr_identifier_literal() {
843 check_expr("'foo'", expect![[r#"
844 ROOT@0..5
845 LITERAL_IDENT@0..5
846 IDENT_LIT@0..5 "'foo'"
847 "#]]);
848 }
849
850 #[test]
855 fn parse_expr_dynamic_call_basic() {
856 check_expr("Adder@(target)::sum(x, y)", expect![[r#"
857 ROOT@0..25
858 DYNAMIC_CALL_EXPR@0..25
859 TYPE_PATH@0..5
860 IDENT@0..5 "Adder"
861 AT@5..6 "@"
862 L_PAREN@6..7 "("
863 PATH_EXPR@7..13
864 IDENT@7..13 "target"
865 R_PAREN@13..14 ")"
866 COLON_COLON@14..16 "::"
867 IDENT@16..19 "sum"
868 L_PAREN@19..20 "("
869 PATH_EXPR@20..21
870 IDENT@20..21 "x"
871 COMMA@21..22 ","
872 WHITESPACE@22..23 " "
873 PATH_EXPR@23..24
874 IDENT@23..24 "y"
875 R_PAREN@24..25 ")"
876 "#]]);
877 }
878
879 #[test]
880 fn parse_expr_dynamic_call_identifier_target() {
881 check_expr("Adder@('foo')::sum(x, y)", expect![[r#"
882 ROOT@0..24
883 DYNAMIC_CALL_EXPR@0..24
884 TYPE_PATH@0..5
885 IDENT@0..5 "Adder"
886 AT@5..6 "@"
887 L_PAREN@6..7 "("
888 LITERAL_IDENT@7..12
889 IDENT_LIT@7..12 "'foo'"
890 R_PAREN@12..13 ")"
891 COLON_COLON@13..15 "::"
892 IDENT@15..18 "sum"
893 L_PAREN@18..19 "("
894 PATH_EXPR@19..20
895 IDENT@19..20 "x"
896 COMMA@20..21 ","
897 WHITESPACE@21..22 " "
898 PATH_EXPR@22..23
899 IDENT@22..23 "y"
900 R_PAREN@23..24 ")"
901 "#]]);
902 }
903
904 #[test]
905 fn parse_expr_dynamic_call_with_network() {
906 check_expr("Adder@('foo', 'aleo')::sum(x, y)", expect![[r#"
907 ROOT@0..32
908 DYNAMIC_CALL_EXPR@0..32
909 TYPE_PATH@0..5
910 IDENT@0..5 "Adder"
911 AT@5..6 "@"
912 L_PAREN@6..7 "("
913 LITERAL_IDENT@7..12
914 IDENT_LIT@7..12 "'foo'"
915 COMMA@12..13 ","
916 WHITESPACE@13..14 " "
917 LITERAL_IDENT@14..20
918 IDENT_LIT@14..20 "'aleo'"
919 R_PAREN@20..21 ")"
920 COLON_COLON@21..23 "::"
921 IDENT@23..26 "sum"
922 L_PAREN@26..27 "("
923 PATH_EXPR@27..28
924 IDENT@27..28 "x"
925 COMMA@28..29 ","
926 WHITESPACE@29..30 " "
927 PATH_EXPR@30..31
928 IDENT@30..31 "y"
929 R_PAREN@31..32 ")"
930 "#]]);
931 }
932
933 #[test]
934 fn parse_expr_dynamic_call_no_args() {
935 check_expr("Adder@(target)::sum()", expect![[r#"
936 ROOT@0..21
937 DYNAMIC_CALL_EXPR@0..21
938 TYPE_PATH@0..5
939 IDENT@0..5 "Adder"
940 AT@5..6 "@"
941 L_PAREN@6..7 "("
942 PATH_EXPR@7..13
943 IDENT@7..13 "target"
944 R_PAREN@13..14 ")"
945 COLON_COLON@14..16 "::"
946 IDENT@16..19 "sum"
947 L_PAREN@19..20 "("
948 R_PAREN@20..21 ")"
949 "#]]);
950 }
951
952 #[test]
957 fn parse_expr_ident() {
958 check_expr("foo", expect![[r#"
959 ROOT@0..3
960 PATH_EXPR@0..3
961 IDENT@0..3 "foo"
962 "#]]);
963 }
964
965 #[test]
966 fn parse_expr_path() {
967 check_expr("Foo::bar", expect![[r#"
968 ROOT@0..8
969 PATH_EXPR@0..8
970 IDENT@0..3 "Foo"
971 COLON_COLON@3..5 "::"
972 IDENT@5..8 "bar"
973 "#]]);
974 }
975
976 #[test]
977 fn parse_expr_self() {
978 check_expr("self", expect![[r#"
979 ROOT@0..4
980 SELF_EXPR@0..4
981 KW_SELF@0..4 "self"
982 "#]]);
983 }
984
985 #[test]
986 fn parse_expr_self_colon_colon_is_error() {
987 let (tokens, _) = lex("self::y");
989 let mut parser = Parser::new("self::y", &tokens);
990 let root = parser.start();
991 parser.parse_expr();
992 parser.skip_trivia();
993 root.complete(&mut parser, ROOT);
994 let parse: Parse = parser.finish(vec![]);
995 assert!(!parse.errors().is_empty(), "expected error for self::");
996 assert!(
997 parse.errors().iter().any(|e| e.message.contains("expected '.'")),
998 "expected error message to mention expected '.', got: {:?}",
999 parse.errors()
1000 );
1001 }
1002
1003 #[test]
1008 fn parse_expr_add() {
1009 check_expr("1 + 2", expect![[r#"
1010 ROOT@0..5
1011 BINARY_EXPR@0..5
1012 LITERAL_INT@0..1
1013 INTEGER@0..1 "1"
1014 WHITESPACE@1..2 " "
1015 PLUS@2..3 "+"
1016 WHITESPACE@3..4 " "
1017 LITERAL_INT@4..5
1018 INTEGER@4..5 "2"
1019 "#]]);
1020 }
1021
1022 #[test]
1023 fn parse_expr_mul() {
1024 check_expr("a * b", expect![[r#"
1025 ROOT@0..5
1026 BINARY_EXPR@0..5
1027 PATH_EXPR@0..2
1028 IDENT@0..1 "a"
1029 WHITESPACE@1..2 " "
1030 STAR@2..3 "*"
1031 WHITESPACE@3..4 " "
1032 PATH_EXPR@4..5
1033 IDENT@4..5 "b"
1034 "#]]);
1035 }
1036
1037 #[test]
1038 fn parse_expr_precedence() {
1039 check_expr("1 + 2 * 3", expect![[r#"
1041 ROOT@0..9
1042 BINARY_EXPR@0..9
1043 LITERAL_INT@0..1
1044 INTEGER@0..1 "1"
1045 WHITESPACE@1..2 " "
1046 PLUS@2..3 "+"
1047 WHITESPACE@3..4 " "
1048 BINARY_EXPR@4..9
1049 LITERAL_INT@4..5
1050 INTEGER@4..5 "2"
1051 WHITESPACE@5..6 " "
1052 STAR@6..7 "*"
1053 WHITESPACE@7..8 " "
1054 LITERAL_INT@8..9
1055 INTEGER@8..9 "3"
1056 "#]]);
1057 }
1058
1059 #[test]
1060 fn parse_expr_power_right_assoc() {
1061 check_expr("a ** b ** c", expect![[r#"
1063 ROOT@0..11
1064 BINARY_EXPR@0..11
1065 PATH_EXPR@0..2
1066 IDENT@0..1 "a"
1067 WHITESPACE@1..2 " "
1068 STAR2@2..4 "**"
1069 WHITESPACE@4..5 " "
1070 BINARY_EXPR@5..11
1071 PATH_EXPR@5..7
1072 IDENT@5..6 "b"
1073 WHITESPACE@6..7 " "
1074 STAR2@7..9 "**"
1075 WHITESPACE@9..10 " "
1076 PATH_EXPR@10..11
1077 IDENT@10..11 "c"
1078 "#]]);
1079 }
1080
1081 #[test]
1086 fn parse_expr_unary_neg() {
1087 check_expr("-x", expect![[r#"
1088 ROOT@0..2
1089 UNARY_EXPR@0..2
1090 MINUS@0..1 "-"
1091 PATH_EXPR@1..2
1092 IDENT@1..2 "x"
1093 "#]]);
1094 }
1095
1096 #[test]
1097 fn parse_expr_unary_not() {
1098 check_expr("!flag", expect![[r#"
1099 ROOT@0..5
1100 UNARY_EXPR@0..5
1101 BANG@0..1 "!"
1102 PATH_EXPR@1..5
1103 IDENT@1..5 "flag"
1104 "#]]);
1105 }
1106
1107 #[test]
1112 fn parse_expr_comparison() {
1113 check_expr("a < b", expect![[r#"
1114 ROOT@0..5
1115 BINARY_EXPR@0..5
1116 PATH_EXPR@0..2
1117 IDENT@0..1 "a"
1118 WHITESPACE@1..2 " "
1119 LT@2..3 "<"
1120 WHITESPACE@3..4 " "
1121 PATH_EXPR@4..5
1122 IDENT@4..5 "b"
1123 "#]]);
1124 }
1125
1126 #[test]
1127 fn parse_expr_logical_and() {
1128 check_expr("a && b", expect![[r#"
1129 ROOT@0..6
1130 BINARY_EXPR@0..6
1131 PATH_EXPR@0..2
1132 IDENT@0..1 "a"
1133 WHITESPACE@1..2 " "
1134 AMP2@2..4 "&&"
1135 WHITESPACE@4..5 " "
1136 PATH_EXPR@5..6
1137 IDENT@5..6 "b"
1138 "#]]);
1139 }
1140
1141 #[test]
1142 fn parse_expr_logical_or() {
1143 check_expr("a || b", expect![[r#"
1144 ROOT@0..6
1145 BINARY_EXPR@0..6
1146 PATH_EXPR@0..2
1147 IDENT@0..1 "a"
1148 WHITESPACE@1..2 " "
1149 PIPE2@2..4 "||"
1150 WHITESPACE@4..5 " "
1151 PATH_EXPR@5..6
1152 IDENT@5..6 "b"
1153 "#]]);
1154 }
1155
1156 #[test]
1161 fn parse_expr_ternary() {
1162 check_expr("a ? b : c", expect![[r#"
1163 ROOT@0..9
1164 TERNARY_EXPR@0..9
1165 PATH_EXPR@0..2
1166 IDENT@0..1 "a"
1167 WHITESPACE@1..2 " "
1168 QUESTION@2..3 "?"
1169 WHITESPACE@3..4 " "
1170 PATH_EXPR@4..6
1171 IDENT@4..5 "b"
1172 WHITESPACE@5..6 " "
1173 COLON@6..7 ":"
1174 WHITESPACE@7..8 " "
1175 PATH_EXPR@8..9
1176 IDENT@8..9 "c"
1177 "#]]);
1178 }
1179
1180 #[test]
1185 fn parse_expr_member_access() {
1186 check_expr("foo.bar", expect![[r#"
1187 ROOT@0..7
1188 FIELD_EXPR@0..7
1189 PATH_EXPR@0..3
1190 IDENT@0..3 "foo"
1191 DOT@3..4 "."
1192 IDENT@4..7 "bar"
1193 "#]]);
1194 }
1195
1196 #[test]
1197 fn parse_expr_tuple_access() {
1198 check_expr("tuple.0", expect![[r#"
1199 ROOT@0..7
1200 TUPLE_ACCESS_EXPR@0..7
1201 PATH_EXPR@0..5
1202 IDENT@0..5 "tuple"
1203 DOT@5..6 "."
1204 INTEGER@6..7 "0"
1205 "#]]);
1206 }
1207
1208 #[test]
1209 fn parse_expr_index() {
1210 check_expr("arr[0]", expect![[r#"
1211 ROOT@0..6
1212 INDEX_EXPR@0..6
1213 PATH_EXPR@0..3
1214 IDENT@0..3 "arr"
1215 L_BRACKET@3..4 "["
1216 LITERAL_INT@4..5
1217 INTEGER@4..5 "0"
1218 R_BRACKET@5..6 "]"
1219 "#]]);
1220 }
1221
1222 #[test]
1223 fn parse_expr_call() {
1224 check_expr("foo(a, b)", expect![[r#"
1225 ROOT@0..9
1226 CALL_EXPR@0..9
1227 PATH_EXPR@0..3
1228 IDENT@0..3 "foo"
1229 L_PAREN@3..4 "("
1230 PATH_EXPR@4..5
1231 IDENT@4..5 "a"
1232 COMMA@5..6 ","
1233 WHITESPACE@6..7 " "
1234 PATH_EXPR@7..8
1235 IDENT@7..8 "b"
1236 R_PAREN@8..9 ")"
1237 "#]]);
1238 }
1239
1240 #[test]
1241 fn parse_expr_method_call() {
1242 check_expr("x.foo()", expect![[r#"
1243 ROOT@0..7
1244 METHOD_CALL_EXPR@0..7
1245 PATH_EXPR@0..1
1246 IDENT@0..1 "x"
1247 DOT@1..2 "."
1248 IDENT@2..5 "foo"
1249 L_PAREN@5..6 "("
1250 R_PAREN@6..7 ")"
1251 "#]]);
1252 }
1253
1254 #[test]
1259 fn parse_expr_cast() {
1260 check_expr("x as u64", expect![[r#"
1261 ROOT@0..8
1262 CAST_EXPR@0..8
1263 PATH_EXPR@0..2
1264 IDENT@0..1 "x"
1265 WHITESPACE@1..2 " "
1266 KW_AS@2..4 "as"
1267 WHITESPACE@4..5 " "
1268 TYPE_PRIMITIVE@5..8
1269 KW_U64@5..8 "u64"
1270 "#]]);
1271 }
1272
1273 #[test]
1278 fn parse_expr_paren() {
1279 check_expr("(a + b)", expect![[r#"
1280 ROOT@0..7
1281 PAREN_EXPR@0..7
1282 L_PAREN@0..1 "("
1283 BINARY_EXPR@1..6
1284 PATH_EXPR@1..3
1285 IDENT@1..2 "a"
1286 WHITESPACE@2..3 " "
1287 PLUS@3..4 "+"
1288 WHITESPACE@4..5 " "
1289 PATH_EXPR@5..6
1290 IDENT@5..6 "b"
1291 R_PAREN@6..7 ")"
1292 "#]]);
1293 }
1294
1295 #[test]
1296 fn parse_expr_tuple() {
1297 check_expr("(a, b)", expect![[r#"
1298 ROOT@0..6
1299 TUPLE_EXPR@0..6
1300 L_PAREN@0..1 "("
1301 PATH_EXPR@1..2
1302 IDENT@1..2 "a"
1303 COMMA@2..3 ","
1304 WHITESPACE@3..4 " "
1305 PATH_EXPR@4..5
1306 IDENT@4..5 "b"
1307 R_PAREN@5..6 ")"
1308 "#]]);
1309 }
1310
1311 #[test]
1312 fn parse_expr_unit() {
1313 check_expr("()", expect![[r#"
1314 ROOT@0..2
1315 TUPLE_EXPR@0..2
1316 L_PAREN@0..1 "("
1317 R_PAREN@1..2 ")"
1318 "#]]);
1319 }
1320
1321 #[test]
1326 fn parse_expr_array() {
1327 check_expr("[1, 2, 3]", expect![[r#"
1328 ROOT@0..9
1329 ARRAY_EXPR@0..9
1330 L_BRACKET@0..1 "["
1331 LITERAL_INT@1..2
1332 INTEGER@1..2 "1"
1333 COMMA@2..3 ","
1334 WHITESPACE@3..4 " "
1335 LITERAL_INT@4..5
1336 INTEGER@4..5 "2"
1337 COMMA@5..6 ","
1338 WHITESPACE@6..7 " "
1339 LITERAL_INT@7..8
1340 INTEGER@7..8 "3"
1341 R_BRACKET@8..9 "]"
1342 "#]]);
1343 }
1344
1345 #[test]
1346 fn parse_expr_array_repeat() {
1347 check_expr("[0; 10]", expect![[r#"
1348 ROOT@0..7
1349 REPEAT_EXPR@0..7
1350 L_BRACKET@0..1 "["
1351 LITERAL_INT@1..2
1352 INTEGER@1..2 "0"
1353 SEMICOLON@2..3 ";"
1354 WHITESPACE@3..4 " "
1355 LITERAL_INT@4..6
1356 INTEGER@4..6 "10"
1357 R_BRACKET@6..7 "]"
1358 "#]]);
1359 }
1360
1361 #[test]
1366 fn parse_expr_struct_init() {
1367 check_expr("Point { x: 1, y: 2 }", expect![[r#"
1368 ROOT@0..20
1369 STRUCT_EXPR@0..20
1370 IDENT@0..5 "Point"
1371 WHITESPACE@5..6 " "
1372 L_BRACE@6..7 "{"
1373 STRUCT_FIELD_INIT@7..12
1374 WHITESPACE@7..8 " "
1375 IDENT@8..9 "x"
1376 COLON@9..10 ":"
1377 WHITESPACE@10..11 " "
1378 LITERAL_INT@11..12
1379 INTEGER@11..12 "1"
1380 COMMA@12..13 ","
1381 STRUCT_FIELD_INIT@13..18
1382 WHITESPACE@13..14 " "
1383 IDENT@14..15 "y"
1384 COLON@15..16 ":"
1385 WHITESPACE@16..17 " "
1386 LITERAL_INT@17..18
1387 INTEGER@17..18 "2"
1388 WHITESPACE@18..19 " "
1389 R_BRACE@19..20 "}"
1390 "#]]);
1391 }
1392
1393 #[test]
1394 fn parse_expr_struct_shorthand() {
1395 check_expr("Point { x, y }", expect![[r#"
1396 ROOT@0..14
1397 STRUCT_EXPR@0..14
1398 IDENT@0..5 "Point"
1399 WHITESPACE@5..6 " "
1400 L_BRACE@6..7 "{"
1401 STRUCT_FIELD_SHORTHAND@7..9
1402 WHITESPACE@7..8 " "
1403 IDENT@8..9 "x"
1404 COMMA@9..10 ","
1405 STRUCT_FIELD_SHORTHAND@10..13
1406 WHITESPACE@10..11 " "
1407 IDENT@11..12 "y"
1408 WHITESPACE@12..13 " "
1409 R_BRACE@13..14 "}"
1410 "#]]);
1411 }
1412
1413 fn check_expr_no_errors(input: &str) {
1422 let (tokens, _) = lex(input);
1423 let mut parser = Parser::new(input, &tokens);
1424 let root = parser.start();
1425 parser.parse_expr();
1426 parser.skip_trivia();
1427 root.complete(&mut parser, ROOT);
1428 let parse: Parse = parser.finish(vec![]);
1429 if !parse.errors().is_empty() {
1430 for err in parse.errors() {
1431 eprintln!("error at {:?}: {}", err.range, err.message);
1432 }
1433 eprintln!("tree:\n{:#?}", parse.syntax());
1434 panic!("expression parse had {} error(s)", parse.errors().len());
1435 }
1436 }
1437
1438 #[test]
1439 fn parse_expr_call_const_generic_simple() {
1440 check_expr("foo::[5]()", expect![[r#"
1442 ROOT@0..10
1443 CALL_EXPR@0..10
1444 PATH_EXPR@0..8
1445 IDENT@0..3 "foo"
1446 COLON_COLON@3..5 "::"
1447 CONST_ARG_LIST@5..8
1448 L_BRACKET@5..6 "["
1449 LITERAL_INT@6..7
1450 INTEGER@6..7 "5"
1451 R_BRACKET@7..8 "]"
1452 L_PAREN@8..9 "("
1453 R_PAREN@9..10 ")"
1454 "#]]);
1455 }
1456
1457 #[test]
1458 fn parse_expr_call_const_generic_expr() {
1459 check_expr_no_errors("foo::[N + 1]()");
1461 }
1462
1463 #[test]
1464 fn parse_expr_call_const_generic_multi() {
1465 check_expr_no_errors("bar::[M, K, N]()");
1467 }
1468
1469 #[test]
1470 fn parse_expr_struct_lit_const_generic() {
1471 check_expr("Foo::[8u32] { arr: x }", expect![[r#"
1473 ROOT@0..22
1474 STRUCT_EXPR@0..22
1475 IDENT@0..3 "Foo"
1476 COLON_COLON@3..5 "::"
1477 CONST_ARG_LIST@5..11
1478 L_BRACKET@5..6 "["
1479 LITERAL_INT@6..10
1480 INTEGER@6..10 "8u32"
1481 R_BRACKET@10..11 "]"
1482 WHITESPACE@11..12 " "
1483 L_BRACE@12..13 "{"
1484 STRUCT_FIELD_INIT@13..21
1485 WHITESPACE@13..14 " "
1486 IDENT@14..17 "arr"
1487 COLON@17..18 ":"
1488 WHITESPACE@18..19 " "
1489 PATH_EXPR@19..21
1490 IDENT@19..20 "x"
1491 WHITESPACE@20..21 " "
1492 R_BRACE@21..22 "}"
1493 "#]]);
1494 }
1495
1496 #[test]
1497 fn parse_expr_locator_call_const_generic() {
1498 check_expr_no_errors("child.aleo::foo::[3]()");
1500 }
1501
1502 #[test]
1503 fn parse_expr_assoc_fn_const_generic() {
1504 check_expr_no_errors("Foo::bar::[N]()");
1506 }
1507
1508 #[test]
1513 fn parse_expr_complex() {
1514 check_expr("a.b[c](d) + e", expect![[r#"
1515 ROOT@0..13
1516 BINARY_EXPR@0..13
1517 CALL_EXPR@0..9
1518 INDEX_EXPR@0..6
1519 FIELD_EXPR@0..3
1520 PATH_EXPR@0..1
1521 IDENT@0..1 "a"
1522 DOT@1..2 "."
1523 IDENT@2..3 "b"
1524 L_BRACKET@3..4 "["
1525 PATH_EXPR@4..5
1526 IDENT@4..5 "c"
1527 R_BRACKET@5..6 "]"
1528 L_PAREN@6..7 "("
1529 PATH_EXPR@7..8
1530 IDENT@7..8 "d"
1531 R_PAREN@8..9 ")"
1532 WHITESPACE@9..10 " "
1533 PLUS@10..11 "+"
1534 WHITESPACE@11..12 " "
1535 PATH_EXPR@12..13
1536 IDENT@12..13 "e"
1537 "#]]);
1538 }
1539
1540 fn parse_expr_for_test(input: &str) -> Parse {
1545 let (tokens, _) = lex(input);
1546 let mut parser = Parser::new(input, &tokens);
1547 let root = parser.start();
1548 parser.parse_expr();
1549 parser.skip_trivia();
1550 root.complete(&mut parser, ROOT);
1551 parser.finish(vec![])
1552 }
1553
1554 #[test]
1555 fn parse_expr_chained_eq_is_error() {
1556 let parse = parse_expr_for_test("1 == 2 == 3");
1558 assert!(!parse.errors().is_empty(), "expected error for chained ==, got none");
1559 assert!(
1560 parse.errors().iter().any(|e| e.message.contains("'&&'") || e.message.contains("expected")),
1561 "expected error message about valid operators, got: {:?}",
1562 parse.errors()
1563 );
1564 }
1565
1566 #[test]
1567 fn parse_expr_chained_neq_is_error() {
1568 let parse = parse_expr_for_test("1 != 2 != 3");
1570 assert!(!parse.errors().is_empty(), "expected error for chained !=, got none");
1571 }
1572
1573 #[test]
1574 fn parse_expr_chained_lt_is_error() {
1575 let parse = parse_expr_for_test("1 < 2 < 3");
1577 assert!(!parse.errors().is_empty(), "expected error for chained <, got none");
1578 }
1579
1580 #[test]
1581 fn parse_expr_chained_gt_is_error() {
1582 let parse = parse_expr_for_test("1 > 2 > 3");
1584 assert!(!parse.errors().is_empty(), "expected error for chained >, got none");
1585 }
1586
1587 #[test]
1588 fn parse_expr_comparison_with_logical_is_ok() {
1589 check_expr_no_errors("1 == 2 && 3 == 4");
1591 check_expr_no_errors("1 < 2 || 3 > 4");
1592 }
1593
1594 #[test]
1599 fn parse_expr_group_associated_fn() {
1600 check_expr("group::to_x_coordinate(a)", expect![[r#"
1603 ROOT@0..25
1604 CALL_EXPR@0..25
1605 PATH_EXPR@0..22
1606 IDENT@0..22 "group::to_x_coordinate"
1607 L_PAREN@22..23 "("
1608 PATH_EXPR@23..24
1609 IDENT@23..24 "a"
1610 R_PAREN@24..25 ")"
1611 "#]]);
1612 }
1613
1614 #[test]
1615 fn parse_expr_signature_associated_fn() {
1616 check_expr("signature::verify(s, a, v)", expect![[r#"
1619 ROOT@0..26
1620 CALL_EXPR@0..26
1621 PATH_EXPR@0..17
1622 IDENT@0..17 "signature::verify"
1623 L_PAREN@17..18 "("
1624 PATH_EXPR@18..19
1625 IDENT@18..19 "s"
1626 COMMA@19..20 ","
1627 WHITESPACE@20..21 " "
1628 PATH_EXPR@21..22
1629 IDENT@21..22 "a"
1630 COMMA@22..23 ","
1631 WHITESPACE@23..24 " "
1632 PATH_EXPR@24..25
1633 IDENT@24..25 "v"
1634 R_PAREN@25..26 ")"
1635 "#]]);
1636 }
1637
1638 #[test]
1643 fn parse_expr_chained_le_is_error() {
1644 let parse = parse_expr_for_test("1 <= 2 <= 3");
1645 assert!(!parse.errors().is_empty(), "expected error for chained <=, got none");
1646 }
1647
1648 #[test]
1649 fn parse_expr_chained_ge_is_error() {
1650 let parse = parse_expr_for_test("1 >= 2 >= 3");
1651 assert!(!parse.errors().is_empty(), "expected error for chained >=, got none");
1652 }
1653
1654 #[test]
1655 fn parse_expr_chained_mixed_cmp_is_error() {
1656 let parse = parse_expr_for_test("1 < 2 > 3");
1657 assert!(!parse.errors().is_empty(), "expected error for mixed chained comparisons, got none");
1658 }
1659
1660 #[test]
1665 fn parse_expr_ternary_nested() {
1666 check_expr("a ? b ? c : d : e", expect![[r#"
1667 ROOT@0..17
1668 TERNARY_EXPR@0..17
1669 PATH_EXPR@0..2
1670 IDENT@0..1 "a"
1671 WHITESPACE@1..2 " "
1672 QUESTION@2..3 "?"
1673 WHITESPACE@3..4 " "
1674 TERNARY_EXPR@4..14
1675 PATH_EXPR@4..6
1676 IDENT@4..5 "b"
1677 WHITESPACE@5..6 " "
1678 QUESTION@6..7 "?"
1679 WHITESPACE@7..8 " "
1680 PATH_EXPR@8..10
1681 IDENT@8..9 "c"
1682 WHITESPACE@9..10 " "
1683 COLON@10..11 ":"
1684 WHITESPACE@11..12 " "
1685 PATH_EXPR@12..14
1686 IDENT@12..13 "d"
1687 WHITESPACE@13..14 " "
1688 COLON@14..15 ":"
1689 WHITESPACE@15..16 " "
1690 PATH_EXPR@16..17
1691 IDENT@16..17 "e"
1692 "#]]);
1693 }
1694
1695 #[test]
1700 fn parse_expr_cast_chained() {
1701 check_expr("x as u32 as u64", expect![[r#"
1702 ROOT@0..15
1703 CAST_EXPR@0..15
1704 CAST_EXPR@0..8
1705 PATH_EXPR@0..2
1706 IDENT@0..1 "x"
1707 WHITESPACE@1..2 " "
1708 KW_AS@2..4 "as"
1709 WHITESPACE@4..5 " "
1710 TYPE_PRIMITIVE@5..8
1711 KW_U32@5..8 "u32"
1712 WHITESPACE@8..9 " "
1713 KW_AS@9..11 "as"
1714 WHITESPACE@11..12 " "
1715 TYPE_PRIMITIVE@12..15
1716 KW_U64@12..15 "u64"
1717 "#]]);
1718 }
1719
1720 #[test]
1725 fn parse_expr_array_trailing_comma() {
1726 check_expr("[1, 2, 3,]", expect![[r#"
1727 ROOT@0..10
1728 ARRAY_EXPR@0..10
1729 L_BRACKET@0..1 "["
1730 LITERAL_INT@1..2
1731 INTEGER@1..2 "1"
1732 COMMA@2..3 ","
1733 WHITESPACE@3..4 " "
1734 LITERAL_INT@4..5
1735 INTEGER@4..5 "2"
1736 COMMA@5..6 ","
1737 WHITESPACE@6..7 " "
1738 LITERAL_INT@7..8
1739 INTEGER@7..8 "3"
1740 COMMA@8..9 ","
1741 R_BRACKET@9..10 "]"
1742 "#]]);
1743 }
1744
1745 #[test]
1746 fn parse_expr_array_empty() {
1747 check_expr("[]", expect![[r#"
1748 ROOT@0..2
1749 ARRAY_EXPR@0..2
1750 L_BRACKET@0..1 "["
1751 R_BRACKET@1..2 "]"
1752 "#]]);
1753 }
1754
1755 #[test]
1756 fn parse_expr_tuple_single() {
1757 check_expr("(a,)", expect![[r#"
1758 ROOT@0..4
1759 TUPLE_EXPR@0..4
1760 L_PAREN@0..1 "("
1761 PATH_EXPR@1..2
1762 IDENT@1..2 "a"
1763 COMMA@2..3 ","
1764 R_PAREN@3..4 ")"
1765 "#]]);
1766 }
1767
1768 #[test]
1769 fn parse_expr_tuple_trailing_comma() {
1770 check_expr("(1, 2,)", expect![[r#"
1771 ROOT@0..7
1772 TUPLE_EXPR@0..7
1773 L_PAREN@0..1 "("
1774 LITERAL_INT@1..2
1775 INTEGER@1..2 "1"
1776 COMMA@2..3 ","
1777 WHITESPACE@3..4 " "
1778 LITERAL_INT@4..5
1779 INTEGER@4..5 "2"
1780 COMMA@5..6 ","
1781 R_PAREN@6..7 ")"
1782 "#]]);
1783 }
1784
1785 #[test]
1790 fn parse_expr_struct_empty() {
1791 check_expr("Point { }", expect![[r#"
1792 ROOT@0..9
1793 STRUCT_EXPR@0..9
1794 IDENT@0..5 "Point"
1795 WHITESPACE@5..6 " "
1796 L_BRACE@6..7 "{"
1797 WHITESPACE@7..8 " "
1798 R_BRACE@8..9 "}"
1799 "#]]);
1800 }
1801
1802 #[test]
1803 fn parse_expr_struct_trailing_comma() {
1804 check_expr("Point { x: 1, }", expect![[r#"
1805 ROOT@0..15
1806 STRUCT_EXPR@0..15
1807 IDENT@0..5 "Point"
1808 WHITESPACE@5..6 " "
1809 L_BRACE@6..7 "{"
1810 STRUCT_FIELD_INIT@7..12
1811 WHITESPACE@7..8 " "
1812 IDENT@8..9 "x"
1813 COLON@9..10 ":"
1814 WHITESPACE@10..11 " "
1815 LITERAL_INT@11..12
1816 INTEGER@11..12 "1"
1817 COMMA@12..13 ","
1818 WHITESPACE@13..14 " "
1819 R_BRACE@14..15 "}"
1820 "#]]);
1821 }
1822
1823 #[test]
1824 fn parse_expr_struct_mixed_fields() {
1825 check_expr("Point { x, y: 2 }", expect![[r#"
1826 ROOT@0..17
1827 STRUCT_EXPR@0..17
1828 IDENT@0..5 "Point"
1829 WHITESPACE@5..6 " "
1830 L_BRACE@6..7 "{"
1831 STRUCT_FIELD_SHORTHAND@7..9
1832 WHITESPACE@7..8 " "
1833 IDENT@8..9 "x"
1834 COMMA@9..10 ","
1835 STRUCT_FIELD_INIT@10..15
1836 WHITESPACE@10..11 " "
1837 IDENT@11..12 "y"
1838 COLON@12..13 ":"
1839 WHITESPACE@13..14 " "
1840 LITERAL_INT@14..15
1841 INTEGER@14..15 "2"
1842 WHITESPACE@15..16 " "
1843 R_BRACE@16..17 "}"
1844 "#]]);
1845 }
1846
1847 #[test]
1852 fn parse_expr_string() {
1853 check_expr("\"hello\"", expect![[r#"
1854 ROOT@0..7
1855 LITERAL_STRING@0..7
1856 STRING@0..7 "\"hello\""
1857 "#]]);
1858 }
1859
1860 #[test]
1861 fn parse_expr_address() {
1862 check_expr("aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9", expect![[r#"
1863 ROOT@0..63
1864 LITERAL_ADDRESS@0..63
1865 ADDRESS_LIT@0..63 "aleo1qnr4dkkvkgfqph0v ..."
1866 "#]]);
1867 }
1868
1869 #[test]
1874 fn parse_expr_deep_postfix() {
1875 check_expr("a[0].b.c(x)[1]", expect![[r#"
1876 ROOT@0..14
1877 INDEX_EXPR@0..14
1878 METHOD_CALL_EXPR@0..11
1879 FIELD_EXPR@0..6
1880 INDEX_EXPR@0..4
1881 PATH_EXPR@0..1
1882 IDENT@0..1 "a"
1883 L_BRACKET@1..2 "["
1884 LITERAL_INT@2..3
1885 INTEGER@2..3 "0"
1886 R_BRACKET@3..4 "]"
1887 DOT@4..5 "."
1888 IDENT@5..6 "b"
1889 DOT@6..7 "."
1890 IDENT@7..8 "c"
1891 L_PAREN@8..9 "("
1892 PATH_EXPR@9..10
1893 IDENT@9..10 "x"
1894 R_PAREN@10..11 ")"
1895 L_BRACKET@11..12 "["
1896 LITERAL_INT@12..13
1897 INTEGER@12..13 "1"
1898 R_BRACKET@13..14 "]"
1899 "#]]);
1900 }
1901
1902 #[test]
1907 fn parse_expr_final() {
1908 check_expr("final { foo() }", expect![[r#"
1909 ROOT@0..15
1910 FINAL_EXPR@0..15
1911 KW_FINAL@0..5 "final"
1912 WHITESPACE@5..6 " "
1913 BLOCK@6..15
1914 L_BRACE@6..7 "{"
1915 WHITESPACE@7..8 " "
1916 EXPR_STMT@8..14
1917 CALL_EXPR@8..13
1918 PATH_EXPR@8..11
1919 IDENT@8..11 "foo"
1920 L_PAREN@11..12 "("
1921 R_PAREN@12..13 ")"
1922 WHITESPACE@13..14 " "
1923 ERROR@14..14
1924 R_BRACE@14..15 "}"
1925 "#]]);
1926 }
1927
1928 #[test]
1933 fn parse_expr_mixed_arithmetic() {
1934 check_expr("a + b * c / d - e", expect![[r#"
1936 ROOT@0..17
1937 BINARY_EXPR@0..17
1938 BINARY_EXPR@0..14
1939 PATH_EXPR@0..2
1940 IDENT@0..1 "a"
1941 WHITESPACE@1..2 " "
1942 PLUS@2..3 "+"
1943 WHITESPACE@3..4 " "
1944 BINARY_EXPR@4..14
1945 BINARY_EXPR@4..10
1946 PATH_EXPR@4..6
1947 IDENT@4..5 "b"
1948 WHITESPACE@5..6 " "
1949 STAR@6..7 "*"
1950 WHITESPACE@7..8 " "
1951 PATH_EXPR@8..10
1952 IDENT@8..9 "c"
1953 WHITESPACE@9..10 " "
1954 SLASH@10..11 "/"
1955 WHITESPACE@11..12 " "
1956 PATH_EXPR@12..14
1957 IDENT@12..13 "d"
1958 WHITESPACE@13..14 " "
1959 MINUS@14..15 "-"
1960 WHITESPACE@15..16 " "
1961 PATH_EXPR@16..17
1962 IDENT@16..17 "e"
1963 "#]]);
1964 }
1965
1966 #[test]
1967 fn parse_expr_bitwise_precedence() {
1968 check_expr("a | b & c ^ d", expect![[r#"
1972 ROOT@0..13
1973 BINARY_EXPR@0..13
1974 PATH_EXPR@0..2
1975 IDENT@0..1 "a"
1976 WHITESPACE@1..2 " "
1977 PIPE@2..3 "|"
1978 WHITESPACE@3..4 " "
1979 BINARY_EXPR@4..13
1980 BINARY_EXPR@4..10
1981 PATH_EXPR@4..6
1982 IDENT@4..5 "b"
1983 WHITESPACE@5..6 " "
1984 AMP@6..7 "&"
1985 WHITESPACE@7..8 " "
1986 PATH_EXPR@8..10
1987 IDENT@8..9 "c"
1988 WHITESPACE@9..10 " "
1989 CARET@10..11 "^"
1990 WHITESPACE@11..12 " "
1991 PATH_EXPR@12..13
1992 IDENT@12..13 "d"
1993 "#]]);
1994 }
1995
1996 #[test]
1997 fn parse_expr_shift_chain() {
1998 check_expr("x << 1 >> 2", expect![[r#"
2001 ROOT@0..11
2002 BINARY_EXPR@0..11
2003 BINARY_EXPR@0..6
2004 PATH_EXPR@0..2
2005 IDENT@0..1 "x"
2006 WHITESPACE@1..2 " "
2007 SHL@2..4 "<<"
2008 WHITESPACE@4..5 " "
2009 LITERAL_INT@5..6
2010 INTEGER@5..6 "1"
2011 WHITESPACE@6..7 " "
2012 SHR@7..9 ">>"
2013 WHITESPACE@9..10 " "
2014 LITERAL_INT@10..11
2015 INTEGER@10..11 "2"
2016 "#]]);
2017 }
2018}