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.bump_any(); if !self.at(R_BRACE) {
658 self.parse_struct_field();
659 while self.eat(COMMA) {
660 if self.at(R_BRACE) {
661 break;
662 }
663 self.parse_struct_field();
664 }
665 }
666 self.expect(R_BRACE);
667 let kind = if is_locator { STRUCT_LOCATOR_EXPR } else { STRUCT_EXPR };
668 return Some(m.complete(self, kind));
669 }
670
671 if self.at(L_PAREN) {
673 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
674 let cm = m.complete(self, kind);
675 return self.parse_call_expr(cm);
676 }
677
678 if self.at(AT) {
680 let cm = m.complete(self, TYPE_LOCATOR);
681 return self.parse_dynamic_op_expr(cm);
682 }
683
684 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
685 return Some(m.complete(self, kind));
686 }
687
688 while self.eat(COLON_COLON) {
690 if self.at(L_BRACKET) {
691 self.parse_const_generic_args_bracket();
693 break;
694 } else if self.at(LT) {
695 self.parse_const_generic_args_angle();
698 break;
699 } else if self.at(IDENT) {
700 self.bump_any();
701 } else {
702 self.error("expected identifier after ::");
703 break;
704 }
705 }
706
707 if !opts.no_struct && self.at(L_BRACE) {
709 self.bump_any(); if !self.at(R_BRACE) {
713 self.parse_struct_field();
714 while self.eat(COMMA) {
715 if self.at(R_BRACE) {
716 break;
717 }
718 self.parse_struct_field();
719 }
720 }
721
722 self.expect(R_BRACE);
723 return Some(m.complete(self, STRUCT_EXPR));
724 }
725
726 if self.at(L_PAREN) {
728 let cm = m.complete(self, PATH_EXPR);
729 return self.parse_call_expr(cm);
730 }
731
732 if self.at(AT) {
734 let cm = m.complete(self, TYPE_PATH);
735 return self.parse_dynamic_op_expr(cm);
736 }
737
738 Some(m.complete(self, PATH_EXPR))
739 }
740
741 fn parse_struct_field(&mut self) {
743 let m = self.start();
744 self.skip_trivia();
745
746 if self.at(IDENT) {
747 self.bump_any(); if self.eat(COLON) {
750 if self.parse_expr().is_none() && !self.at(R_BRACE) && !self.at(COMMA) {
752 self.error("expected field value");
753 }
754 m.complete(self, STRUCT_FIELD_INIT);
755 } else {
756 m.complete(self, STRUCT_FIELD_SHORTHAND);
758 }
759 } else {
760 self.error("expected field name");
761 m.complete(self, STRUCT_FIELD_INIT);
762 }
763 }
764
765 fn parse_self_expr(&mut self) -> Option<CompletedMarker> {
767 let m = self.start();
768 self.bump_any(); if self.at(COLON_COLON) {
772 self.error("expected '.' -- found '::'");
773 }
774
775 Some(m.complete(self, SELF_EXPR))
776 }
777
778 fn parse_block_access(&mut self) -> Option<CompletedMarker> {
780 let m = self.start();
781 self.bump_any(); Some(m.complete(self, BLOCK_KW_EXPR))
783 }
784
785 fn parse_network_access(&mut self) -> Option<CompletedMarker> {
787 let m = self.start();
788 self.bump_any(); Some(m.complete(self, NETWORK_KW_EXPR))
790 }
791
792 fn parse_final_block_expr(&mut self) -> Option<CompletedMarker> {
794 let m = self.start();
795 self.bump_any(); self.skip_trivia();
797 if self.parse_block().is_none() {
798 self.error("expected block after 'final'");
799 }
800 Some(m.complete(self, FINAL_EXPR))
801 }
802}
803
804#[cfg(test)]
805mod tests {
806 use super::*;
807 use crate::{lexer::lex, parser::Parse};
808 use expect_test::{Expect, expect};
809
810 fn check_expr(input: &str, expect: Expect) {
811 let (tokens, _) = lex(input);
812 let mut parser = Parser::new(input, &tokens);
813 let root = parser.start();
814 parser.parse_expr();
815 parser.skip_trivia();
816 root.complete(&mut parser, ROOT);
817 let parse: Parse = parser.finish(vec![]);
818 let output = format!("{:#?}", parse.syntax());
819 expect.assert_eq(&output);
820 }
821
822 #[test]
827 fn parse_expr_integer() {
828 check_expr("42", expect![[r#"
829 ROOT@0..2
830 LITERAL_INT@0..2
831 INTEGER@0..2 "42"
832 "#]]);
833 }
834
835 #[test]
836 fn parse_expr_bool_true() {
837 check_expr("true", expect![[r#"
838 ROOT@0..4
839 LITERAL_BOOL@0..4
840 KW_TRUE@0..4 "true"
841 "#]]);
842 }
843
844 #[test]
845 fn parse_expr_bool_false() {
846 check_expr("false", expect![[r#"
847 ROOT@0..5
848 LITERAL_BOOL@0..5
849 KW_FALSE@0..5 "false"
850 "#]]);
851 }
852
853 #[test]
854 fn parse_expr_none() {
855 check_expr("none", expect![[r#"
856 ROOT@0..4
857 LITERAL_NONE@0..4
858 KW_NONE@0..4 "none"
859 "#]]);
860 }
861
862 #[test]
863 fn parse_expr_identifier_literal() {
864 check_expr("'foo'", expect![[r#"
865 ROOT@0..5
866 LITERAL_IDENT@0..5
867 IDENT_LIT@0..5 "'foo'"
868 "#]]);
869 }
870
871 #[test]
876 fn parse_expr_dynamic_call_basic() {
877 check_expr("Adder@(target)::sum(x, y)", expect![[r#"
878 ROOT@0..25
879 DYNAMIC_OP_EXPR@0..25
880 TYPE_PATH@0..5
881 IDENT@0..5 "Adder"
882 AT@5..6 "@"
883 L_PAREN@6..7 "("
884 PATH_EXPR@7..13
885 IDENT@7..13 "target"
886 R_PAREN@13..14 ")"
887 COLON_COLON@14..16 "::"
888 IDENT@16..19 "sum"
889 L_PAREN@19..20 "("
890 PATH_EXPR@20..21
891 IDENT@20..21 "x"
892 COMMA@21..22 ","
893 WHITESPACE@22..23 " "
894 PATH_EXPR@23..24
895 IDENT@23..24 "y"
896 R_PAREN@24..25 ")"
897 "#]]);
898 }
899
900 #[test]
901 fn parse_expr_dynamic_call_identifier_target() {
902 check_expr("Adder@('foo')::sum(x, y)", expect![[r#"
903 ROOT@0..24
904 DYNAMIC_OP_EXPR@0..24
905 TYPE_PATH@0..5
906 IDENT@0..5 "Adder"
907 AT@5..6 "@"
908 L_PAREN@6..7 "("
909 LITERAL_IDENT@7..12
910 IDENT_LIT@7..12 "'foo'"
911 R_PAREN@12..13 ")"
912 COLON_COLON@13..15 "::"
913 IDENT@15..18 "sum"
914 L_PAREN@18..19 "("
915 PATH_EXPR@19..20
916 IDENT@19..20 "x"
917 COMMA@20..21 ","
918 WHITESPACE@21..22 " "
919 PATH_EXPR@22..23
920 IDENT@22..23 "y"
921 R_PAREN@23..24 ")"
922 "#]]);
923 }
924
925 #[test]
926 fn parse_expr_dynamic_call_with_network() {
927 check_expr("Adder@('foo', 'aleo')::sum(x, y)", expect![[r#"
928 ROOT@0..32
929 DYNAMIC_OP_EXPR@0..32
930 TYPE_PATH@0..5
931 IDENT@0..5 "Adder"
932 AT@5..6 "@"
933 L_PAREN@6..7 "("
934 LITERAL_IDENT@7..12
935 IDENT_LIT@7..12 "'foo'"
936 COMMA@12..13 ","
937 WHITESPACE@13..14 " "
938 LITERAL_IDENT@14..20
939 IDENT_LIT@14..20 "'aleo'"
940 R_PAREN@20..21 ")"
941 COLON_COLON@21..23 "::"
942 IDENT@23..26 "sum"
943 L_PAREN@26..27 "("
944 PATH_EXPR@27..28
945 IDENT@27..28 "x"
946 COMMA@28..29 ","
947 WHITESPACE@29..30 " "
948 PATH_EXPR@30..31
949 IDENT@30..31 "y"
950 R_PAREN@31..32 ")"
951 "#]]);
952 }
953
954 #[test]
955 fn parse_expr_dynamic_call_no_args() {
956 check_expr("Adder@(target)::sum()", expect![[r#"
957 ROOT@0..21
958 DYNAMIC_OP_EXPR@0..21
959 TYPE_PATH@0..5
960 IDENT@0..5 "Adder"
961 AT@5..6 "@"
962 L_PAREN@6..7 "("
963 PATH_EXPR@7..13
964 IDENT@7..13 "target"
965 R_PAREN@13..14 ")"
966 COLON_COLON@14..16 "::"
967 IDENT@16..19 "sum"
968 L_PAREN@19..20 "("
969 R_PAREN@20..21 ")"
970 "#]]);
971 }
972
973 #[test]
974 fn parse_expr_dynamic_storage_access() {
975 check_expr("Bank@(target)::balances.get(key)", expect![[r#"
976 ROOT@0..32
977 DYNAMIC_OP_EXPR@0..32
978 TYPE_PATH@0..4
979 IDENT@0..4 "Bank"
980 AT@4..5 "@"
981 L_PAREN@5..6 "("
982 PATH_EXPR@6..12
983 IDENT@6..12 "target"
984 R_PAREN@12..13 ")"
985 COLON_COLON@13..15 "::"
986 IDENT@15..23 "balances"
987 DOT@23..24 "."
988 IDENT@24..27 "get"
989 L_PAREN@27..28 "("
990 PATH_EXPR@28..31
991 IDENT@28..31 "key"
992 R_PAREN@31..32 ")"
993 "#]]);
994 }
995
996 #[test]
997 fn parse_expr_dynamic_storage_access_missing_storage_name() {
998 check_expr("Bank@(target)::.get(key)", expect![[r#"
1002 ROOT@0..24
1003 DYNAMIC_OP_EXPR@0..24
1004 TYPE_PATH@0..4
1005 IDENT@0..4 "Bank"
1006 AT@4..5 "@"
1007 L_PAREN@5..6 "("
1008 PATH_EXPR@6..12
1009 IDENT@6..12 "target"
1010 R_PAREN@12..13 ")"
1011 COLON_COLON@13..15 "::"
1012 DOT@15..16 "."
1013 IDENT@16..19 "get"
1014 L_PAREN@19..20 "("
1015 PATH_EXPR@20..23
1016 IDENT@20..23 "key"
1017 R_PAREN@23..24 ")"
1018 "#]]);
1019 }
1020
1021 #[test]
1022 fn parse_expr_dynamic_storage_access_missing_op() {
1023 check_expr("Bank@(target)::balances.(key)", expect![[r#"
1025 ROOT@0..29
1026 DYNAMIC_OP_EXPR@0..29
1027 TYPE_PATH@0..4
1028 IDENT@0..4 "Bank"
1029 AT@4..5 "@"
1030 L_PAREN@5..6 "("
1031 PATH_EXPR@6..12
1032 IDENT@6..12 "target"
1033 R_PAREN@12..13 ")"
1034 COLON_COLON@13..15 "::"
1035 IDENT@15..23 "balances"
1036 DOT@23..24 "."
1037 L_PAREN@24..25 "("
1038 PATH_EXPR@25..28
1039 IDENT@25..28 "key"
1040 R_PAREN@28..29 ")"
1041 "#]]);
1042 }
1043
1044 #[test]
1045 fn parse_expr_dynamic_read() {
1046 check_expr("Bank@(target)::total", expect![[r#"
1047 ROOT@0..20
1048 DYNAMIC_OP_EXPR@0..20
1049 TYPE_PATH@0..4
1050 IDENT@0..4 "Bank"
1051 AT@4..5 "@"
1052 L_PAREN@5..6 "("
1053 PATH_EXPR@6..12
1054 IDENT@6..12 "target"
1055 R_PAREN@12..13 ")"
1056 COLON_COLON@13..15 "::"
1057 IDENT@15..20 "total"
1058 "#]]);
1059 }
1060
1061 #[test]
1062 fn parse_expr_dynamic_read_with_network() {
1063 check_expr("Bank@('foo', 'aleo')::total", expect![[r#"
1064 ROOT@0..27
1065 DYNAMIC_OP_EXPR@0..27
1066 TYPE_PATH@0..4
1067 IDENT@0..4 "Bank"
1068 AT@4..5 "@"
1069 L_PAREN@5..6 "("
1070 LITERAL_IDENT@6..11
1071 IDENT_LIT@6..11 "'foo'"
1072 COMMA@11..12 ","
1073 WHITESPACE@12..13 " "
1074 LITERAL_IDENT@13..19
1075 IDENT_LIT@13..19 "'aleo'"
1076 R_PAREN@19..20 ")"
1077 COLON_COLON@20..22 "::"
1078 IDENT@22..27 "total"
1079 "#]]);
1080 }
1081
1082 #[test]
1087 fn parse_expr_ident() {
1088 check_expr("foo", expect![[r#"
1089 ROOT@0..3
1090 PATH_EXPR@0..3
1091 IDENT@0..3 "foo"
1092 "#]]);
1093 }
1094
1095 #[test]
1096 fn parse_expr_path() {
1097 check_expr("Foo::bar", expect![[r#"
1098 ROOT@0..8
1099 PATH_EXPR@0..8
1100 IDENT@0..3 "Foo"
1101 COLON_COLON@3..5 "::"
1102 IDENT@5..8 "bar"
1103 "#]]);
1104 }
1105
1106 #[test]
1107 fn parse_expr_self() {
1108 check_expr("self", expect![[r#"
1109 ROOT@0..4
1110 SELF_EXPR@0..4
1111 KW_SELF@0..4 "self"
1112 "#]]);
1113 }
1114
1115 #[test]
1116 fn parse_expr_self_colon_colon_is_error() {
1117 let (tokens, _) = lex("self::y");
1119 let mut parser = Parser::new("self::y", &tokens);
1120 let root = parser.start();
1121 parser.parse_expr();
1122 parser.skip_trivia();
1123 root.complete(&mut parser, ROOT);
1124 let parse: Parse = parser.finish(vec![]);
1125 assert!(!parse.errors().is_empty(), "expected error for self::");
1126 assert!(
1127 parse.errors().iter().any(|e| e.message.contains("expected '.'")),
1128 "expected error message to mention expected '.', got: {:?}",
1129 parse.errors()
1130 );
1131 }
1132
1133 #[test]
1138 fn parse_expr_add() {
1139 check_expr("1 + 2", expect![[r#"
1140 ROOT@0..5
1141 BINARY_EXPR@0..5
1142 LITERAL_INT@0..1
1143 INTEGER@0..1 "1"
1144 WHITESPACE@1..2 " "
1145 PLUS@2..3 "+"
1146 WHITESPACE@3..4 " "
1147 LITERAL_INT@4..5
1148 INTEGER@4..5 "2"
1149 "#]]);
1150 }
1151
1152 #[test]
1153 fn parse_expr_mul() {
1154 check_expr("a * b", expect![[r#"
1155 ROOT@0..5
1156 BINARY_EXPR@0..5
1157 PATH_EXPR@0..2
1158 IDENT@0..1 "a"
1159 WHITESPACE@1..2 " "
1160 STAR@2..3 "*"
1161 WHITESPACE@3..4 " "
1162 PATH_EXPR@4..5
1163 IDENT@4..5 "b"
1164 "#]]);
1165 }
1166
1167 #[test]
1168 fn parse_expr_precedence() {
1169 check_expr("1 + 2 * 3", expect![[r#"
1171 ROOT@0..9
1172 BINARY_EXPR@0..9
1173 LITERAL_INT@0..1
1174 INTEGER@0..1 "1"
1175 WHITESPACE@1..2 " "
1176 PLUS@2..3 "+"
1177 WHITESPACE@3..4 " "
1178 BINARY_EXPR@4..9
1179 LITERAL_INT@4..5
1180 INTEGER@4..5 "2"
1181 WHITESPACE@5..6 " "
1182 STAR@6..7 "*"
1183 WHITESPACE@7..8 " "
1184 LITERAL_INT@8..9
1185 INTEGER@8..9 "3"
1186 "#]]);
1187 }
1188
1189 #[test]
1190 fn parse_expr_power_right_assoc() {
1191 check_expr("a ** b ** c", expect![[r#"
1193 ROOT@0..11
1194 BINARY_EXPR@0..11
1195 PATH_EXPR@0..2
1196 IDENT@0..1 "a"
1197 WHITESPACE@1..2 " "
1198 STAR2@2..4 "**"
1199 WHITESPACE@4..5 " "
1200 BINARY_EXPR@5..11
1201 PATH_EXPR@5..7
1202 IDENT@5..6 "b"
1203 WHITESPACE@6..7 " "
1204 STAR2@7..9 "**"
1205 WHITESPACE@9..10 " "
1206 PATH_EXPR@10..11
1207 IDENT@10..11 "c"
1208 "#]]);
1209 }
1210
1211 #[test]
1216 fn parse_expr_unary_neg() {
1217 check_expr("-x", expect![[r#"
1218 ROOT@0..2
1219 UNARY_EXPR@0..2
1220 MINUS@0..1 "-"
1221 PATH_EXPR@1..2
1222 IDENT@1..2 "x"
1223 "#]]);
1224 }
1225
1226 #[test]
1227 fn parse_expr_unary_not() {
1228 check_expr("!flag", expect![[r#"
1229 ROOT@0..5
1230 UNARY_EXPR@0..5
1231 BANG@0..1 "!"
1232 PATH_EXPR@1..5
1233 IDENT@1..5 "flag"
1234 "#]]);
1235 }
1236
1237 #[test]
1242 fn parse_expr_comparison() {
1243 check_expr("a < b", expect![[r#"
1244 ROOT@0..5
1245 BINARY_EXPR@0..5
1246 PATH_EXPR@0..2
1247 IDENT@0..1 "a"
1248 WHITESPACE@1..2 " "
1249 LT@2..3 "<"
1250 WHITESPACE@3..4 " "
1251 PATH_EXPR@4..5
1252 IDENT@4..5 "b"
1253 "#]]);
1254 }
1255
1256 #[test]
1257 fn parse_expr_logical_and() {
1258 check_expr("a && b", expect![[r#"
1259 ROOT@0..6
1260 BINARY_EXPR@0..6
1261 PATH_EXPR@0..2
1262 IDENT@0..1 "a"
1263 WHITESPACE@1..2 " "
1264 AMP2@2..4 "&&"
1265 WHITESPACE@4..5 " "
1266 PATH_EXPR@5..6
1267 IDENT@5..6 "b"
1268 "#]]);
1269 }
1270
1271 #[test]
1272 fn parse_expr_logical_or() {
1273 check_expr("a || b", expect![[r#"
1274 ROOT@0..6
1275 BINARY_EXPR@0..6
1276 PATH_EXPR@0..2
1277 IDENT@0..1 "a"
1278 WHITESPACE@1..2 " "
1279 PIPE2@2..4 "||"
1280 WHITESPACE@4..5 " "
1281 PATH_EXPR@5..6
1282 IDENT@5..6 "b"
1283 "#]]);
1284 }
1285
1286 #[test]
1291 fn parse_expr_ternary() {
1292 check_expr("a ? b : c", expect![[r#"
1293 ROOT@0..9
1294 TERNARY_EXPR@0..9
1295 PATH_EXPR@0..2
1296 IDENT@0..1 "a"
1297 WHITESPACE@1..2 " "
1298 QUESTION@2..3 "?"
1299 WHITESPACE@3..4 " "
1300 PATH_EXPR@4..6
1301 IDENT@4..5 "b"
1302 WHITESPACE@5..6 " "
1303 COLON@6..7 ":"
1304 WHITESPACE@7..8 " "
1305 PATH_EXPR@8..9
1306 IDENT@8..9 "c"
1307 "#]]);
1308 }
1309
1310 #[test]
1315 fn parse_expr_member_access() {
1316 check_expr("foo.bar", expect![[r#"
1317 ROOT@0..7
1318 FIELD_EXPR@0..7
1319 PATH_EXPR@0..3
1320 IDENT@0..3 "foo"
1321 DOT@3..4 "."
1322 IDENT@4..7 "bar"
1323 "#]]);
1324 }
1325
1326 #[test]
1327 fn parse_expr_tuple_access() {
1328 check_expr("tuple.0", expect![[r#"
1329 ROOT@0..7
1330 TUPLE_ACCESS_EXPR@0..7
1331 PATH_EXPR@0..5
1332 IDENT@0..5 "tuple"
1333 DOT@5..6 "."
1334 INTEGER@6..7 "0"
1335 "#]]);
1336 }
1337
1338 #[test]
1339 fn parse_expr_index() {
1340 check_expr("arr[0]", expect![[r#"
1341 ROOT@0..6
1342 INDEX_EXPR@0..6
1343 PATH_EXPR@0..3
1344 IDENT@0..3 "arr"
1345 L_BRACKET@3..4 "["
1346 LITERAL_INT@4..5
1347 INTEGER@4..5 "0"
1348 R_BRACKET@5..6 "]"
1349 "#]]);
1350 }
1351
1352 #[test]
1353 fn parse_expr_call() {
1354 check_expr("foo(a, b)", expect![[r#"
1355 ROOT@0..9
1356 CALL_EXPR@0..9
1357 PATH_EXPR@0..3
1358 IDENT@0..3 "foo"
1359 L_PAREN@3..4 "("
1360 PATH_EXPR@4..5
1361 IDENT@4..5 "a"
1362 COMMA@5..6 ","
1363 WHITESPACE@6..7 " "
1364 PATH_EXPR@7..8
1365 IDENT@7..8 "b"
1366 R_PAREN@8..9 ")"
1367 "#]]);
1368 }
1369
1370 #[test]
1371 fn parse_expr_method_call() {
1372 check_expr("x.foo()", expect![[r#"
1373 ROOT@0..7
1374 METHOD_CALL_EXPR@0..7
1375 PATH_EXPR@0..1
1376 IDENT@0..1 "x"
1377 DOT@1..2 "."
1378 IDENT@2..5 "foo"
1379 L_PAREN@5..6 "("
1380 R_PAREN@6..7 ")"
1381 "#]]);
1382 }
1383
1384 #[test]
1389 fn parse_expr_cast() {
1390 check_expr("x as u64", expect![[r#"
1391 ROOT@0..8
1392 CAST_EXPR@0..8
1393 PATH_EXPR@0..2
1394 IDENT@0..1 "x"
1395 WHITESPACE@1..2 " "
1396 KW_AS@2..4 "as"
1397 WHITESPACE@4..5 " "
1398 TYPE_PRIMITIVE@5..8
1399 KW_U64@5..8 "u64"
1400 "#]]);
1401 }
1402
1403 #[test]
1408 fn parse_expr_paren() {
1409 check_expr("(a + b)", expect![[r#"
1410 ROOT@0..7
1411 PAREN_EXPR@0..7
1412 L_PAREN@0..1 "("
1413 BINARY_EXPR@1..6
1414 PATH_EXPR@1..3
1415 IDENT@1..2 "a"
1416 WHITESPACE@2..3 " "
1417 PLUS@3..4 "+"
1418 WHITESPACE@4..5 " "
1419 PATH_EXPR@5..6
1420 IDENT@5..6 "b"
1421 R_PAREN@6..7 ")"
1422 "#]]);
1423 }
1424
1425 #[test]
1426 fn parse_expr_tuple() {
1427 check_expr("(a, b)", expect![[r#"
1428 ROOT@0..6
1429 TUPLE_EXPR@0..6
1430 L_PAREN@0..1 "("
1431 PATH_EXPR@1..2
1432 IDENT@1..2 "a"
1433 COMMA@2..3 ","
1434 WHITESPACE@3..4 " "
1435 PATH_EXPR@4..5
1436 IDENT@4..5 "b"
1437 R_PAREN@5..6 ")"
1438 "#]]);
1439 }
1440
1441 #[test]
1442 fn parse_expr_unit() {
1443 check_expr("()", expect![[r#"
1444 ROOT@0..2
1445 TUPLE_EXPR@0..2
1446 L_PAREN@0..1 "("
1447 R_PAREN@1..2 ")"
1448 "#]]);
1449 }
1450
1451 #[test]
1456 fn parse_expr_array() {
1457 check_expr("[1, 2, 3]", expect![[r#"
1458 ROOT@0..9
1459 ARRAY_EXPR@0..9
1460 L_BRACKET@0..1 "["
1461 LITERAL_INT@1..2
1462 INTEGER@1..2 "1"
1463 COMMA@2..3 ","
1464 WHITESPACE@3..4 " "
1465 LITERAL_INT@4..5
1466 INTEGER@4..5 "2"
1467 COMMA@5..6 ","
1468 WHITESPACE@6..7 " "
1469 LITERAL_INT@7..8
1470 INTEGER@7..8 "3"
1471 R_BRACKET@8..9 "]"
1472 "#]]);
1473 }
1474
1475 #[test]
1476 fn parse_expr_array_repeat() {
1477 check_expr("[0; 10]", expect![[r#"
1478 ROOT@0..7
1479 REPEAT_EXPR@0..7
1480 L_BRACKET@0..1 "["
1481 LITERAL_INT@1..2
1482 INTEGER@1..2 "0"
1483 SEMICOLON@2..3 ";"
1484 WHITESPACE@3..4 " "
1485 LITERAL_INT@4..6
1486 INTEGER@4..6 "10"
1487 R_BRACKET@6..7 "]"
1488 "#]]);
1489 }
1490
1491 #[test]
1496 fn parse_expr_struct_init() {
1497 check_expr("Point { x: 1, y: 2 }", expect![[r#"
1498 ROOT@0..20
1499 STRUCT_EXPR@0..20
1500 IDENT@0..5 "Point"
1501 WHITESPACE@5..6 " "
1502 L_BRACE@6..7 "{"
1503 STRUCT_FIELD_INIT@7..12
1504 WHITESPACE@7..8 " "
1505 IDENT@8..9 "x"
1506 COLON@9..10 ":"
1507 WHITESPACE@10..11 " "
1508 LITERAL_INT@11..12
1509 INTEGER@11..12 "1"
1510 COMMA@12..13 ","
1511 STRUCT_FIELD_INIT@13..18
1512 WHITESPACE@13..14 " "
1513 IDENT@14..15 "y"
1514 COLON@15..16 ":"
1515 WHITESPACE@16..17 " "
1516 LITERAL_INT@17..18
1517 INTEGER@17..18 "2"
1518 WHITESPACE@18..19 " "
1519 R_BRACE@19..20 "}"
1520 "#]]);
1521 }
1522
1523 #[test]
1524 fn parse_expr_struct_shorthand() {
1525 check_expr("Point { x, y }", expect![[r#"
1526 ROOT@0..14
1527 STRUCT_EXPR@0..14
1528 IDENT@0..5 "Point"
1529 WHITESPACE@5..6 " "
1530 L_BRACE@6..7 "{"
1531 STRUCT_FIELD_SHORTHAND@7..9
1532 WHITESPACE@7..8 " "
1533 IDENT@8..9 "x"
1534 COMMA@9..10 ","
1535 STRUCT_FIELD_SHORTHAND@10..13
1536 WHITESPACE@10..11 " "
1537 IDENT@11..12 "y"
1538 WHITESPACE@12..13 " "
1539 R_BRACE@13..14 "}"
1540 "#]]);
1541 }
1542
1543 fn check_expr_no_errors(input: &str) {
1552 let (tokens, _) = lex(input);
1553 let mut parser = Parser::new(input, &tokens);
1554 let root = parser.start();
1555 parser.parse_expr();
1556 parser.skip_trivia();
1557 root.complete(&mut parser, ROOT);
1558 let parse: Parse = parser.finish(vec![]);
1559 if !parse.errors().is_empty() {
1560 for err in parse.errors() {
1561 eprintln!("error at {:?}: {}", err.range, err.message);
1562 }
1563 eprintln!("tree:\n{:#?}", parse.syntax());
1564 panic!("expression parse had {} error(s)", parse.errors().len());
1565 }
1566 }
1567
1568 #[test]
1569 fn parse_expr_call_const_generic_simple() {
1570 check_expr("foo::[5]()", expect![[r#"
1572 ROOT@0..10
1573 CALL_EXPR@0..10
1574 PATH_EXPR@0..8
1575 IDENT@0..3 "foo"
1576 COLON_COLON@3..5 "::"
1577 CONST_ARG_LIST@5..8
1578 L_BRACKET@5..6 "["
1579 LITERAL_INT@6..7
1580 INTEGER@6..7 "5"
1581 R_BRACKET@7..8 "]"
1582 L_PAREN@8..9 "("
1583 R_PAREN@9..10 ")"
1584 "#]]);
1585 }
1586
1587 #[test]
1588 fn parse_expr_call_const_generic_expr() {
1589 check_expr_no_errors("foo::[N + 1]()");
1591 }
1592
1593 #[test]
1594 fn parse_expr_call_const_generic_multi() {
1595 check_expr_no_errors("bar::[M, K, N]()");
1597 }
1598
1599 #[test]
1600 fn parse_expr_struct_lit_const_generic() {
1601 check_expr("Foo::[8u32] { arr: x }", expect![[r#"
1603 ROOT@0..22
1604 STRUCT_EXPR@0..22
1605 IDENT@0..3 "Foo"
1606 COLON_COLON@3..5 "::"
1607 CONST_ARG_LIST@5..11
1608 L_BRACKET@5..6 "["
1609 LITERAL_INT@6..10
1610 INTEGER@6..10 "8u32"
1611 R_BRACKET@10..11 "]"
1612 WHITESPACE@11..12 " "
1613 L_BRACE@12..13 "{"
1614 STRUCT_FIELD_INIT@13..21
1615 WHITESPACE@13..14 " "
1616 IDENT@14..17 "arr"
1617 COLON@17..18 ":"
1618 WHITESPACE@18..19 " "
1619 PATH_EXPR@19..21
1620 IDENT@19..20 "x"
1621 WHITESPACE@20..21 " "
1622 R_BRACE@21..22 "}"
1623 "#]]);
1624 }
1625
1626 #[test]
1627 fn parse_expr_locator_call_const_generic() {
1628 check_expr_no_errors("child.aleo::foo::[3]()");
1630 }
1631
1632 #[test]
1633 fn parse_expr_assoc_fn_const_generic() {
1634 check_expr_no_errors("Foo::bar::[N]()");
1636 }
1637
1638 #[test]
1643 fn parse_expr_complex() {
1644 check_expr("a.b[c](d) + e", expect![[r#"
1645 ROOT@0..13
1646 BINARY_EXPR@0..13
1647 CALL_EXPR@0..9
1648 INDEX_EXPR@0..6
1649 FIELD_EXPR@0..3
1650 PATH_EXPR@0..1
1651 IDENT@0..1 "a"
1652 DOT@1..2 "."
1653 IDENT@2..3 "b"
1654 L_BRACKET@3..4 "["
1655 PATH_EXPR@4..5
1656 IDENT@4..5 "c"
1657 R_BRACKET@5..6 "]"
1658 L_PAREN@6..7 "("
1659 PATH_EXPR@7..8
1660 IDENT@7..8 "d"
1661 R_PAREN@8..9 ")"
1662 WHITESPACE@9..10 " "
1663 PLUS@10..11 "+"
1664 WHITESPACE@11..12 " "
1665 PATH_EXPR@12..13
1666 IDENT@12..13 "e"
1667 "#]]);
1668 }
1669
1670 fn parse_expr_for_test(input: &str) -> Parse {
1675 let (tokens, _) = lex(input);
1676 let mut parser = Parser::new(input, &tokens);
1677 let root = parser.start();
1678 parser.parse_expr();
1679 parser.skip_trivia();
1680 root.complete(&mut parser, ROOT);
1681 parser.finish(vec![])
1682 }
1683
1684 #[test]
1685 fn parse_expr_chained_eq_is_error() {
1686 let parse = parse_expr_for_test("1 == 2 == 3");
1688 assert!(!parse.errors().is_empty(), "expected error for chained ==, got none");
1689 assert!(
1690 parse.errors().iter().any(|e| e.message.contains("'&&'") || e.message.contains("expected")),
1691 "expected error message about valid operators, got: {:?}",
1692 parse.errors()
1693 );
1694 }
1695
1696 #[test]
1697 fn parse_expr_chained_neq_is_error() {
1698 let parse = parse_expr_for_test("1 != 2 != 3");
1700 assert!(!parse.errors().is_empty(), "expected error for chained !=, got none");
1701 }
1702
1703 #[test]
1704 fn parse_expr_chained_lt_is_error() {
1705 let parse = parse_expr_for_test("1 < 2 < 3");
1707 assert!(!parse.errors().is_empty(), "expected error for chained <, got none");
1708 }
1709
1710 #[test]
1711 fn parse_expr_chained_gt_is_error() {
1712 let parse = parse_expr_for_test("1 > 2 > 3");
1714 assert!(!parse.errors().is_empty(), "expected error for chained >, got none");
1715 }
1716
1717 #[test]
1718 fn parse_expr_comparison_with_logical_is_ok() {
1719 check_expr_no_errors("1 == 2 && 3 == 4");
1721 check_expr_no_errors("1 < 2 || 3 > 4");
1722 }
1723
1724 #[test]
1729 fn parse_expr_group_associated_fn() {
1730 check_expr("group::to_x_coordinate(a)", expect![[r#"
1733 ROOT@0..25
1734 CALL_EXPR@0..25
1735 PATH_EXPR@0..22
1736 IDENT@0..22 "group::to_x_coordinate"
1737 L_PAREN@22..23 "("
1738 PATH_EXPR@23..24
1739 IDENT@23..24 "a"
1740 R_PAREN@24..25 ")"
1741 "#]]);
1742 }
1743
1744 #[test]
1745 fn parse_expr_signature_associated_fn() {
1746 check_expr("signature::verify(s, a, v)", expect![[r#"
1749 ROOT@0..26
1750 CALL_EXPR@0..26
1751 PATH_EXPR@0..17
1752 IDENT@0..17 "signature::verify"
1753 L_PAREN@17..18 "("
1754 PATH_EXPR@18..19
1755 IDENT@18..19 "s"
1756 COMMA@19..20 ","
1757 WHITESPACE@20..21 " "
1758 PATH_EXPR@21..22
1759 IDENT@21..22 "a"
1760 COMMA@22..23 ","
1761 WHITESPACE@23..24 " "
1762 PATH_EXPR@24..25
1763 IDENT@24..25 "v"
1764 R_PAREN@25..26 ")"
1765 "#]]);
1766 }
1767
1768 #[test]
1773 fn parse_expr_chained_le_is_error() {
1774 let parse = parse_expr_for_test("1 <= 2 <= 3");
1775 assert!(!parse.errors().is_empty(), "expected error for chained <=, got none");
1776 }
1777
1778 #[test]
1779 fn parse_expr_chained_ge_is_error() {
1780 let parse = parse_expr_for_test("1 >= 2 >= 3");
1781 assert!(!parse.errors().is_empty(), "expected error for chained >=, got none");
1782 }
1783
1784 #[test]
1785 fn parse_expr_chained_mixed_cmp_is_error() {
1786 let parse = parse_expr_for_test("1 < 2 > 3");
1787 assert!(!parse.errors().is_empty(), "expected error for mixed chained comparisons, got none");
1788 }
1789
1790 #[test]
1795 fn parse_expr_ternary_nested() {
1796 check_expr("a ? b ? c : d : e", expect![[r#"
1797 ROOT@0..17
1798 TERNARY_EXPR@0..17
1799 PATH_EXPR@0..2
1800 IDENT@0..1 "a"
1801 WHITESPACE@1..2 " "
1802 QUESTION@2..3 "?"
1803 WHITESPACE@3..4 " "
1804 TERNARY_EXPR@4..14
1805 PATH_EXPR@4..6
1806 IDENT@4..5 "b"
1807 WHITESPACE@5..6 " "
1808 QUESTION@6..7 "?"
1809 WHITESPACE@7..8 " "
1810 PATH_EXPR@8..10
1811 IDENT@8..9 "c"
1812 WHITESPACE@9..10 " "
1813 COLON@10..11 ":"
1814 WHITESPACE@11..12 " "
1815 PATH_EXPR@12..14
1816 IDENT@12..13 "d"
1817 WHITESPACE@13..14 " "
1818 COLON@14..15 ":"
1819 WHITESPACE@15..16 " "
1820 PATH_EXPR@16..17
1821 IDENT@16..17 "e"
1822 "#]]);
1823 }
1824
1825 #[test]
1830 fn parse_expr_cast_chained() {
1831 check_expr("x as u32 as u64", expect![[r#"
1832 ROOT@0..15
1833 CAST_EXPR@0..15
1834 CAST_EXPR@0..8
1835 PATH_EXPR@0..2
1836 IDENT@0..1 "x"
1837 WHITESPACE@1..2 " "
1838 KW_AS@2..4 "as"
1839 WHITESPACE@4..5 " "
1840 TYPE_PRIMITIVE@5..8
1841 KW_U32@5..8 "u32"
1842 WHITESPACE@8..9 " "
1843 KW_AS@9..11 "as"
1844 WHITESPACE@11..12 " "
1845 TYPE_PRIMITIVE@12..15
1846 KW_U64@12..15 "u64"
1847 "#]]);
1848 }
1849
1850 #[test]
1855 fn parse_expr_array_trailing_comma() {
1856 check_expr("[1, 2, 3,]", expect![[r#"
1857 ROOT@0..10
1858 ARRAY_EXPR@0..10
1859 L_BRACKET@0..1 "["
1860 LITERAL_INT@1..2
1861 INTEGER@1..2 "1"
1862 COMMA@2..3 ","
1863 WHITESPACE@3..4 " "
1864 LITERAL_INT@4..5
1865 INTEGER@4..5 "2"
1866 COMMA@5..6 ","
1867 WHITESPACE@6..7 " "
1868 LITERAL_INT@7..8
1869 INTEGER@7..8 "3"
1870 COMMA@8..9 ","
1871 R_BRACKET@9..10 "]"
1872 "#]]);
1873 }
1874
1875 #[test]
1876 fn parse_expr_array_empty() {
1877 check_expr("[]", expect![[r#"
1878 ROOT@0..2
1879 ARRAY_EXPR@0..2
1880 L_BRACKET@0..1 "["
1881 R_BRACKET@1..2 "]"
1882 "#]]);
1883 }
1884
1885 #[test]
1886 fn parse_expr_tuple_single() {
1887 check_expr("(a,)", expect![[r#"
1888 ROOT@0..4
1889 TUPLE_EXPR@0..4
1890 L_PAREN@0..1 "("
1891 PATH_EXPR@1..2
1892 IDENT@1..2 "a"
1893 COMMA@2..3 ","
1894 R_PAREN@3..4 ")"
1895 "#]]);
1896 }
1897
1898 #[test]
1899 fn parse_expr_tuple_trailing_comma() {
1900 check_expr("(1, 2,)", expect![[r#"
1901 ROOT@0..7
1902 TUPLE_EXPR@0..7
1903 L_PAREN@0..1 "("
1904 LITERAL_INT@1..2
1905 INTEGER@1..2 "1"
1906 COMMA@2..3 ","
1907 WHITESPACE@3..4 " "
1908 LITERAL_INT@4..5
1909 INTEGER@4..5 "2"
1910 COMMA@5..6 ","
1911 R_PAREN@6..7 ")"
1912 "#]]);
1913 }
1914
1915 #[test]
1920 fn parse_expr_struct_empty() {
1921 check_expr("Point { }", expect![[r#"
1922 ROOT@0..9
1923 STRUCT_EXPR@0..9
1924 IDENT@0..5 "Point"
1925 WHITESPACE@5..6 " "
1926 L_BRACE@6..7 "{"
1927 WHITESPACE@7..8 " "
1928 R_BRACE@8..9 "}"
1929 "#]]);
1930 }
1931
1932 #[test]
1933 fn parse_expr_struct_trailing_comma() {
1934 check_expr("Point { x: 1, }", expect![[r#"
1935 ROOT@0..15
1936 STRUCT_EXPR@0..15
1937 IDENT@0..5 "Point"
1938 WHITESPACE@5..6 " "
1939 L_BRACE@6..7 "{"
1940 STRUCT_FIELD_INIT@7..12
1941 WHITESPACE@7..8 " "
1942 IDENT@8..9 "x"
1943 COLON@9..10 ":"
1944 WHITESPACE@10..11 " "
1945 LITERAL_INT@11..12
1946 INTEGER@11..12 "1"
1947 COMMA@12..13 ","
1948 WHITESPACE@13..14 " "
1949 R_BRACE@14..15 "}"
1950 "#]]);
1951 }
1952
1953 #[test]
1954 fn parse_expr_struct_mixed_fields() {
1955 check_expr("Point { x, y: 2 }", expect![[r#"
1956 ROOT@0..17
1957 STRUCT_EXPR@0..17
1958 IDENT@0..5 "Point"
1959 WHITESPACE@5..6 " "
1960 L_BRACE@6..7 "{"
1961 STRUCT_FIELD_SHORTHAND@7..9
1962 WHITESPACE@7..8 " "
1963 IDENT@8..9 "x"
1964 COMMA@9..10 ","
1965 STRUCT_FIELD_INIT@10..15
1966 WHITESPACE@10..11 " "
1967 IDENT@11..12 "y"
1968 COLON@12..13 ":"
1969 WHITESPACE@13..14 " "
1970 LITERAL_INT@14..15
1971 INTEGER@14..15 "2"
1972 WHITESPACE@15..16 " "
1973 R_BRACE@16..17 "}"
1974 "#]]);
1975 }
1976
1977 #[test]
1982 fn parse_expr_string() {
1983 check_expr("\"hello\"", expect![[r#"
1984 ROOT@0..7
1985 LITERAL_STRING@0..7
1986 STRING@0..7 "\"hello\""
1987 "#]]);
1988 }
1989
1990 #[test]
1991 fn parse_expr_address() {
1992 check_expr("aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9", expect![[r#"
1993 ROOT@0..63
1994 LITERAL_ADDRESS@0..63
1995 ADDRESS_LIT@0..63 "aleo1qnr4dkkvkgfqph0v ..."
1996 "#]]);
1997 }
1998
1999 #[test]
2004 fn parse_expr_deep_postfix() {
2005 check_expr("a[0].b.c(x)[1]", expect![[r#"
2006 ROOT@0..14
2007 INDEX_EXPR@0..14
2008 METHOD_CALL_EXPR@0..11
2009 FIELD_EXPR@0..6
2010 INDEX_EXPR@0..4
2011 PATH_EXPR@0..1
2012 IDENT@0..1 "a"
2013 L_BRACKET@1..2 "["
2014 LITERAL_INT@2..3
2015 INTEGER@2..3 "0"
2016 R_BRACKET@3..4 "]"
2017 DOT@4..5 "."
2018 IDENT@5..6 "b"
2019 DOT@6..7 "."
2020 IDENT@7..8 "c"
2021 L_PAREN@8..9 "("
2022 PATH_EXPR@9..10
2023 IDENT@9..10 "x"
2024 R_PAREN@10..11 ")"
2025 L_BRACKET@11..12 "["
2026 LITERAL_INT@12..13
2027 INTEGER@12..13 "1"
2028 R_BRACKET@13..14 "]"
2029 "#]]);
2030 }
2031
2032 #[test]
2037 fn parse_expr_final() {
2038 check_expr("final { foo() }", expect![[r#"
2039 ROOT@0..15
2040 FINAL_EXPR@0..15
2041 KW_FINAL@0..5 "final"
2042 WHITESPACE@5..6 " "
2043 BLOCK@6..15
2044 L_BRACE@6..7 "{"
2045 WHITESPACE@7..8 " "
2046 EXPR_STMT@8..14
2047 CALL_EXPR@8..13
2048 PATH_EXPR@8..11
2049 IDENT@8..11 "foo"
2050 L_PAREN@11..12 "("
2051 R_PAREN@12..13 ")"
2052 WHITESPACE@13..14 " "
2053 ERROR@14..14
2054 R_BRACE@14..15 "}"
2055 "#]]);
2056 }
2057
2058 #[test]
2063 fn parse_expr_mixed_arithmetic() {
2064 check_expr("a + b * c / d - e", expect![[r#"
2066 ROOT@0..17
2067 BINARY_EXPR@0..17
2068 BINARY_EXPR@0..14
2069 PATH_EXPR@0..2
2070 IDENT@0..1 "a"
2071 WHITESPACE@1..2 " "
2072 PLUS@2..3 "+"
2073 WHITESPACE@3..4 " "
2074 BINARY_EXPR@4..14
2075 BINARY_EXPR@4..10
2076 PATH_EXPR@4..6
2077 IDENT@4..5 "b"
2078 WHITESPACE@5..6 " "
2079 STAR@6..7 "*"
2080 WHITESPACE@7..8 " "
2081 PATH_EXPR@8..10
2082 IDENT@8..9 "c"
2083 WHITESPACE@9..10 " "
2084 SLASH@10..11 "/"
2085 WHITESPACE@11..12 " "
2086 PATH_EXPR@12..14
2087 IDENT@12..13 "d"
2088 WHITESPACE@13..14 " "
2089 MINUS@14..15 "-"
2090 WHITESPACE@15..16 " "
2091 PATH_EXPR@16..17
2092 IDENT@16..17 "e"
2093 "#]]);
2094 }
2095
2096 #[test]
2097 fn parse_expr_bitwise_precedence() {
2098 check_expr("a | b & c ^ d", expect![[r#"
2102 ROOT@0..13
2103 BINARY_EXPR@0..13
2104 PATH_EXPR@0..2
2105 IDENT@0..1 "a"
2106 WHITESPACE@1..2 " "
2107 PIPE@2..3 "|"
2108 WHITESPACE@3..4 " "
2109 BINARY_EXPR@4..13
2110 BINARY_EXPR@4..10
2111 PATH_EXPR@4..6
2112 IDENT@4..5 "b"
2113 WHITESPACE@5..6 " "
2114 AMP@6..7 "&"
2115 WHITESPACE@7..8 " "
2116 PATH_EXPR@8..10
2117 IDENT@8..9 "c"
2118 WHITESPACE@9..10 " "
2119 CARET@10..11 "^"
2120 WHITESPACE@11..12 " "
2121 PATH_EXPR@12..13
2122 IDENT@12..13 "d"
2123 "#]]);
2124 }
2125
2126 #[test]
2127 fn parse_expr_shift_chain() {
2128 check_expr("x << 1 >> 2", expect![[r#"
2131 ROOT@0..11
2132 BINARY_EXPR@0..11
2133 BINARY_EXPR@0..6
2134 PATH_EXPR@0..2
2135 IDENT@0..1 "x"
2136 WHITESPACE@1..2 " "
2137 SHL@2..4 "<<"
2138 WHITESPACE@4..5 " "
2139 LITERAL_INT@5..6
2140 INTEGER@5..6 "1"
2141 WHITESPACE@6..7 " "
2142 SHR@7..9 ">>"
2143 WHITESPACE@9..10 " "
2144 LITERAL_INT@10..11
2145 INTEGER@10..11 "2"
2146 "#]]);
2147 }
2148}