@@ -946,6 +946,8 @@ impl<'a> Parser<'a> {
946
946
self . token = next. tok ;
947
947
self . tokens_consumed += 1 u;
948
948
self . expected_tokens . clear ( ) ;
949
+ // check after each token
950
+ self . check_unknown_macro_variable ( ) ;
949
951
}
950
952
951
953
/// Advance the parser by one token and return the bumped token.
@@ -2655,6 +2657,70 @@ impl<'a> Parser<'a> {
2655
2657
return e;
2656
2658
}
2657
2659
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
+
2658
2724
/// Parse an optional separator followed by a Kleene-style
2659
2725
/// repetition token (+ or *).
2660
2726
pub fn parse_sep_and_kleene_op ( & mut self ) -> ( Option < token:: Token > , ast:: KleeneOp ) {
@@ -2701,63 +2767,25 @@ impl<'a> Parser<'a> {
2701
2767
fn parse_non_delim_tt_tok ( p : & mut Parser ) -> TokenTree {
2702
2768
maybe_whole ! ( deref p, NtTT ) ;
2703
2769
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" ) ,
2731
2777
} ;
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 ( ) )
2756
2788
}
2757
- }
2758
- _ => {
2759
- TtToken ( p. span , p. bump_and_get ( ) )
2760
- }
2761
2789
}
2762
2790
}
2763
2791
0 commit comments