@@ -76,15 +76,11 @@ use TokenTreeOrTokenTreeSlice::*;
7676
7777use crate :: mbe:: { self , TokenTree } ;
7878
79- use rustc_ast:: ptr:: P ;
8079use 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 ;
8381use rustc_session:: parse:: ParseSess ;
84- use rustc_span:: symbol:: { kw , sym , Ident , MacroRulesNormalizedIdent , Symbol } ;
82+ use rustc_span:: symbol:: MacroRulesNormalizedIdent ;
8583
86- use rustc_errors:: PResult ;
87- use rustc_span:: Span ;
8884use smallvec:: { smallvec, SmallVec } ;
8985
9086use rustc_data_structures:: fx:: FxHashMap ;
@@ -382,7 +378,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
382378 n_rec ( sess, next_m, res. by_ref ( ) , ret_val) ?;
383379 }
384380 }
385- TokenTree :: MetaVarDecl ( span, _, id ) if id . name == kw :: Invalid => {
381+ TokenTree :: MetaVarDecl ( span, _, None ) => {
386382 if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
387383 return Err ( ( span, "missing fragment specifier" . to_string ( ) ) ) ;
388384 }
@@ -565,18 +561,18 @@ fn inner_parse_loop<'root, 'tt>(
565561 }
566562
567563 // 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 ) => {
569565 if sess. missing_fragment_specifiers . borrow_mut ( ) . remove ( & span) . is_some ( ) {
570566 return Error ( span, "missing fragment specifier" . to_string ( ) ) ;
571567 }
572568 }
573569
574570 // We need to match a metavar with a valid ident... call out to the black-box
575571 // parser by adding an item to `bb_items`.
576- TokenTree :: MetaVarDecl ( _, _, id ) => {
572+ TokenTree :: MetaVarDecl ( _, _, Some ( kind ) ) => {
577573 // Built-in nonterminals never start with these tokens,
578574 // so we can eliminate them from consideration.
579- if may_begin_with ( token , id . name ) {
575+ if Parser :: nonterminal_may_begin_with ( kind , token ) {
580576 bb_items. push ( item) ;
581577 }
582578 }
@@ -706,7 +702,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
706702 let nts = bb_items
707703 . iter ( )
708704 . 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) ,
710706 _ => panic ! ( ) ,
711707 } )
712708 . collect :: < Vec < String > > ( )
@@ -736,10 +732,17 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
736732 assert_eq ! ( bb_items. len( ) , 1 ) ;
737733
738734 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 ) {
740736 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+ }
743746 Ok ( nt) => nt,
744747 } ;
745748 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
754757 assert ! ( !cur_items. is_empty( ) ) ;
755758 }
756759}
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