]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/tt/macro_rules.rs
Update E0253.rs
[rust.git] / src / libsyntax / ext / tt / macro_rules.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use ast;
12 use syntax_pos::{Span, DUMMY_SP};
13 use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
14 use ext::base::{NormalTT, TTMacroExpander};
15 use ext::tt::macro_parser::{Success, Error, Failure};
16 use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
17 use ext::tt::macro_parser::parse;
18 use parse::lexer::new_tt_reader;
19 use parse::parser::{Parser, Restrictions};
20 use parse::token::{self, gensym_ident, NtTT, Token};
21 use parse::token::Token::*;
22 use print;
23 use ptr::P;
24 use tokenstream::{self, TokenTree};
25
26 use util::small_vector::SmallVector;
27
28 use std::cell::RefCell;
29 use std::collections::{HashMap};
30 use std::collections::hash_map::{Entry};
31 use std::rc::Rc;
32
33 struct ParserAnyMacro<'a> {
34     parser: RefCell<Parser<'a>>,
35
36     /// Span of the expansion site of the macro this parser is for
37     site_span: Span,
38     /// The ident of the macro we're parsing
39     macro_ident: ast::Ident
40 }
41
42 impl<'a> ParserAnyMacro<'a> {
43     /// Make sure we don't have any tokens left to parse, so we don't
44     /// silently drop anything. `allow_semi` is so that "optional"
45     /// semicolons at the end of normal expressions aren't complained
46     /// about e.g. the semicolon in `macro_rules! kapow { () => {
47     /// panic!(); } }` doesn't get picked up by .parse_expr(), but it's
48     /// allowed to be there.
49     fn ensure_complete_parse(&self, allow_semi: bool, context: &str) {
50         let mut parser = self.parser.borrow_mut();
51         if allow_semi && parser.token == token::Semi {
52             parser.bump();
53         }
54         if parser.token != token::Eof {
55             let token_str = parser.this_token_to_string();
56             let msg = format!("macro expansion ignores token `{}` and any \
57                                following",
58                               token_str);
59             let span = parser.span;
60             let mut err = parser.diagnostic().struct_span_err(span, &msg[..]);
61             let msg = format!("caused by the macro expansion here; the usage \
62                                of `{}!` is likely invalid in {} context",
63                                self.macro_ident, context);
64             err.span_note(self.site_span, &msg[..])
65                .emit();
66         }
67     }
68 }
69
70 impl<'a> MacResult for ParserAnyMacro<'a> {
71     fn make_expr(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Expr>> {
72         let ret = panictry!(self.parser.borrow_mut().parse_expr());
73         self.ensure_complete_parse(true, "expression");
74         Some(ret)
75     }
76     fn make_pat(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Pat>> {
77         let ret = panictry!(self.parser.borrow_mut().parse_pat());
78         self.ensure_complete_parse(false, "pattern");
79         Some(ret)
80     }
81     fn make_items(self: Box<ParserAnyMacro<'a>>) -> Option<SmallVector<P<ast::Item>>> {
82         let mut ret = SmallVector::zero();
83         while let Some(item) = panictry!(self.parser.borrow_mut().parse_item()) {
84             ret.push(item);
85         }
86         self.ensure_complete_parse(false, "item");
87         Some(ret)
88     }
89
90     fn make_impl_items(self: Box<ParserAnyMacro<'a>>)
91                        -> Option<SmallVector<ast::ImplItem>> {
92         let mut ret = SmallVector::zero();
93         loop {
94             let mut parser = self.parser.borrow_mut();
95             match parser.token {
96                 token::Eof => break,
97                 _ => ret.push(panictry!(parser.parse_impl_item()))
98             }
99         }
100         self.ensure_complete_parse(false, "item");
101         Some(ret)
102     }
103
104     fn make_trait_items(self: Box<ParserAnyMacro<'a>>)
105                        -> Option<SmallVector<ast::TraitItem>> {
106         let mut ret = SmallVector::zero();
107         loop {
108             let mut parser = self.parser.borrow_mut();
109             match parser.token {
110                 token::Eof => break,
111                 _ => ret.push(panictry!(parser.parse_trait_item()))
112             }
113         }
114         self.ensure_complete_parse(false, "item");
115         Some(ret)
116     }
117
118
119     fn make_stmts(self: Box<ParserAnyMacro<'a>>)
120                  -> Option<SmallVector<ast::Stmt>> {
121         let mut ret = SmallVector::zero();
122         loop {
123             let mut parser = self.parser.borrow_mut();
124             match parser.token {
125                 token::Eof => break,
126                 _ => match parser.parse_full_stmt(true) {
127                     Ok(maybe_stmt) => match maybe_stmt {
128                         Some(stmt) => ret.push(stmt),
129                         None => (),
130                     },
131                     Err(mut e) => {
132                         e.emit();
133                         break;
134                     }
135                 }
136             }
137         }
138         self.ensure_complete_parse(false, "statement");
139         Some(ret)
140     }
141
142     fn make_ty(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Ty>> {
143         let ret = panictry!(self.parser.borrow_mut().parse_ty());
144         self.ensure_complete_parse(false, "type");
145         Some(ret)
146     }
147 }
148
149 struct MacroRulesMacroExpander {
150     name: ast::Ident,
151     imported_from: Option<ast::Ident>,
152     lhses: Vec<TokenTree>,
153     rhses: Vec<TokenTree>,
154     valid: bool,
155 }
156
157 impl TTMacroExpander for MacroRulesMacroExpander {
158     fn expand<'cx>(&self,
159                    cx: &'cx mut ExtCtxt,
160                    sp: Span,
161                    arg: &[TokenTree])
162                    -> Box<MacResult+'cx> {
163         if !self.valid {
164             return DummyResult::any(sp);
165         }
166         generic_extension(cx,
167                           sp,
168                           self.name,
169                           self.imported_from,
170                           arg,
171                           &self.lhses,
172                           &self.rhses)
173     }
174 }
175
176 /// Given `lhses` and `rhses`, this is the new macro we create
177 fn generic_extension<'cx>(cx: &'cx ExtCtxt,
178                           sp: Span,
179                           name: ast::Ident,
180                           imported_from: Option<ast::Ident>,
181                           arg: &[TokenTree],
182                           lhses: &[TokenTree],
183                           rhses: &[TokenTree])
184                           -> Box<MacResult+'cx> {
185     if cx.trace_macros() {
186         println!("{}! {{ {} }}",
187                  name,
188                  print::pprust::tts_to_string(arg));
189     }
190
191     // Which arm's failure should we report? (the one furthest along)
192     let mut best_fail_spot = DUMMY_SP;
193     let mut best_fail_msg = "internal error: ran no matchers".to_string();
194
195     for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
196         let lhs_tt = match *lhs {
197             TokenTree::Delimited(_, ref delim) => &delim.tts[..],
198             _ => cx.span_bug(sp, "malformed macro lhs")
199         };
200
201         match TokenTree::parse(cx, lhs_tt, arg) {
202             Success(named_matches) => {
203                 let rhs = match rhses[i] {
204                     // ignore delimiters
205                     TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(),
206                     _ => cx.span_bug(sp, "malformed macro rhs"),
207                 };
208                 // rhs has holes ( `$id` and `$(...)` that need filled)
209                 let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic,
210                                            Some(named_matches),
211                                            imported_from,
212                                            rhs);
213                 let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr));
214                 p.filename = cx.filename.clone();
215                 p.mod_path_stack = cx.mod_path_stack.clone();
216                 p.restrictions = match cx.in_block {
217                     true => Restrictions::NO_NONINLINE_MOD,
218                     false => Restrictions::empty(),
219                 };
220                 p.check_unknown_macro_variable();
221                 // Let the context choose how to interpret the result.
222                 // Weird, but useful for X-macros.
223                 return Box::new(ParserAnyMacro {
224                     parser: RefCell::new(p),
225
226                     // Pass along the original expansion site and the name of the macro
227                     // so we can print a useful error message if the parse of the expanded
228                     // macro leaves unparsed tokens.
229                     site_span: sp,
230                     macro_ident: name
231                 })
232             }
233             Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
234                 best_fail_spot = sp;
235                 best_fail_msg = (*msg).clone();
236             },
237             Error(err_sp, ref msg) => {
238                 cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])
239             }
240         }
241     }
242
243      cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..]);
244 }
245
246 // Note that macro-by-example's input is also matched against a token tree:
247 //                   $( $lhs:tt => $rhs:tt );+
248 //
249 // Holy self-referential!
250
251 /// Converts a `macro_rules!` invocation into a syntax extension.
252 pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
253                     def: &ast::MacroDef) -> SyntaxExtension {
254
255     let lhs_nm =  gensym_ident("lhs");
256     let rhs_nm =  gensym_ident("rhs");
257
258     // The pattern that macro_rules matches.
259     // The grammar for macro_rules! is:
260     // $( $lhs:tt => $rhs:tt );+
261     // ...quasiquoting this would be nice.
262     // These spans won't matter, anyways
263     let match_lhs_tok = MatchNt(lhs_nm, token::str_to_ident("tt"));
264     let match_rhs_tok = MatchNt(rhs_nm, token::str_to_ident("tt"));
265     let argument_gram = vec![
266         TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
267             tts: vec![
268                 TokenTree::Token(DUMMY_SP, match_lhs_tok),
269                 TokenTree::Token(DUMMY_SP, token::FatArrow),
270                 TokenTree::Token(DUMMY_SP, match_rhs_tok),
271             ],
272             separator: Some(token::Semi),
273             op: tokenstream::KleeneOp::OneOrMore,
274             num_captures: 2,
275         })),
276         // to phase into semicolon-termination instead of semicolon-separation
277         TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
278             tts: vec![TokenTree::Token(DUMMY_SP, token::Semi)],
279             separator: None,
280             op: tokenstream::KleeneOp::ZeroOrMore,
281             num_captures: 0
282         })),
283     ];
284
285     // Parse the macro_rules! invocation (`none` is for no interpolations):
286     let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic,
287                                    None,
288                                    None,
289                                    def.body.clone());
290
291     let argument_map = match parse(cx.parse_sess(),
292                                    cx.cfg(),
293                                    arg_reader,
294                                    &argument_gram) {
295         Success(m) => m,
296         Failure(sp, str) | Error(sp, str) => {
297             panic!(cx.parse_sess().span_diagnostic
298                      .span_fatal(sp.substitute_dummy(def.span), &str[..]));
299         }
300     };
301
302     let mut valid = true;
303
304     // Extract the arguments:
305     let lhses = match **argument_map.get(&lhs_nm.name).unwrap() {
306         MatchedSeq(ref s, _) => {
307             s.iter().map(|m| match **m {
308                 MatchedNonterminal(NtTT(ref tt)) => {
309                     valid &= check_lhs_nt_follows(cx, tt);
310                     (**tt).clone()
311                 }
312                 _ => cx.span_bug(def.span, "wrong-structured lhs")
313             }).collect()
314         }
315         _ => cx.span_bug(def.span, "wrong-structured lhs")
316     };
317
318     let rhses = match **argument_map.get(&rhs_nm.name).unwrap() {
319         MatchedSeq(ref s, _) => {
320             s.iter().map(|m| match **m {
321                 MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(),
322                 _ => cx.span_bug(def.span, "wrong-structured rhs")
323             }).collect()
324         }
325         _ => cx.span_bug(def.span, "wrong-structured rhs")
326     };
327
328     for rhs in &rhses {
329         valid &= check_rhs(cx, rhs);
330     }
331
332     let exp: Box<_> = Box::new(MacroRulesMacroExpander {
333         name: def.ident,
334         imported_from: def.imported_from,
335         lhses: lhses,
336         rhses: rhses,
337         valid: valid,
338     });
339
340     NormalTT(exp, Some(def.span), def.allow_internal_unstable)
341 }
342
343 fn check_lhs_nt_follows(cx: &mut ExtCtxt, lhs: &TokenTree) -> bool {
344     // lhs is going to be like TokenTree::Delimited(...), where the
345     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
346     match lhs {
347         &TokenTree::Delimited(_, ref tts) => check_matcher(cx, &tts.tts),
348         _ => {
349             cx.span_err(lhs.get_span(), "invalid macro matcher; matchers must \
350                                          be contained in balanced delimiters");
351             false
352         }
353     }
354     // we don't abort on errors on rejection, the driver will do that for us
355     // after parsing/expansion. we can report every error in every macro this way.
356 }
357
358 fn check_rhs(cx: &mut ExtCtxt, rhs: &TokenTree) -> bool {
359     match *rhs {
360         TokenTree::Delimited(..) => return true,
361         _ => cx.span_err(rhs.get_span(), "macro rhs must be delimited")
362     }
363     false
364 }
365
366 fn check_matcher(cx: &mut ExtCtxt, matcher: &[TokenTree]) -> bool {
367     let first_sets = FirstSets::new(matcher);
368     let empty_suffix = TokenSet::empty();
369     let err = cx.parse_sess.span_diagnostic.err_count();
370     check_matcher_core(cx, &first_sets, matcher, &empty_suffix);
371     err == cx.parse_sess.span_diagnostic.err_count()
372 }
373
374 // The FirstSets for a matcher is a mapping from subsequences in the
375 // matcher to the FIRST set for that subsequence.
376 //
377 // This mapping is partially precomputed via a backwards scan over the
378 // token trees of the matcher, which provides a mapping from each
379 // repetition sequence to its FIRST set.
380 //
381 // (Hypothetically sequences should be uniquely identifiable via their
382 // spans, though perhaps that is false e.g. for macro-generated macros
383 // that do not try to inject artificial span information. My plan is
384 // to try to catch such cases ahead of time and not include them in
385 // the precomputed mapping.)
386 struct FirstSets {
387     // this maps each TokenTree::Sequence `$(tt ...) SEP OP` that is uniquely identified by its
388     // span in the original matcher to the First set for the inner sequence `tt ...`.
389     //
390     // If two sequences have the same span in a matcher, then map that
391     // span to None (invalidating the mapping here and forcing the code to
392     // use a slow path).
393     first: HashMap<Span, Option<TokenSet>>,
394 }
395
396 impl FirstSets {
397     fn new(tts: &[TokenTree]) -> FirstSets {
398         let mut sets = FirstSets { first: HashMap::new() };
399         build_recur(&mut sets, tts);
400         return sets;
401
402         // walks backward over `tts`, returning the FIRST for `tts`
403         // and updating `sets` at the same time for all sequence
404         // substructure we find within `tts`.
405         fn build_recur(sets: &mut FirstSets, tts: &[TokenTree]) -> TokenSet {
406             let mut first = TokenSet::empty();
407             for tt in tts.iter().rev() {
408                 match *tt {
409                     TokenTree::Token(sp, ref tok) => {
410                         first.replace_with((sp, tok.clone()));
411                     }
412                     TokenTree::Delimited(_, ref delimited) => {
413                         build_recur(sets, &delimited.tts[..]);
414                         first.replace_with((delimited.open_span,
415                                             Token::OpenDelim(delimited.delim)));
416                     }
417                     TokenTree::Sequence(sp, ref seq_rep) => {
418                         let subfirst = build_recur(sets, &seq_rep.tts[..]);
419
420                         match sets.first.entry(sp) {
421                             Entry::Vacant(vac) => {
422                                 vac.insert(Some(subfirst.clone()));
423                             }
424                             Entry::Occupied(mut occ) => {
425                                 // if there is already an entry, then a span must have collided.
426                                 // This should not happen with typical macro_rules macros,
427                                 // but syntax extensions need not maintain distinct spans,
428                                 // so distinct syntax trees can be assigned the same span.
429                                 // In such a case, the map cannot be trusted; so mark this
430                                 // entry as unusable.
431                                 occ.insert(None);
432                             }
433                         }
434
435                         // If the sequence contents can be empty, then the first
436                         // token could be the separator token itself.
437
438                         if let (Some(ref sep), true) = (seq_rep.separator.clone(),
439                                                         subfirst.maybe_empty) {
440                             first.add_one_maybe((sp, sep.clone()));
441                         }
442
443                         // Reverse scan: Sequence comes before `first`.
444                         if subfirst.maybe_empty || seq_rep.op == tokenstream::KleeneOp::ZeroOrMore {
445                             // If sequence is potentially empty, then
446                             // union them (preserving first emptiness).
447                             first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
448                         } else {
449                             // Otherwise, sequence guaranteed
450                             // non-empty; replace first.
451                             first = subfirst;
452                         }
453                     }
454                 }
455             }
456
457             return first;
458         }
459     }
460
461     // walks forward over `tts` until all potential FIRST tokens are
462     // identified.
463     fn first(&self, tts: &[TokenTree]) -> TokenSet {
464         let mut first = TokenSet::empty();
465         for tt in tts.iter() {
466             assert!(first.maybe_empty);
467             match *tt {
468                 TokenTree::Token(sp, ref tok) => {
469                     first.add_one((sp, tok.clone()));
470                     return first;
471                 }
472                 TokenTree::Delimited(_, ref delimited) => {
473                     first.add_one((delimited.open_span,
474                                    Token::OpenDelim(delimited.delim)));
475                     return first;
476                 }
477                 TokenTree::Sequence(sp, ref seq_rep) => {
478                     match self.first.get(&sp) {
479                         Some(&Some(ref subfirst)) => {
480
481                             // If the sequence contents can be empty, then the first
482                             // token could be the separator token itself.
483
484                             if let (Some(ref sep), true) = (seq_rep.separator.clone(),
485                                                             subfirst.maybe_empty) {
486                                 first.add_one_maybe((sp, sep.clone()));
487                             }
488
489                             assert!(first.maybe_empty);
490                             first.add_all(subfirst);
491                             if subfirst.maybe_empty ||
492                                seq_rep.op == tokenstream::KleeneOp::ZeroOrMore {
493                                 // continue scanning for more first
494                                 // tokens, but also make sure we
495                                 // restore empty-tracking state
496                                 first.maybe_empty = true;
497                                 continue;
498                             } else {
499                                 return first;
500                             }
501                         }
502
503                         Some(&None) => {
504                             panic!("assume all sequences have (unique) spans for now");
505                         }
506
507                         None => {
508                             panic!("We missed a sequence during FirstSets construction");
509                         }
510                     }
511                 }
512             }
513         }
514
515         // we only exit the loop if `tts` was empty or if every
516         // element of `tts` matches the empty sequence.
517         assert!(first.maybe_empty);
518         return first;
519     }
520 }
521
522 // A set of Tokens, which may include MatchNt tokens (for
523 // macro-by-example syntactic variables). It also carries the
524 // `maybe_empty` flag; that is true if and only if the matcher can
525 // match an empty token sequence.
526 //
527 // The First set is computed on submatchers like `$($a:expr b),* $(c)* d`,
528 // which has corresponding FIRST = {$a:expr, c, d}.
529 // Likewise, `$($a:expr b),* $(c)+ d` has FIRST = {$a:expr, c}.
530 //
531 // (Notably, we must allow for *-op to occur zero times.)
532 #[derive(Clone, Debug)]
533 struct TokenSet {
534     tokens: Vec<(Span, Token)>,
535     maybe_empty: bool,
536 }
537
538 impl TokenSet {
539     // Returns a set for the empty sequence.
540     fn empty() -> Self { TokenSet { tokens: Vec::new(), maybe_empty: true } }
541
542     // Returns the set `{ tok }` for the single-token (and thus
543     // non-empty) sequence [tok].
544     fn singleton(tok: (Span, Token)) -> Self {
545         TokenSet { tokens: vec![tok], maybe_empty: false }
546     }
547
548     // Changes self to be the set `{ tok }`.
549     // Since `tok` is always present, marks self as non-empty.
550     fn replace_with(&mut self, tok: (Span, Token)) {
551         self.tokens.clear();
552         self.tokens.push(tok);
553         self.maybe_empty = false;
554     }
555
556     // Changes self to be the empty set `{}`; meant for use when
557     // the particular token does not matter, but we want to
558     // record that it occurs.
559     fn replace_with_irrelevant(&mut self) {
560         self.tokens.clear();
561         self.maybe_empty = false;
562     }
563
564     // Adds `tok` to the set for `self`, marking sequence as non-empy.
565     fn add_one(&mut self, tok: (Span, Token)) {
566         if !self.tokens.contains(&tok) {
567             self.tokens.push(tok);
568         }
569         self.maybe_empty = false;
570     }
571
572     // Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.)
573     fn add_one_maybe(&mut self, tok: (Span, Token)) {
574         if !self.tokens.contains(&tok) {
575             self.tokens.push(tok);
576         }
577     }
578
579     // Adds all elements of `other` to this.
580     //
581     // (Since this is a set, we filter out duplicates.)
582     //
583     // If `other` is potentially empty, then preserves the previous
584     // setting of the empty flag of `self`. If `other` is guaranteed
585     // non-empty, then `self` is marked non-empty.
586     fn add_all(&mut self, other: &Self) {
587         for tok in &other.tokens {
588             if !self.tokens.contains(tok) {
589                 self.tokens.push(tok.clone());
590             }
591         }
592         if !other.maybe_empty {
593             self.maybe_empty = false;
594         }
595     }
596 }
597
598 // Checks that `matcher` is internally consistent and that it
599 // can legally by followed by a token N, for all N in `follow`.
600 // (If `follow` is empty, then it imposes no constraint on
601 // the `matcher`.)
602 //
603 // Returns the set of NT tokens that could possibly come last in
604 // `matcher`. (If `matcher` matches the empty sequence, then
605 // `maybe_empty` will be set to true.)
606 //
607 // Requires that `first_sets` is pre-computed for `matcher`;
608 // see `FirstSets::new`.
609 fn check_matcher_core(cx: &mut ExtCtxt,
610                       first_sets: &FirstSets,
611                       matcher: &[TokenTree],
612                       follow: &TokenSet) -> TokenSet {
613     use print::pprust::token_to_string;
614
615     let mut last = TokenSet::empty();
616
617     // 2. For each token and suffix  [T, SUFFIX] in M:
618     // ensure that T can be followed by SUFFIX, and if SUFFIX may be empty,
619     // then ensure T can also be followed by any element of FOLLOW.
620     'each_token: for i in 0..matcher.len() {
621         let token = &matcher[i];
622         let suffix = &matcher[i+1..];
623
624         let build_suffix_first = || {
625             let mut s = first_sets.first(suffix);
626             if s.maybe_empty { s.add_all(follow); }
627             return s;
628         };
629
630         // (we build `suffix_first` on demand below; you can tell
631         // which cases are supposed to fall through by looking for the
632         // initialization of this variable.)
633         let suffix_first;
634
635         // First, update `last` so that it corresponds to the set
636         // of NT tokens that might end the sequence `... token`.
637         match *token {
638             TokenTree::Token(sp, ref tok) => {
639                 let can_be_followed_by_any;
640                 if let Err(bad_frag) = has_legal_fragment_specifier(tok) {
641                     cx.struct_span_err(sp, &format!("invalid fragment specifier `{}`", bad_frag))
642                         .help("valid fragment specifiers are `ident`, `block`, \
643                                `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
644                                and `item`")
645                         .emit();
646                     // (This eliminates false positives and duplicates
647                     // from error messages.)
648                     can_be_followed_by_any = true;
649                 } else {
650                     can_be_followed_by_any = token_can_be_followed_by_any(tok);
651                 }
652
653                 if can_be_followed_by_any {
654                     // don't need to track tokens that work with any,
655                     last.replace_with_irrelevant();
656                     // ... and don't need to check tokens that can be
657                     // followed by anything against SUFFIX.
658                     continue 'each_token;
659                 } else {
660                     last.replace_with((sp, tok.clone()));
661                     suffix_first = build_suffix_first();
662                 }
663             }
664             TokenTree::Delimited(_, ref d) => {
665                 let my_suffix = TokenSet::singleton((d.close_span, Token::CloseDelim(d.delim)));
666                 check_matcher_core(cx, first_sets, &d.tts, &my_suffix);
667                 // don't track non NT tokens
668                 last.replace_with_irrelevant();
669
670                 // also, we don't need to check delimited sequences
671                 // against SUFFIX
672                 continue 'each_token;
673             }
674             TokenTree::Sequence(sp, ref seq_rep) => {
675                 suffix_first = build_suffix_first();
676                 // The trick here: when we check the interior, we want
677                 // to include the separator (if any) as a potential
678                 // (but not guaranteed) element of FOLLOW. So in that
679                 // case, we make a temp copy of suffix and stuff
680                 // delimiter in there.
681                 //
682                 // FIXME: Should I first scan suffix_first to see if
683                 // delimiter is already in it before I go through the
684                 // work of cloning it? But then again, this way I may
685                 // get a "tighter" span?
686                 let mut new;
687                 let my_suffix = if let Some(ref u) = seq_rep.separator {
688                     new = suffix_first.clone();
689                     new.add_one_maybe((sp, u.clone()));
690                     &new
691                 } else {
692                     &suffix_first
693                 };
694
695                 // At this point, `suffix_first` is built, and
696                 // `my_suffix` is some TokenSet that we can use
697                 // for checking the interior of `seq_rep`.
698                 let next = check_matcher_core(cx, first_sets, &seq_rep.tts, my_suffix);
699                 if next.maybe_empty {
700                     last.add_all(&next);
701                 } else {
702                     last = next;
703                 }
704
705                 // the recursive call to check_matcher_core already ran the 'each_last
706                 // check below, so we can just keep going forward here.
707                 continue 'each_token;
708             }
709         }
710
711         // (`suffix_first` guaranteed initialized once reaching here.)
712
713         // Now `last` holds the complete set of NT tokens that could
714         // end the sequence before SUFFIX. Check that every one works with `suffix`.
715         'each_last: for &(_sp, ref t) in &last.tokens {
716             if let MatchNt(ref name, ref frag_spec) = *t {
717                 for &(sp, ref next_token) in &suffix_first.tokens {
718                     match is_in_follow(cx, next_token, &frag_spec.name.as_str()) {
719                         Err((msg, help)) => {
720                             cx.struct_span_err(sp, &msg).help(help).emit();
721                             // don't bother reporting every source of
722                             // conflict for a particular element of `last`.
723                             continue 'each_last;
724                         }
725                         Ok(true) => {}
726                         Ok(false) => {
727                             let may_be = if last.tokens.len() == 1 &&
728                                 suffix_first.tokens.len() == 1
729                             {
730                                 "is"
731                             } else {
732                                 "may be"
733                             };
734
735                             cx.span_err(
736                                 sp,
737                                 &format!("`${name}:{frag}` {may_be} followed by `{next}`, which \
738                                           is not allowed for `{frag}` fragments",
739                                          name=name,
740                                          frag=frag_spec,
741                                          next=token_to_string(next_token),
742                                          may_be=may_be)
743                             );
744                         }
745                     }
746                 }
747             }
748         }
749     }
750     last
751 }
752
753 fn token_can_be_followed_by_any(tok: &Token) -> bool {
754     if let &MatchNt(_, ref frag_spec) = tok {
755         frag_can_be_followed_by_any(&frag_spec.name.as_str())
756     } else {
757         // (Non NT's can always be followed by anthing in matchers.)
758         true
759     }
760 }
761
762 /// True if a fragment of type `frag` can be followed by any sort of
763 /// token.  We use this (among other things) as a useful approximation
764 /// for when `frag` can be followed by a repetition like `$(...)*` or
765 /// `$(...)+`. In general, these can be a bit tricky to reason about,
766 /// so we adopt a conservative position that says that any fragment
767 /// specifier which consumes at most one token tree can be followed by
768 /// a fragment specifier (indeed, these fragments can be followed by
769 /// ANYTHING without fear of future compatibility hazards).
770 fn frag_can_be_followed_by_any(frag: &str) -> bool {
771     match frag {
772         "item"  | // always terminated by `}` or `;`
773         "block" | // exactly one token tree
774         "ident" | // exactly one token tree
775         "meta"  | // exactly one token tree
776         "tt" =>   // exactly one token tree
777             true,
778
779         _ =>
780             false,
781     }
782 }
783
784 /// True if `frag` can legally be followed by the token `tok`. For
785 /// fragments that can consume an unbounded number of tokens, `tok`
786 /// must be within a well-defined follow set. This is intended to
787 /// guarantee future compatibility: for example, without this rule, if
788 /// we expanded `expr` to include a new binary operator, we might
789 /// break macros that were relying on that binary operator as a
790 /// separator.
791 // when changing this do not forget to update doc/book/macros.md!
792 fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, (String, &'static str)> {
793     if let &CloseDelim(_) = tok {
794         // closing a token tree can never be matched by any fragment;
795         // iow, we always require that `(` and `)` match, etc.
796         Ok(true)
797     } else {
798         match frag {
799             "item" => {
800                 // since items *must* be followed by either a `;` or a `}`, we can
801                 // accept anything after them
802                 Ok(true)
803             },
804             "block" => {
805                 // anything can follow block, the braces provide an easy boundary to
806                 // maintain
807                 Ok(true)
808             },
809             "stmt" | "expr"  => {
810                 match *tok {
811                     FatArrow | Comma | Semi => Ok(true),
812                     _ => Ok(false)
813                 }
814             },
815             "pat" => {
816                 match *tok {
817                     FatArrow | Comma | Eq | BinOp(token::Or) => Ok(true),
818                     Ident(i) if (i.name.as_str() == "if" ||
819                                  i.name.as_str() == "in") => Ok(true),
820                     _ => Ok(false)
821                 }
822             },
823             "path" | "ty" => {
824                 match *tok {
825                     OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) |
826                     Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true),
827                     MatchNt(_, ref frag) if frag.name.as_str() == "block" => Ok(true),
828                     Ident(i) if i.name.as_str() == "as" || i.name.as_str() == "where" => Ok(true),
829                     _ => Ok(false)
830                 }
831             },
832             "ident" => {
833                 // being a single token, idents are harmless
834                 Ok(true)
835             },
836             "meta" | "tt" => {
837                 // being either a single token or a delimited sequence, tt is
838                 // harmless
839                 Ok(true)
840             },
841             _ => Err((format!("invalid fragment specifier `{}`", frag),
842                      "valid fragment specifiers are `ident`, `block`, \
843                       `stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
844                       and `item`"))
845         }
846     }
847 }
848
849 fn has_legal_fragment_specifier(tok: &Token) -> Result<(), String> {
850     debug!("has_legal_fragment_specifier({:?})", tok);
851     if let &MatchNt(_, ref frag_spec) = tok {
852         let s = &frag_spec.name.as_str();
853         if !is_legal_fragment_specifier(s) {
854             return Err(s.to_string());
855         }
856     }
857     Ok(())
858 }
859
860 fn is_legal_fragment_specifier(frag: &str) -> bool {
861     match frag {
862         "item" | "block" | "stmt" | "expr" | "pat" |
863         "path" | "ty" | "ident" | "meta" | "tt" => true,
864         _ => false,
865     }
866 }