1use super::{CompletedMarker, Parser};
29use crate::syntax_kind::SyntaxKind::*;
30
31#[derive(Default, Clone, Copy)]
33pub struct TypeOpts {
34 pub allow_optional: bool,
36}
37
38impl TypeOpts {
39 pub fn allow_optional(mut self) -> Self {
41 self.allow_optional = true;
42 self
43 }
44}
45
46impl Parser<'_, '_> {
47 pub fn parse_type(&mut self) -> Option<CompletedMarker> {
51 self.parse_type_with_opts(TypeOpts::default().allow_optional())
52 }
53
54 pub fn parse_type_with_opts(&mut self, opts: TypeOpts) -> Option<CompletedMarker> {
56 let ty = self.parse_type_inner()?;
57
58 if opts.allow_optional && self.at(QUESTION) {
60 let m = ty.precede(self);
61 self.bump_any(); return Some(m.complete(self, TYPE_OPTIONAL));
63 }
64
65 Some(ty)
66 }
67
68 fn parse_type_inner(&mut self) -> Option<CompletedMarker> {
70 self.skip_trivia();
72
73 match self.current() {
74 L_PAREN => self.parse_tuple_type(),
76 L_BRACKET => self.parse_array_or_vector_type(),
78 KW_FUTURE => self.parse_future_type(),
80 KW_MAPPING => self.parse_mapping_type(),
82 _ if self.at_primitive_type() => self.parse_primitive_type(),
84 IDENT => self.parse_named_type(),
86 _ => None,
87 }
88 }
89
90 fn at_primitive_type(&self) -> bool {
92 matches!(
93 self.current(),
94 KW_ADDRESS
95 | KW_BOOL
96 | KW_FIELD
97 | KW_GROUP
98 | KW_SCALAR
99 | KW_SIGNATURE
100 | KW_STRING
101 | KW_I8
102 | KW_I16
103 | KW_I32
104 | KW_I64
105 | KW_I128
106 | KW_U8
107 | KW_U16
108 | KW_U32
109 | KW_U64
110 | KW_U128
111 )
112 }
113
114 fn parse_primitive_type(&mut self) -> Option<CompletedMarker> {
116 if !self.at_primitive_type() {
117 return None;
118 }
119
120 let m = self.start();
121 self.bump_any();
122 Some(m.complete(self, TYPE_PATH))
123 }
124
125 fn parse_tuple_type(&mut self) -> Option<CompletedMarker> {
127 if !self.at(L_PAREN) {
128 return None;
129 }
130
131 let m = self.start();
132 self.bump_any(); if self.eat(R_PAREN) {
136 return Some(m.complete(self, TYPE_TUPLE));
137 }
138
139 self.parse_type_with_opts(TypeOpts::default().allow_optional());
141
142 while self.eat(COMMA) {
144 if self.at(R_PAREN) {
145 break;
147 }
148 self.parse_type_with_opts(TypeOpts::default().allow_optional());
149 }
150
151 self.expect(R_PAREN);
152 Some(m.complete(self, TYPE_TUPLE))
153 }
154
155 fn parse_array_or_vector_type(&mut self) -> Option<CompletedMarker> {
157 if !self.at(L_BRACKET) {
158 return None;
159 }
160
161 let m = self.start();
162 self.bump_any(); self.parse_type_with_opts(TypeOpts::default().allow_optional());
166
167 if self.eat(SEMICOLON) {
169 self.parse_array_length();
171 self.expect(R_BRACKET);
172 return Some(m.complete(self, TYPE_ARRAY));
173 }
174
175 self.expect(R_BRACKET);
177 Some(m.complete(self, TYPE_ARRAY))
178 }
179
180 fn parse_array_length(&mut self) {
185 self.parse_expr();
186 }
187
188 fn parse_future_type(&mut self) -> Option<CompletedMarker> {
190 if !self.at(KW_FUTURE) {
191 return None;
192 }
193
194 let m = self.start();
195 self.bump_any(); if self.eat(LT) {
199 self.expect(KW_FN);
201 self.expect(L_PAREN);
202
203 if !self.at(R_PAREN) {
205 self.parse_type_with_opts(TypeOpts::default().allow_optional());
206 while self.eat(COMMA) {
207 if self.at(R_PAREN) {
208 break;
209 }
210 self.parse_type_with_opts(TypeOpts::default().allow_optional());
211 }
212 }
213
214 self.expect(R_PAREN);
215
216 if self.eat(ARROW) {
218 self.parse_type_with_opts(TypeOpts::default().allow_optional());
219 }
220
221 self.expect(GT);
222 }
223
224 Some(m.complete(self, TYPE_FUTURE))
225 }
226
227 fn parse_mapping_type(&mut self) -> Option<CompletedMarker> {
229 if !self.at(KW_MAPPING) {
230 return None;
231 }
232
233 let m = self.start();
234 self.bump_any(); self.parse_type();
238
239 self.expect(FAT_ARROW);
241
242 self.parse_type();
244
245 Some(m.complete(self, TYPE_MAPPING))
246 }
247
248 fn parse_named_type(&mut self) -> Option<CompletedMarker> {
256 if !self.at(IDENT) {
257 return None;
258 }
259
260 let m = self.start();
261 self.bump_any(); if self.at(DOT) && self.nth(1) == KW_ALEO {
265 self.bump_any(); self.bump_any(); if self.eat(SLASH) {
269 if self.at(IDENT) {
271 self.bump_any();
272 } else {
273 self.error("expected type name after /".to_string());
274 }
275 }
276
277 if self.at(COLON_COLON) && self.nth(1) == L_BRACKET {
279 self.bump_any(); self.parse_const_generic_args_bracket();
281 }
282
283 return Some(m.complete(self, TYPE_PATH));
284 }
285
286 while self.eat(COLON_COLON) {
288 if self.at(L_BRACKET) {
289 self.parse_const_generic_args_bracket();
291 break;
292 } else if self.at(LT) {
293 self.parse_const_generic_args_angle();
295 break;
296 } else if self.at(IDENT) {
297 self.bump_any();
298 } else {
299 self.error("expected identifier, [, or < after ::".to_string());
300 break;
301 }
302 }
303
304 Some(m.complete(self, TYPE_PATH))
305 }
306
307 pub fn parse_const_param_list(&mut self) {
312 let m = self.start();
313
314 if !self.eat(L_BRACKET) {
315 m.abandon(self);
316 return;
317 }
318
319 if !self.at(R_BRACKET) {
321 self.parse_const_param();
322 while self.eat(COMMA) {
323 if self.at(R_BRACKET) {
324 break;
325 }
326 self.parse_const_param();
327 }
328 }
329
330 self.expect(R_BRACKET);
331 m.complete(self, CONST_PARAM_LIST);
332 }
333
334 fn parse_const_param(&mut self) {
336 let m = self.start();
337 self.skip_trivia();
338
339 if self.at(IDENT) {
340 self.bump_any(); } else {
342 self.error("expected const parameter name".to_string());
343 }
344
345 self.expect(COLON);
346 self.parse_type();
347
348 m.complete(self, CONST_PARAM);
349 }
350
351 pub fn parse_const_generic_args_bracket(&mut self) {
356 let m = self.start();
357
358 if !self.eat(L_BRACKET) {
359 m.abandon(self);
360 return;
361 }
362
363 if !self.at(R_BRACKET) {
365 self.parse_const_generic_arg();
366 while self.eat(COMMA) {
367 if self.at(R_BRACKET) {
368 break;
369 }
370 self.parse_const_generic_arg();
371 }
372 }
373
374 self.expect(R_BRACKET);
375 m.complete(self, CONST_ARG_LIST);
376 }
377
378 pub fn parse_const_generic_args_angle(&mut self) {
384 let m = self.start();
385
386 if !self.eat(LT) {
387 m.abandon(self);
388 return;
389 }
390
391 if self.at(IDENT) || self.at(INTEGER) {
393 self.bump_any();
394 }
395
396 while self.eat(COMMA) {
397 if self.at(GT) {
398 break;
399 }
400 if self.at(IDENT) || self.at(INTEGER) {
401 self.bump_any();
402 } else {
403 self.error("expected const generic argument".to_string());
404 break;
405 }
406 }
407
408 self.expect(GT);
409 m.complete(self, CONST_ARG_LIST);
410 }
411
412 fn parse_const_generic_arg(&mut self) {
420 self.skip_trivia();
421 if self.at_primitive_type() {
422 self.parse_type();
424 } else if self.at(L_BRACKET) && self.nth(1).is_type_keyword() {
425 self.parse_type();
427 } else {
428 self.parse_expr();
430 }
431 }
432}
433
434#[cfg(test)]
435mod tests {
436 use super::*;
437 use crate::{lexer::lex, parser::Parse};
438 use expect_test::{Expect, expect};
439
440 fn check_type(input: &str, expect: Expect) {
441 let (tokens, _) = lex(input);
442 let mut parser = Parser::new(input, &tokens);
443 let root = parser.start();
444 parser.parse_type();
445 parser.skip_trivia();
446 root.complete(&mut parser, ROOT);
447 let parse: Parse = parser.finish();
448 let output = format!("{:#?}", parse.syntax());
449 expect.assert_eq(&output);
450 }
451
452 fn check_type_optional(input: &str, expect: Expect) {
453 let (tokens, _) = lex(input);
454 let mut parser = Parser::new(input, &tokens);
455 let root = parser.start();
456 parser.parse_type_with_opts(TypeOpts::default().allow_optional());
457 parser.skip_trivia();
458 root.complete(&mut parser, ROOT);
459 let parse: Parse = parser.finish();
460 let output = format!("{:#?}", parse.syntax());
461 expect.assert_eq(&output);
462 }
463
464 #[test]
469 fn parse_type_bool() {
470 check_type("bool", expect![[r#"
471 ROOT@0..4
472 TYPE_PATH@0..4
473 KW_BOOL@0..4 "bool"
474 "#]]);
475 }
476
477 #[test]
478 fn parse_type_field() {
479 check_type("field", expect![[r#"
480 ROOT@0..5
481 TYPE_PATH@0..5
482 KW_FIELD@0..5 "field"
483 "#]]);
484 }
485
486 #[test]
487 fn parse_type_group() {
488 check_type("group", expect![[r#"
489 ROOT@0..5
490 TYPE_PATH@0..5
491 KW_GROUP@0..5 "group"
492 "#]]);
493 }
494
495 #[test]
496 fn parse_type_address() {
497 check_type("address", expect![[r#"
498 ROOT@0..7
499 TYPE_PATH@0..7
500 KW_ADDRESS@0..7 "address"
501 "#]]);
502 }
503
504 #[test]
505 fn parse_type_scalar() {
506 check_type("scalar", expect![[r#"
507 ROOT@0..6
508 TYPE_PATH@0..6
509 KW_SCALAR@0..6 "scalar"
510 "#]]);
511 }
512
513 #[test]
514 fn parse_type_signature() {
515 check_type("signature", expect![[r#"
516 ROOT@0..9
517 TYPE_PATH@0..9
518 KW_SIGNATURE@0..9 "signature"
519 "#]]);
520 }
521
522 #[test]
523 fn parse_type_string() {
524 check_type("string", expect![[r#"
525 ROOT@0..6
526 TYPE_PATH@0..6
527 KW_STRING@0..6 "string"
528 "#]]);
529 }
530
531 #[test]
532 fn parse_type_u32() {
533 check_type("u32", expect![[r#"
534 ROOT@0..3
535 TYPE_PATH@0..3
536 KW_U32@0..3 "u32"
537 "#]]);
538 }
539
540 #[test]
541 fn parse_type_i128() {
542 check_type("i128", expect![[r#"
543 ROOT@0..4
544 TYPE_PATH@0..4
545 KW_I128@0..4 "i128"
546 "#]]);
547 }
548
549 #[test]
554 fn parse_type_unit() {
555 check_type("()", expect![[r#"
556 ROOT@0..2
557 TYPE_TUPLE@0..2
558 L_PAREN@0..1 "("
559 R_PAREN@1..2 ")"
560 "#]]);
561 }
562
563 #[test]
564 fn parse_type_tuple_single() {
565 check_type("(u32)", expect![[r#"
566 ROOT@0..5
567 TYPE_TUPLE@0..5
568 L_PAREN@0..1 "("
569 TYPE_PATH@1..4
570 KW_U32@1..4 "u32"
571 R_PAREN@4..5 ")"
572 "#]]);
573 }
574
575 #[test]
576 fn parse_type_tuple_pair() {
577 check_type("(u32, field)", expect![[r#"
578 ROOT@0..12
579 TYPE_TUPLE@0..12
580 L_PAREN@0..1 "("
581 TYPE_PATH@1..4
582 KW_U32@1..4 "u32"
583 COMMA@4..5 ","
584 WHITESPACE@5..6 " "
585 TYPE_PATH@6..11
586 KW_FIELD@6..11 "field"
587 R_PAREN@11..12 ")"
588 "#]]);
589 }
590
591 #[test]
592 fn parse_type_tuple_trailing_comma() {
593 check_type("(u32, field,)", expect![[r#"
594 ROOT@0..13
595 TYPE_TUPLE@0..13
596 L_PAREN@0..1 "("
597 TYPE_PATH@1..4
598 KW_U32@1..4 "u32"
599 COMMA@4..5 ","
600 WHITESPACE@5..6 " "
601 TYPE_PATH@6..11
602 KW_FIELD@6..11 "field"
603 COMMA@11..12 ","
604 R_PAREN@12..13 ")"
605 "#]]);
606 }
607
608 #[test]
613 fn parse_type_array_fixed() {
614 check_type("[u32; 10]", expect![[r#"
615 ROOT@0..9
616 TYPE_ARRAY@0..9
617 L_BRACKET@0..1 "["
618 TYPE_PATH@1..4
619 KW_U32@1..4 "u32"
620 SEMICOLON@4..5 ";"
621 WHITESPACE@5..6 " "
622 LITERAL@6..8
623 INTEGER@6..8 "10"
624 R_BRACKET@8..9 "]"
625 "#]]);
626 }
627
628 #[test]
629 fn parse_type_array_const_generic() {
630 check_type("[field; N]", expect![[r#"
631 ROOT@0..10
632 TYPE_ARRAY@0..10
633 L_BRACKET@0..1 "["
634 TYPE_PATH@1..6
635 KW_FIELD@1..6 "field"
636 SEMICOLON@6..7 ";"
637 WHITESPACE@7..8 " "
638 PATH_EXPR@8..9
639 IDENT@8..9 "N"
640 R_BRACKET@9..10 "]"
641 "#]]);
642 }
643
644 #[test]
645 fn parse_type_vector() {
646 check_type("[u8]", expect![[r#"
647 ROOT@0..4
648 TYPE_ARRAY@0..4
649 L_BRACKET@0..1 "["
650 TYPE_PATH@1..3
651 KW_U8@1..3 "u8"
652 R_BRACKET@3..4 "]"
653 "#]]);
654 }
655
656 #[test]
657 fn parse_type_nested_array() {
658 check_type("[[u32; 3]; 2]", expect![[r#"
659 ROOT@0..13
660 TYPE_ARRAY@0..13
661 L_BRACKET@0..1 "["
662 TYPE_ARRAY@1..9
663 L_BRACKET@1..2 "["
664 TYPE_PATH@2..5
665 KW_U32@2..5 "u32"
666 SEMICOLON@5..6 ";"
667 WHITESPACE@6..7 " "
668 LITERAL@7..8
669 INTEGER@7..8 "3"
670 R_BRACKET@8..9 "]"
671 SEMICOLON@9..10 ";"
672 WHITESPACE@10..11 " "
673 LITERAL@11..12
674 INTEGER@11..12 "2"
675 R_BRACKET@12..13 "]"
676 "#]]);
677 }
678
679 #[test]
684 fn parse_type_optional() {
685 check_type_optional("u32?", expect![[r#"
686 ROOT@0..4
687 TYPE_OPTIONAL@0..4
688 TYPE_PATH@0..3
689 KW_U32@0..3 "u32"
690 QUESTION@3..4 "?"
691 "#]]);
692 }
693
694 #[test]
695 fn parse_type_optional_named() {
696 check_type_optional("Token?", expect![[r#"
697 ROOT@0..6
698 TYPE_OPTIONAL@0..6
699 TYPE_PATH@0..5
700 IDENT@0..5 "Token"
701 QUESTION@5..6 "?"
702 "#]]);
703 }
704
705 #[test]
710 fn parse_type_named_simple() {
711 check_type("Token", expect![[r#"
712 ROOT@0..5
713 TYPE_PATH@0..5
714 IDENT@0..5 "Token"
715 "#]]);
716 }
717
718 #[test]
719 fn parse_type_named_path() {
720 check_type("Foo::Bar", expect![[r#"
721 ROOT@0..8
722 TYPE_PATH@0..8
723 IDENT@0..3 "Foo"
724 COLON_COLON@3..5 "::"
725 IDENT@5..8 "Bar"
726 "#]]);
727 }
728
729 #[test]
730 fn parse_type_named_const_generic_bracket() {
731 check_type("Poseidon::[N]", expect![[r#"
732 ROOT@0..13
733 TYPE_PATH@0..13
734 IDENT@0..8 "Poseidon"
735 COLON_COLON@8..10 "::"
736 CONST_ARG_LIST@10..13
737 L_BRACKET@10..11 "["
738 PATH_EXPR@11..12
739 IDENT@11..12 "N"
740 R_BRACKET@12..13 "]"
741 "#]]);
742 }
743
744 #[test]
745 fn parse_type_named_const_generic_angle() {
746 check_type("Poseidon::<4>", expect![[r#"
747 ROOT@0..13
748 TYPE_PATH@0..13
749 IDENT@0..8 "Poseidon"
750 COLON_COLON@8..10 "::"
751 CONST_ARG_LIST@10..13
752 LT@10..11 "<"
753 INTEGER@11..12 "4"
754 GT@12..13 ">"
755 "#]]);
756 }
757
758 #[test]
759 fn parse_type_locator() {
760 check_type("credits.aleo/Token", expect![[r#"
761 ROOT@0..18
762 TYPE_PATH@0..18
763 IDENT@0..7 "credits"
764 DOT@7..8 "."
765 KW_ALEO@8..12 "aleo"
766 SLASH@12..13 "/"
767 IDENT@13..18 "Token"
768 "#]]);
769 }
770
771 #[test]
772 fn parse_type_program_id_without_type() {
773 check_type("credits.aleo", expect![[r#"
775 ROOT@0..12
776 TYPE_PATH@0..12
777 IDENT@0..7 "credits"
778 DOT@7..8 "."
779 KW_ALEO@8..12 "aleo"
780 "#]]);
781 }
782
783 #[test]
788 fn parse_type_future_simple() {
789 check_type("Future", expect![[r#"
790 ROOT@0..6
791 TYPE_FUTURE@0..6
792 KW_FUTURE@0..6 "Future"
793 "#]]);
794 }
795
796 #[test]
797 fn parse_type_future_explicit() {
798 check_type("Future<Fn(u32) -> field>", expect![[r#"
799 ROOT@0..24
800 TYPE_FUTURE@0..24
801 KW_FUTURE@0..6 "Future"
802 LT@6..7 "<"
803 KW_FN@7..9 "Fn"
804 L_PAREN@9..10 "("
805 TYPE_PATH@10..13
806 KW_U32@10..13 "u32"
807 R_PAREN@13..14 ")"
808 WHITESPACE@14..15 " "
809 ARROW@15..17 "->"
810 WHITESPACE@17..18 " "
811 TYPE_PATH@18..23
812 KW_FIELD@18..23 "field"
813 GT@23..24 ">"
814 "#]]);
815 }
816
817 #[test]
818 fn parse_type_future_no_params() {
819 check_type("Future<Fn() -> ()>", expect![[r#"
820 ROOT@0..18
821 TYPE_FUTURE@0..18
822 KW_FUTURE@0..6 "Future"
823 LT@6..7 "<"
824 KW_FN@7..9 "Fn"
825 L_PAREN@9..10 "("
826 R_PAREN@10..11 ")"
827 WHITESPACE@11..12 " "
828 ARROW@12..14 "->"
829 WHITESPACE@14..15 " "
830 TYPE_TUPLE@15..17
831 L_PAREN@15..16 "("
832 R_PAREN@16..17 ")"
833 GT@17..18 ">"
834 "#]]);
835 }
836
837 #[test]
842 fn parse_type_mapping() {
843 check_type("mapping address => u64", expect![[r#"
844 ROOT@0..22
845 TYPE_MAPPING@0..22
846 KW_MAPPING@0..7 "mapping"
847 WHITESPACE@7..8 " "
848 TYPE_PATH@8..15
849 KW_ADDRESS@8..15 "address"
850 WHITESPACE@15..16 " "
851 FAT_ARROW@16..18 "=>"
852 WHITESPACE@18..19 " "
853 TYPE_PATH@19..22
854 KW_U64@19..22 "u64"
855 "#]]);
856 }
857
858 fn check_type_no_errors(input: &str) {
863 let (tokens, _) = lex(input);
864 let mut parser = Parser::new(input, &tokens);
865 let root = parser.start();
866 parser.parse_type();
867 parser.skip_trivia();
868 root.complete(&mut parser, ROOT);
869 let parse: Parse = parser.finish();
870 if !parse.errors().is_empty() {
871 for err in parse.errors() {
872 eprintln!("error at {:?}: {}", err.range, err.message);
873 }
874 eprintln!("tree:\n{:#?}", parse.syntax());
875 panic!("type parse had {} error(s)", parse.errors().len());
876 }
877 }
878
879 #[test]
880 fn parse_type_const_generic_expr_simple() {
881 check_type_no_errors("Foo::[3]");
883 }
884
885 #[test]
886 fn parse_type_const_generic_expr_add() {
887 check_type_no_errors("Foo::[N + 1]");
889 }
890
891 #[test]
892 fn parse_type_const_generic_expr_mul() {
893 check_type_no_errors("Foo::[2 * N]");
894 }
895
896 #[test]
897 fn parse_type_const_generic_multi_args() {
898 check_type_no_errors("Matrix::[M, K, N]");
899 }
900
901 #[test]
902 fn parse_type_const_generic_type_arg() {
903 check_type_no_errors("Deserialize::[u32]");
905 }
906
907 #[test]
908 fn parse_type_const_generic_array_type_arg() {
909 check_type_no_errors("Deserialize::[[u8; 4]]");
911 }
912
913 #[test]
914 fn parse_type_locator_const_generic() {
915 check_type_no_errors("child.aleo/Bar::[4]");
917 }
918}