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_op_expr(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
365 let m = lhs.precede(self);
366
367 self.bump_any(); self.expect(L_PAREN);
369 self.parse_expr(); if self.eat(COMMA) {
372 self.parse_expr(); }
374 self.expect(R_PAREN);
375 self.expect(COLON_COLON);
376 self.expect(IDENT); if !self.at(DOT) && !self.at(L_PAREN) {
380 return Some(m.complete(self, DYNAMIC_OP_EXPR));
381 }
382
383 if self.at(DOT) {
385 self.bump_any(); if self.at(IDENT) {
387 self.bump_any(); }
389 }
390 self.expect(L_PAREN);
392 if !self.at(R_PAREN) {
393 self.parse_expr();
394 while self.eat(COMMA) {
395 if self.at(R_PAREN) {
396 break;
397 }
398 self.parse_expr();
399 }
400 }
401 self.expect(R_PAREN);
402 Some(m.complete(self, DYNAMIC_OP_EXPR))
403 }
404
405 fn parse_call_expr(&mut self, lhs: CompletedMarker) -> Option<CompletedMarker> {
407 let m = lhs.precede(self);
408 self.bump_any(); if !self.at(R_PAREN) {
412 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
413 self.error_recover("expected argument expression", EXPR_RECOVERY);
415 }
416 while self.eat(COMMA) {
417 if self.at(R_PAREN) {
418 break;
419 }
420 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
421 self.error_recover("expected argument expression", EXPR_RECOVERY);
422 }
423 }
424 }
425
426 self.expect(R_PAREN);
427
428 Some(m.complete(self, CALL_EXPR))
429 }
430
431 fn parse_primary_expr(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
437 self.skip_trivia();
438
439 match self.current() {
440 INTEGER => self.parse_integer_literal(),
442 STRING => self.parse_string_literal(),
443 ADDRESS_LIT => self.parse_address_literal(),
444 IDENT_LIT => self.parse_identifier_literal(),
445 KW_TRUE | KW_FALSE => self.parse_bool_literal(),
446 KW_NONE => self.parse_none_literal(),
447
448 L_PAREN => self.parse_paren_or_tuple_expr(),
450
451 L_BRACKET => self.parse_array_expr(),
453
454 IDENT | KW_FINAL_UPPER => self.parse_ident_expr(opts),
456
457 KW_SELF => self.parse_self_expr(),
459
460 KW_BLOCK => self.parse_block_access(),
462 KW_NETWORK => self.parse_network_access(),
463
464 KW_FINAL => self.parse_final_block_expr(),
466
467 _ => {
468 self.error_unexpected(self.current(), &[
469 "an identifier",
470 "a program id",
471 "an address literal",
472 "an integer literal",
473 "a static string",
474 "'!'",
475 "'-'",
476 "'('",
477 "'['",
478 "'true'",
479 "'false'",
480 "'final'",
481 "'block'",
482 "'network'",
483 "'self'",
484 ]);
485 None
486 }
487 }
488 }
489
490 fn parse_integer_literal(&mut self) -> Option<CompletedMarker> {
495 let m = self.start();
496 let text = self.current_text();
497 let kind = if text.ends_with("field") {
498 LITERAL_FIELD
499 } else if text.ends_with("group") {
500 LITERAL_GROUP
501 } else if text.ends_with("scalar") {
502 LITERAL_SCALAR
503 } else {
504 LITERAL_INT
505 };
506 self.bump_any();
507 Some(m.complete(self, kind))
508 }
509
510 fn parse_string_literal(&mut self) -> Option<CompletedMarker> {
512 let m = self.start();
513 self.bump_any();
514 Some(m.complete(self, LITERAL_STRING))
515 }
516
517 fn parse_identifier_literal(&mut self) -> Option<CompletedMarker> {
519 let m = self.start();
520 self.bump_any();
521 Some(m.complete(self, LITERAL_IDENT))
522 }
523
524 fn parse_address_literal(&mut self) -> Option<CompletedMarker> {
526 let m = self.start();
527 self.bump_any();
528 Some(m.complete(self, LITERAL_ADDRESS))
529 }
530
531 fn parse_bool_literal(&mut self) -> Option<CompletedMarker> {
533 let m = self.start();
534 self.bump_any();
535 Some(m.complete(self, LITERAL_BOOL))
536 }
537
538 fn parse_none_literal(&mut self) -> Option<CompletedMarker> {
540 let m = self.start();
541 self.bump_any();
542 Some(m.complete(self, LITERAL_NONE))
543 }
544
545 fn parse_paren_or_tuple_expr(&mut self) -> Option<CompletedMarker> {
547 let m = self.start();
548 self.bump_any(); if self.eat(R_PAREN) {
552 return Some(m.complete(self, TUPLE_EXPR));
553 }
554
555 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
557 self.error_recover("expected expression", EXPR_RECOVERY);
558 }
559
560 if self.eat(COMMA) {
562 if !self.at(R_PAREN) {
564 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
565 self.error_recover("expected tuple element", EXPR_RECOVERY);
566 }
567 while self.eat(COMMA) {
568 if self.at(R_PAREN) {
569 break;
570 }
571 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
572 self.error_recover("expected tuple element", EXPR_RECOVERY);
573 }
574 }
575 }
576 self.expect(R_PAREN);
577 return Some(m.complete(self, TUPLE_EXPR));
578 }
579
580 self.expect(R_PAREN);
582 Some(m.complete(self, PAREN_EXPR))
583 }
584
585 fn parse_array_expr(&mut self) -> Option<CompletedMarker> {
587 let m = self.start();
588 self.bump_any(); if self.eat(R_BRACKET) {
592 return Some(m.complete(self, ARRAY_EXPR));
593 }
594
595 if self.parse_expr().is_none() && !self.at(R_BRACKET) && !self.at(COMMA) && !self.at(SEMICOLON) {
597 self.error_recover("expected array element", EXPR_RECOVERY);
598 }
599
600 if self.eat(SEMICOLON) {
602 if self.parse_expr().is_none() && !self.at(R_BRACKET) {
603 self.error("expected repeat count");
604 }
605 self.expect(R_BRACKET);
606 return Some(m.complete(self, REPEAT_EXPR));
607 }
608
609 while self.eat(COMMA) {
611 if self.at(R_BRACKET) {
612 break;
613 }
614 if self.parse_expr().is_none() && !self.at(R_BRACKET) && !self.at(COMMA) {
615 self.error_recover("expected array element", EXPR_RECOVERY);
616 }
617 }
618
619 self.expect(R_BRACKET);
620 Some(m.complete(self, ARRAY_EXPR))
621 }
622
623 fn parse_ident_expr(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
625 let m = self.start();
626 self.bump_any(); if self.at(DOT) && self.nth(1) == KW_ALEO {
630 self.bump_any(); self.bump_any(); let is_locator = if self.eat(COLON_COLON) {
634 if self.at(IDENT) {
636 self.bump_any();
637 while self.at(COLON_COLON) && self.nth(1) == IDENT {
639 self.bump_any(); self.bump_any(); }
642 }
643 true
644 } else {
645 false
646 };
647
648 if self.at(COLON_COLON) && self.nth(1) == L_BRACKET {
650 self.bump_any(); self.parse_const_generic_args_bracket();
652 }
653
654 if !opts.no_struct && self.at(L_BRACE) {
656 self.parse_struct_body();
657 let kind = if is_locator { STRUCT_LOCATOR_EXPR } else { STRUCT_EXPR };
658 return Some(m.complete(self, kind));
659 }
660
661 if self.at(L_PAREN) {
663 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
664 let cm = m.complete(self, kind);
665 return self.parse_call_expr(cm);
666 }
667
668 if self.at(AT) {
670 let cm = m.complete(self, TYPE_LOCATOR);
671 return self.parse_dynamic_op_expr(cm);
672 }
673
674 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
675 return Some(m.complete(self, kind));
676 }
677
678 while self.eat(COLON_COLON) {
680 if self.at(L_BRACKET) {
681 self.parse_const_generic_args_bracket();
683 break;
684 } else if self.at(LT) {
685 self.parse_const_generic_args_angle();
688 break;
689 } else if self.at(IDENT) {
690 self.bump_any();
691 } else {
692 self.error("expected identifier after ::");
693 break;
694 }
695 }
696
697 if !opts.no_struct && self.at(L_BRACE) {
699 self.parse_struct_body();
700 return Some(m.complete(self, STRUCT_EXPR));
701 }
702
703 if self.at(L_PAREN) {
705 let cm = m.complete(self, PATH_EXPR);
706 return self.parse_call_expr(cm);
707 }
708
709 if self.at(AT) {
711 let cm = m.complete(self, TYPE_PATH);
712 return self.parse_dynamic_op_expr(cm);
713 }
714
715 Some(m.complete(self, PATH_EXPR))
716 }
717
718 fn parse_struct_body(&mut self) {
721 self.bump_any(); if !self.at(R_BRACE) {
724 if self.at(DOT_DOT) {
726 self.parse_struct_base_update();
727 } else {
728 self.parse_struct_field();
729 while self.eat(COMMA) {
730 if self.at(R_BRACE) {
731 break;
732 }
733 if self.at(DOT_DOT) {
735 self.parse_struct_base_update();
736 break;
737 }
738 self.parse_struct_field();
739 }
740 }
741
742 if self.at(COMMA) {
745 self.error("the base update `..` must be the last entry in a struct initializer");
746 while self.eat(COMMA) {
747 if self.at(R_BRACE) {
748 break;
749 }
750 if self.at(DOT_DOT) {
751 self.parse_struct_base_update();
752 } else {
753 self.parse_struct_field();
754 }
755 }
756 }
757 }
758
759 self.expect(R_BRACE);
760 }
761
762 fn parse_struct_base_update(&mut self) {
764 let m = self.start();
765 self.bump_any(); if self.at(R_BRACE) {
767 self.error("expected base expression after `..`");
769 } else {
770 self.parse_expr();
772 }
773 m.complete(self, STRUCT_BASE_UPDATE);
774 }
775
776 fn parse_struct_field(&mut self) {
778 let m = self.start();
779 self.skip_trivia();
780
781 if self.at(IDENT) {
782 self.bump_any(); if self.eat(COLON) {
785 if self.parse_expr().is_none() && !self.at(R_BRACE) && !self.at(COMMA) {
787 self.error("expected field value");
788 }
789 m.complete(self, STRUCT_FIELD_INIT);
790 } else {
791 m.complete(self, STRUCT_FIELD_SHORTHAND);
793 }
794 } else {
795 self.error("expected field name");
796 m.complete(self, STRUCT_FIELD_INIT);
797 }
798 }
799
800 fn parse_self_expr(&mut self) -> Option<CompletedMarker> {
802 let m = self.start();
803 self.bump_any(); if self.at(COLON_COLON) {
807 self.error("expected '.' -- found '::'");
808 }
809
810 Some(m.complete(self, SELF_EXPR))
811 }
812
813 fn parse_block_access(&mut self) -> Option<CompletedMarker> {
815 let m = self.start();
816 self.bump_any(); Some(m.complete(self, BLOCK_KW_EXPR))
818 }
819
820 fn parse_network_access(&mut self) -> Option<CompletedMarker> {
822 let m = self.start();
823 self.bump_any(); Some(m.complete(self, NETWORK_KW_EXPR))
825 }
826
827 fn parse_final_block_expr(&mut self) -> Option<CompletedMarker> {
829 let m = self.start();
830 self.bump_any(); self.skip_trivia();
832 if self.parse_block().is_none() {
833 self.error("expected block after 'final'");
834 }
835 Some(m.complete(self, FINAL_EXPR))
836 }
837}
838
839#[cfg(test)]
840mod tests {
841 use super::*;
842 use crate::{lexer::lex, parser::Parse};
843 use expect_test::{Expect, expect};
844
845 fn check_expr(input: &str, expect: Expect) {
846 let (tokens, _) = lex(input);
847 let mut parser = Parser::new(input, &tokens);
848 let root = parser.start();
849 parser.parse_expr();
850 parser.skip_trivia();
851 root.complete(&mut parser, ROOT);
852 let parse: Parse = parser.finish(vec![]);
853 let output = format!("{:#?}", parse.syntax());
854 expect.assert_eq(&output);
855 }
856
857 #[test]
862 fn parse_expr_integer() {
863 check_expr("42", expect![[r#"
864 ROOT@0..2
865 LITERAL_INT@0..2
866 INTEGER@0..2 "42"
867 "#]]);
868 }
869
870 #[test]
871 fn parse_expr_bool_true() {
872 check_expr("true", expect![[r#"
873 ROOT@0..4
874 LITERAL_BOOL@0..4
875 KW_TRUE@0..4 "true"
876 "#]]);
877 }
878
879 #[test]
880 fn parse_expr_bool_false() {
881 check_expr("false", expect![[r#"
882 ROOT@0..5
883 LITERAL_BOOL@0..5
884 KW_FALSE@0..5 "false"
885 "#]]);
886 }
887
888 #[test]
889 fn parse_expr_none() {
890 check_expr("none", expect![[r#"
891 ROOT@0..4
892 LITERAL_NONE@0..4
893 KW_NONE@0..4 "none"
894 "#]]);
895 }
896
897 #[test]
898 fn parse_expr_identifier_literal() {
899 check_expr("'foo'", expect![[r#"
900 ROOT@0..5
901 LITERAL_IDENT@0..5
902 IDENT_LIT@0..5 "'foo'"
903 "#]]);
904 }
905
906 #[test]
911 fn parse_expr_dynamic_call_basic() {
912 check_expr("Adder@(target)::sum(x, y)", expect![[r#"
913 ROOT@0..25
914 DYNAMIC_OP_EXPR@0..25
915 TYPE_PATH@0..5
916 IDENT@0..5 "Adder"
917 AT@5..6 "@"
918 L_PAREN@6..7 "("
919 PATH_EXPR@7..13
920 IDENT@7..13 "target"
921 R_PAREN@13..14 ")"
922 COLON_COLON@14..16 "::"
923 IDENT@16..19 "sum"
924 L_PAREN@19..20 "("
925 PATH_EXPR@20..21
926 IDENT@20..21 "x"
927 COMMA@21..22 ","
928 WHITESPACE@22..23 " "
929 PATH_EXPR@23..24
930 IDENT@23..24 "y"
931 R_PAREN@24..25 ")"
932 "#]]);
933 }
934
935 #[test]
936 fn parse_expr_dynamic_call_identifier_target() {
937 check_expr("Adder@('foo')::sum(x, y)", expect![[r#"
938 ROOT@0..24
939 DYNAMIC_OP_EXPR@0..24
940 TYPE_PATH@0..5
941 IDENT@0..5 "Adder"
942 AT@5..6 "@"
943 L_PAREN@6..7 "("
944 LITERAL_IDENT@7..12
945 IDENT_LIT@7..12 "'foo'"
946 R_PAREN@12..13 ")"
947 COLON_COLON@13..15 "::"
948 IDENT@15..18 "sum"
949 L_PAREN@18..19 "("
950 PATH_EXPR@19..20
951 IDENT@19..20 "x"
952 COMMA@20..21 ","
953 WHITESPACE@21..22 " "
954 PATH_EXPR@22..23
955 IDENT@22..23 "y"
956 R_PAREN@23..24 ")"
957 "#]]);
958 }
959
960 #[test]
961 fn parse_expr_dynamic_call_with_network() {
962 check_expr("Adder@('foo', 'aleo')::sum(x, y)", expect![[r#"
963 ROOT@0..32
964 DYNAMIC_OP_EXPR@0..32
965 TYPE_PATH@0..5
966 IDENT@0..5 "Adder"
967 AT@5..6 "@"
968 L_PAREN@6..7 "("
969 LITERAL_IDENT@7..12
970 IDENT_LIT@7..12 "'foo'"
971 COMMA@12..13 ","
972 WHITESPACE@13..14 " "
973 LITERAL_IDENT@14..20
974 IDENT_LIT@14..20 "'aleo'"
975 R_PAREN@20..21 ")"
976 COLON_COLON@21..23 "::"
977 IDENT@23..26 "sum"
978 L_PAREN@26..27 "("
979 PATH_EXPR@27..28
980 IDENT@27..28 "x"
981 COMMA@28..29 ","
982 WHITESPACE@29..30 " "
983 PATH_EXPR@30..31
984 IDENT@30..31 "y"
985 R_PAREN@31..32 ")"
986 "#]]);
987 }
988
989 #[test]
990 fn parse_expr_dynamic_call_no_args() {
991 check_expr("Adder@(target)::sum()", expect![[r#"
992 ROOT@0..21
993 DYNAMIC_OP_EXPR@0..21
994 TYPE_PATH@0..5
995 IDENT@0..5 "Adder"
996 AT@5..6 "@"
997 L_PAREN@6..7 "("
998 PATH_EXPR@7..13
999 IDENT@7..13 "target"
1000 R_PAREN@13..14 ")"
1001 COLON_COLON@14..16 "::"
1002 IDENT@16..19 "sum"
1003 L_PAREN@19..20 "("
1004 R_PAREN@20..21 ")"
1005 "#]]);
1006 }
1007
1008 #[test]
1009 fn parse_expr_dynamic_storage_access() {
1010 check_expr("Bank@(target)::balances.get(key)", expect![[r#"
1011 ROOT@0..32
1012 DYNAMIC_OP_EXPR@0..32
1013 TYPE_PATH@0..4
1014 IDENT@0..4 "Bank"
1015 AT@4..5 "@"
1016 L_PAREN@5..6 "("
1017 PATH_EXPR@6..12
1018 IDENT@6..12 "target"
1019 R_PAREN@12..13 ")"
1020 COLON_COLON@13..15 "::"
1021 IDENT@15..23 "balances"
1022 DOT@23..24 "."
1023 IDENT@24..27 "get"
1024 L_PAREN@27..28 "("
1025 PATH_EXPR@28..31
1026 IDENT@28..31 "key"
1027 R_PAREN@31..32 ")"
1028 "#]]);
1029 }
1030
1031 #[test]
1032 fn parse_expr_dynamic_storage_access_missing_storage_name() {
1033 check_expr("Bank@(target)::.get(key)", expect![[r#"
1037 ROOT@0..24
1038 DYNAMIC_OP_EXPR@0..24
1039 TYPE_PATH@0..4
1040 IDENT@0..4 "Bank"
1041 AT@4..5 "@"
1042 L_PAREN@5..6 "("
1043 PATH_EXPR@6..12
1044 IDENT@6..12 "target"
1045 R_PAREN@12..13 ")"
1046 COLON_COLON@13..15 "::"
1047 DOT@15..16 "."
1048 IDENT@16..19 "get"
1049 L_PAREN@19..20 "("
1050 PATH_EXPR@20..23
1051 IDENT@20..23 "key"
1052 R_PAREN@23..24 ")"
1053 "#]]);
1054 }
1055
1056 #[test]
1057 fn parse_expr_dynamic_storage_access_missing_op() {
1058 check_expr("Bank@(target)::balances.(key)", expect![[r#"
1060 ROOT@0..29
1061 DYNAMIC_OP_EXPR@0..29
1062 TYPE_PATH@0..4
1063 IDENT@0..4 "Bank"
1064 AT@4..5 "@"
1065 L_PAREN@5..6 "("
1066 PATH_EXPR@6..12
1067 IDENT@6..12 "target"
1068 R_PAREN@12..13 ")"
1069 COLON_COLON@13..15 "::"
1070 IDENT@15..23 "balances"
1071 DOT@23..24 "."
1072 L_PAREN@24..25 "("
1073 PATH_EXPR@25..28
1074 IDENT@25..28 "key"
1075 R_PAREN@28..29 ")"
1076 "#]]);
1077 }
1078
1079 #[test]
1080 fn parse_expr_dynamic_read() {
1081 check_expr("Bank@(target)::total", expect![[r#"
1082 ROOT@0..20
1083 DYNAMIC_OP_EXPR@0..20
1084 TYPE_PATH@0..4
1085 IDENT@0..4 "Bank"
1086 AT@4..5 "@"
1087 L_PAREN@5..6 "("
1088 PATH_EXPR@6..12
1089 IDENT@6..12 "target"
1090 R_PAREN@12..13 ")"
1091 COLON_COLON@13..15 "::"
1092 IDENT@15..20 "total"
1093 "#]]);
1094 }
1095
1096 #[test]
1097 fn parse_expr_dynamic_read_with_network() {
1098 check_expr("Bank@('foo', 'aleo')::total", expect![[r#"
1099 ROOT@0..27
1100 DYNAMIC_OP_EXPR@0..27
1101 TYPE_PATH@0..4
1102 IDENT@0..4 "Bank"
1103 AT@4..5 "@"
1104 L_PAREN@5..6 "("
1105 LITERAL_IDENT@6..11
1106 IDENT_LIT@6..11 "'foo'"
1107 COMMA@11..12 ","
1108 WHITESPACE@12..13 " "
1109 LITERAL_IDENT@13..19
1110 IDENT_LIT@13..19 "'aleo'"
1111 R_PAREN@19..20 ")"
1112 COLON_COLON@20..22 "::"
1113 IDENT@22..27 "total"
1114 "#]]);
1115 }
1116
1117 #[test]
1122 fn parse_expr_ident() {
1123 check_expr("foo", expect![[r#"
1124 ROOT@0..3
1125 PATH_EXPR@0..3
1126 IDENT@0..3 "foo"
1127 "#]]);
1128 }
1129
1130 #[test]
1131 fn parse_expr_path() {
1132 check_expr("Foo::bar", expect![[r#"
1133 ROOT@0..8
1134 PATH_EXPR@0..8
1135 IDENT@0..3 "Foo"
1136 COLON_COLON@3..5 "::"
1137 IDENT@5..8 "bar"
1138 "#]]);
1139 }
1140
1141 #[test]
1142 fn parse_expr_self() {
1143 check_expr("self", expect![[r#"
1144 ROOT@0..4
1145 SELF_EXPR@0..4
1146 KW_SELF@0..4 "self"
1147 "#]]);
1148 }
1149
1150 #[test]
1151 fn parse_expr_self_colon_colon_is_error() {
1152 let (tokens, _) = lex("self::y");
1154 let mut parser = Parser::new("self::y", &tokens);
1155 let root = parser.start();
1156 parser.parse_expr();
1157 parser.skip_trivia();
1158 root.complete(&mut parser, ROOT);
1159 let parse: Parse = parser.finish(vec![]);
1160 assert!(!parse.errors().is_empty(), "expected error for self::");
1161 assert!(
1162 parse.errors().iter().any(|e| e.message.contains("expected '.'")),
1163 "expected error message to mention expected '.', got: {:?}",
1164 parse.errors()
1165 );
1166 }
1167
1168 #[test]
1173 fn parse_expr_add() {
1174 check_expr("1 + 2", expect![[r#"
1175 ROOT@0..5
1176 BINARY_EXPR@0..5
1177 LITERAL_INT@0..1
1178 INTEGER@0..1 "1"
1179 WHITESPACE@1..2 " "
1180 PLUS@2..3 "+"
1181 WHITESPACE@3..4 " "
1182 LITERAL_INT@4..5
1183 INTEGER@4..5 "2"
1184 "#]]);
1185 }
1186
1187 #[test]
1188 fn parse_expr_mul() {
1189 check_expr("a * b", expect![[r#"
1190 ROOT@0..5
1191 BINARY_EXPR@0..5
1192 PATH_EXPR@0..2
1193 IDENT@0..1 "a"
1194 WHITESPACE@1..2 " "
1195 STAR@2..3 "*"
1196 WHITESPACE@3..4 " "
1197 PATH_EXPR@4..5
1198 IDENT@4..5 "b"
1199 "#]]);
1200 }
1201
1202 #[test]
1203 fn parse_expr_precedence() {
1204 check_expr("1 + 2 * 3", expect![[r#"
1206 ROOT@0..9
1207 BINARY_EXPR@0..9
1208 LITERAL_INT@0..1
1209 INTEGER@0..1 "1"
1210 WHITESPACE@1..2 " "
1211 PLUS@2..3 "+"
1212 WHITESPACE@3..4 " "
1213 BINARY_EXPR@4..9
1214 LITERAL_INT@4..5
1215 INTEGER@4..5 "2"
1216 WHITESPACE@5..6 " "
1217 STAR@6..7 "*"
1218 WHITESPACE@7..8 " "
1219 LITERAL_INT@8..9
1220 INTEGER@8..9 "3"
1221 "#]]);
1222 }
1223
1224 #[test]
1225 fn parse_expr_power_right_assoc() {
1226 check_expr("a ** b ** c", expect![[r#"
1228 ROOT@0..11
1229 BINARY_EXPR@0..11
1230 PATH_EXPR@0..2
1231 IDENT@0..1 "a"
1232 WHITESPACE@1..2 " "
1233 STAR2@2..4 "**"
1234 WHITESPACE@4..5 " "
1235 BINARY_EXPR@5..11
1236 PATH_EXPR@5..7
1237 IDENT@5..6 "b"
1238 WHITESPACE@6..7 " "
1239 STAR2@7..9 "**"
1240 WHITESPACE@9..10 " "
1241 PATH_EXPR@10..11
1242 IDENT@10..11 "c"
1243 "#]]);
1244 }
1245
1246 #[test]
1251 fn parse_expr_unary_neg() {
1252 check_expr("-x", expect![[r#"
1253 ROOT@0..2
1254 UNARY_EXPR@0..2
1255 MINUS@0..1 "-"
1256 PATH_EXPR@1..2
1257 IDENT@1..2 "x"
1258 "#]]);
1259 }
1260
1261 #[test]
1262 fn parse_expr_unary_not() {
1263 check_expr("!flag", expect![[r#"
1264 ROOT@0..5
1265 UNARY_EXPR@0..5
1266 BANG@0..1 "!"
1267 PATH_EXPR@1..5
1268 IDENT@1..5 "flag"
1269 "#]]);
1270 }
1271
1272 #[test]
1277 fn parse_expr_comparison() {
1278 check_expr("a < b", expect![[r#"
1279 ROOT@0..5
1280 BINARY_EXPR@0..5
1281 PATH_EXPR@0..2
1282 IDENT@0..1 "a"
1283 WHITESPACE@1..2 " "
1284 LT@2..3 "<"
1285 WHITESPACE@3..4 " "
1286 PATH_EXPR@4..5
1287 IDENT@4..5 "b"
1288 "#]]);
1289 }
1290
1291 #[test]
1292 fn parse_expr_logical_and() {
1293 check_expr("a && b", expect![[r#"
1294 ROOT@0..6
1295 BINARY_EXPR@0..6
1296 PATH_EXPR@0..2
1297 IDENT@0..1 "a"
1298 WHITESPACE@1..2 " "
1299 AMP2@2..4 "&&"
1300 WHITESPACE@4..5 " "
1301 PATH_EXPR@5..6
1302 IDENT@5..6 "b"
1303 "#]]);
1304 }
1305
1306 #[test]
1307 fn parse_expr_logical_or() {
1308 check_expr("a || b", expect![[r#"
1309 ROOT@0..6
1310 BINARY_EXPR@0..6
1311 PATH_EXPR@0..2
1312 IDENT@0..1 "a"
1313 WHITESPACE@1..2 " "
1314 PIPE2@2..4 "||"
1315 WHITESPACE@4..5 " "
1316 PATH_EXPR@5..6
1317 IDENT@5..6 "b"
1318 "#]]);
1319 }
1320
1321 #[test]
1326 fn parse_expr_ternary() {
1327 check_expr("a ? b : c", expect![[r#"
1328 ROOT@0..9
1329 TERNARY_EXPR@0..9
1330 PATH_EXPR@0..2
1331 IDENT@0..1 "a"
1332 WHITESPACE@1..2 " "
1333 QUESTION@2..3 "?"
1334 WHITESPACE@3..4 " "
1335 PATH_EXPR@4..6
1336 IDENT@4..5 "b"
1337 WHITESPACE@5..6 " "
1338 COLON@6..7 ":"
1339 WHITESPACE@7..8 " "
1340 PATH_EXPR@8..9
1341 IDENT@8..9 "c"
1342 "#]]);
1343 }
1344
1345 #[test]
1350 fn parse_expr_member_access() {
1351 check_expr("foo.bar", expect![[r#"
1352 ROOT@0..7
1353 FIELD_EXPR@0..7
1354 PATH_EXPR@0..3
1355 IDENT@0..3 "foo"
1356 DOT@3..4 "."
1357 IDENT@4..7 "bar"
1358 "#]]);
1359 }
1360
1361 #[test]
1362 fn parse_expr_tuple_access() {
1363 check_expr("tuple.0", expect![[r#"
1364 ROOT@0..7
1365 TUPLE_ACCESS_EXPR@0..7
1366 PATH_EXPR@0..5
1367 IDENT@0..5 "tuple"
1368 DOT@5..6 "."
1369 INTEGER@6..7 "0"
1370 "#]]);
1371 }
1372
1373 #[test]
1374 fn parse_expr_index() {
1375 check_expr("arr[0]", expect![[r#"
1376 ROOT@0..6
1377 INDEX_EXPR@0..6
1378 PATH_EXPR@0..3
1379 IDENT@0..3 "arr"
1380 L_BRACKET@3..4 "["
1381 LITERAL_INT@4..5
1382 INTEGER@4..5 "0"
1383 R_BRACKET@5..6 "]"
1384 "#]]);
1385 }
1386
1387 #[test]
1388 fn parse_expr_call() {
1389 check_expr("foo(a, b)", expect![[r#"
1390 ROOT@0..9
1391 CALL_EXPR@0..9
1392 PATH_EXPR@0..3
1393 IDENT@0..3 "foo"
1394 L_PAREN@3..4 "("
1395 PATH_EXPR@4..5
1396 IDENT@4..5 "a"
1397 COMMA@5..6 ","
1398 WHITESPACE@6..7 " "
1399 PATH_EXPR@7..8
1400 IDENT@7..8 "b"
1401 R_PAREN@8..9 ")"
1402 "#]]);
1403 }
1404
1405 #[test]
1406 fn parse_expr_method_call() {
1407 check_expr("x.foo()", expect![[r#"
1408 ROOT@0..7
1409 METHOD_CALL_EXPR@0..7
1410 PATH_EXPR@0..1
1411 IDENT@0..1 "x"
1412 DOT@1..2 "."
1413 IDENT@2..5 "foo"
1414 L_PAREN@5..6 "("
1415 R_PAREN@6..7 ")"
1416 "#]]);
1417 }
1418
1419 #[test]
1424 fn parse_expr_cast() {
1425 check_expr("x as u64", expect![[r#"
1426 ROOT@0..8
1427 CAST_EXPR@0..8
1428 PATH_EXPR@0..2
1429 IDENT@0..1 "x"
1430 WHITESPACE@1..2 " "
1431 KW_AS@2..4 "as"
1432 WHITESPACE@4..5 " "
1433 TYPE_PRIMITIVE@5..8
1434 KW_U64@5..8 "u64"
1435 "#]]);
1436 }
1437
1438 #[test]
1443 fn parse_expr_paren() {
1444 check_expr("(a + b)", expect![[r#"
1445 ROOT@0..7
1446 PAREN_EXPR@0..7
1447 L_PAREN@0..1 "("
1448 BINARY_EXPR@1..6
1449 PATH_EXPR@1..3
1450 IDENT@1..2 "a"
1451 WHITESPACE@2..3 " "
1452 PLUS@3..4 "+"
1453 WHITESPACE@4..5 " "
1454 PATH_EXPR@5..6
1455 IDENT@5..6 "b"
1456 R_PAREN@6..7 ")"
1457 "#]]);
1458 }
1459
1460 #[test]
1461 fn parse_expr_tuple() {
1462 check_expr("(a, b)", expect![[r#"
1463 ROOT@0..6
1464 TUPLE_EXPR@0..6
1465 L_PAREN@0..1 "("
1466 PATH_EXPR@1..2
1467 IDENT@1..2 "a"
1468 COMMA@2..3 ","
1469 WHITESPACE@3..4 " "
1470 PATH_EXPR@4..5
1471 IDENT@4..5 "b"
1472 R_PAREN@5..6 ")"
1473 "#]]);
1474 }
1475
1476 #[test]
1477 fn parse_expr_unit() {
1478 check_expr("()", expect![[r#"
1479 ROOT@0..2
1480 TUPLE_EXPR@0..2
1481 L_PAREN@0..1 "("
1482 R_PAREN@1..2 ")"
1483 "#]]);
1484 }
1485
1486 #[test]
1491 fn parse_expr_array() {
1492 check_expr("[1, 2, 3]", expect![[r#"
1493 ROOT@0..9
1494 ARRAY_EXPR@0..9
1495 L_BRACKET@0..1 "["
1496 LITERAL_INT@1..2
1497 INTEGER@1..2 "1"
1498 COMMA@2..3 ","
1499 WHITESPACE@3..4 " "
1500 LITERAL_INT@4..5
1501 INTEGER@4..5 "2"
1502 COMMA@5..6 ","
1503 WHITESPACE@6..7 " "
1504 LITERAL_INT@7..8
1505 INTEGER@7..8 "3"
1506 R_BRACKET@8..9 "]"
1507 "#]]);
1508 }
1509
1510 #[test]
1511 fn parse_expr_array_repeat() {
1512 check_expr("[0; 10]", expect![[r#"
1513 ROOT@0..7
1514 REPEAT_EXPR@0..7
1515 L_BRACKET@0..1 "["
1516 LITERAL_INT@1..2
1517 INTEGER@1..2 "0"
1518 SEMICOLON@2..3 ";"
1519 WHITESPACE@3..4 " "
1520 LITERAL_INT@4..6
1521 INTEGER@4..6 "10"
1522 R_BRACKET@6..7 "]"
1523 "#]]);
1524 }
1525
1526 #[test]
1531 fn parse_expr_struct_init() {
1532 check_expr("Point { x: 1, y: 2 }", expect![[r#"
1533 ROOT@0..20
1534 STRUCT_EXPR@0..20
1535 IDENT@0..5 "Point"
1536 WHITESPACE@5..6 " "
1537 L_BRACE@6..7 "{"
1538 STRUCT_FIELD_INIT@7..12
1539 WHITESPACE@7..8 " "
1540 IDENT@8..9 "x"
1541 COLON@9..10 ":"
1542 WHITESPACE@10..11 " "
1543 LITERAL_INT@11..12
1544 INTEGER@11..12 "1"
1545 COMMA@12..13 ","
1546 STRUCT_FIELD_INIT@13..18
1547 WHITESPACE@13..14 " "
1548 IDENT@14..15 "y"
1549 COLON@15..16 ":"
1550 WHITESPACE@16..17 " "
1551 LITERAL_INT@17..18
1552 INTEGER@17..18 "2"
1553 WHITESPACE@18..19 " "
1554 R_BRACE@19..20 "}"
1555 "#]]);
1556 }
1557
1558 #[test]
1559 fn parse_expr_struct_shorthand() {
1560 check_expr("Point { x, y }", expect![[r#"
1561 ROOT@0..14
1562 STRUCT_EXPR@0..14
1563 IDENT@0..5 "Point"
1564 WHITESPACE@5..6 " "
1565 L_BRACE@6..7 "{"
1566 STRUCT_FIELD_SHORTHAND@7..9
1567 WHITESPACE@7..8 " "
1568 IDENT@8..9 "x"
1569 COMMA@9..10 ","
1570 STRUCT_FIELD_SHORTHAND@10..13
1571 WHITESPACE@10..11 " "
1572 IDENT@11..12 "y"
1573 WHITESPACE@12..13 " "
1574 R_BRACE@13..14 "}"
1575 "#]]);
1576 }
1577
1578 #[test]
1579 fn parse_expr_struct_update_base() {
1580 check_expr("Point { x: 1, ..other }", expect![[r#"
1581 ROOT@0..23
1582 STRUCT_EXPR@0..23
1583 IDENT@0..5 "Point"
1584 WHITESPACE@5..6 " "
1585 L_BRACE@6..7 "{"
1586 STRUCT_FIELD_INIT@7..12
1587 WHITESPACE@7..8 " "
1588 IDENT@8..9 "x"
1589 COLON@9..10 ":"
1590 WHITESPACE@10..11 " "
1591 LITERAL_INT@11..12
1592 INTEGER@11..12 "1"
1593 COMMA@12..13 ","
1594 STRUCT_BASE_UPDATE@13..22
1595 WHITESPACE@13..14 " "
1596 DOT_DOT@14..16 ".."
1597 PATH_EXPR@16..22
1598 IDENT@16..21 "other"
1599 WHITESPACE@21..22 " "
1600 R_BRACE@22..23 "}"
1601 "#]]);
1602 }
1603
1604 #[test]
1605 fn parse_expr_struct_update_base_only() {
1606 check_expr("Point { ..other }", expect![[r#"
1607 ROOT@0..17
1608 STRUCT_EXPR@0..17
1609 IDENT@0..5 "Point"
1610 WHITESPACE@5..6 " "
1611 L_BRACE@6..7 "{"
1612 STRUCT_BASE_UPDATE@7..16
1613 WHITESPACE@7..8 " "
1614 DOT_DOT@8..10 ".."
1615 PATH_EXPR@10..16
1616 IDENT@10..15 "other"
1617 WHITESPACE@15..16 " "
1618 R_BRACE@16..17 "}"
1619 "#]]);
1620 }
1621
1622 fn check_expr_no_errors(input: &str) {
1631 let (tokens, _) = lex(input);
1632 let mut parser = Parser::new(input, &tokens);
1633 let root = parser.start();
1634 parser.parse_expr();
1635 parser.skip_trivia();
1636 root.complete(&mut parser, ROOT);
1637 let parse: Parse = parser.finish(vec![]);
1638 if !parse.errors().is_empty() {
1639 for err in parse.errors() {
1640 eprintln!("error at {:?}: {}", err.range, err.message);
1641 }
1642 eprintln!("tree:\n{:#?}", parse.syntax());
1643 panic!("expression parse had {} error(s)", parse.errors().len());
1644 }
1645 }
1646
1647 #[test]
1648 fn parse_expr_call_const_generic_simple() {
1649 check_expr("foo::[5]()", expect![[r#"
1651 ROOT@0..10
1652 CALL_EXPR@0..10
1653 PATH_EXPR@0..8
1654 IDENT@0..3 "foo"
1655 COLON_COLON@3..5 "::"
1656 CONST_ARG_LIST@5..8
1657 L_BRACKET@5..6 "["
1658 LITERAL_INT@6..7
1659 INTEGER@6..7 "5"
1660 R_BRACKET@7..8 "]"
1661 L_PAREN@8..9 "("
1662 R_PAREN@9..10 ")"
1663 "#]]);
1664 }
1665
1666 #[test]
1667 fn parse_expr_call_const_generic_expr() {
1668 check_expr_no_errors("foo::[N + 1]()");
1670 }
1671
1672 #[test]
1673 fn parse_expr_call_const_generic_multi() {
1674 check_expr_no_errors("bar::[M, K, N]()");
1676 }
1677
1678 #[test]
1679 fn parse_expr_struct_lit_const_generic() {
1680 check_expr("Foo::[8u32] { arr: x }", expect![[r#"
1682 ROOT@0..22
1683 STRUCT_EXPR@0..22
1684 IDENT@0..3 "Foo"
1685 COLON_COLON@3..5 "::"
1686 CONST_ARG_LIST@5..11
1687 L_BRACKET@5..6 "["
1688 LITERAL_INT@6..10
1689 INTEGER@6..10 "8u32"
1690 R_BRACKET@10..11 "]"
1691 WHITESPACE@11..12 " "
1692 L_BRACE@12..13 "{"
1693 STRUCT_FIELD_INIT@13..21
1694 WHITESPACE@13..14 " "
1695 IDENT@14..17 "arr"
1696 COLON@17..18 ":"
1697 WHITESPACE@18..19 " "
1698 PATH_EXPR@19..21
1699 IDENT@19..20 "x"
1700 WHITESPACE@20..21 " "
1701 R_BRACE@21..22 "}"
1702 "#]]);
1703 }
1704
1705 #[test]
1706 fn parse_expr_locator_call_const_generic() {
1707 check_expr_no_errors("child.aleo::foo::[3]()");
1709 }
1710
1711 #[test]
1712 fn parse_expr_assoc_fn_const_generic() {
1713 check_expr_no_errors("Foo::bar::[N]()");
1715 }
1716
1717 #[test]
1722 fn parse_expr_complex() {
1723 check_expr("a.b[c](d) + e", expect![[r#"
1724 ROOT@0..13
1725 BINARY_EXPR@0..13
1726 CALL_EXPR@0..9
1727 INDEX_EXPR@0..6
1728 FIELD_EXPR@0..3
1729 PATH_EXPR@0..1
1730 IDENT@0..1 "a"
1731 DOT@1..2 "."
1732 IDENT@2..3 "b"
1733 L_BRACKET@3..4 "["
1734 PATH_EXPR@4..5
1735 IDENT@4..5 "c"
1736 R_BRACKET@5..6 "]"
1737 L_PAREN@6..7 "("
1738 PATH_EXPR@7..8
1739 IDENT@7..8 "d"
1740 R_PAREN@8..9 ")"
1741 WHITESPACE@9..10 " "
1742 PLUS@10..11 "+"
1743 WHITESPACE@11..12 " "
1744 PATH_EXPR@12..13
1745 IDENT@12..13 "e"
1746 "#]]);
1747 }
1748
1749 fn parse_expr_for_test(input: &str) -> Parse {
1754 let (tokens, _) = lex(input);
1755 let mut parser = Parser::new(input, &tokens);
1756 let root = parser.start();
1757 parser.parse_expr();
1758 parser.skip_trivia();
1759 root.complete(&mut parser, ROOT);
1760 parser.finish(vec![])
1761 }
1762
1763 #[test]
1764 fn parse_expr_chained_eq_is_error() {
1765 let parse = parse_expr_for_test("1 == 2 == 3");
1767 assert!(!parse.errors().is_empty(), "expected error for chained ==, got none");
1768 assert!(
1769 parse.errors().iter().any(|e| e.message.contains("'&&'") || e.message.contains("expected")),
1770 "expected error message about valid operators, got: {:?}",
1771 parse.errors()
1772 );
1773 }
1774
1775 #[test]
1776 fn parse_expr_chained_neq_is_error() {
1777 let parse = parse_expr_for_test("1 != 2 != 3");
1779 assert!(!parse.errors().is_empty(), "expected error for chained !=, got none");
1780 }
1781
1782 #[test]
1783 fn parse_expr_chained_lt_is_error() {
1784 let parse = parse_expr_for_test("1 < 2 < 3");
1786 assert!(!parse.errors().is_empty(), "expected error for chained <, got none");
1787 }
1788
1789 #[test]
1790 fn parse_expr_chained_gt_is_error() {
1791 let parse = parse_expr_for_test("1 > 2 > 3");
1793 assert!(!parse.errors().is_empty(), "expected error for chained >, got none");
1794 }
1795
1796 #[test]
1797 fn parse_expr_comparison_with_logical_is_ok() {
1798 check_expr_no_errors("1 == 2 && 3 == 4");
1800 check_expr_no_errors("1 < 2 || 3 > 4");
1801 }
1802
1803 #[test]
1808 fn parse_expr_group_associated_fn() {
1809 check_expr("group::to_x_coordinate(a)", expect![[r#"
1812 ROOT@0..25
1813 CALL_EXPR@0..25
1814 PATH_EXPR@0..22
1815 IDENT@0..22 "group::to_x_coordinate"
1816 L_PAREN@22..23 "("
1817 PATH_EXPR@23..24
1818 IDENT@23..24 "a"
1819 R_PAREN@24..25 ")"
1820 "#]]);
1821 }
1822
1823 #[test]
1824 fn parse_expr_signature_associated_fn() {
1825 check_expr("signature::verify(s, a, v)", expect![[r#"
1828 ROOT@0..26
1829 CALL_EXPR@0..26
1830 PATH_EXPR@0..17
1831 IDENT@0..17 "signature::verify"
1832 L_PAREN@17..18 "("
1833 PATH_EXPR@18..19
1834 IDENT@18..19 "s"
1835 COMMA@19..20 ","
1836 WHITESPACE@20..21 " "
1837 PATH_EXPR@21..22
1838 IDENT@21..22 "a"
1839 COMMA@22..23 ","
1840 WHITESPACE@23..24 " "
1841 PATH_EXPR@24..25
1842 IDENT@24..25 "v"
1843 R_PAREN@25..26 ")"
1844 "#]]);
1845 }
1846
1847 #[test]
1852 fn parse_expr_chained_le_is_error() {
1853 let parse = parse_expr_for_test("1 <= 2 <= 3");
1854 assert!(!parse.errors().is_empty(), "expected error for chained <=, got none");
1855 }
1856
1857 #[test]
1858 fn parse_expr_chained_ge_is_error() {
1859 let parse = parse_expr_for_test("1 >= 2 >= 3");
1860 assert!(!parse.errors().is_empty(), "expected error for chained >=, got none");
1861 }
1862
1863 #[test]
1864 fn parse_expr_chained_mixed_cmp_is_error() {
1865 let parse = parse_expr_for_test("1 < 2 > 3");
1866 assert!(!parse.errors().is_empty(), "expected error for mixed chained comparisons, got none");
1867 }
1868
1869 #[test]
1874 fn parse_expr_ternary_nested() {
1875 check_expr("a ? b ? c : d : e", expect![[r#"
1876 ROOT@0..17
1877 TERNARY_EXPR@0..17
1878 PATH_EXPR@0..2
1879 IDENT@0..1 "a"
1880 WHITESPACE@1..2 " "
1881 QUESTION@2..3 "?"
1882 WHITESPACE@3..4 " "
1883 TERNARY_EXPR@4..14
1884 PATH_EXPR@4..6
1885 IDENT@4..5 "b"
1886 WHITESPACE@5..6 " "
1887 QUESTION@6..7 "?"
1888 WHITESPACE@7..8 " "
1889 PATH_EXPR@8..10
1890 IDENT@8..9 "c"
1891 WHITESPACE@9..10 " "
1892 COLON@10..11 ":"
1893 WHITESPACE@11..12 " "
1894 PATH_EXPR@12..14
1895 IDENT@12..13 "d"
1896 WHITESPACE@13..14 " "
1897 COLON@14..15 ":"
1898 WHITESPACE@15..16 " "
1899 PATH_EXPR@16..17
1900 IDENT@16..17 "e"
1901 "#]]);
1902 }
1903
1904 #[test]
1909 fn parse_expr_cast_chained() {
1910 check_expr("x as u32 as u64", expect![[r#"
1911 ROOT@0..15
1912 CAST_EXPR@0..15
1913 CAST_EXPR@0..8
1914 PATH_EXPR@0..2
1915 IDENT@0..1 "x"
1916 WHITESPACE@1..2 " "
1917 KW_AS@2..4 "as"
1918 WHITESPACE@4..5 " "
1919 TYPE_PRIMITIVE@5..8
1920 KW_U32@5..8 "u32"
1921 WHITESPACE@8..9 " "
1922 KW_AS@9..11 "as"
1923 WHITESPACE@11..12 " "
1924 TYPE_PRIMITIVE@12..15
1925 KW_U64@12..15 "u64"
1926 "#]]);
1927 }
1928
1929 #[test]
1934 fn parse_expr_array_trailing_comma() {
1935 check_expr("[1, 2, 3,]", expect![[r#"
1936 ROOT@0..10
1937 ARRAY_EXPR@0..10
1938 L_BRACKET@0..1 "["
1939 LITERAL_INT@1..2
1940 INTEGER@1..2 "1"
1941 COMMA@2..3 ","
1942 WHITESPACE@3..4 " "
1943 LITERAL_INT@4..5
1944 INTEGER@4..5 "2"
1945 COMMA@5..6 ","
1946 WHITESPACE@6..7 " "
1947 LITERAL_INT@7..8
1948 INTEGER@7..8 "3"
1949 COMMA@8..9 ","
1950 R_BRACKET@9..10 "]"
1951 "#]]);
1952 }
1953
1954 #[test]
1955 fn parse_expr_array_empty() {
1956 check_expr("[]", expect![[r#"
1957 ROOT@0..2
1958 ARRAY_EXPR@0..2
1959 L_BRACKET@0..1 "["
1960 R_BRACKET@1..2 "]"
1961 "#]]);
1962 }
1963
1964 #[test]
1965 fn parse_expr_tuple_single() {
1966 check_expr("(a,)", expect![[r#"
1967 ROOT@0..4
1968 TUPLE_EXPR@0..4
1969 L_PAREN@0..1 "("
1970 PATH_EXPR@1..2
1971 IDENT@1..2 "a"
1972 COMMA@2..3 ","
1973 R_PAREN@3..4 ")"
1974 "#]]);
1975 }
1976
1977 #[test]
1978 fn parse_expr_tuple_trailing_comma() {
1979 check_expr("(1, 2,)", expect![[r#"
1980 ROOT@0..7
1981 TUPLE_EXPR@0..7
1982 L_PAREN@0..1 "("
1983 LITERAL_INT@1..2
1984 INTEGER@1..2 "1"
1985 COMMA@2..3 ","
1986 WHITESPACE@3..4 " "
1987 LITERAL_INT@4..5
1988 INTEGER@4..5 "2"
1989 COMMA@5..6 ","
1990 R_PAREN@6..7 ")"
1991 "#]]);
1992 }
1993
1994 #[test]
1999 fn parse_expr_struct_empty() {
2000 check_expr("Point { }", expect![[r#"
2001 ROOT@0..9
2002 STRUCT_EXPR@0..9
2003 IDENT@0..5 "Point"
2004 WHITESPACE@5..6 " "
2005 L_BRACE@6..7 "{"
2006 WHITESPACE@7..8 " "
2007 R_BRACE@8..9 "}"
2008 "#]]);
2009 }
2010
2011 #[test]
2012 fn parse_expr_struct_trailing_comma() {
2013 check_expr("Point { x: 1, }", expect![[r#"
2014 ROOT@0..15
2015 STRUCT_EXPR@0..15
2016 IDENT@0..5 "Point"
2017 WHITESPACE@5..6 " "
2018 L_BRACE@6..7 "{"
2019 STRUCT_FIELD_INIT@7..12
2020 WHITESPACE@7..8 " "
2021 IDENT@8..9 "x"
2022 COLON@9..10 ":"
2023 WHITESPACE@10..11 " "
2024 LITERAL_INT@11..12
2025 INTEGER@11..12 "1"
2026 COMMA@12..13 ","
2027 WHITESPACE@13..14 " "
2028 R_BRACE@14..15 "}"
2029 "#]]);
2030 }
2031
2032 #[test]
2033 fn parse_expr_struct_mixed_fields() {
2034 check_expr("Point { x, y: 2 }", expect![[r#"
2035 ROOT@0..17
2036 STRUCT_EXPR@0..17
2037 IDENT@0..5 "Point"
2038 WHITESPACE@5..6 " "
2039 L_BRACE@6..7 "{"
2040 STRUCT_FIELD_SHORTHAND@7..9
2041 WHITESPACE@7..8 " "
2042 IDENT@8..9 "x"
2043 COMMA@9..10 ","
2044 STRUCT_FIELD_INIT@10..15
2045 WHITESPACE@10..11 " "
2046 IDENT@11..12 "y"
2047 COLON@12..13 ":"
2048 WHITESPACE@13..14 " "
2049 LITERAL_INT@14..15
2050 INTEGER@14..15 "2"
2051 WHITESPACE@15..16 " "
2052 R_BRACE@16..17 "}"
2053 "#]]);
2054 }
2055
2056 #[test]
2061 fn parse_expr_string() {
2062 check_expr("\"hello\"", expect![[r#"
2063 ROOT@0..7
2064 LITERAL_STRING@0..7
2065 STRING@0..7 "\"hello\""
2066 "#]]);
2067 }
2068
2069 #[test]
2070 fn parse_expr_address() {
2071 check_expr("aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9", expect![[r#"
2072 ROOT@0..63
2073 LITERAL_ADDRESS@0..63
2074 ADDRESS_LIT@0..63 "aleo1qnr4dkkvkgfqph0v ..."
2075 "#]]);
2076 }
2077
2078 #[test]
2083 fn parse_expr_deep_postfix() {
2084 check_expr("a[0].b.c(x)[1]", expect![[r#"
2085 ROOT@0..14
2086 INDEX_EXPR@0..14
2087 METHOD_CALL_EXPR@0..11
2088 FIELD_EXPR@0..6
2089 INDEX_EXPR@0..4
2090 PATH_EXPR@0..1
2091 IDENT@0..1 "a"
2092 L_BRACKET@1..2 "["
2093 LITERAL_INT@2..3
2094 INTEGER@2..3 "0"
2095 R_BRACKET@3..4 "]"
2096 DOT@4..5 "."
2097 IDENT@5..6 "b"
2098 DOT@6..7 "."
2099 IDENT@7..8 "c"
2100 L_PAREN@8..9 "("
2101 PATH_EXPR@9..10
2102 IDENT@9..10 "x"
2103 R_PAREN@10..11 ")"
2104 L_BRACKET@11..12 "["
2105 LITERAL_INT@12..13
2106 INTEGER@12..13 "1"
2107 R_BRACKET@13..14 "]"
2108 "#]]);
2109 }
2110
2111 #[test]
2116 fn parse_expr_final() {
2117 check_expr("final { foo() }", expect![[r#"
2118 ROOT@0..15
2119 FINAL_EXPR@0..15
2120 KW_FINAL@0..5 "final"
2121 WHITESPACE@5..6 " "
2122 BLOCK@6..15
2123 L_BRACE@6..7 "{"
2124 WHITESPACE@7..8 " "
2125 EXPR_STMT@8..14
2126 CALL_EXPR@8..13
2127 PATH_EXPR@8..11
2128 IDENT@8..11 "foo"
2129 L_PAREN@11..12 "("
2130 R_PAREN@12..13 ")"
2131 WHITESPACE@13..14 " "
2132 ERROR@14..14
2133 R_BRACE@14..15 "}"
2134 "#]]);
2135 }
2136
2137 #[test]
2142 fn parse_expr_mixed_arithmetic() {
2143 check_expr("a + b * c / d - e", expect![[r#"
2145 ROOT@0..17
2146 BINARY_EXPR@0..17
2147 BINARY_EXPR@0..14
2148 PATH_EXPR@0..2
2149 IDENT@0..1 "a"
2150 WHITESPACE@1..2 " "
2151 PLUS@2..3 "+"
2152 WHITESPACE@3..4 " "
2153 BINARY_EXPR@4..14
2154 BINARY_EXPR@4..10
2155 PATH_EXPR@4..6
2156 IDENT@4..5 "b"
2157 WHITESPACE@5..6 " "
2158 STAR@6..7 "*"
2159 WHITESPACE@7..8 " "
2160 PATH_EXPR@8..10
2161 IDENT@8..9 "c"
2162 WHITESPACE@9..10 " "
2163 SLASH@10..11 "/"
2164 WHITESPACE@11..12 " "
2165 PATH_EXPR@12..14
2166 IDENT@12..13 "d"
2167 WHITESPACE@13..14 " "
2168 MINUS@14..15 "-"
2169 WHITESPACE@15..16 " "
2170 PATH_EXPR@16..17
2171 IDENT@16..17 "e"
2172 "#]]);
2173 }
2174
2175 #[test]
2176 fn parse_expr_bitwise_precedence() {
2177 check_expr("a | b & c ^ d", expect![[r#"
2181 ROOT@0..13
2182 BINARY_EXPR@0..13
2183 PATH_EXPR@0..2
2184 IDENT@0..1 "a"
2185 WHITESPACE@1..2 " "
2186 PIPE@2..3 "|"
2187 WHITESPACE@3..4 " "
2188 BINARY_EXPR@4..13
2189 BINARY_EXPR@4..10
2190 PATH_EXPR@4..6
2191 IDENT@4..5 "b"
2192 WHITESPACE@5..6 " "
2193 AMP@6..7 "&"
2194 WHITESPACE@7..8 " "
2195 PATH_EXPR@8..10
2196 IDENT@8..9 "c"
2197 WHITESPACE@9..10 " "
2198 CARET@10..11 "^"
2199 WHITESPACE@11..12 " "
2200 PATH_EXPR@12..13
2201 IDENT@12..13 "d"
2202 "#]]);
2203 }
2204
2205 #[test]
2206 fn parse_expr_shift_chain() {
2207 check_expr("x << 1 >> 2", expect![[r#"
2210 ROOT@0..11
2211 BINARY_EXPR@0..11
2212 BINARY_EXPR@0..6
2213 PATH_EXPR@0..2
2214 IDENT@0..1 "x"
2215 WHITESPACE@1..2 " "
2216 SHL@2..4 "<<"
2217 WHITESPACE@4..5 " "
2218 LITERAL_INT@5..6
2219 INTEGER@5..6 "1"
2220 WHITESPACE@6..7 " "
2221 SHR@7..9 ">>"
2222 WHITESPACE@9..10 " "
2223 LITERAL_INT@10..11
2224 INTEGER@10..11 "2"
2225 "#]]);
2226 }
2227}