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