@@ -122,7 +122,7 @@ impl<'tt> TokenTreeOrTokenTreeSlice<'tt> {
122
122
123
123
/// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`.
124
124
///
125
- /// This is used by `inner_parse_loop ` to keep track of delimited submatchers that we have
125
+ /// This is used by `parse_tt_inner ` to keep track of delimited submatchers that we have
126
126
/// descended into.
127
127
#[ derive( Clone ) ]
128
128
struct MatcherTtFrame < ' tt > {
@@ -439,9 +439,8 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
439
439
}
440
440
Occupied ( ..) => return Err ( ( sp, format ! ( "duplicated bind name: {}" , bind_name) ) ) ,
441
441
} ,
442
- // FIXME(c410-f3r) MetaVar and MetaVarExpr should be handled instead of being ignored
443
- // https://github.com/rust-lang/rust/issues/9390
444
- TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarExpr ( ..) | TokenTree :: Token ( ..) => { }
442
+ TokenTree :: Token ( ..) => ( ) ,
443
+ TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarExpr ( ..) => unreachable ! ( ) ,
445
444
}
446
445
447
446
Ok ( ( ) )
@@ -481,21 +480,24 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
481
480
/// successful execution of this function.
482
481
/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
483
482
/// the function `parse`.
484
- /// - `eof_items`: the set of items that would be valid if this was the EOF.
485
483
/// - `bb_items`: the set of items that are waiting for the black-box parser.
486
484
/// - `token`: the current token of the parser.
487
485
///
488
486
/// # Returns
489
487
///
490
- /// A `ParseResult`. Note that matches are kept track of through the items generated.
491
- fn inner_parse_loop < ' root , ' tt > (
488
+ /// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept track of
489
+ /// through the items generated.
490
+ fn parse_tt_inner < ' root , ' tt > (
492
491
sess : & ParseSess ,
492
+ ms : & [ TokenTree ] ,
493
493
cur_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
494
- next_items : & mut Vec < MatcherPosHandle < ' root , ' tt > > ,
494
+ next_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
495
495
bb_items : & mut SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
496
- eof_items : & mut EofItems < ' root , ' tt > ,
497
496
token : & Token ,
498
- ) -> Result < ( ) , ( rustc_span:: Span , String ) > {
497
+ ) -> Option < NamedParseResult > {
498
+ // Matcher positions that would be valid if the macro invocation was over now
499
+ let mut eof_items = EofItems :: None ;
500
+
499
501
// Pop items from `cur_items` until it is empty.
500
502
while let Some ( mut item) = cur_items. pop ( ) {
501
503
// When unzipped trees end, remove them. This corresponds to backtracking out of a
@@ -522,6 +524,8 @@ fn inner_parse_loop<'root, 'tt>(
522
524
// then we could be at the end of a sequence or at the beginning of the next
523
525
// repetition.
524
526
if let Some ( repetition) = & item. repetition {
527
+ debug_assert ! ( matches!( item. top_elts, Tt ( TokenTree :: Sequence ( ..) ) ) ) ;
528
+
525
529
// At this point, regardless of whether there is a separator, we should add all
526
530
// matches from the complete repetition of the sequence to the shared, top-level
527
531
// `matches` list (actually, `up.matches`, which could itself not be the top-level,
@@ -565,7 +569,7 @@ fn inner_parse_loop<'root, 'tt>(
565
569
} else {
566
570
// If we are not in a repetition, then being at the end of a matcher means that we
567
571
// have reached the potential end of the input.
568
- * eof_items = match eof_items {
572
+ eof_items = match eof_items {
569
573
EofItems :: None => EofItems :: One ( item) ,
570
574
EofItems :: One ( _) | EofItems :: Multiple => EofItems :: Multiple ,
571
575
}
@@ -613,7 +617,7 @@ fn inner_parse_loop<'root, 'tt>(
613
617
// We need to match a metavar (but the identifier is invalid)... this is an error
614
618
TokenTree :: MetaVarDecl ( span, _, None ) => {
615
619
if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
616
- return Err ( ( span, "missing fragment specifier" . to_string ( ) ) ) ;
620
+ return Some ( Error ( span, "missing fragment specifier" . to_string ( ) ) ) ;
617
621
}
618
622
}
619
623
@@ -655,13 +659,36 @@ fn inner_parse_loop<'root, 'tt>(
655
659
// rules. NOTE that this is not necessarily an error unless _all_ items in
656
660
// `cur_items` end up doing this. There may still be some other matchers that do
657
661
// end up working out.
658
- TokenTree :: Token ( ..) | TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarExpr ( ..) => { }
662
+ TokenTree :: Token ( ..) => { }
663
+
664
+ TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarExpr ( ..) => unreachable ! ( ) ,
659
665
}
660
666
}
661
667
}
662
668
663
- // Yay a successful parse (so far)!
664
- Ok ( ( ) )
669
+ // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
670
+ // either the parse is ambiguous (which should never happen) or there is a syntax error.
671
+ if * token == token:: Eof {
672
+ Some ( match eof_items {
673
+ EofItems :: One ( mut eof_item) => {
674
+ let matches =
675
+ eof_item. matches . iter_mut ( ) . map ( |dv| Lrc :: make_mut ( dv) . pop ( ) . unwrap ( ) ) ;
676
+ nameize ( sess, ms, matches)
677
+ }
678
+ EofItems :: Multiple => {
679
+ Error ( token. span , "ambiguity: multiple successful parses" . to_string ( ) )
680
+ }
681
+ EofItems :: None => Failure (
682
+ Token :: new (
683
+ token:: Eof ,
684
+ if token. span . is_dummy ( ) { token. span } else { token. span . shrink_to_hi ( ) } ,
685
+ ) ,
686
+ "missing tokens in macro arguments" ,
687
+ ) ,
688
+ } )
689
+ } else {
690
+ None
691
+ }
665
692
}
666
693
667
694
/// Use the given sequence of token trees (`ms`) as a matcher. Match the token
@@ -672,7 +699,7 @@ pub(super) fn parse_tt(
672
699
macro_name : Ident ,
673
700
) -> NamedParseResult {
674
701
// A queue of possible matcher positions. We initialize it with the matcher position in which
675
- // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop ` then
702
+ // the "dot" is before the first token of the first token tree in `ms`. `parse_tt_inner ` then
676
703
// processes all of these possible matcher positions and produces possible next positions into
677
704
// `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items`
678
705
// and we start over again.
@@ -681,135 +708,118 @@ pub(super) fn parse_tt(
681
708
// there are frequently *no* others! -- are allocated on the heap.
682
709
let mut initial = MatcherPos :: new ( ms) ;
683
710
let mut cur_items = smallvec ! [ MatcherPosHandle :: Ref ( & mut initial) ] ;
684
- let mut next_items = Vec :: new ( ) ;
685
711
686
712
loop {
687
- assert ! ( next_items. is_empty ( ) ) ;
713
+ let mut next_items = SmallVec :: new ( ) ;
688
714
689
715
// Matcher positions black-box parsed by parser.rs (`parser`)
690
716
let mut bb_items = SmallVec :: new ( ) ;
691
717
692
- // Matcher positions that would be valid if the macro invocation was over now
693
- let mut eof_items = EofItems :: None ;
694
-
695
718
// Process `cur_items` until either we have finished the input or we need to get some
696
719
// parsing from the black-box parser done. The result is that `next_items` will contain a
697
720
// bunch of possible next matcher positions in `next_items`.
698
- match inner_parse_loop (
721
+ if let Some ( result ) = parse_tt_inner (
699
722
parser. sess ,
723
+ ms,
700
724
& mut cur_items,
701
725
& mut next_items,
702
726
& mut bb_items,
703
- & mut eof_items,
704
727
& parser. token ,
705
728
) {
706
- Ok ( ( ) ) => { }
707
- Err ( ( sp, msg) ) => return Error ( sp, msg) ,
729
+ return result;
708
730
}
709
731
710
- // inner parse loop handled all cur_items, so it's empty
732
+ // `parse_tt_inner` handled all cur_items, so it's empty.
711
733
assert ! ( cur_items. is_empty( ) ) ;
712
734
713
- // We need to do some post processing after the `inner_parse_loop `.
735
+ // We need to do some post processing after the `parse_tt_inner `.
714
736
//
715
737
// Error messages here could be improved with links to original rules.
716
738
717
- // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
718
- // either the parse is ambiguous (which should never happen) or there is a syntax error.
719
- if parser. token == token:: Eof {
720
- return match eof_items {
721
- EofItems :: One ( mut eof_item) => {
722
- let matches =
723
- eof_item. matches . iter_mut ( ) . map ( |dv| Lrc :: make_mut ( dv) . pop ( ) . unwrap ( ) ) ;
724
- nameize ( parser. sess , ms, matches)
725
- }
726
- EofItems :: Multiple => {
727
- Error ( parser. token . span , "ambiguity: multiple successful parses" . to_string ( ) )
728
- }
729
- EofItems :: None => Failure (
730
- Token :: new (
731
- token:: Eof ,
732
- if parser. token . span . is_dummy ( ) {
733
- parser. token . span
734
- } else {
735
- parser. token . span . shrink_to_hi ( )
736
- } ,
737
- ) ,
738
- "missing tokens in macro arguments" ,
739
- ) ,
740
- } ;
741
- }
742
- // Performance hack: `eof_items` may share matchers via `Rc` with other things that we want
743
- // to modify. Dropping `eof_items` now may drop these refcounts to 1, preventing an
744
- // unnecessary implicit clone later in `Rc::make_mut`.
745
- drop ( eof_items) ;
746
-
747
- // If there are no possible next positions AND we aren't waiting for the black-box parser,
748
- // then there is a syntax error.
749
- if bb_items. is_empty ( ) && next_items. is_empty ( ) {
750
- return Failure ( parser. token . clone ( ) , "no rules expected this token in macro call" ) ;
751
- }
739
+ match ( next_items. len ( ) , bb_items. len ( ) ) {
740
+ ( 0 , 0 ) => {
741
+ // There are no possible next positions AND we aren't waiting for the black-box
742
+ // parser: syntax error.
743
+ return Failure ( parser. token . clone ( ) , "no rules expected this token in macro call" ) ;
744
+ }
752
745
753
- if ( !bb_items. is_empty ( ) && !next_items. is_empty ( ) ) || bb_items. len ( ) > 1 {
754
- // We need to call out to parse some rust nonterminal (black-box) parser. But something
755
- // is wrong, because there is not EXACTLY ONE of these.
756
- let nts = bb_items
757
- . iter ( )
758
- . map ( |item| match item. top_elts . get_tt ( item. idx ) {
759
- TokenTree :: MetaVarDecl ( _, bind, Some ( kind) ) => format ! ( "{} ('{}')" , kind, bind) ,
760
- _ => panic ! ( ) ,
761
- } )
762
- . collect :: < Vec < String > > ( )
763
- . join ( " or " ) ;
764
-
765
- return Error (
766
- parser. token . span ,
767
- format ! (
768
- "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}" ,
769
- match next_items. len( ) {
770
- 0 => format!( "built-in NTs {}." , nts) ,
771
- 1 => format!( "built-in NTs {} or 1 other option." , nts) ,
772
- n => format!( "built-in NTs {} or {} other options." , nts, n) ,
773
- }
774
- ) ,
775
- ) ;
776
- }
746
+ ( _, 0 ) => {
747
+ // Dump all possible `next_items` into `cur_items` for the next iteration. Then
748
+ // process the next token.
749
+ cur_items. extend ( next_items. drain ( ..) ) ;
750
+ parser. to_mut ( ) . bump ( ) ;
751
+ }
777
752
778
- if !next_items. is_empty ( ) {
779
- // Dump all possible `next_items` into `cur_items` for the next iteration. Then process
780
- // the next token.
781
- cur_items. extend ( next_items. drain ( ..) ) ;
782
- parser. to_mut ( ) . bump ( ) ;
783
- } else {
784
- // Finally, we have the case where we need to call the black-box parser to get some
785
- // nonterminal.
786
- assert_eq ! ( bb_items. len( ) , 1 ) ;
787
-
788
- let mut item = bb_items. pop ( ) . unwrap ( ) ;
789
- if let TokenTree :: MetaVarDecl ( span, _, Some ( kind) ) = item. top_elts . get_tt ( item. idx ) {
790
- let match_cur = item. match_cur ;
791
- // We use the span of the metavariable declaration to determine any
792
- // edition-specific matching behavior for non-terminals.
793
- let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
794
- Err ( mut err) => {
795
- err. span_label (
796
- span,
797
- format ! ( "while parsing argument for this `{}` macro fragment" , kind) ,
798
- )
799
- . emit ( ) ;
800
- return ErrorReported ;
801
- }
802
- Ok ( nt) => nt,
803
- } ;
804
- item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
805
- item. idx += 1 ;
806
- item. match_cur += 1 ;
807
- } else {
808
- unreachable ! ( )
753
+ ( 0 , 1 ) => {
754
+ // We need to call the black-box parser to get some nonterminal.
755
+ let mut item = bb_items. pop ( ) . unwrap ( ) ;
756
+ if let TokenTree :: MetaVarDecl ( span, _, Some ( kind) ) = item. top_elts . get_tt ( item. idx )
757
+ {
758
+ let match_cur = item. match_cur ;
759
+ // We use the span of the metavariable declaration to determine any
760
+ // edition-specific matching behavior for non-terminals.
761
+ let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
762
+ Err ( mut err) => {
763
+ err. span_label (
764
+ span,
765
+ format ! ( "while parsing argument for this `{kind}` macro fragment" ) ,
766
+ )
767
+ . emit ( ) ;
768
+ return ErrorReported ;
769
+ }
770
+ Ok ( nt) => nt,
771
+ } ;
772
+ item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
773
+ item. idx += 1 ;
774
+ item. match_cur += 1 ;
775
+ } else {
776
+ unreachable ! ( )
777
+ }
778
+ cur_items. push ( item) ;
779
+ }
780
+
781
+ ( _, _) => {
782
+ // We need to call the black-box parser to get some nonterminal, but something is
783
+ // wrong.
784
+ return bb_items_ambiguity_error (
785
+ macro_name,
786
+ next_items,
787
+ bb_items,
788
+ parser. token . span ,
789
+ ) ;
809
790
}
810
- cur_items. push ( item) ;
811
791
}
812
792
813
793
assert ! ( !cur_items. is_empty( ) ) ;
814
794
}
815
795
}
796
+
797
+ fn bb_items_ambiguity_error < ' root , ' tt > (
798
+ macro_name : Ident ,
799
+ next_items : SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
800
+ bb_items : SmallVec < [ MatcherPosHandle < ' root , ' tt > ; 1 ] > ,
801
+ token_span : rustc_span:: Span ,
802
+ ) -> NamedParseResult {
803
+ let nts = bb_items
804
+ . iter ( )
805
+ . map ( |item| match item. top_elts . get_tt ( item. idx ) {
806
+ TokenTree :: MetaVarDecl ( _, bind, Some ( kind) ) => {
807
+ format ! ( "{} ('{}')" , kind, bind)
808
+ }
809
+ _ => panic ! ( ) ,
810
+ } )
811
+ . collect :: < Vec < String > > ( )
812
+ . join ( " or " ) ;
813
+
814
+ Error (
815
+ token_span,
816
+ format ! (
817
+ "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}" ,
818
+ match next_items. len( ) {
819
+ 0 => format!( "built-in NTs {}." , nts) ,
820
+ 1 => format!( "built-in NTs {} or 1 other option." , nts) ,
821
+ n => format!( "built-in NTs {} or {} other options." , nts, n) ,
822
+ }
823
+ ) ,
824
+ )
825
+ }
0 commit comments