@@ -20,7 +20,7 @@ use ext::tt::quoted;
2020use ext:: tt:: transcribe:: transcribe;
2121use parse:: { Directory , ParseSess } ;
2222use parse:: parser:: Parser ;
23- use parse:: token:: { self , NtTT , Token } ;
23+ use parse:: token:: { self , NtTT } ;
2424use parse:: token:: Token :: * ;
2525use print;
2626use symbol:: Symbol ;
@@ -165,14 +165,12 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
165165 // $( $lhs:tt => $rhs:tt );+
166166 // ...quasiquoting this would be nice.
167167 // 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" ) ) ;
170168 let argument_gram = vec ! [
171169 quoted:: TokenTree :: Sequence ( DUMMY_SP , Rc :: new( quoted:: SequenceRepetition {
172170 tts: vec![
173- quoted:: TokenTree :: Token ( DUMMY_SP , match_lhs_tok ) ,
171+ quoted:: TokenTree :: MetaVarDecl ( DUMMY_SP , lhs_nm , ast :: Ident :: from_str ( "tt" ) ) ,
174172 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" ) ) ,
176174 ] ,
177175 separator: Some ( token:: Semi ) ,
178176 op: quoted:: KleeneOp :: OneOrMore ,
@@ -272,7 +270,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool {
272270 use self :: quoted:: TokenTree ;
273271 for tt in tts {
274272 match * tt {
275- TokenTree :: Token ( _ , _ ) => ( ) ,
273+ TokenTree :: Token ( .. ) | TokenTree :: MetaVarDecl ( .. ) => ( ) ,
276274 TokenTree :: Delimited ( _, ref del) => if !check_lhs_no_empty_seq ( sess, & del. tts ) {
277275 return false ;
278276 } ,
@@ -352,13 +350,12 @@ impl FirstSets {
352350 let mut first = TokenSet :: empty ( ) ;
353351 for tt in tts. iter ( ) . rev ( ) {
354352 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 ( ) ) ;
357355 }
358356 TokenTree :: Delimited ( span, ref delimited) => {
359357 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) ) ;
362359 }
363360 TokenTree :: Sequence ( sp, ref seq_rep) => {
364361 let subfirst = build_recur ( sets, & seq_rep. tts [ ..] ) ;
@@ -383,7 +380,7 @@ impl FirstSets {
383380
384381 if let ( Some ( ref sep) , true ) = ( seq_rep. separator . clone ( ) ,
385382 subfirst. maybe_empty ) {
386- first. add_one_maybe ( ( sp, sep. clone ( ) ) ) ;
383+ first. add_one_maybe ( TokenTree :: Token ( sp, sep. clone ( ) ) ) ;
387384 }
388385
389386 // Reverse scan: Sequence comes before `first`.
@@ -413,13 +410,12 @@ impl FirstSets {
413410 for tt in tts. iter ( ) {
414411 assert ! ( first. maybe_empty) ;
415412 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 ( ) ) ;
418415 return first;
419416 }
420417 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) ) ;
423419 return first;
424420 }
425421 TokenTree :: Sequence ( sp, ref seq_rep) => {
@@ -431,7 +427,7 @@ impl FirstSets {
431427
432428 if let ( Some ( ref sep) , true ) = ( seq_rep. separator . clone ( ) ,
433429 subfirst. maybe_empty ) {
434- first. add_one_maybe ( ( sp, sep. clone ( ) ) ) ;
430+ first. add_one_maybe ( TokenTree :: Token ( sp, sep. clone ( ) ) ) ;
435431 }
436432
437433 assert ! ( first. maybe_empty) ;
@@ -467,8 +463,8 @@ impl FirstSets {
467463 }
468464}
469465
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
472468// `maybe_empty` flag; that is true if and only if the matcher can
473469// match an empty token sequence.
474470//
@@ -479,7 +475,7 @@ impl FirstSets {
479475// (Notably, we must allow for *-op to occur zero times.)
480476#[ derive( Clone , Debug ) ]
481477struct TokenSet {
482- tokens : Vec < ( Span , Token ) > ,
478+ tokens : Vec < quoted :: TokenTree > ,
483479 maybe_empty : bool ,
484480}
485481
@@ -489,13 +485,13 @@ impl TokenSet {
489485
490486 // Returns the set `{ tok }` for the single-token (and thus
491487 // non-empty) sequence [tok].
492- fn singleton ( tok : ( Span , Token ) ) -> Self {
488+ fn singleton ( tok : quoted :: TokenTree ) -> Self {
493489 TokenSet { tokens : vec ! [ tok] , maybe_empty : false }
494490 }
495491
496492 // Changes self to be the set `{ tok }`.
497493 // 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 ) {
499495 self . tokens . clear ( ) ;
500496 self . tokens . push ( tok) ;
501497 self . maybe_empty = false ;
@@ -510,15 +506,15 @@ impl TokenSet {
510506 }
511507
512508 // 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 ) {
514510 if !self . tokens . contains ( & tok) {
515511 self . tokens . push ( tok) ;
516512 }
517513 self . maybe_empty = false ;
518514 }
519515
520516 // 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 ) {
522518 if !self . tokens . contains ( & tok) {
523519 self . tokens . push ( tok) ;
524520 }
@@ -558,7 +554,6 @@ fn check_matcher_core(sess: &ParseSess,
558554 first_sets : & FirstSets ,
559555 matcher : & [ quoted:: TokenTree ] ,
560556 follow : & TokenSet ) -> TokenSet {
561- use print:: pprust:: token_to_string;
562557 use self :: quoted:: TokenTree ;
563558
564559 let mut last = TokenSet :: empty ( ) ;
@@ -584,11 +579,11 @@ fn check_matcher_core(sess: &ParseSess,
584579 // First, update `last` so that it corresponds to the set
585580 // of NT tokens that might end the sequence `... token`.
586581 match * token {
587- TokenTree :: Token ( sp , ref tok ) => {
582+ TokenTree :: Token ( .. ) | TokenTree :: MetaVarDecl ( .. ) => {
588583 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 ) {
590585 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)
592587 . help ( "valid fragment specifiers are `ident`, `block`, \
593588 `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
594589 and `item`")
@@ -597,7 +592,7 @@ fn check_matcher_core(sess: &ParseSess,
597592 // from error messages.)
598593 can_be_followed_by_any = true ;
599594 } 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 ) ;
601596 }
602597
603598 if can_be_followed_by_any {
@@ -607,13 +602,12 @@ fn check_matcher_core(sess: &ParseSess,
607602 // followed by anything against SUFFIX.
608603 continue ' each_token;
609604 } else {
610- last. replace_with ( ( sp , tok . clone ( ) ) ) ;
605+ last. replace_with ( token . clone ( ) ) ;
611606 suffix_first = build_suffix_first ( ) ;
612607 }
613608 }
614609 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) ) ;
617611 check_matcher_core ( sess, first_sets, & d. tts , & my_suffix) ;
618612 // don't track non NT tokens
619613 last. replace_with_irrelevant ( ) ;
@@ -637,7 +631,7 @@ fn check_matcher_core(sess: &ParseSess,
637631 let mut new;
638632 let my_suffix = if let Some ( ref u) = seq_rep. separator {
639633 new = suffix_first. clone ( ) ;
640- new. add_one_maybe ( ( sp, u. clone ( ) ) ) ;
634+ new. add_one_maybe ( TokenTree :: Token ( sp, u. clone ( ) ) ) ;
641635 & new
642636 } else {
643637 & suffix_first
@@ -663,12 +657,13 @@ fn check_matcher_core(sess: &ParseSess,
663657
664658 // Now `last` holds the complete set of NT tokens that could
665659 // 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 {
669663 match is_in_follow ( next_token, & frag_spec. name . as_str ( ) ) {
670664 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 ( ) ;
672667 // don't bother reporting every source of
673668 // conflict for a particular element of `last`.
674669 continue ' each_last;
@@ -684,12 +679,12 @@ fn check_matcher_core(sess: &ParseSess,
684679 } ;
685680
686681 sess. span_diagnostic . span_err (
687- sp ,
682+ next_token . span ( ) ,
688683 & format ! ( "`${name}:{frag}` {may_be} followed by `{next}`, which \
689684 is not allowed for `{frag}` fragments",
690685 name=name,
691686 frag=frag_spec,
692- next=token_to_string ( next_token) ,
687+ next=quoted_tt_to_string ( next_token) ,
693688 may_be=may_be)
694689 ) ;
695690 }
@@ -701,8 +696,8 @@ fn check_matcher_core(sess: &ParseSess,
701696 last
702697}
703698
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 {
706701 frag_can_be_followed_by_any ( & frag_spec. name . as_str ( ) )
707702 } else {
708703 // (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 {
740735/// break macros that were relying on that binary operator as a
741736/// separator.
742737// 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 {
745742 // closing a token tree can never be matched by any fragment;
746743 // iow, we always require that `(` and `)` match, etc.
747744 Ok ( true )
@@ -757,27 +754,30 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result<bool, (String, &'static str)>
757754 // maintain
758755 Ok ( true )
759756 } ,
760- "stmt" | "expr" => {
761- match * tok {
757+ "stmt" | "expr" => match * tok {
758+ TokenTree :: Token ( _ , ref tok ) => match * tok {
762759 FatArrow | Comma | Semi => Ok ( true ) ,
763760 _ => Ok ( false )
764- }
761+ } ,
762+ _ => Ok ( false ) ,
765763 } ,
766- "pat" => {
767- match * tok {
764+ "pat" => match * tok {
765+ TokenTree :: Token ( _ , ref tok ) => match * tok {
768766 FatArrow | Comma | Eq | BinOp ( token:: Or ) => Ok ( true ) ,
769767 Ident ( i) if i. name == "if" || i. name == "in" => Ok ( true ) ,
770768 _ => Ok ( false )
771- }
769+ } ,
770+ _ => Ok ( false ) ,
772771 } ,
773- "path" | "ty" => {
774- match * tok {
772+ "path" | "ty" => match * tok {
773+ TokenTree :: Token ( _ , ref tok ) => match * tok {
775774 OpenDelim ( token:: DelimToken :: Brace ) | OpenDelim ( token:: DelimToken :: Bracket ) |
776775 Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp ( token:: Or ) => Ok ( true ) ,
777- MatchNt ( _, ref frag) if frag. name == "block" => Ok ( true ) ,
778776 Ident ( i) if i. name == "as" || i. name == "where" => Ok ( true ) ,
779777 _ => Ok ( false )
780- }
778+ } ,
779+ TokenTree :: MetaVarDecl ( _, _, frag) if frag. name == "block" => Ok ( true ) ,
780+ _ => Ok ( false ) ,
781781 } ,
782782 "ident" => {
783783 // being a single token, idents are harmless
@@ -796,9 +796,9 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result<bool, (String, &'static str)>
796796 }
797797}
798798
799- fn has_legal_fragment_specifier ( tok : & Token ) -> Result < ( ) , String > {
799+ fn has_legal_fragment_specifier ( tok : & quoted :: TokenTree ) -> Result < ( ) , String > {
800800 debug ! ( "has_legal_fragment_specifier({:?})" , tok) ;
801- if let & MatchNt ( _, ref frag_spec) = tok {
801+ if let quoted :: TokenTree :: MetaVarDecl ( _, _ , frag_spec) = * tok {
802802 let s = & frag_spec. name . as_str ( ) ;
803803 if !is_legal_fragment_specifier ( s) {
804804 return Err ( s. to_string ( ) ) ;
@@ -814,3 +814,11 @@ fn is_legal_fragment_specifier(frag: &str) -> bool {
814814 _ => false ,
815815 }
816816}
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