@@ -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.
@@ -2596,6 +2598,70 @@ impl<'a> Parser<'a> {
25962598 return e;
25972599 }
25982600
2601+ // Parse unquoted tokens after a `$` in a token tree
2602+ fn parse_unquoted ( & mut self ) -> TokenTree {
2603+ let mut sp = self . span ;
2604+ let ( name, namep) = match self . token {
2605+ token:: Dollar => {
2606+ self . bump ( ) ;
2607+
2608+ if self . token == token:: OpenDelim ( token:: Paren ) {
2609+ let Spanned { node : seq, span : seq_span } = self . parse_seq (
2610+ & token:: OpenDelim ( token:: Paren ) ,
2611+ & token:: CloseDelim ( token:: Paren ) ,
2612+ seq_sep_none ( ) ,
2613+ |p| p. parse_token_tree ( )
2614+ ) ;
2615+ let ( sep, repeat) = self . parse_sep_and_kleene_op ( ) ;
2616+ let name_num = macro_parser:: count_names ( seq[ ] ) ;
2617+ return TtSequence ( mk_sp ( sp. lo , seq_span. hi ) ,
2618+ Rc :: new ( SequenceRepetition {
2619+ tts : seq,
2620+ separator : sep,
2621+ op : repeat,
2622+ num_captures : name_num
2623+ } ) ) ;
2624+ } else if self . token . is_keyword_allow_following_colon ( keywords:: Crate ) {
2625+ self . bump ( ) ;
2626+ return TtToken ( sp, SpecialVarNt ( SpecialMacroVar :: CrateMacroVar ) ) ;
2627+ } else {
2628+ sp = mk_sp ( sp. lo , self . span . hi ) ;
2629+ let namep = match self . token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2630+ let name = self . parse_ident ( ) ;
2631+ ( name, namep)
2632+ }
2633+ }
2634+ token:: SubstNt ( name, namep) => {
2635+ self . bump ( ) ;
2636+ ( name, namep)
2637+ }
2638+ _ => unreachable ! ( )
2639+ } ;
2640+ // continue by trying to parse the `:ident` after `$name`
2641+ if self . token == token:: Colon && self . look_ahead ( 1 , |t| t. is_ident ( ) &&
2642+ !t. is_strict_keyword ( ) &&
2643+ !t. is_reserved_keyword ( ) ) {
2644+ self . bump ( ) ;
2645+ sp = mk_sp ( sp. lo , self . span . hi ) ;
2646+ let kindp = match self . token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2647+ let nt_kind = self . parse_ident ( ) ;
2648+ TtToken ( sp, MatchNt ( name, nt_kind, namep, kindp) )
2649+ } else {
2650+ TtToken ( sp, SubstNt ( name, namep) )
2651+ }
2652+ }
2653+
2654+ pub fn check_unknown_macro_variable ( & mut self ) {
2655+ if self . quote_depth == 0 u {
2656+ match self . token {
2657+ token:: SubstNt ( name, _) =>
2658+ self . fatal ( format ! ( "unknown macro variable `{}`" ,
2659+ token:: get_ident( name) ) [ ] ) ,
2660+ _ => { }
2661+ }
2662+ }
2663+ }
2664+
25992665 /// Parse an optional separator followed by a Kleene-style
26002666 /// repetition token (+ or *).
26012667 pub fn parse_sep_and_kleene_op ( & mut self ) -> ( Option < token:: Token > , ast:: KleeneOp ) {
@@ -2642,63 +2708,25 @@ impl<'a> Parser<'a> {
26422708 fn parse_non_delim_tt_tok ( p : & mut Parser ) -> TokenTree {
26432709 maybe_whole ! ( deref p, NtTT ) ;
26442710 match p. token {
2645- token:: CloseDelim ( _) => {
2646- // This is a conservative error: only report the last unclosed delimiter. The
2647- // previous unclosed delimiters could actually be closed! The parser just hasn't
2648- // gotten to them yet.
2649- match p. open_braces . last ( ) {
2650- None => { }
2651- Some ( & sp) => p. span_note ( sp, "unclosed delimiter" ) ,
2652- } ;
2653- let token_str = p. this_token_to_string ( ) ;
2654- p. fatal ( format ! ( "incorrect close delimiter: `{}`" ,
2655- token_str) . index ( & FullRange ) )
2656- } ,
2657- /* we ought to allow different depths of unquotation */
2658- token:: Dollar if p. quote_depth > 0 u => {
2659- p. bump ( ) ;
2660- let sp = p. span ;
2661-
2662- if p. token == token:: OpenDelim ( token:: Paren ) {
2663- let seq = p. parse_seq (
2664- & token:: OpenDelim ( token:: Paren ) ,
2665- & token:: CloseDelim ( token:: Paren ) ,
2666- seq_sep_none ( ) ,
2667- |p| p. parse_token_tree ( )
2668- ) ;
2669- let ( sep, repeat) = p. parse_sep_and_kleene_op ( ) ;
2670- let seq = match seq {
2671- Spanned { node, .. } => node,
2711+ token:: CloseDelim ( _) => {
2712+ // This is a conservative error: only report the last unclosed delimiter. The
2713+ // previous unclosed delimiters could actually be closed! The parser just hasn't
2714+ // gotten to them yet.
2715+ match p. open_braces . last ( ) {
2716+ None => { }
2717+ Some ( & sp) => p. span_note ( sp, "unclosed delimiter" ) ,
26722718 } ;
2673- let name_num = macro_parser:: count_names ( seq. index ( & FullRange ) ) ;
2674- TtSequence ( mk_sp ( sp. lo , p. span . hi ) ,
2675- Rc :: new ( SequenceRepetition {
2676- tts : seq,
2677- separator : sep,
2678- op : repeat,
2679- num_captures : name_num
2680- } ) )
2681- } else if p. token . is_keyword_allow_following_colon ( keywords:: Crate ) {
2682- p. bump ( ) ;
2683- TtToken ( sp, SpecialVarNt ( SpecialMacroVar :: CrateMacroVar ) )
2684- } else {
2685- // A nonterminal that matches or not
2686- let namep = match p. token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2687- let name = p. parse_ident ( ) ;
2688- if p. token == token:: Colon && p. look_ahead ( 1 , |t| t. is_ident ( ) ) {
2689- p. bump ( ) ;
2690- let kindp = match p. token { token:: Ident ( _, p) => p, _ => token:: Plain } ;
2691- let nt_kind = p. parse_ident ( ) ;
2692- let m = TtToken ( sp, MatchNt ( name, nt_kind, namep, kindp) ) ;
2693- m
2694- } else {
2695- TtToken ( sp, SubstNt ( name, namep) )
2696- }
2719+ let token_str = p. this_token_to_string ( ) ;
2720+ p. fatal ( format ! ( "incorrect close delimiter: `{}`" ,
2721+ token_str) . index ( & FullRange ) )
2722+ } ,
2723+ /* we ought to allow different depths of unquotation */
2724+ token:: Dollar | token:: SubstNt ( ..) if p. quote_depth > 0 u => {
2725+ p. parse_unquoted ( )
2726+ }
2727+ _ => {
2728+ TtToken ( p. span , p. bump_and_get ( ) )
26972729 }
2698- }
2699- _ => {
2700- TtToken ( p. span , p. bump_and_get ( ) )
2701- }
27022730 }
27032731 }
27042732
0 commit comments