@@ -946,6 +946,8 @@ impl<'a> Parser<'a> {
946946 self . token = next. tok ;
947947 self . tokens_consumed += 1 u;
948948 self . expected_tokens . clear ( ) ;
949+ // check after each token
950+ self . check_unknown_macro_variable ( ) ;
949951 }
950952
951953 /// Advance the parser by one token and return the bumped token.
@@ -2655,6 +2657,70 @@ impl<'a> Parser<'a> {
26552657 return e;
26562658 }
26572659
2660+ // Parse unquoted tokens after a `$` in a token tree
2661+ fn parse_unquoted ( & mut self ) -> TokenTree {
2662+ let mut sp = self . span ;
2663+ let ( name, namep) = match self . token {
2664+ token:: Dollar => {
2665+ self . bump ( ) ;
2666+
2667+ if self . token == token:: OpenDelim ( token:: Paren ) {
2668+ let Spanned { node : seq, span : seq_span } = self . parse_seq (
2669+ & token:: OpenDelim ( token:: Paren ) ,
2670+ & token:: CloseDelim ( token:: Paren ) ,
2671+ seq_sep_none ( ) ,
2672+ |p| p. parse_token_tree ( )
2673+ ) ;
2674+ let ( sep, repeat) = self . parse_sep_and_kleene_op ( ) ;
2675+ let name_num = macro_parser:: count_names ( seq[ ] ) ;
2676+ return TtSequence ( mk_sp ( sp. lo , seq_span. hi ) ,
2677+ Rc :: new ( SequenceRepetition {
2678+ tts : seq,
2679+ separator : sep,
2680+ op : repeat,
2681+ num_captures : name_num
2682+ } ) ) ;
2683+ } else if self . token . is_keyword_allow_following_colon ( keywords:: Crate ) {
2684+ self . bump ( ) ;
2685+ return TtToken ( sp, SpecialVarNt ( SpecialMacroVar :: CrateMacroVar ) ) ;
2686+ } else {
2687+ sp = mk_sp ( sp. lo , self . span . hi ) ;
2688+ let namep = match self . token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2689+ let name = self . parse_ident ( ) ;
2690+ ( name, namep)
2691+ }
2692+ }
2693+ token:: SubstNt ( name, namep) => {
2694+ self . bump ( ) ;
2695+ ( name, namep)
2696+ }
2697+ _ => unreachable ! ( )
2698+ } ;
2699+ // continue by trying to parse the `:ident` after `$name`
2700+ if self . token == token:: Colon && self . look_ahead ( 1 , |t| t. is_ident ( ) &&
2701+ !t. is_strict_keyword ( ) &&
2702+ !t. is_reserved_keyword ( ) ) {
2703+ self . bump ( ) ;
2704+ sp = mk_sp ( sp. lo , self . span . hi ) ;
2705+ let kindp = match self . token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2706+ let nt_kind = self . parse_ident ( ) ;
2707+ TtToken ( sp, MatchNt ( name, nt_kind, namep, kindp) )
2708+ } else {
2709+ TtToken ( sp, SubstNt ( name, namep) )
2710+ }
2711+ }
2712+
2713+ pub fn check_unknown_macro_variable ( & mut self ) {
2714+ if self . quote_depth == 0 u {
2715+ match self . token {
2716+ token:: SubstNt ( name, _) =>
2717+ self . fatal ( format ! ( "unknown macro variable `{}`" ,
2718+ token:: get_ident( name) ) [ ] ) ,
2719+ _ => { }
2720+ }
2721+ }
2722+ }
2723+
26582724 /// Parse an optional separator followed by a Kleene-style
26592725 /// repetition token (+ or *).
26602726 pub fn parse_sep_and_kleene_op ( & mut self ) -> ( Option < token:: Token > , ast:: KleeneOp ) {
@@ -2701,63 +2767,25 @@ impl<'a> Parser<'a> {
27012767 fn parse_non_delim_tt_tok ( p : & mut Parser ) -> TokenTree {
27022768 maybe_whole ! ( deref p, NtTT ) ;
27032769 match p. token {
2704- token:: CloseDelim ( _) => {
2705- // This is a conservative error: only report the last unclosed delimiter. The
2706- // previous unclosed delimiters could actually be closed! The parser just hasn't
2707- // gotten to them yet.
2708- match p. open_braces . last ( ) {
2709- None => { }
2710- Some ( & sp) => p. span_note ( sp, "unclosed delimiter" ) ,
2711- } ;
2712- let token_str = p. this_token_to_string ( ) ;
2713- p. fatal ( format ! ( "incorrect close delimiter: `{}`" ,
2714- token_str) [ ] )
2715- } ,
2716- /* we ought to allow different depths of unquotation */
2717- token:: Dollar if p. quote_depth > 0 u => {
2718- p. bump ( ) ;
2719- let sp = p. span ;
2720-
2721- if p. token == token:: OpenDelim ( token:: Paren ) {
2722- let seq = p. parse_seq (
2723- & token:: OpenDelim ( token:: Paren ) ,
2724- & token:: CloseDelim ( token:: Paren ) ,
2725- seq_sep_none ( ) ,
2726- |p| p. parse_token_tree ( )
2727- ) ;
2728- let ( sep, repeat) = p. parse_sep_and_kleene_op ( ) ;
2729- let seq = match seq {
2730- Spanned { node, .. } => node,
2770+ token:: CloseDelim ( _) => {
2771+ // This is a conservative error: only report the last unclosed delimiter. The
2772+ // previous unclosed delimiters could actually be closed! The parser just hasn't
2773+ // gotten to them yet.
2774+ match p. open_braces . last ( ) {
2775+ None => { }
2776+ Some ( & sp) => p. span_note ( sp, "unclosed delimiter" ) ,
27312777 } ;
2732- let name_num = macro_parser:: count_names ( seq[ ] ) ;
2733- TtSequence ( mk_sp ( sp. lo , p. span . hi ) ,
2734- Rc :: new ( SequenceRepetition {
2735- tts : seq,
2736- separator : sep,
2737- op : repeat,
2738- num_captures : name_num
2739- } ) )
2740- } else if p. token . is_keyword_allow_following_colon ( keywords:: Crate ) {
2741- p. bump ( ) ;
2742- TtToken ( sp, SpecialVarNt ( SpecialMacroVar :: CrateMacroVar ) )
2743- } else {
2744- // A nonterminal that matches or not
2745- let namep = match p. token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2746- let name = p. parse_ident ( ) ;
2747- if p. token == token:: Colon && p. look_ahead ( 1 , |t| t. is_ident ( ) ) {
2748- p. bump ( ) ;
2749- let kindp = match p. token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2750- let nt_kind = p. parse_ident ( ) ;
2751- let m = TtToken ( sp, MatchNt ( name, nt_kind, namep, kindp) ) ;
2752- m
2753- } else {
2754- TtToken ( sp, SubstNt ( name, namep) )
2755- }
2778+ let token_str = p. this_token_to_string ( ) ;
2779+ p. fatal ( format ! ( "incorrect close delimiter: `{}`" ,
2780+ token_str) [ ] )
2781+ } ,
2782+ /* we ought to allow different depths of unquotation */
2783+ token:: Dollar | token:: SubstNt ( ..) if p. quote_depth > 0 u => {
2784+ p. parse_unquoted ( )
2785+ }
2786+ _ => {
2787+ TtToken ( p. span , p. bump_and_get ( ) )
27562788 }
2757- }
2758- _ => {
2759- TtToken ( p. span , p. bump_and_get ( ) )
2760- }
27612789 }
27622790 }
27632791
0 commit comments