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