@@ -76,15 +76,11 @@ use TokenTreeOrTokenTreeSlice::*;
76
76
77
77
use crate :: mbe:: { self , TokenTree } ;
78
78
79
- use rustc_ast:: ptr:: P ;
80
79
use rustc_ast:: token:: { self , DocComment , Nonterminal , Token } ;
81
- use rustc_ast_pretty:: pprust;
82
- use rustc_parse:: parser:: { FollowedByType , Parser , PathStyle } ;
80
+ use rustc_parse:: parser:: Parser ;
83
81
use rustc_session:: parse:: ParseSess ;
84
- use rustc_span:: symbol:: { kw , sym , Ident , MacroRulesNormalizedIdent , Symbol } ;
82
+ use rustc_span:: symbol:: MacroRulesNormalizedIdent ;
85
83
86
- use rustc_errors:: PResult ;
87
- use rustc_span:: Span ;
88
84
use smallvec:: { smallvec, SmallVec } ;
89
85
90
86
use rustc_data_structures:: fx:: FxHashMap ;
@@ -382,7 +378,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
382
378
n_rec ( sess, next_m, res. by_ref ( ) , ret_val) ?;
383
379
}
384
380
}
385
- TokenTree :: MetaVarDecl ( span, _, id ) if id . name == kw :: Invalid => {
381
+ TokenTree :: MetaVarDecl ( span, _, None ) => {
386
382
if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
387
383
return Err ( ( span, "missing fragment specifier" . to_string ( ) ) ) ;
388
384
}
@@ -565,18 +561,18 @@ fn inner_parse_loop<'root, 'tt>(
565
561
}
566
562
567
563
// We need to match a metavar (but the identifier is invalid)... this is an error
568
- TokenTree :: MetaVarDecl ( span, _, id ) if id . name == kw :: Invalid => {
564
+ TokenTree :: MetaVarDecl ( span, _, None ) => {
569
565
if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
570
566
return Error ( span, "missing fragment specifier" . to_string ( ) ) ;
571
567
}
572
568
}
573
569
574
570
// We need to match a metavar with a valid ident... call out to the black-box
575
571
// parser by adding an item to `bb_items`.
576
- TokenTree :: MetaVarDecl ( _, _, id ) => {
572
+ TokenTree :: MetaVarDecl ( _, _, Some ( kind ) ) => {
577
573
// Built-in nonterminals never start with these tokens,
578
574
// so we can eliminate them from consideration.
579
- if may_begin_with ( token , id . name ) {
575
+ if Parser :: nonterminal_may_begin_with ( kind , token ) {
580
576
bb_items. push ( item) ;
581
577
}
582
578
}
@@ -706,7 +702,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
706
702
let nts = bb_items
707
703
. iter ( )
708
704
. map ( |item| match item. top_elts . get_tt ( item. idx ) {
709
- TokenTree :: MetaVarDecl ( _, bind, name ) => format ! ( "{} ('{}')" , name , bind) ,
705
+ TokenTree :: MetaVarDecl ( _, bind, Some ( kind ) ) => format ! ( "{} ('{}')" , kind , bind) ,
710
706
_ => panic ! ( ) ,
711
707
} )
712
708
. collect :: < Vec < String > > ( )
@@ -736,10 +732,17 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
736
732
assert_eq ! ( bb_items. len( ) , 1 ) ;
737
733
738
734
let mut item = bb_items. pop ( ) . unwrap ( ) ;
739
- if let TokenTree :: MetaVarDecl ( span, _, ident ) = item. top_elts . get_tt ( item. idx ) {
735
+ if let TokenTree :: MetaVarDecl ( span, _, Some ( kind ) ) = item. top_elts . get_tt ( item. idx ) {
740
736
let match_cur = item. match_cur ;
741
- let nt = match parse_nt ( parser. to_mut ( ) , span, ident. name ) {
742
- Err ( ( ) ) => return ErrorReported ,
737
+ let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
738
+ Err ( mut err) => {
739
+ err. span_label (
740
+ span,
741
+ format ! ( "while parsing argument for this `{}` macro fragment" , kind) ,
742
+ )
743
+ . emit ( ) ;
744
+ return ErrorReported ;
745
+ }
743
746
Ok ( nt) => nt,
744
747
} ;
745
748
item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
@@ -754,178 +757,3 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
754
757
assert ! ( !cur_items. is_empty( ) ) ;
755
758
}
756
759
}
757
-
758
- /// The token is an identifier, but not `_`.
759
- /// We prohibit passing `_` to macros expecting `ident` for now.
760
- fn get_macro_ident ( token : & Token ) -> Option < ( Ident , bool ) > {
761
- token. ident ( ) . filter ( |( ident, _) | ident. name != kw:: Underscore )
762
- }
763
-
764
- /// Checks whether a non-terminal may begin with a particular token.
765
- ///
766
- /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
767
- /// token. Be conservative (return true) if not sure.
768
- fn may_begin_with ( token : & Token , name : Symbol ) -> bool {
769
- /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
770
- fn may_be_ident ( nt : & token:: Nonterminal ) -> bool {
771
- match * nt {
772
- token:: NtItem ( _) | token:: NtBlock ( _) | token:: NtVis ( _) | token:: NtLifetime ( _) => false ,
773
- _ => true ,
774
- }
775
- }
776
-
777
- match name {
778
- sym:: expr => {
779
- token. can_begin_expr ( )
780
- // This exception is here for backwards compatibility.
781
- && !token. is_keyword ( kw:: Let )
782
- }
783
- sym:: ty => token. can_begin_type ( ) ,
784
- sym:: ident => get_macro_ident ( token) . is_some ( ) ,
785
- sym:: literal => token. can_begin_literal_maybe_minus ( ) ,
786
- sym:: vis => match token. kind {
787
- // The follow-set of :vis + "priv" keyword + interpolated
788
- token:: Comma | token:: Ident ( ..) | token:: Interpolated ( ..) => true ,
789
- _ => token. can_begin_type ( ) ,
790
- } ,
791
- sym:: block => match token. kind {
792
- token:: OpenDelim ( token:: Brace ) => true ,
793
- token:: Interpolated ( ref nt) => match * * nt {
794
- token:: NtItem ( _)
795
- | token:: NtPat ( _)
796
- | token:: NtTy ( _)
797
- | token:: NtIdent ( ..)
798
- | token:: NtMeta ( _)
799
- | token:: NtPath ( _)
800
- | token:: NtVis ( _) => false , // none of these may start with '{'.
801
- _ => true ,
802
- } ,
803
- _ => false ,
804
- } ,
805
- sym:: path | sym:: meta => match token. kind {
806
- token:: ModSep | token:: Ident ( ..) => true ,
807
- token:: Interpolated ( ref nt) => match * * nt {
808
- token:: NtPath ( _) | token:: NtMeta ( _) => true ,
809
- _ => may_be_ident ( & nt) ,
810
- } ,
811
- _ => false ,
812
- } ,
813
- sym:: pat => match token. kind {
814
- token:: Ident ( ..) | // box, ref, mut, and other identifiers (can stricten)
815
- token:: OpenDelim ( token:: Paren ) | // tuple pattern
816
- token:: OpenDelim ( token:: Bracket ) | // slice pattern
817
- token:: BinOp ( token:: And ) | // reference
818
- token:: BinOp ( token:: Minus ) | // negative literal
819
- token:: AndAnd | // double reference
820
- token:: Literal ( ..) | // literal
821
- token:: DotDot | // range pattern (future compat)
822
- token:: DotDotDot | // range pattern (future compat)
823
- token:: ModSep | // path
824
- token:: Lt | // path (UFCS constant)
825
- token:: BinOp ( token:: Shl ) => true , // path (double UFCS)
826
- token:: Interpolated ( ref nt) => may_be_ident ( nt) ,
827
- _ => false ,
828
- } ,
829
- sym:: lifetime => match token. kind {
830
- token:: Lifetime ( _) => true ,
831
- token:: Interpolated ( ref nt) => match * * nt {
832
- token:: NtLifetime ( _) | token:: NtTT ( _) => true ,
833
- _ => false ,
834
- } ,
835
- _ => false ,
836
- } ,
837
- _ => match token. kind {
838
- token:: CloseDelim ( _) => false ,
839
- _ => true ,
840
- } ,
841
- }
842
- }
843
-
844
- /// A call to the "black-box" parser to parse some Rust non-terminal.
845
- ///
846
- /// # Parameters
847
- ///
848
- /// - `p`: the "black-box" parser to use
849
- /// - `sp`: the `Span` we want to parse
850
- /// - `name`: the name of the metavar _matcher_ we want to match (e.g., `tt`, `ident`, `block`,
851
- /// etc...)
852
- ///
853
- /// # Returns
854
- ///
855
- /// The parsed non-terminal.
856
- fn parse_nt ( p : & mut Parser < ' _ > , sp : Span , name : Symbol ) -> Result < Nonterminal , ( ) > {
857
- // FIXME(Centril): Consider moving this to `parser.rs` to make
858
- // the visibilities of the methods used below `pub(super)` at most.
859
- if name == sym:: tt {
860
- return Ok ( token:: NtTT ( p. parse_token_tree ( ) ) ) ;
861
- }
862
- parse_nt_inner ( p, sp, name) . map_err ( |mut err| {
863
- err. span_label ( sp, format ! ( "while parsing argument for this `{}` macro fragment" , name) )
864
- . emit ( )
865
- } )
866
- }
867
-
868
- fn parse_nt_inner < ' a > ( p : & mut Parser < ' a > , sp : Span , name : Symbol ) -> PResult < ' a , Nonterminal > {
869
- // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
870
- // needs to have them force-captured here.
871
- // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
872
- // which requires having captured tokens available. Since we cannot determine
873
- // in advance whether or not a proc-macro will be (transitively) invoked,
874
- // we always capture tokens for any `Nonterminal` which needs them.
875
- Ok ( match name {
876
- sym:: item => match p. collect_tokens ( |this| this. parse_item ( ) ) ? {
877
- ( Some ( mut item) , tokens) => {
878
- // If we captured tokens during parsing (due to outer attributes),
879
- // use those.
880
- if item. tokens . is_none ( ) {
881
- item. tokens = Some ( tokens) ;
882
- }
883
- token:: NtItem ( item)
884
- }
885
- ( None , _) => return Err ( p. struct_span_err ( p. token . span , "expected an item keyword" ) ) ,
886
- } ,
887
- sym:: block => token:: NtBlock ( p. parse_block ( ) ?) ,
888
- sym:: stmt => match p. parse_stmt ( ) ? {
889
- Some ( s) => token:: NtStmt ( s) ,
890
- None => return Err ( p. struct_span_err ( p. token . span , "expected a statement" ) ) ,
891
- } ,
892
- sym:: pat => token:: NtPat ( p. parse_pat ( None ) ?) ,
893
- sym:: expr => {
894
- let ( mut expr, tokens) = p. collect_tokens ( |this| this. parse_expr ( ) ) ?;
895
- // If we captured tokens during parsing (due to outer attributes),
896
- // use those.
897
- if expr. tokens . is_none ( ) {
898
- expr. tokens = Some ( tokens) ;
899
- }
900
- token:: NtExpr ( expr)
901
- }
902
- sym:: literal => token:: NtLiteral ( p. parse_literal_maybe_minus ( ) ?) ,
903
- sym:: ty => token:: NtTy ( p. parse_ty ( ) ?) ,
904
- // this could be handled like a token, since it is one
905
- sym:: ident => {
906
- if let Some ( ( ident, is_raw) ) = get_macro_ident ( & p. token ) {
907
- p. bump ( ) ;
908
- token:: NtIdent ( ident, is_raw)
909
- } else {
910
- let token_str = pprust:: token_to_string ( & p. token ) ;
911
- let msg = & format ! ( "expected ident, found {}" , & token_str) ;
912
- return Err ( p. struct_span_err ( p. token . span , msg) ) ;
913
- }
914
- }
915
- sym:: path => token:: NtPath ( p. parse_path ( PathStyle :: Type ) ?) ,
916
- sym:: meta => token:: NtMeta ( P ( p. parse_attr_item ( ) ?) ) ,
917
- sym:: vis => token:: NtVis ( p. parse_visibility ( FollowedByType :: Yes ) ?) ,
918
- sym:: lifetime => {
919
- if p. check_lifetime ( ) {
920
- token:: NtLifetime ( p. expect_lifetime ( ) . ident )
921
- } else {
922
- let token_str = pprust:: token_to_string ( & p. token ) ;
923
- let msg = & format ! ( "expected a lifetime, found `{}`" , & token_str) ;
924
- return Err ( p. struct_span_err ( p. token . span , msg) ) ;
925
- }
926
- }
927
- // this is not supposed to happen, since it has been checked
928
- // when compiling the macro.
929
- _ => p. span_bug ( sp, "invalid fragment specifier" ) ,
930
- } )
931
- }
0 commit comments