@@ -55,7 +55,7 @@ mod function {
5555 . next_if ( )
5656 . map ( |tok_thin_arrow| cst:: FunctionReturnType {
5757 tok_thin_arrow,
58- ty : lexer . expect ( ) . unwrap ( ) ,
58+ ty : cst :: CstType :: parse ( lexer ) ,
5959 } ) ,
6060 body : cst:: Block :: parse ( lexer) ,
6161 }
@@ -67,7 +67,7 @@ mod function {
6767 Self {
6868 name : lexer. expect ( ) . unwrap ( ) ,
6969 tok_colon : lexer. expect ( ) . unwrap ( ) ,
70- ty : lexer . expect ( ) . unwrap ( ) ,
70+ ty : cst :: CstType :: parse ( lexer ) ,
7171 }
7272 }
7373 }
@@ -95,6 +95,68 @@ impl Parse for cst::Block {
9595 }
9696}
9797
98+ impl < T > cst:: Tuple < T >
99+ where
100+ T : Parse ,
101+ {
102+ /// Parse a tuple from an existing [`tok::LParenthesis`] and an optional first item with
103+ /// it's [`tok::Comma`]. If an item isn't provided, it will still attempt to be parsed.
104+ ///
105+ /// The [`tok::Comma`] must be provided with an item to ensure that single-item tuples are
106+ /// only accepted if they were terminated with a [`tok::Comma`].
107+ fn parse_with_parts (
108+ tok_l_parenthesis : tok:: LParenthesis ,
109+ first_item : Option < ( T , tok:: Comma ) > ,
110+ lexer : & mut Lexer ,
111+ ) -> Self {
112+ Self {
113+ tok_l_parenthesis,
114+ items : {
115+ // Parse out remaining values.
116+ let mut values = cst:: PunctuatedList :: parse_while ( lexer, |tok| {
117+ !matches ! ( tok, Tok :: RParenthesis )
118+ } ) ;
119+
120+ // Prepend the provided first expression.
121+ if let Some ( ( item, comma) ) = first_item {
122+ values. items . insert ( 0 , item) ;
123+ values. punctuation . insert ( 0 , comma) ;
124+ }
125+
126+ assert ! (
127+ values. items. len( ) != 1 || values. has_trailing( ) ,
128+ "if tuple is of length 1, it must end in a trailing comma"
129+ ) ;
130+
131+ values
132+ } ,
133+ tok_r_parenthesis : lexer. expect ( ) . unwrap ( ) ,
134+ }
135+ }
136+ }
137+ impl < T > Parse for cst:: Tuple < T >
138+ where
139+ T : Parse ,
140+ {
141+ fn parse ( lexer : & mut Lexer < ' _ > ) -> Self {
142+ Self :: parse_with_parts ( lexer. expect ( ) . unwrap ( ) , None , lexer)
143+ }
144+ }
145+
146+ mod ty {
147+ use super :: * ;
148+
149+ impl Parse for cst:: CstType {
150+ fn parse ( lexer : & mut Lexer < ' _ > ) -> Self {
151+ match lexer. peek ( ) {
152+ Tok :: Ident ( _) => lexer. expect :: < tok:: Ident > ( ) . unwrap ( ) . into ( ) ,
153+ Tok :: LParenthesis => cst:: Tuple :: parse ( lexer) . into ( ) ,
154+ tok => panic ! ( "unexpected tok when parsing type: {tok}" ) ,
155+ }
156+ }
157+ }
158+ }
159+
98160mod statement {
99161 use super :: * ;
100162
@@ -461,50 +523,6 @@ mod expression {
461523 }
462524 }
463525 }
464-
465- impl cst:: Tuple {
466- /// Parse a tuple from an existing [`tok::LParenthesis`] and an optional first
467- /// [`cst::Expression`] with it's [`tok::Comma`]. If the expression isn't provided, it will
468- /// still attempt to be parsed.
469- ///
470- /// The [`tok::Comma`] must be provided with the [`cst::Expression`] to ensure that
471- /// single-expression tuples are only accepted if they were terminated with a
472- /// [`tok::Comma`].
473- fn parse_with_parts (
474- tok_l_parenthesis : tok:: LParenthesis ,
475- first_expression : Option < ( cst:: Expression , tok:: Comma ) > ,
476- lexer : & mut Lexer ,
477- ) -> Self {
478- Self {
479- tok_l_parenthesis,
480- values : {
481- // Parse out remaining values.
482- let mut values = cst:: PunctuatedList :: parse_while ( lexer, |tok| {
483- !matches ! ( tok, Tok :: RParenthesis )
484- } ) ;
485-
486- // Prepend the provided first expression.
487- if let Some ( ( expression, comma) ) = first_expression {
488- values. items . insert ( 0 , expression) ;
489- values. punctuation . insert ( 0 , comma) ;
490- }
491-
492- assert ! (
493- values. items. len( ) != 1 || values. has_trailing( ) ,
494- "if tuple is of length 1, it must end in a trailing comma"
495- ) ;
496-
497- values
498- } ,
499- tok_r_parenthesis : lexer. expect ( ) . unwrap ( ) ,
500- }
501- }
502- }
503- impl Parse for cst:: Tuple {
504- fn parse ( lexer : & mut Lexer < ' _ > ) -> Self {
505- Self :: parse_with_parts ( lexer. expect ( ) . unwrap ( ) , None , lexer)
506- }
507- }
508526}
509527
510528mod util {
@@ -551,6 +569,56 @@ mod test {
551569 assert_eq ! ( lexer. next( ) , Tok :: Eof )
552570 }
553571
572+ mod tuple {
573+ use super :: * ;
574+
575+ #[ rstest]
576+ #[ case( "tuple_empty" , "()" ) ]
577+ #[ case( "tuple_single_item_trailing_comma" , "(1,)" ) ]
578+ #[ case( "tuple_many_items" , "(1, 2, 3)" ) ]
579+ #[ case( "tuple_many_items_trailing_comma" , "(1, 2, 3,)" ) ]
580+ fn tuple ( #[ case] name : & str , #[ case] source : & str ) {
581+ test_with_lexer ( source, |lexer| {
582+ let tuple = cst:: Tuple :: < cst:: Literal > :: parse ( lexer) ;
583+ assert_debug_snapshot ! ( name, tuple, source) ;
584+ } ) ;
585+ }
586+
587+ #[ rstest]
588+ #[ should_panic]
589+ #[ case:: single_item_no_comma( "(1)" ) ]
590+ fn tuple_failure ( #[ case] source : & str ) {
591+ test_with_lexer ( source, |lexer| {
592+ cst:: Tuple :: < cst:: Literal > :: parse ( lexer) ;
593+ } ) ;
594+ }
595+ }
596+
597+ mod ty {
598+ use super :: * ;
599+
600+ #[ rstest]
601+ #[ case( "named_ident" , "i8" ) ]
602+ #[ case( "tuple_empty" , "()" ) ]
603+ #[ case( "tuple_single" , "(i8,)" ) ]
604+ #[ case( "tuple_many" , "(i8, bool, u8)" ) ]
605+ fn ty ( #[ case] name : & str , #[ case] source : & str ) {
606+ test_with_lexer ( source, |lexer| {
607+ let ty = cst:: CstType :: parse ( lexer) ;
608+ assert_debug_snapshot ! ( name, ty, source) ;
609+ } ) ;
610+ }
611+
612+ #[ rstest]
613+ #[ should_panic]
614+ #[ case:: tuple_no_trailing_comma( "(i8)" ) ]
615+ fn ty_failure ( #[ case] source : & str ) {
616+ test_with_lexer ( source, |lexer| {
617+ cst:: CstType :: parse ( lexer) ;
618+ } ) ;
619+ }
620+ }
621+
554622 mod expression {
555623 use super :: * ;
556624
@@ -688,27 +756,6 @@ mod test {
688756 assert_debug_snapshot ! ( name, variable, source) ;
689757 } ) ;
690758 }
691-
692- #[ rstest]
693- #[ case( "tuple_empty" , "()" ) ]
694- #[ case( "tuple_single_item_trailing_comma" , "(1,)" ) ]
695- #[ case( "tuple_many_items" , "(1, 2, 3)" ) ]
696- #[ case( "tuple_many_items_trailing_comma" , "(1, 2, 3,)" ) ]
697- fn tuple ( #[ case] name : & str , #[ case] source : & str ) {
698- test_with_lexer ( source, |lexer| {
699- let tuple = cst:: Tuple :: parse ( lexer) ;
700- assert_debug_snapshot ! ( name, tuple, source) ;
701- } ) ;
702- }
703-
704- #[ rstest]
705- #[ should_panic]
706- #[ case:: single_item_no_comma( "(1)" ) ]
707- fn tuple_failure ( #[ case] source : & str ) {
708- test_with_lexer ( source, |lexer| {
709- cst:: Tuple :: parse ( lexer) ;
710- } ) ;
711- }
712759 }
713760
714761 #[ rstest]
0 commit comments