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_SELF_UPPER => self.parse_self_upper_expr(),
462
463 KW_BLOCK => self.parse_block_access(),
465 KW_NETWORK => self.parse_network_access(),
466
467 KW_FINAL => self.parse_final_block_expr(),
469
470 _ => {
471 self.error_unexpected(self.current(), &[
472 "an identifier",
473 "a program id",
474 "an address literal",
475 "an integer literal",
476 "a static string",
477 "'!'",
478 "'-'",
479 "'('",
480 "'['",
481 "'true'",
482 "'false'",
483 "'final'",
484 "'block'",
485 "'network'",
486 "'self'",
487 ]);
488 None
489 }
490 }
491 }
492
493 fn parse_integer_literal(&mut self) -> Option<CompletedMarker> {
498 let m = self.start();
499 let text = self.current_text();
500 let kind = if text.ends_with("field") {
501 LITERAL_FIELD
502 } else if text.ends_with("group") {
503 LITERAL_GROUP
504 } else if text.ends_with("scalar") {
505 LITERAL_SCALAR
506 } else {
507 LITERAL_INT
508 };
509 self.bump_any();
510 Some(m.complete(self, kind))
511 }
512
513 fn parse_string_literal(&mut self) -> Option<CompletedMarker> {
515 let m = self.start();
516 self.bump_any();
517 Some(m.complete(self, LITERAL_STRING))
518 }
519
520 fn parse_identifier_literal(&mut self) -> Option<CompletedMarker> {
522 let m = self.start();
523 self.bump_any();
524 Some(m.complete(self, LITERAL_IDENT))
525 }
526
527 fn parse_address_literal(&mut self) -> Option<CompletedMarker> {
529 let m = self.start();
530 self.bump_any();
531 Some(m.complete(self, LITERAL_ADDRESS))
532 }
533
534 fn parse_bool_literal(&mut self) -> Option<CompletedMarker> {
536 let m = self.start();
537 self.bump_any();
538 Some(m.complete(self, LITERAL_BOOL))
539 }
540
541 fn parse_none_literal(&mut self) -> Option<CompletedMarker> {
543 let m = self.start();
544 self.bump_any();
545 Some(m.complete(self, LITERAL_NONE))
546 }
547
548 fn parse_paren_or_tuple_expr(&mut self) -> Option<CompletedMarker> {
550 let m = self.start();
551 self.bump_any(); if self.eat(R_PAREN) {
555 return Some(m.complete(self, TUPLE_EXPR));
556 }
557
558 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
560 self.error_recover("expected expression", EXPR_RECOVERY);
561 }
562
563 if self.eat(COMMA) {
565 if !self.at(R_PAREN) {
567 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
568 self.error_recover("expected tuple element", EXPR_RECOVERY);
569 }
570 while self.eat(COMMA) {
571 if self.at(R_PAREN) {
572 break;
573 }
574 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
575 self.error_recover("expected tuple element", EXPR_RECOVERY);
576 }
577 }
578 }
579 self.expect(R_PAREN);
580 return Some(m.complete(self, TUPLE_EXPR));
581 }
582
583 self.expect(R_PAREN);
585 Some(m.complete(self, PAREN_EXPR))
586 }
587
588 fn parse_array_expr(&mut self) -> Option<CompletedMarker> {
590 let m = self.start();
591 self.bump_any(); if self.eat(R_BRACKET) {
595 return Some(m.complete(self, ARRAY_EXPR));
596 }
597
598 if self.parse_expr().is_none() && !self.at(R_BRACKET) && !self.at(COMMA) && !self.at(SEMICOLON) {
600 self.error_recover("expected array element", EXPR_RECOVERY);
601 }
602
603 if self.eat(SEMICOLON) {
605 if self.parse_expr().is_none() && !self.at(R_BRACKET) {
606 self.error("expected repeat count");
607 }
608 self.expect(R_BRACKET);
609 return Some(m.complete(self, REPEAT_EXPR));
610 }
611
612 while self.eat(COMMA) {
614 if self.at(R_BRACKET) {
615 break;
616 }
617 if self.parse_expr().is_none() && !self.at(R_BRACKET) && !self.at(COMMA) {
618 self.error_recover("expected array element", EXPR_RECOVERY);
619 }
620 }
621
622 self.expect(R_BRACKET);
623 Some(m.complete(self, ARRAY_EXPR))
624 }
625
626 fn parse_ident_expr(&mut self, opts: ExprOpts) -> Option<CompletedMarker> {
628 let m = self.start();
629 self.bump_any(); if self.at(DOT) && self.nth(1) == KW_ALEO {
633 self.bump_any(); self.bump_any(); let is_locator = if self.eat(COLON_COLON) {
637 if self.at(IDENT) {
639 self.bump_any();
640 while self.at(COLON_COLON) && self.nth(1) == IDENT {
642 self.bump_any(); self.bump_any(); }
645 }
646 true
647 } else {
648 false
649 };
650
651 if self.at(COLON_COLON) && self.nth(1) == L_BRACKET {
653 self.bump_any(); self.parse_const_generic_args_bracket();
655 }
656
657 if !opts.no_struct && self.at(L_BRACE) {
659 self.parse_struct_body();
660 let kind = if is_locator { STRUCT_LOCATOR_EXPR } else { STRUCT_EXPR };
661 return Some(m.complete(self, kind));
662 }
663
664 if self.at(L_PAREN) {
666 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
667 let cm = m.complete(self, kind);
668 return self.parse_call_expr(cm);
669 }
670
671 if self.at(AT) {
673 let cm = m.complete(self, TYPE_LOCATOR);
674 return self.parse_dynamic_op_expr(cm);
675 }
676
677 let kind = if is_locator { PATH_LOCATOR_EXPR } else { PROGRAM_REF_EXPR };
678 return Some(m.complete(self, kind));
679 }
680
681 while self.eat(COLON_COLON) {
683 if self.at(L_BRACKET) {
684 self.parse_const_generic_args_bracket();
686 break;
687 } else if self.at(LT) {
688 self.parse_const_generic_args_angle();
691 break;
692 } else if self.at(IDENT) {
693 self.bump_any();
694 } else {
695 self.error("expected identifier after ::");
696 break;
697 }
698 }
699
700 if !opts.no_struct && self.at(L_BRACE) {
702 self.parse_struct_body();
703 return Some(m.complete(self, STRUCT_EXPR));
704 }
705
706 if self.at(L_PAREN) {
708 let cm = m.complete(self, PATH_EXPR);
709 return self.parse_call_expr(cm);
710 }
711
712 if self.at(AT) {
714 let cm = m.complete(self, TYPE_PATH);
715 return self.parse_dynamic_op_expr(cm);
716 }
717
718 Some(m.complete(self, PATH_EXPR))
719 }
720
721 fn parse_struct_body(&mut self) {
724 self.bump_any(); if !self.at(R_BRACE) {
727 if self.at(DOT_DOT) {
729 self.parse_struct_base_update();
730 } else {
731 self.parse_struct_field();
732 while self.eat(COMMA) {
733 if self.at(R_BRACE) {
734 break;
735 }
736 if self.at(DOT_DOT) {
738 self.parse_struct_base_update();
739 break;
740 }
741 self.parse_struct_field();
742 }
743 }
744
745 if self.at(COMMA) {
748 self.error("the base update `..` must be the last entry in a struct initializer");
749 while self.eat(COMMA) {
750 if self.at(R_BRACE) {
751 break;
752 }
753 if self.at(DOT_DOT) {
754 self.parse_struct_base_update();
755 } else {
756 self.parse_struct_field();
757 }
758 }
759 }
760 }
761
762 self.expect(R_BRACE);
763 }
764
765 fn parse_struct_base_update(&mut self) {
767 let m = self.start();
768 self.bump_any(); if self.at(R_BRACE) {
770 self.error("expected base expression after `..`");
772 } else {
773 self.parse_expr();
775 }
776 m.complete(self, STRUCT_BASE_UPDATE);
777 }
778
779 fn parse_struct_field(&mut self) {
781 let m = self.start();
782 self.skip_trivia();
783
784 if self.at(IDENT) {
785 self.bump_any(); if self.eat(COLON) {
788 if self.parse_expr().is_none() && !self.at(R_BRACE) && !self.at(COMMA) {
790 self.error("expected field value");
791 }
792 m.complete(self, STRUCT_FIELD_INIT);
793 } else {
794 m.complete(self, STRUCT_FIELD_SHORTHAND);
796 }
797 } else {
798 self.error("expected field name");
799 m.complete(self, STRUCT_FIELD_INIT);
800 }
801 }
802
803 fn parse_self_expr(&mut self) -> Option<CompletedMarker> {
805 let m = self.start();
806 self.bump_any(); if self.at(COLON_COLON) {
810 self.error("expected '.' -- found '::'");
811 }
812
813 Some(m.complete(self, SELF_EXPR))
814 }
815
816 fn parse_block_access(&mut self) -> Option<CompletedMarker> {
818 let m = self.start();
819 self.bump_any(); Some(m.complete(self, BLOCK_KW_EXPR))
821 }
822
823 fn parse_self_upper_expr(&mut self) -> Option<CompletedMarker> {
830 let m = self.start();
831 self.bump_any(); while self.eat(COLON_COLON) {
834 if self.at(L_BRACKET) {
835 self.parse_const_generic_args_bracket();
836 break;
837 } else if self.at(LT) {
838 self.parse_const_generic_args_angle();
839 break;
840 } else if self.at(IDENT) {
841 self.bump_any();
842 } else {
843 break;
844 }
845 }
846 if self.at(L_PAREN) {
847 self.bump_any(); if !self.at(R_PAREN) {
849 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
850 self.error_recover("expected argument expression", EXPR_RECOVERY);
851 }
852 while self.eat(COMMA) {
853 if self.at(R_PAREN) {
854 break;
855 }
856 if self.parse_expr().is_none() && !self.at(R_PAREN) && !self.at(COMMA) {
857 self.error_recover("expected argument expression", EXPR_RECOVERY);
858 }
859 }
860 }
861 self.expect(R_PAREN);
862 }
863
864 Some(m.complete(self, SELF_UPPER_EXPR))
865 }
866
867 fn parse_network_access(&mut self) -> Option<CompletedMarker> {
869 let m = self.start();
870 self.bump_any(); Some(m.complete(self, NETWORK_KW_EXPR))
872 }
873
874 fn parse_final_block_expr(&mut self) -> Option<CompletedMarker> {
876 let m = self.start();
877 self.bump_any(); self.skip_trivia();
879 if self.parse_block().is_none() {
880 self.error("expected block after 'final'");
881 }
882 Some(m.complete(self, FINAL_EXPR))
883 }
884}
885
886#[cfg(test)]
887mod tests {
888 use super::*;
889 use crate::{lexer::lex, parser::Parse};
890 use expect_test::{Expect, expect};
891
892 fn check_expr(input: &str, expect: Expect) {
893 let (tokens, _) = lex(input);
894 let mut parser = Parser::new(input, &tokens);
895 let root = parser.start();
896 parser.parse_expr();
897 parser.skip_trivia();
898 root.complete(&mut parser, ROOT);
899 let parse: Parse = parser.finish(vec![]);
900 let output = format!("{:#?}", parse.syntax());
901 expect.assert_eq(&output);
902 }
903
904 #[test]
909 fn parse_expr_integer() {
910 check_expr("42", expect![[r#"
911 ROOT@0..2
912 LITERAL_INT@0..2
913 INTEGER@0..2 "42"
914 "#]]);
915 }
916
917 #[test]
918 fn parse_expr_bool_true() {
919 check_expr("true", expect![[r#"
920 ROOT@0..4
921 LITERAL_BOOL@0..4
922 KW_TRUE@0..4 "true"
923 "#]]);
924 }
925
926 #[test]
927 fn parse_expr_bool_false() {
928 check_expr("false", expect![[r#"
929 ROOT@0..5
930 LITERAL_BOOL@0..5
931 KW_FALSE@0..5 "false"
932 "#]]);
933 }
934
935 #[test]
936 fn parse_expr_none() {
937 check_expr("none", expect![[r#"
938 ROOT@0..4
939 LITERAL_NONE@0..4
940 KW_NONE@0..4 "none"
941 "#]]);
942 }
943
944 #[test]
945 fn parse_expr_identifier_literal() {
946 check_expr("'foo'", expect![[r#"
947 ROOT@0..5
948 LITERAL_IDENT@0..5
949 IDENT_LIT@0..5 "'foo'"
950 "#]]);
951 }
952
953 #[test]
958 fn parse_expr_dynamic_call_basic() {
959 check_expr("Adder@(target)::sum(x, y)", expect![[r#"
960 ROOT@0..25
961 DYNAMIC_OP_EXPR@0..25
962 TYPE_PATH@0..5
963 IDENT@0..5 "Adder"
964 AT@5..6 "@"
965 L_PAREN@6..7 "("
966 PATH_EXPR@7..13
967 IDENT@7..13 "target"
968 R_PAREN@13..14 ")"
969 COLON_COLON@14..16 "::"
970 IDENT@16..19 "sum"
971 L_PAREN@19..20 "("
972 PATH_EXPR@20..21
973 IDENT@20..21 "x"
974 COMMA@21..22 ","
975 WHITESPACE@22..23 " "
976 PATH_EXPR@23..24
977 IDENT@23..24 "y"
978 R_PAREN@24..25 ")"
979 "#]]);
980 }
981
982 #[test]
983 fn parse_expr_dynamic_call_identifier_target() {
984 check_expr("Adder@('foo')::sum(x, y)", expect![[r#"
985 ROOT@0..24
986 DYNAMIC_OP_EXPR@0..24
987 TYPE_PATH@0..5
988 IDENT@0..5 "Adder"
989 AT@5..6 "@"
990 L_PAREN@6..7 "("
991 LITERAL_IDENT@7..12
992 IDENT_LIT@7..12 "'foo'"
993 R_PAREN@12..13 ")"
994 COLON_COLON@13..15 "::"
995 IDENT@15..18 "sum"
996 L_PAREN@18..19 "("
997 PATH_EXPR@19..20
998 IDENT@19..20 "x"
999 COMMA@20..21 ","
1000 WHITESPACE@21..22 " "
1001 PATH_EXPR@22..23
1002 IDENT@22..23 "y"
1003 R_PAREN@23..24 ")"
1004 "#]]);
1005 }
1006
1007 #[test]
1008 fn parse_expr_dynamic_call_with_network() {
1009 check_expr("Adder@('foo', 'aleo')::sum(x, y)", expect![[r#"
1010 ROOT@0..32
1011 DYNAMIC_OP_EXPR@0..32
1012 TYPE_PATH@0..5
1013 IDENT@0..5 "Adder"
1014 AT@5..6 "@"
1015 L_PAREN@6..7 "("
1016 LITERAL_IDENT@7..12
1017 IDENT_LIT@7..12 "'foo'"
1018 COMMA@12..13 ","
1019 WHITESPACE@13..14 " "
1020 LITERAL_IDENT@14..20
1021 IDENT_LIT@14..20 "'aleo'"
1022 R_PAREN@20..21 ")"
1023 COLON_COLON@21..23 "::"
1024 IDENT@23..26 "sum"
1025 L_PAREN@26..27 "("
1026 PATH_EXPR@27..28
1027 IDENT@27..28 "x"
1028 COMMA@28..29 ","
1029 WHITESPACE@29..30 " "
1030 PATH_EXPR@30..31
1031 IDENT@30..31 "y"
1032 R_PAREN@31..32 ")"
1033 "#]]);
1034 }
1035
1036 #[test]
1037 fn parse_expr_dynamic_call_no_args() {
1038 check_expr("Adder@(target)::sum()", expect![[r#"
1039 ROOT@0..21
1040 DYNAMIC_OP_EXPR@0..21
1041 TYPE_PATH@0..5
1042 IDENT@0..5 "Adder"
1043 AT@5..6 "@"
1044 L_PAREN@6..7 "("
1045 PATH_EXPR@7..13
1046 IDENT@7..13 "target"
1047 R_PAREN@13..14 ")"
1048 COLON_COLON@14..16 "::"
1049 IDENT@16..19 "sum"
1050 L_PAREN@19..20 "("
1051 R_PAREN@20..21 ")"
1052 "#]]);
1053 }
1054
1055 #[test]
1056 fn parse_expr_dynamic_storage_access() {
1057 check_expr("Bank@(target)::balances.get(key)", expect![[r#"
1058 ROOT@0..32
1059 DYNAMIC_OP_EXPR@0..32
1060 TYPE_PATH@0..4
1061 IDENT@0..4 "Bank"
1062 AT@4..5 "@"
1063 L_PAREN@5..6 "("
1064 PATH_EXPR@6..12
1065 IDENT@6..12 "target"
1066 R_PAREN@12..13 ")"
1067 COLON_COLON@13..15 "::"
1068 IDENT@15..23 "balances"
1069 DOT@23..24 "."
1070 IDENT@24..27 "get"
1071 L_PAREN@27..28 "("
1072 PATH_EXPR@28..31
1073 IDENT@28..31 "key"
1074 R_PAREN@31..32 ")"
1075 "#]]);
1076 }
1077
1078 #[test]
1079 fn parse_expr_dynamic_storage_access_missing_storage_name() {
1080 check_expr("Bank@(target)::.get(key)", expect![[r#"
1084 ROOT@0..24
1085 DYNAMIC_OP_EXPR@0..24
1086 TYPE_PATH@0..4
1087 IDENT@0..4 "Bank"
1088 AT@4..5 "@"
1089 L_PAREN@5..6 "("
1090 PATH_EXPR@6..12
1091 IDENT@6..12 "target"
1092 R_PAREN@12..13 ")"
1093 COLON_COLON@13..15 "::"
1094 DOT@15..16 "."
1095 IDENT@16..19 "get"
1096 L_PAREN@19..20 "("
1097 PATH_EXPR@20..23
1098 IDENT@20..23 "key"
1099 R_PAREN@23..24 ")"
1100 "#]]);
1101 }
1102
1103 #[test]
1104 fn parse_expr_dynamic_storage_access_missing_op() {
1105 check_expr("Bank@(target)::balances.(key)", expect![[r#"
1107 ROOT@0..29
1108 DYNAMIC_OP_EXPR@0..29
1109 TYPE_PATH@0..4
1110 IDENT@0..4 "Bank"
1111 AT@4..5 "@"
1112 L_PAREN@5..6 "("
1113 PATH_EXPR@6..12
1114 IDENT@6..12 "target"
1115 R_PAREN@12..13 ")"
1116 COLON_COLON@13..15 "::"
1117 IDENT@15..23 "balances"
1118 DOT@23..24 "."
1119 L_PAREN@24..25 "("
1120 PATH_EXPR@25..28
1121 IDENT@25..28 "key"
1122 R_PAREN@28..29 ")"
1123 "#]]);
1124 }
1125
1126 #[test]
1127 fn parse_expr_dynamic_read() {
1128 check_expr("Bank@(target)::total", expect![[r#"
1129 ROOT@0..20
1130 DYNAMIC_OP_EXPR@0..20
1131 TYPE_PATH@0..4
1132 IDENT@0..4 "Bank"
1133 AT@4..5 "@"
1134 L_PAREN@5..6 "("
1135 PATH_EXPR@6..12
1136 IDENT@6..12 "target"
1137 R_PAREN@12..13 ")"
1138 COLON_COLON@13..15 "::"
1139 IDENT@15..20 "total"
1140 "#]]);
1141 }
1142
1143 #[test]
1144 fn parse_expr_dynamic_read_with_network() {
1145 check_expr("Bank@('foo', 'aleo')::total", expect![[r#"
1146 ROOT@0..27
1147 DYNAMIC_OP_EXPR@0..27
1148 TYPE_PATH@0..4
1149 IDENT@0..4 "Bank"
1150 AT@4..5 "@"
1151 L_PAREN@5..6 "("
1152 LITERAL_IDENT@6..11
1153 IDENT_LIT@6..11 "'foo'"
1154 COMMA@11..12 ","
1155 WHITESPACE@12..13 " "
1156 LITERAL_IDENT@13..19
1157 IDENT_LIT@13..19 "'aleo'"
1158 R_PAREN@19..20 ")"
1159 COLON_COLON@20..22 "::"
1160 IDENT@22..27 "total"
1161 "#]]);
1162 }
1163
1164 #[test]
1169 fn parse_expr_ident() {
1170 check_expr("foo", expect![[r#"
1171 ROOT@0..3
1172 PATH_EXPR@0..3
1173 IDENT@0..3 "foo"
1174 "#]]);
1175 }
1176
1177 #[test]
1178 fn parse_expr_path() {
1179 check_expr("Foo::bar", expect![[r#"
1180 ROOT@0..8
1181 PATH_EXPR@0..8
1182 IDENT@0..3 "Foo"
1183 COLON_COLON@3..5 "::"
1184 IDENT@5..8 "bar"
1185 "#]]);
1186 }
1187
1188 #[test]
1189 fn parse_expr_self() {
1190 check_expr("self", expect![[r#"
1191 ROOT@0..4
1192 SELF_EXPR@0..4
1193 KW_SELF@0..4 "self"
1194 "#]]);
1195 }
1196
1197 #[test]
1198 fn parse_expr_self_colon_colon_is_error() {
1199 let (tokens, _) = lex("self::y");
1201 let mut parser = Parser::new("self::y", &tokens);
1202 let root = parser.start();
1203 parser.parse_expr();
1204 parser.skip_trivia();
1205 root.complete(&mut parser, ROOT);
1206 let parse: Parse = parser.finish(vec![]);
1207 assert!(!parse.errors().is_empty(), "expected error for self::");
1208 assert!(
1209 parse.errors().iter().any(|e| e.message.contains("expected '.'")),
1210 "expected error message to mention expected '.', got: {:?}",
1211 parse.errors()
1212 );
1213 }
1214
1215 #[test]
1220 fn parse_expr_add() {
1221 check_expr("1 + 2", expect![[r#"
1222 ROOT@0..5
1223 BINARY_EXPR@0..5
1224 LITERAL_INT@0..1
1225 INTEGER@0..1 "1"
1226 WHITESPACE@1..2 " "
1227 PLUS@2..3 "+"
1228 WHITESPACE@3..4 " "
1229 LITERAL_INT@4..5
1230 INTEGER@4..5 "2"
1231 "#]]);
1232 }
1233
1234 #[test]
1235 fn parse_expr_mul() {
1236 check_expr("a * b", expect![[r#"
1237 ROOT@0..5
1238 BINARY_EXPR@0..5
1239 PATH_EXPR@0..2
1240 IDENT@0..1 "a"
1241 WHITESPACE@1..2 " "
1242 STAR@2..3 "*"
1243 WHITESPACE@3..4 " "
1244 PATH_EXPR@4..5
1245 IDENT@4..5 "b"
1246 "#]]);
1247 }
1248
1249 #[test]
1250 fn parse_expr_precedence() {
1251 check_expr("1 + 2 * 3", expect![[r#"
1253 ROOT@0..9
1254 BINARY_EXPR@0..9
1255 LITERAL_INT@0..1
1256 INTEGER@0..1 "1"
1257 WHITESPACE@1..2 " "
1258 PLUS@2..3 "+"
1259 WHITESPACE@3..4 " "
1260 BINARY_EXPR@4..9
1261 LITERAL_INT@4..5
1262 INTEGER@4..5 "2"
1263 WHITESPACE@5..6 " "
1264 STAR@6..7 "*"
1265 WHITESPACE@7..8 " "
1266 LITERAL_INT@8..9
1267 INTEGER@8..9 "3"
1268 "#]]);
1269 }
1270
1271 #[test]
1272 fn parse_expr_power_right_assoc() {
1273 check_expr("a ** b ** c", expect![[r#"
1275 ROOT@0..11
1276 BINARY_EXPR@0..11
1277 PATH_EXPR@0..2
1278 IDENT@0..1 "a"
1279 WHITESPACE@1..2 " "
1280 STAR2@2..4 "**"
1281 WHITESPACE@4..5 " "
1282 BINARY_EXPR@5..11
1283 PATH_EXPR@5..7
1284 IDENT@5..6 "b"
1285 WHITESPACE@6..7 " "
1286 STAR2@7..9 "**"
1287 WHITESPACE@9..10 " "
1288 PATH_EXPR@10..11
1289 IDENT@10..11 "c"
1290 "#]]);
1291 }
1292
1293 #[test]
1298 fn parse_expr_unary_neg() {
1299 check_expr("-x", expect![[r#"
1300 ROOT@0..2
1301 UNARY_EXPR@0..2
1302 MINUS@0..1 "-"
1303 PATH_EXPR@1..2
1304 IDENT@1..2 "x"
1305 "#]]);
1306 }
1307
1308 #[test]
1309 fn parse_expr_unary_not() {
1310 check_expr("!flag", expect![[r#"
1311 ROOT@0..5
1312 UNARY_EXPR@0..5
1313 BANG@0..1 "!"
1314 PATH_EXPR@1..5
1315 IDENT@1..5 "flag"
1316 "#]]);
1317 }
1318
1319 #[test]
1324 fn parse_expr_comparison() {
1325 check_expr("a < b", expect![[r#"
1326 ROOT@0..5
1327 BINARY_EXPR@0..5
1328 PATH_EXPR@0..2
1329 IDENT@0..1 "a"
1330 WHITESPACE@1..2 " "
1331 LT@2..3 "<"
1332 WHITESPACE@3..4 " "
1333 PATH_EXPR@4..5
1334 IDENT@4..5 "b"
1335 "#]]);
1336 }
1337
1338 #[test]
1339 fn parse_expr_logical_and() {
1340 check_expr("a && b", expect![[r#"
1341 ROOT@0..6
1342 BINARY_EXPR@0..6
1343 PATH_EXPR@0..2
1344 IDENT@0..1 "a"
1345 WHITESPACE@1..2 " "
1346 AMP2@2..4 "&&"
1347 WHITESPACE@4..5 " "
1348 PATH_EXPR@5..6
1349 IDENT@5..6 "b"
1350 "#]]);
1351 }
1352
1353 #[test]
1354 fn parse_expr_logical_or() {
1355 check_expr("a || b", expect![[r#"
1356 ROOT@0..6
1357 BINARY_EXPR@0..6
1358 PATH_EXPR@0..2
1359 IDENT@0..1 "a"
1360 WHITESPACE@1..2 " "
1361 PIPE2@2..4 "||"
1362 WHITESPACE@4..5 " "
1363 PATH_EXPR@5..6
1364 IDENT@5..6 "b"
1365 "#]]);
1366 }
1367
1368 #[test]
1373 fn parse_expr_ternary() {
1374 check_expr("a ? b : c", expect![[r#"
1375 ROOT@0..9
1376 TERNARY_EXPR@0..9
1377 PATH_EXPR@0..2
1378 IDENT@0..1 "a"
1379 WHITESPACE@1..2 " "
1380 QUESTION@2..3 "?"
1381 WHITESPACE@3..4 " "
1382 PATH_EXPR@4..6
1383 IDENT@4..5 "b"
1384 WHITESPACE@5..6 " "
1385 COLON@6..7 ":"
1386 WHITESPACE@7..8 " "
1387 PATH_EXPR@8..9
1388 IDENT@8..9 "c"
1389 "#]]);
1390 }
1391
1392 #[test]
1397 fn parse_expr_member_access() {
1398 check_expr("foo.bar", expect![[r#"
1399 ROOT@0..7
1400 FIELD_EXPR@0..7
1401 PATH_EXPR@0..3
1402 IDENT@0..3 "foo"
1403 DOT@3..4 "."
1404 IDENT@4..7 "bar"
1405 "#]]);
1406 }
1407
1408 #[test]
1409 fn parse_expr_tuple_access() {
1410 check_expr("tuple.0", expect![[r#"
1411 ROOT@0..7
1412 TUPLE_ACCESS_EXPR@0..7
1413 PATH_EXPR@0..5
1414 IDENT@0..5 "tuple"
1415 DOT@5..6 "."
1416 INTEGER@6..7 "0"
1417 "#]]);
1418 }
1419
1420 #[test]
1421 fn parse_expr_index() {
1422 check_expr("arr[0]", expect![[r#"
1423 ROOT@0..6
1424 INDEX_EXPR@0..6
1425 PATH_EXPR@0..3
1426 IDENT@0..3 "arr"
1427 L_BRACKET@3..4 "["
1428 LITERAL_INT@4..5
1429 INTEGER@4..5 "0"
1430 R_BRACKET@5..6 "]"
1431 "#]]);
1432 }
1433
1434 #[test]
1435 fn parse_expr_call() {
1436 check_expr("foo(a, b)", expect![[r#"
1437 ROOT@0..9
1438 CALL_EXPR@0..9
1439 PATH_EXPR@0..3
1440 IDENT@0..3 "foo"
1441 L_PAREN@3..4 "("
1442 PATH_EXPR@4..5
1443 IDENT@4..5 "a"
1444 COMMA@5..6 ","
1445 WHITESPACE@6..7 " "
1446 PATH_EXPR@7..8
1447 IDENT@7..8 "b"
1448 R_PAREN@8..9 ")"
1449 "#]]);
1450 }
1451
1452 #[test]
1453 fn parse_expr_method_call() {
1454 check_expr("x.foo()", expect![[r#"
1455 ROOT@0..7
1456 METHOD_CALL_EXPR@0..7
1457 PATH_EXPR@0..1
1458 IDENT@0..1 "x"
1459 DOT@1..2 "."
1460 IDENT@2..5 "foo"
1461 L_PAREN@5..6 "("
1462 R_PAREN@6..7 ")"
1463 "#]]);
1464 }
1465
1466 #[test]
1471 fn parse_expr_cast() {
1472 check_expr("x as u64", expect![[r#"
1473 ROOT@0..8
1474 CAST_EXPR@0..8
1475 PATH_EXPR@0..2
1476 IDENT@0..1 "x"
1477 WHITESPACE@1..2 " "
1478 KW_AS@2..4 "as"
1479 WHITESPACE@4..5 " "
1480 TYPE_PRIMITIVE@5..8
1481 KW_U64@5..8 "u64"
1482 "#]]);
1483 }
1484
1485 #[test]
1490 fn parse_expr_paren() {
1491 check_expr("(a + b)", expect![[r#"
1492 ROOT@0..7
1493 PAREN_EXPR@0..7
1494 L_PAREN@0..1 "("
1495 BINARY_EXPR@1..6
1496 PATH_EXPR@1..3
1497 IDENT@1..2 "a"
1498 WHITESPACE@2..3 " "
1499 PLUS@3..4 "+"
1500 WHITESPACE@4..5 " "
1501 PATH_EXPR@5..6
1502 IDENT@5..6 "b"
1503 R_PAREN@6..7 ")"
1504 "#]]);
1505 }
1506
1507 #[test]
1508 fn parse_expr_tuple() {
1509 check_expr("(a, b)", expect![[r#"
1510 ROOT@0..6
1511 TUPLE_EXPR@0..6
1512 L_PAREN@0..1 "("
1513 PATH_EXPR@1..2
1514 IDENT@1..2 "a"
1515 COMMA@2..3 ","
1516 WHITESPACE@3..4 " "
1517 PATH_EXPR@4..5
1518 IDENT@4..5 "b"
1519 R_PAREN@5..6 ")"
1520 "#]]);
1521 }
1522
1523 #[test]
1524 fn parse_expr_unit() {
1525 check_expr("()", expect![[r#"
1526 ROOT@0..2
1527 TUPLE_EXPR@0..2
1528 L_PAREN@0..1 "("
1529 R_PAREN@1..2 ")"
1530 "#]]);
1531 }
1532
1533 #[test]
1538 fn parse_expr_array() {
1539 check_expr("[1, 2, 3]", expect![[r#"
1540 ROOT@0..9
1541 ARRAY_EXPR@0..9
1542 L_BRACKET@0..1 "["
1543 LITERAL_INT@1..2
1544 INTEGER@1..2 "1"
1545 COMMA@2..3 ","
1546 WHITESPACE@3..4 " "
1547 LITERAL_INT@4..5
1548 INTEGER@4..5 "2"
1549 COMMA@5..6 ","
1550 WHITESPACE@6..7 " "
1551 LITERAL_INT@7..8
1552 INTEGER@7..8 "3"
1553 R_BRACKET@8..9 "]"
1554 "#]]);
1555 }
1556
1557 #[test]
1558 fn parse_expr_array_repeat() {
1559 check_expr("[0; 10]", expect![[r#"
1560 ROOT@0..7
1561 REPEAT_EXPR@0..7
1562 L_BRACKET@0..1 "["
1563 LITERAL_INT@1..2
1564 INTEGER@1..2 "0"
1565 SEMICOLON@2..3 ";"
1566 WHITESPACE@3..4 " "
1567 LITERAL_INT@4..6
1568 INTEGER@4..6 "10"
1569 R_BRACKET@6..7 "]"
1570 "#]]);
1571 }
1572
1573 #[test]
1578 fn parse_expr_struct_init() {
1579 check_expr("Point { x: 1, y: 2 }", expect![[r#"
1580 ROOT@0..20
1581 STRUCT_EXPR@0..20
1582 IDENT@0..5 "Point"
1583 WHITESPACE@5..6 " "
1584 L_BRACE@6..7 "{"
1585 STRUCT_FIELD_INIT@7..12
1586 WHITESPACE@7..8 " "
1587 IDENT@8..9 "x"
1588 COLON@9..10 ":"
1589 WHITESPACE@10..11 " "
1590 LITERAL_INT@11..12
1591 INTEGER@11..12 "1"
1592 COMMA@12..13 ","
1593 STRUCT_FIELD_INIT@13..18
1594 WHITESPACE@13..14 " "
1595 IDENT@14..15 "y"
1596 COLON@15..16 ":"
1597 WHITESPACE@16..17 " "
1598 LITERAL_INT@17..18
1599 INTEGER@17..18 "2"
1600 WHITESPACE@18..19 " "
1601 R_BRACE@19..20 "}"
1602 "#]]);
1603 }
1604
1605 #[test]
1606 fn parse_expr_struct_shorthand() {
1607 check_expr("Point { x, y }", expect![[r#"
1608 ROOT@0..14
1609 STRUCT_EXPR@0..14
1610 IDENT@0..5 "Point"
1611 WHITESPACE@5..6 " "
1612 L_BRACE@6..7 "{"
1613 STRUCT_FIELD_SHORTHAND@7..9
1614 WHITESPACE@7..8 " "
1615 IDENT@8..9 "x"
1616 COMMA@9..10 ","
1617 STRUCT_FIELD_SHORTHAND@10..13
1618 WHITESPACE@10..11 " "
1619 IDENT@11..12 "y"
1620 WHITESPACE@12..13 " "
1621 R_BRACE@13..14 "}"
1622 "#]]);
1623 }
1624
1625 #[test]
1626 fn parse_expr_struct_update_base() {
1627 check_expr("Point { x: 1, ..other }", expect![[r#"
1628 ROOT@0..23
1629 STRUCT_EXPR@0..23
1630 IDENT@0..5 "Point"
1631 WHITESPACE@5..6 " "
1632 L_BRACE@6..7 "{"
1633 STRUCT_FIELD_INIT@7..12
1634 WHITESPACE@7..8 " "
1635 IDENT@8..9 "x"
1636 COLON@9..10 ":"
1637 WHITESPACE@10..11 " "
1638 LITERAL_INT@11..12
1639 INTEGER@11..12 "1"
1640 COMMA@12..13 ","
1641 STRUCT_BASE_UPDATE@13..22
1642 WHITESPACE@13..14 " "
1643 DOT_DOT@14..16 ".."
1644 PATH_EXPR@16..22
1645 IDENT@16..21 "other"
1646 WHITESPACE@21..22 " "
1647 R_BRACE@22..23 "}"
1648 "#]]);
1649 }
1650
1651 #[test]
1652 fn parse_expr_struct_update_base_only() {
1653 check_expr("Point { ..other }", expect![[r#"
1654 ROOT@0..17
1655 STRUCT_EXPR@0..17
1656 IDENT@0..5 "Point"
1657 WHITESPACE@5..6 " "
1658 L_BRACE@6..7 "{"
1659 STRUCT_BASE_UPDATE@7..16
1660 WHITESPACE@7..8 " "
1661 DOT_DOT@8..10 ".."
1662 PATH_EXPR@10..16
1663 IDENT@10..15 "other"
1664 WHITESPACE@15..16 " "
1665 R_BRACE@16..17 "}"
1666 "#]]);
1667 }
1668
1669 fn check_expr_no_errors(input: &str) {
1678 let (tokens, _) = lex(input);
1679 let mut parser = Parser::new(input, &tokens);
1680 let root = parser.start();
1681 parser.parse_expr();
1682 parser.skip_trivia();
1683 root.complete(&mut parser, ROOT);
1684 let parse: Parse = parser.finish(vec![]);
1685 if !parse.errors().is_empty() {
1686 for err in parse.errors() {
1687 eprintln!("error at {:?}: {}", err.range, err.message);
1688 }
1689 eprintln!("tree:\n{:#?}", parse.syntax());
1690 panic!("expression parse had {} error(s)", parse.errors().len());
1691 }
1692 }
1693
1694 #[test]
1695 fn parse_expr_call_const_generic_simple() {
1696 check_expr("foo::[5]()", expect![[r#"
1698 ROOT@0..10
1699 CALL_EXPR@0..10
1700 PATH_EXPR@0..8
1701 IDENT@0..3 "foo"
1702 COLON_COLON@3..5 "::"
1703 CONST_ARG_LIST@5..8
1704 L_BRACKET@5..6 "["
1705 LITERAL_INT@6..7
1706 INTEGER@6..7 "5"
1707 R_BRACKET@7..8 "]"
1708 L_PAREN@8..9 "("
1709 R_PAREN@9..10 ")"
1710 "#]]);
1711 }
1712
1713 #[test]
1714 fn parse_expr_call_const_generic_expr() {
1715 check_expr_no_errors("foo::[N + 1]()");
1717 }
1718
1719 #[test]
1720 fn parse_expr_call_const_generic_multi() {
1721 check_expr_no_errors("bar::[M, K, N]()");
1723 }
1724
1725 #[test]
1726 fn parse_expr_struct_lit_const_generic() {
1727 check_expr("Foo::[8u32] { arr: x }", expect![[r#"
1729 ROOT@0..22
1730 STRUCT_EXPR@0..22
1731 IDENT@0..3 "Foo"
1732 COLON_COLON@3..5 "::"
1733 CONST_ARG_LIST@5..11
1734 L_BRACKET@5..6 "["
1735 LITERAL_INT@6..10
1736 INTEGER@6..10 "8u32"
1737 R_BRACKET@10..11 "]"
1738 WHITESPACE@11..12 " "
1739 L_BRACE@12..13 "{"
1740 STRUCT_FIELD_INIT@13..21
1741 WHITESPACE@13..14 " "
1742 IDENT@14..17 "arr"
1743 COLON@17..18 ":"
1744 WHITESPACE@18..19 " "
1745 PATH_EXPR@19..21
1746 IDENT@19..20 "x"
1747 WHITESPACE@20..21 " "
1748 R_BRACE@21..22 "}"
1749 "#]]);
1750 }
1751
1752 #[test]
1753 fn parse_expr_locator_call_const_generic() {
1754 check_expr_no_errors("child.aleo::foo::[3]()");
1756 }
1757
1758 #[test]
1759 fn parse_expr_assoc_fn_const_generic() {
1760 check_expr_no_errors("Foo::bar::[N]()");
1762 }
1763
1764 #[test]
1769 fn parse_expr_complex() {
1770 check_expr("a.b[c](d) + e", expect![[r#"
1771 ROOT@0..13
1772 BINARY_EXPR@0..13
1773 CALL_EXPR@0..9
1774 INDEX_EXPR@0..6
1775 FIELD_EXPR@0..3
1776 PATH_EXPR@0..1
1777 IDENT@0..1 "a"
1778 DOT@1..2 "."
1779 IDENT@2..3 "b"
1780 L_BRACKET@3..4 "["
1781 PATH_EXPR@4..5
1782 IDENT@4..5 "c"
1783 R_BRACKET@5..6 "]"
1784 L_PAREN@6..7 "("
1785 PATH_EXPR@7..8
1786 IDENT@7..8 "d"
1787 R_PAREN@8..9 ")"
1788 WHITESPACE@9..10 " "
1789 PLUS@10..11 "+"
1790 WHITESPACE@11..12 " "
1791 PATH_EXPR@12..13
1792 IDENT@12..13 "e"
1793 "#]]);
1794 }
1795
1796 fn parse_expr_for_test(input: &str) -> Parse {
1801 let (tokens, _) = lex(input);
1802 let mut parser = Parser::new(input, &tokens);
1803 let root = parser.start();
1804 parser.parse_expr();
1805 parser.skip_trivia();
1806 root.complete(&mut parser, ROOT);
1807 parser.finish(vec![])
1808 }
1809
1810 #[test]
1811 fn parse_expr_chained_eq_is_error() {
1812 let parse = parse_expr_for_test("1 == 2 == 3");
1814 assert!(!parse.errors().is_empty(), "expected error for chained ==, got none");
1815 assert!(
1816 parse.errors().iter().any(|e| e.message.contains("'&&'") || e.message.contains("expected")),
1817 "expected error message about valid operators, got: {:?}",
1818 parse.errors()
1819 );
1820 }
1821
1822 #[test]
1823 fn parse_expr_chained_neq_is_error() {
1824 let parse = parse_expr_for_test("1 != 2 != 3");
1826 assert!(!parse.errors().is_empty(), "expected error for chained !=, got none");
1827 }
1828
1829 #[test]
1830 fn parse_expr_chained_lt_is_error() {
1831 let parse = parse_expr_for_test("1 < 2 < 3");
1833 assert!(!parse.errors().is_empty(), "expected error for chained <, got none");
1834 }
1835
1836 #[test]
1837 fn parse_expr_chained_gt_is_error() {
1838 let parse = parse_expr_for_test("1 > 2 > 3");
1840 assert!(!parse.errors().is_empty(), "expected error for chained >, got none");
1841 }
1842
1843 #[test]
1844 fn parse_expr_comparison_with_logical_is_ok() {
1845 check_expr_no_errors("1 == 2 && 3 == 4");
1847 check_expr_no_errors("1 < 2 || 3 > 4");
1848 }
1849
1850 #[test]
1855 fn parse_expr_group_associated_fn() {
1856 check_expr("group::to_x_coordinate(a)", expect![[r#"
1859 ROOT@0..25
1860 CALL_EXPR@0..25
1861 PATH_EXPR@0..22
1862 IDENT@0..22 "group::to_x_coordinate"
1863 L_PAREN@22..23 "("
1864 PATH_EXPR@23..24
1865 IDENT@23..24 "a"
1866 R_PAREN@24..25 ")"
1867 "#]]);
1868 }
1869
1870 #[test]
1871 fn parse_expr_signature_associated_fn() {
1872 check_expr("signature::verify(s, a, v)", expect![[r#"
1875 ROOT@0..26
1876 CALL_EXPR@0..26
1877 PATH_EXPR@0..17
1878 IDENT@0..17 "signature::verify"
1879 L_PAREN@17..18 "("
1880 PATH_EXPR@18..19
1881 IDENT@18..19 "s"
1882 COMMA@19..20 ","
1883 WHITESPACE@20..21 " "
1884 PATH_EXPR@21..22
1885 IDENT@21..22 "a"
1886 COMMA@22..23 ","
1887 WHITESPACE@23..24 " "
1888 PATH_EXPR@24..25
1889 IDENT@24..25 "v"
1890 R_PAREN@25..26 ")"
1891 "#]]);
1892 }
1893
1894 #[test]
1899 fn parse_expr_chained_le_is_error() {
1900 let parse = parse_expr_for_test("1 <= 2 <= 3");
1901 assert!(!parse.errors().is_empty(), "expected error for chained <=, got none");
1902 }
1903
1904 #[test]
1905 fn parse_expr_chained_ge_is_error() {
1906 let parse = parse_expr_for_test("1 >= 2 >= 3");
1907 assert!(!parse.errors().is_empty(), "expected error for chained >=, got none");
1908 }
1909
1910 #[test]
1911 fn parse_expr_chained_mixed_cmp_is_error() {
1912 let parse = parse_expr_for_test("1 < 2 > 3");
1913 assert!(!parse.errors().is_empty(), "expected error for mixed chained comparisons, got none");
1914 }
1915
1916 #[test]
1921 fn parse_expr_ternary_nested() {
1922 check_expr("a ? b ? c : d : e", expect![[r#"
1923 ROOT@0..17
1924 TERNARY_EXPR@0..17
1925 PATH_EXPR@0..2
1926 IDENT@0..1 "a"
1927 WHITESPACE@1..2 " "
1928 QUESTION@2..3 "?"
1929 WHITESPACE@3..4 " "
1930 TERNARY_EXPR@4..14
1931 PATH_EXPR@4..6
1932 IDENT@4..5 "b"
1933 WHITESPACE@5..6 " "
1934 QUESTION@6..7 "?"
1935 WHITESPACE@7..8 " "
1936 PATH_EXPR@8..10
1937 IDENT@8..9 "c"
1938 WHITESPACE@9..10 " "
1939 COLON@10..11 ":"
1940 WHITESPACE@11..12 " "
1941 PATH_EXPR@12..14
1942 IDENT@12..13 "d"
1943 WHITESPACE@13..14 " "
1944 COLON@14..15 ":"
1945 WHITESPACE@15..16 " "
1946 PATH_EXPR@16..17
1947 IDENT@16..17 "e"
1948 "#]]);
1949 }
1950
1951 #[test]
1956 fn parse_expr_cast_chained() {
1957 check_expr("x as u32 as u64", expect![[r#"
1958 ROOT@0..15
1959 CAST_EXPR@0..15
1960 CAST_EXPR@0..8
1961 PATH_EXPR@0..2
1962 IDENT@0..1 "x"
1963 WHITESPACE@1..2 " "
1964 KW_AS@2..4 "as"
1965 WHITESPACE@4..5 " "
1966 TYPE_PRIMITIVE@5..8
1967 KW_U32@5..8 "u32"
1968 WHITESPACE@8..9 " "
1969 KW_AS@9..11 "as"
1970 WHITESPACE@11..12 " "
1971 TYPE_PRIMITIVE@12..15
1972 KW_U64@12..15 "u64"
1973 "#]]);
1974 }
1975
1976 #[test]
1981 fn parse_expr_array_trailing_comma() {
1982 check_expr("[1, 2, 3,]", expect![[r#"
1983 ROOT@0..10
1984 ARRAY_EXPR@0..10
1985 L_BRACKET@0..1 "["
1986 LITERAL_INT@1..2
1987 INTEGER@1..2 "1"
1988 COMMA@2..3 ","
1989 WHITESPACE@3..4 " "
1990 LITERAL_INT@4..5
1991 INTEGER@4..5 "2"
1992 COMMA@5..6 ","
1993 WHITESPACE@6..7 " "
1994 LITERAL_INT@7..8
1995 INTEGER@7..8 "3"
1996 COMMA@8..9 ","
1997 R_BRACKET@9..10 "]"
1998 "#]]);
1999 }
2000
2001 #[test]
2002 fn parse_expr_array_empty() {
2003 check_expr("[]", expect![[r#"
2004 ROOT@0..2
2005 ARRAY_EXPR@0..2
2006 L_BRACKET@0..1 "["
2007 R_BRACKET@1..2 "]"
2008 "#]]);
2009 }
2010
2011 #[test]
2012 fn parse_expr_tuple_single() {
2013 check_expr("(a,)", expect![[r#"
2014 ROOT@0..4
2015 TUPLE_EXPR@0..4
2016 L_PAREN@0..1 "("
2017 PATH_EXPR@1..2
2018 IDENT@1..2 "a"
2019 COMMA@2..3 ","
2020 R_PAREN@3..4 ")"
2021 "#]]);
2022 }
2023
2024 #[test]
2025 fn parse_expr_tuple_trailing_comma() {
2026 check_expr("(1, 2,)", expect![[r#"
2027 ROOT@0..7
2028 TUPLE_EXPR@0..7
2029 L_PAREN@0..1 "("
2030 LITERAL_INT@1..2
2031 INTEGER@1..2 "1"
2032 COMMA@2..3 ","
2033 WHITESPACE@3..4 " "
2034 LITERAL_INT@4..5
2035 INTEGER@4..5 "2"
2036 COMMA@5..6 ","
2037 R_PAREN@6..7 ")"
2038 "#]]);
2039 }
2040
2041 #[test]
2046 fn parse_expr_struct_empty() {
2047 check_expr("Point { }", expect![[r#"
2048 ROOT@0..9
2049 STRUCT_EXPR@0..9
2050 IDENT@0..5 "Point"
2051 WHITESPACE@5..6 " "
2052 L_BRACE@6..7 "{"
2053 WHITESPACE@7..8 " "
2054 R_BRACE@8..9 "}"
2055 "#]]);
2056 }
2057
2058 #[test]
2059 fn parse_expr_struct_trailing_comma() {
2060 check_expr("Point { x: 1, }", expect![[r#"
2061 ROOT@0..15
2062 STRUCT_EXPR@0..15
2063 IDENT@0..5 "Point"
2064 WHITESPACE@5..6 " "
2065 L_BRACE@6..7 "{"
2066 STRUCT_FIELD_INIT@7..12
2067 WHITESPACE@7..8 " "
2068 IDENT@8..9 "x"
2069 COLON@9..10 ":"
2070 WHITESPACE@10..11 " "
2071 LITERAL_INT@11..12
2072 INTEGER@11..12 "1"
2073 COMMA@12..13 ","
2074 WHITESPACE@13..14 " "
2075 R_BRACE@14..15 "}"
2076 "#]]);
2077 }
2078
2079 #[test]
2080 fn parse_expr_struct_mixed_fields() {
2081 check_expr("Point { x, y: 2 }", expect![[r#"
2082 ROOT@0..17
2083 STRUCT_EXPR@0..17
2084 IDENT@0..5 "Point"
2085 WHITESPACE@5..6 " "
2086 L_BRACE@6..7 "{"
2087 STRUCT_FIELD_SHORTHAND@7..9
2088 WHITESPACE@7..8 " "
2089 IDENT@8..9 "x"
2090 COMMA@9..10 ","
2091 STRUCT_FIELD_INIT@10..15
2092 WHITESPACE@10..11 " "
2093 IDENT@11..12 "y"
2094 COLON@12..13 ":"
2095 WHITESPACE@13..14 " "
2096 LITERAL_INT@14..15
2097 INTEGER@14..15 "2"
2098 WHITESPACE@15..16 " "
2099 R_BRACE@16..17 "}"
2100 "#]]);
2101 }
2102
2103 #[test]
2108 fn parse_expr_string() {
2109 check_expr("\"hello\"", expect![[r#"
2110 ROOT@0..7
2111 LITERAL_STRING@0..7
2112 STRING@0..7 "\"hello\""
2113 "#]]);
2114 }
2115
2116 #[test]
2117 fn parse_expr_address() {
2118 check_expr("aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9", expect![[r#"
2119 ROOT@0..63
2120 LITERAL_ADDRESS@0..63
2121 ADDRESS_LIT@0..63 "aleo1qnr4dkkvkgfqph0v ..."
2122 "#]]);
2123 }
2124
2125 #[test]
2130 fn parse_expr_deep_postfix() {
2131 check_expr("a[0].b.c(x)[1]", expect![[r#"
2132 ROOT@0..14
2133 INDEX_EXPR@0..14
2134 METHOD_CALL_EXPR@0..11
2135 FIELD_EXPR@0..6
2136 INDEX_EXPR@0..4
2137 PATH_EXPR@0..1
2138 IDENT@0..1 "a"
2139 L_BRACKET@1..2 "["
2140 LITERAL_INT@2..3
2141 INTEGER@2..3 "0"
2142 R_BRACKET@3..4 "]"
2143 DOT@4..5 "."
2144 IDENT@5..6 "b"
2145 DOT@6..7 "."
2146 IDENT@7..8 "c"
2147 L_PAREN@8..9 "("
2148 PATH_EXPR@9..10
2149 IDENT@9..10 "x"
2150 R_PAREN@10..11 ")"
2151 L_BRACKET@11..12 "["
2152 LITERAL_INT@12..13
2153 INTEGER@12..13 "1"
2154 R_BRACKET@13..14 "]"
2155 "#]]);
2156 }
2157
2158 #[test]
2163 fn parse_expr_final() {
2164 check_expr("final { foo() }", expect![[r#"
2165 ROOT@0..15
2166 FINAL_EXPR@0..15
2167 KW_FINAL@0..5 "final"
2168 WHITESPACE@5..6 " "
2169 BLOCK@6..15
2170 L_BRACE@6..7 "{"
2171 WHITESPACE@7..8 " "
2172 EXPR_STMT@8..14
2173 CALL_EXPR@8..13
2174 PATH_EXPR@8..11
2175 IDENT@8..11 "foo"
2176 L_PAREN@11..12 "("
2177 R_PAREN@12..13 ")"
2178 WHITESPACE@13..14 " "
2179 ERROR@14..14
2180 R_BRACE@14..15 "}"
2181 "#]]);
2182 }
2183
2184 #[test]
2189 fn parse_expr_mixed_arithmetic() {
2190 check_expr("a + b * c / d - e", expect![[r#"
2192 ROOT@0..17
2193 BINARY_EXPR@0..17
2194 BINARY_EXPR@0..14
2195 PATH_EXPR@0..2
2196 IDENT@0..1 "a"
2197 WHITESPACE@1..2 " "
2198 PLUS@2..3 "+"
2199 WHITESPACE@3..4 " "
2200 BINARY_EXPR@4..14
2201 BINARY_EXPR@4..10
2202 PATH_EXPR@4..6
2203 IDENT@4..5 "b"
2204 WHITESPACE@5..6 " "
2205 STAR@6..7 "*"
2206 WHITESPACE@7..8 " "
2207 PATH_EXPR@8..10
2208 IDENT@8..9 "c"
2209 WHITESPACE@9..10 " "
2210 SLASH@10..11 "/"
2211 WHITESPACE@11..12 " "
2212 PATH_EXPR@12..14
2213 IDENT@12..13 "d"
2214 WHITESPACE@13..14 " "
2215 MINUS@14..15 "-"
2216 WHITESPACE@15..16 " "
2217 PATH_EXPR@16..17
2218 IDENT@16..17 "e"
2219 "#]]);
2220 }
2221
2222 #[test]
2223 fn parse_expr_bitwise_precedence() {
2224 check_expr("a | b & c ^ d", expect![[r#"
2228 ROOT@0..13
2229 BINARY_EXPR@0..13
2230 PATH_EXPR@0..2
2231 IDENT@0..1 "a"
2232 WHITESPACE@1..2 " "
2233 PIPE@2..3 "|"
2234 WHITESPACE@3..4 " "
2235 BINARY_EXPR@4..13
2236 BINARY_EXPR@4..10
2237 PATH_EXPR@4..6
2238 IDENT@4..5 "b"
2239 WHITESPACE@5..6 " "
2240 AMP@6..7 "&"
2241 WHITESPACE@7..8 " "
2242 PATH_EXPR@8..10
2243 IDENT@8..9 "c"
2244 WHITESPACE@9..10 " "
2245 CARET@10..11 "^"
2246 WHITESPACE@11..12 " "
2247 PATH_EXPR@12..13
2248 IDENT@12..13 "d"
2249 "#]]);
2250 }
2251
2252 #[test]
2253 fn parse_expr_shift_chain() {
2254 check_expr("x << 1 >> 2", expect![[r#"
2257 ROOT@0..11
2258 BINARY_EXPR@0..11
2259 BINARY_EXPR@0..6
2260 PATH_EXPR@0..2
2261 IDENT@0..1 "x"
2262 WHITESPACE@1..2 " "
2263 SHL@2..4 "<<"
2264 WHITESPACE@4..5 " "
2265 LITERAL_INT@5..6
2266 INTEGER@5..6 "1"
2267 WHITESPACE@6..7 " "
2268 SHR@7..9 ">>"
2269 WHITESPACE@9..10 " "
2270 LITERAL_INT@10..11
2271 INTEGER@10..11 "2"
2272 "#]]);
2273 }
2274}