@@ -76,15 +76,11 @@ use TokenTreeOrTokenTreeSlice::*;
7676
7777use crate :: mbe:: { self , TokenTree } ;
7878
79- use rustc_ast:: ptr:: P ;
80- use rustc_ast:: token:: { self , DocComment , Nonterminal , Token } ;
81- use rustc_ast_pretty:: pprust;
82- use rustc_parse:: parser:: { FollowedByType , Parser , PathStyle } ;
79+ use rustc_ast:: token:: { self , DocComment , Nonterminal , NonterminalKind , Token } ;
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:: { kw, MacroRulesNormalizedIdent } ;
8583
86- use rustc_errors:: PResult ;
87- use rustc_span:: Span ;
8884use smallvec:: { smallvec, SmallVec } ;
8985
9086use rustc_data_structures:: fx:: FxHashMap ;
@@ -576,7 +572,8 @@ fn inner_parse_loop<'root, 'tt>(
576572 TokenTree :: MetaVarDecl ( _, _, id) => {
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+ let kind = NonterminalKind :: from_symbol ( id. name ) . unwrap ( ) ;
576+ if Parser :: nonterminal_may_begin_with ( kind, token) {
580577 bb_items. push ( item) ;
581578 }
582579 }
@@ -738,8 +735,19 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
738735 let mut item = bb_items. pop ( ) . unwrap ( ) ;
739736 if let TokenTree :: MetaVarDecl ( span, _, ident) = item. top_elts . get_tt ( item. idx ) {
740737 let match_cur = item. match_cur ;
741- let nt = match parse_nt ( parser. to_mut ( ) , span, ident. name ) {
742- Err ( ( ) ) => return ErrorReported ,
738+ let kind = NonterminalKind :: from_symbol ( ident. name ) . unwrap ( ) ;
739+ let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
740+ Err ( mut err) => {
741+ err. span_label (
742+ span,
743+ format ! (
744+ "while parsing argument for this `{}` macro fragment" ,
745+ ident. name
746+ ) ,
747+ )
748+ . emit ( ) ;
749+ return ErrorReported ;
750+ }
743751 Ok ( nt) => nt,
744752 } ;
745753 item. push_match ( match_cur, MatchedNonterminal ( Lrc :: new ( nt) ) ) ;
@@ -754,178 +762,3 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
754762 assert ! ( !cur_items. is_empty( ) ) ;
755763 }
756764}
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