@@ -20,7 +20,7 @@ use ext::tt::quoted;
20
20
use ext:: tt:: transcribe:: transcribe;
21
21
use parse:: { Directory , ParseSess } ;
22
22
use parse:: parser:: Parser ;
23
- use parse:: token:: { self , NtTT , Token } ;
23
+ use parse:: token:: { self , NtTT } ;
24
24
use parse:: token:: Token :: * ;
25
25
use print;
26
26
use symbol:: Symbol ;
@@ -165,14 +165,12 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
165
165
// $( $lhs:tt => $rhs:tt );+
166
166
// ...quasiquoting this would be nice.
167
167
// These spans won't matter, anyways
168
- let match_lhs_tok = MatchNt ( lhs_nm, ast:: Ident :: from_str ( "tt" ) ) ;
169
- let match_rhs_tok = MatchNt ( rhs_nm, ast:: Ident :: from_str ( "tt" ) ) ;
170
168
let argument_gram = vec ! [
171
169
quoted:: TokenTree :: Sequence ( DUMMY_SP , Rc :: new( quoted:: SequenceRepetition {
172
170
tts: vec![
173
- quoted:: TokenTree :: Token ( DUMMY_SP , match_lhs_tok ) ,
171
+ quoted:: TokenTree :: MetaVarDecl ( DUMMY_SP , lhs_nm , ast :: Ident :: from_str ( "tt" ) ) ,
174
172
quoted:: TokenTree :: Token ( DUMMY_SP , token:: FatArrow ) ,
175
- quoted:: TokenTree :: Token ( DUMMY_SP , match_rhs_tok ) ,
173
+ quoted:: TokenTree :: MetaVarDecl ( DUMMY_SP , rhs_nm , ast :: Ident :: from_str ( "tt" ) ) ,
176
174
] ,
177
175
separator: Some ( token:: Semi ) ,
178
176
op: quoted:: KleeneOp :: OneOrMore ,
@@ -272,7 +270,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
272
270
use self :: quoted:: TokenTree ;
273
271
for tt in tts {
274
272
match * tt {
275
- TokenTree :: Token ( _ , _ ) => ( ) ,
273
+ TokenTree :: Token ( .. ) | TokenTree :: MetaVarDecl ( .. ) => ( ) ,
276
274
TokenTree :: Delimited ( _, ref del) => if !check_lhs_no_empty_seq ( sess, & del. tts ) {
277
275
return false ;
278
276
} ,
@@ -352,13 +350,12 @@ impl FirstSets {
352
350
let mut first = TokenSet :: empty ( ) ;
353
351
for tt in tts. iter ( ) . rev ( ) {
354
352
match * tt {
355
- TokenTree :: Token ( sp , ref tok ) => {
356
- first. replace_with ( ( sp , tok . clone ( ) ) ) ;
353
+ TokenTree :: Token ( .. ) | TokenTree :: MetaVarDecl ( .. ) => {
354
+ first. replace_with ( tt . clone ( ) ) ;
357
355
}
358
356
TokenTree :: Delimited ( span, ref delimited) => {
359
357
build_recur ( sets, & delimited. tts [ ..] ) ;
360
- first. replace_with ( ( delimited. open_tt ( span) . span ( ) ,
361
- Token :: OpenDelim ( delimited. delim ) ) ) ;
358
+ first. replace_with ( delimited. open_tt ( span) ) ;
362
359
}
363
360
TokenTree :: Sequence ( sp, ref seq_rep) => {
364
361
let subfirst = build_recur ( sets, & seq_rep. tts [ ..] ) ;
@@ -383,7 +380,7 @@ impl FirstSets {
383
380
384
381
if let ( Some ( ref sep) , true ) = ( seq_rep. separator . clone ( ) ,
385
382
subfirst. maybe_empty ) {
386
- first. add_one_maybe ( ( sp, sep. clone ( ) ) ) ;
383
+ first. add_one_maybe ( TokenTree :: Token ( sp, sep. clone ( ) ) ) ;
387
384
}
388
385
389
386
// Reverse scan: Sequence comes before `first`.
@@ -413,13 +410,12 @@ impl FirstSets {
413
410
for tt in tts. iter ( ) {
414
411
assert ! ( first. maybe_empty) ;
415
412
match * tt {
416
- TokenTree :: Token ( sp , ref tok ) => {
417
- first. add_one ( ( sp , tok . clone ( ) ) ) ;
413
+ TokenTree :: Token ( .. ) | TokenTree :: MetaVarDecl ( .. ) => {
414
+ first. add_one ( tt . clone ( ) ) ;
418
415
return first;
419
416
}
420
417
TokenTree :: Delimited ( span, ref delimited) => {
421
- first. add_one ( ( delimited. open_tt ( span) . span ( ) ,
422
- Token :: OpenDelim ( delimited. delim ) ) ) ;
418
+ first. add_one ( delimited. open_tt ( span) ) ;
423
419
return first;
424
420
}
425
421
TokenTree :: Sequence ( sp, ref seq_rep) => {
@@ -431,7 +427,7 @@ impl FirstSets {
431
427
432
428
if let ( Some ( ref sep) , true ) = ( seq_rep. separator . clone ( ) ,
433
429
subfirst. maybe_empty ) {
434
- first. add_one_maybe ( ( sp, sep. clone ( ) ) ) ;
430
+ first. add_one_maybe ( TokenTree :: Token ( sp, sep. clone ( ) ) ) ;
435
431
}
436
432
437
433
assert ! ( first. maybe_empty) ;
@@ -467,8 +463,8 @@ impl FirstSets {
467
463
}
468
464
}
469
465
470
- // A set of Tokens , which may include MatchNt tokens (for
471
- // macro-by-example syntactic variables). It also carries the
466
+ // A set of `quoted::TokenTree`s , which may include `TokenTree::Match`s
467
+ // (for macro-by-example syntactic variables). It also carries the
472
468
// `maybe_empty` flag; that is true if and only if the matcher can
473
469
// match an empty token sequence.
474
470
//
@@ -479,7 +475,7 @@ impl FirstSets {
479
475
// (Notably, we must allow for *-op to occur zero times.)
480
476
#[ derive( Clone , Debug ) ]
481
477
struct TokenSet {
482
- tokens : Vec < ( Span , Token ) > ,
478
+ tokens : Vec < quoted :: TokenTree > ,
483
479
maybe_empty : bool ,
484
480
}
485
481
@@ -489,13 +485,13 @@ impl TokenSet {
489
485
490
486
// Returns the set `{ tok }` for the single-token (and thus
491
487
// non-empty) sequence [tok].
492
- fn singleton ( tok : ( Span , Token ) ) -> Self {
488
+ fn singleton ( tok : quoted :: TokenTree ) -> Self {
493
489
TokenSet { tokens : vec ! [ tok] , maybe_empty : false }
494
490
}
495
491
496
492
// Changes self to be the set `{ tok }`.
497
493
// Since `tok` is always present, marks self as non-empty.
498
- fn replace_with ( & mut self , tok : ( Span , Token ) ) {
494
+ fn replace_with ( & mut self , tok : quoted :: TokenTree ) {
499
495
self . tokens . clear ( ) ;
500
496
self . tokens . push ( tok) ;
501
497
self . maybe_empty = false ;
@@ -510,15 +506,15 @@ impl TokenSet {
510
506
}
511
507
512
508
// Adds `tok` to the set for `self`, marking sequence as non-empy.
513
- fn add_one ( & mut self , tok : ( Span , Token ) ) {
509
+ fn add_one ( & mut self , tok : quoted :: TokenTree ) {
514
510
if !self . tokens . contains ( & tok) {
515
511
self . tokens . push ( tok) ;
516
512
}
517
513
self . maybe_empty = false ;
518
514
}
519
515
520
516
// Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.)
521
- fn add_one_maybe ( & mut self , tok : ( Span , Token ) ) {
517
+ fn add_one_maybe ( & mut self , tok : quoted :: TokenTree ) {
522
518
if !self . tokens . contains ( & tok) {
523
519
self . tokens . push ( tok) ;
524
520
}
@@ -558,7 +554,6 @@ fn check_matcher_core(sess: &ParseSess,
558
554
first_sets : & FirstSets ,
559
555
matcher : & [ quoted:: TokenTree ] ,
560
556
follow : & TokenSet ) -> TokenSet {
561
- use print:: pprust:: token_to_string;
562
557
use self :: quoted:: TokenTree ;
563
558
564
559
let mut last = TokenSet :: empty ( ) ;
@@ -584,11 +579,11 @@ fn check_matcher_core(sess: &ParseSess,
584
579
// First, update `last` so that it corresponds to the set
585
580
// of NT tokens that might end the sequence `... token`.
586
581
match * token {
587
- TokenTree :: Token ( sp , ref tok ) => {
582
+ TokenTree :: Token ( .. ) | TokenTree :: MetaVarDecl ( .. ) => {
588
583
let can_be_followed_by_any;
589
- if let Err ( bad_frag) = has_legal_fragment_specifier ( tok ) {
584
+ if let Err ( bad_frag) = has_legal_fragment_specifier ( token ) {
590
585
let msg = format ! ( "invalid fragment specifier `{}`" , bad_frag) ;
591
- sess. span_diagnostic . struct_span_err ( sp , & msg)
586
+ sess. span_diagnostic . struct_span_err ( token . span ( ) , & msg)
592
587
. help ( "valid fragment specifiers are `ident`, `block`, \
593
588
`stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
594
589
and `item`")
@@ -597,7 +592,7 @@ fn check_matcher_core(sess: &ParseSess,
597
592
// from error messages.)
598
593
can_be_followed_by_any = true ;
599
594
} else {
600
- can_be_followed_by_any = token_can_be_followed_by_any ( tok ) ;
595
+ can_be_followed_by_any = token_can_be_followed_by_any ( token ) ;
601
596
}
602
597
603
598
if can_be_followed_by_any {
@@ -607,13 +602,12 @@ fn check_matcher_core(sess: &ParseSess,
607
602
// followed by anything against SUFFIX.
608
603
continue ' each_token;
609
604
} else {
610
- last. replace_with ( ( sp , tok . clone ( ) ) ) ;
605
+ last. replace_with ( token . clone ( ) ) ;
611
606
suffix_first = build_suffix_first ( ) ;
612
607
}
613
608
}
614
609
TokenTree :: Delimited ( span, ref d) => {
615
- let my_suffix = TokenSet :: singleton ( ( d. close_tt ( span) . span ( ) ,
616
- Token :: CloseDelim ( d. delim ) ) ) ;
610
+ let my_suffix = TokenSet :: singleton ( d. close_tt ( span) ) ;
617
611
check_matcher_core ( sess, first_sets, & d. tts , & my_suffix) ;
618
612
// don't track non NT tokens
619
613
last. replace_with_irrelevant ( ) ;
@@ -637,7 +631,7 @@ fn check_matcher_core(sess: &ParseSess,
637
631
let mut new;
638
632
let my_suffix = if let Some ( ref u) = seq_rep. separator {
639
633
new = suffix_first. clone ( ) ;
640
- new. add_one_maybe ( ( sp, u. clone ( ) ) ) ;
634
+ new. add_one_maybe ( TokenTree :: Token ( sp, u. clone ( ) ) ) ;
641
635
& new
642
636
} else {
643
637
& suffix_first
@@ -663,12 +657,13 @@ fn check_matcher_core(sess: &ParseSess,
663
657
664
658
// Now `last` holds the complete set of NT tokens that could
665
659
// end the sequence before SUFFIX. Check that every one works with `suffix`.
666
- ' each_last: for & ( _sp , ref t ) in & last. tokens {
667
- if let MatchNt ( ref name, ref frag_spec) = * t {
668
- for & ( sp , ref next_token) in & suffix_first. tokens {
660
+ ' each_last: for token in & last. tokens {
661
+ if let TokenTree :: MetaVarDecl ( _ , ref name, ref frag_spec) = * token {
662
+ for next_token in & suffix_first. tokens {
669
663
match is_in_follow ( next_token, & frag_spec. name . as_str ( ) ) {
670
664
Err ( ( msg, help) ) => {
671
- sess. span_diagnostic . struct_span_err ( sp, & msg) . help ( help) . emit ( ) ;
665
+ sess. span_diagnostic . struct_span_err ( next_token. span ( ) , & msg)
666
+ . help ( help) . emit ( ) ;
672
667
// don't bother reporting every source of
673
668
// conflict for a particular element of `last`.
674
669
continue ' each_last;
@@ -684,12 +679,12 @@ fn check_matcher_core(sess: &ParseSess,
684
679
} ;
685
680
686
681
sess. span_diagnostic . span_err (
687
- sp ,
682
+ next_token . span ( ) ,
688
683
& format ! ( "`${name}:{frag}` {may_be} followed by `{next}`, which \
689
684
is not allowed for `{frag}` fragments",
690
685
name=name,
691
686
frag=frag_spec,
692
- next=token_to_string ( next_token) ,
687
+ next=quoted_tt_to_string ( next_token) ,
693
688
may_be=may_be)
694
689
) ;
695
690
}
@@ -701,8 +696,8 @@ fn check_matcher_core(sess: &ParseSess,
701
696
last
702
697
}
703
698
704
- fn token_can_be_followed_by_any ( tok : & Token ) -> bool {
705
- if let & MatchNt ( _, ref frag_spec) = tok {
699
+ fn token_can_be_followed_by_any ( tok : & quoted :: TokenTree ) -> bool {
700
+ if let quoted :: TokenTree :: MetaVarDecl ( _, _ , frag_spec) = * tok {
706
701
frag_can_be_followed_by_any ( & frag_spec. name . as_str ( ) )
707
702
} else {
708
703
// (Non NT's can always be followed by anthing in matchers.)
@@ -740,8 +735,10 @@ fn frag_can_be_followed_by_any(frag: &str) -> bool {
740
735
/// break macros that were relying on that binary operator as a
741
736
/// separator.
742
737
// when changing this do not forget to update doc/book/macros.md!
743
- fn is_in_follow ( tok : & Token , frag : & str ) -> Result < bool , ( String , & ' static str ) > {
744
- if let & CloseDelim ( _) = tok {
738
+ fn is_in_follow ( tok : & quoted:: TokenTree , frag : & str ) -> Result < bool , ( String , & ' static str ) > {
739
+ use self :: quoted:: TokenTree ;
740
+
741
+ if let TokenTree :: Token ( _, token:: CloseDelim ( _) ) = * tok {
745
742
// closing a token tree can never be matched by any fragment;
746
743
// iow, we always require that `(` and `)` match, etc.
747
744
Ok ( true )
@@ -757,27 +754,30 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result<bool, (String, &'static str)>
757
754
// maintain
758
755
Ok ( true )
759
756
} ,
760
- "stmt" | "expr" => {
761
- match * tok {
757
+ "stmt" | "expr" => match * tok {
758
+ TokenTree :: Token ( _ , ref tok ) => match * tok {
762
759
FatArrow | Comma | Semi => Ok ( true ) ,
763
760
_ => Ok ( false )
764
- }
761
+ } ,
762
+ _ => Ok ( false ) ,
765
763
} ,
766
- "pat" => {
767
- match * tok {
764
+ "pat" => match * tok {
765
+ TokenTree :: Token ( _ , ref tok ) => match * tok {
768
766
FatArrow | Comma | Eq | BinOp ( token:: Or ) => Ok ( true ) ,
769
767
Ident ( i) if i. name == "if" || i. name == "in" => Ok ( true ) ,
770
768
_ => Ok ( false )
771
- }
769
+ } ,
770
+ _ => Ok ( false ) ,
772
771
} ,
773
- "path" | "ty" => {
774
- match * tok {
772
+ "path" | "ty" => match * tok {
773
+ TokenTree :: Token ( _ , ref tok ) => match * tok {
775
774
OpenDelim ( token:: DelimToken :: Brace ) | OpenDelim ( token:: DelimToken :: Bracket ) |
776
775
Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp ( token:: Or ) => Ok ( true ) ,
777
- MatchNt ( _, ref frag) if frag. name == "block" => Ok ( true ) ,
778
776
Ident ( i) if i. name == "as" || i. name == "where" => Ok ( true ) ,
779
777
_ => Ok ( false )
780
- }
778
+ } ,
779
+ TokenTree :: MetaVarDecl ( _, _, frag) if frag. name == "block" => Ok ( true ) ,
780
+ _ => Ok ( false ) ,
781
781
} ,
782
782
"ident" => {
783
783
// being a single token, idents are harmless
@@ -796,9 +796,9 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result<bool, (String, &'static str)>
796
796
}
797
797
}
798
798
799
- fn has_legal_fragment_specifier ( tok : & Token ) -> Result < ( ) , String > {
799
+ fn has_legal_fragment_specifier ( tok : & quoted :: TokenTree ) -> Result < ( ) , String > {
800
800
debug ! ( "has_legal_fragment_specifier({:?})" , tok) ;
801
- if let & MatchNt ( _, ref frag_spec) = tok {
801
+ if let quoted :: TokenTree :: MetaVarDecl ( _, _ , frag_spec) = * tok {
802
802
let s = & frag_spec. name . as_str ( ) ;
803
803
if !is_legal_fragment_specifier ( s) {
804
804
return Err ( s. to_string ( ) ) ;
@@ -814,3 +814,11 @@ fn is_legal_fragment_specifier(frag: &str) -> bool {
814
814
_ => false ,
815
815
}
816
816
}
817
+
818
+ fn quoted_tt_to_string ( tt : & quoted:: TokenTree ) -> String {
819
+ match * tt {
820
+ quoted:: TokenTree :: Token ( _, ref tok) => :: print:: pprust:: token_to_string ( tok) ,
821
+ quoted:: TokenTree :: MetaVarDecl ( _, name, kind) => format ! ( "${}:{}" , name, kind) ,
822
+ _ => panic ! ( "unexpected quoted::TokenTree::{Sequence or Delimited} in follow set checker" ) ,
823
+ }
824
+ }
0 commit comments