]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/tt/macro_parser.rs
Rollup merge of #58133 - taiki-e:libsyntax_ext-2018, r=Centril
[rust.git] / src / libsyntax / ext / tt / macro_parser.rs
1 //! This is an NFA-based parser, which calls out to the main rust parser for named nonterminals
2 //! (which it commits to fully when it hits one in a grammar). There's a set of current NFA threads
3 //! and a set of next ones. Instead of NTs, we have a special case for Kleene star. The big-O, in
4 //! pathological cases, is worse than traditional use of NFA or Earley parsing, but it's an easier
5 //! fit for Macro-by-Example-style rules.
6 //!
7 //! (In order to prevent the pathological case, we'd need to lazily construct the resulting
8 //! `NamedMatch`es at the very end. It'd be a pain, and require more memory to keep around old
9 //! items, but it would also save overhead)
10 //!
11 //! We don't say this parser uses the Earley algorithm, because it's unnecessarily inaccurate.
12 //! The macro parser restricts itself to the features of finite state automata. Earley parsers
13 //! can be described as an extension of NFAs with completion rules, prediction rules, and recursion.
14 //!
15 //! Quick intro to how the parser works:
16 //!
17 //! A 'position' is a dot in the middle of a matcher, usually represented as a
18 //! dot. For example `· a $( a )* a b` is a position, as is `a $( · a )* a b`.
19 //!
20 //! The parser walks through the input a character at a time, maintaining a list
21 //! of threads consistent with the current position in the input string: `cur_items`.
22 //!
23 //! As it processes them, it fills up `eof_items` with threads that would be valid if
24 //! the macro invocation is now over, `bb_items` with threads that are waiting on
25 //! a Rust nonterminal like `$e:expr`, and `next_items` with threads that are waiting
26 //! on a particular token. Most of the logic concerns moving the · through the
27 //! repetitions indicated by Kleene stars. The rules for moving the · without
28 //! consuming any input are called epsilon transitions. It only advances or calls
29 //! out to the real Rust parser when no `cur_items` threads remain.
30 //!
31 //! Example:
32 //!
33 //! ```text, ignore
34 //! Start parsing a a a a b against [· a $( a )* a b].
35 //!
36 //! Remaining input: a a a a b
37 //! next: [· a $( a )* a b]
38 //!
39 //! - - - Advance over an a. - - -
40 //!
41 //! Remaining input: a a a b
42 //! cur: [a · $( a )* a b]
43 //! Descend/Skip (first item).
44 //! next: [a $( · a )* a b]  [a $( a )* · a b].
45 //!
46 //! - - - Advance over an a. - - -
47 //!
48 //! Remaining input: a a b
49 //! cur: [a $( a · )* a b]  [a $( a )* a · b]
50 //! Follow epsilon transition: Finish/Repeat (first item)
51 //! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
52 //!
53 //! - - - Advance over an a. - - - (this looks exactly like the last step)
54 //!
55 //! Remaining input: a b
56 //! cur: [a $( a · )* a b]  [a $( a )* a · b]
57 //! Follow epsilon transition: Finish/Repeat (first item)
58 //! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
59 //!
60 //! - - - Advance over an a. - - - (this looks exactly like the last step)
61 //!
62 //! Remaining input: b
63 //! cur: [a $( a · )* a b]  [a $( a )* a · b]
64 //! Follow epsilon transition: Finish/Repeat (first item)
65 //! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
66 //!
67 //! - - - Advance over a b. - - -
68 //!
69 //! Remaining input: ''
70 //! eof: [a $( a )* a b ·]
71 //! ```
72
73 pub use NamedMatch::*;
74 pub use ParseResult::*;
75 use TokenTreeOrTokenTreeSlice::*;
76
77 use crate::ast::Ident;
78 use crate::errors::FatalError;
79 use crate::ext::tt::quoted::{self, TokenTree};
80 use crate::parse::{Directory, ParseSess};
81 use crate::parse::parser::{Parser, PathStyle};
82 use crate::parse::token::{self, DocComment, Nonterminal, Token};
83 use crate::print::pprust;
84 use crate::symbol::keywords;
85 use crate::tokenstream::{DelimSpan, TokenStream};
86
87 use smallvec::{smallvec, SmallVec};
88 use syntax_pos::{self, Span};
89
90 use rustc_data_structures::fx::FxHashMap;
91 use std::collections::hash_map::Entry::{Occupied, Vacant};
92 use std::mem;
93 use std::ops::{Deref, DerefMut};
94 use std::rc::Rc;
95
96 // To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body.
97
98 /// Either a sequence of token trees or a single one. This is used as the representation of the
99 /// sequence of tokens that make up a matcher.
100 #[derive(Clone)]
101 enum TokenTreeOrTokenTreeSlice<'tt> {
102     Tt(TokenTree),
103     TtSeq(&'tt [TokenTree]),
104 }
105
106 impl<'tt> TokenTreeOrTokenTreeSlice<'tt> {
107     /// Returns the number of constituent top-level token trees of `self` (top-level in that it
108     /// will not recursively descend into subtrees).
109     fn len(&self) -> usize {
110         match *self {
111             TtSeq(ref v) => v.len(),
112             Tt(ref tt) => tt.len(),
113         }
114     }
115
116     /// The `index`-th token tree of `self`.
117     fn get_tt(&self, index: usize) -> TokenTree {
118         match *self {
119             TtSeq(ref v) => v[index].clone(),
120             Tt(ref tt) => tt.get_tt(index),
121         }
122     }
123 }
124
125 /// An unzipping of `TokenTree`s... see the `stack` field of `MatcherPos`.
126 ///
127 /// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have
128 /// descended into.
129 #[derive(Clone)]
130 struct MatcherTtFrame<'tt> {
131     /// The "parent" matcher that we are descending into.
132     elts: TokenTreeOrTokenTreeSlice<'tt>,
133     /// The position of the "dot" in `elts` at the time we descended.
134     idx: usize,
135 }
136
137 type NamedMatchVec = SmallVec<[NamedMatch; 4]>;
138
139 /// Represents a single "position" (aka "matcher position", aka "item"), as
140 /// described in the module documentation.
141 ///
142 /// Here:
143 ///
144 /// - `'root` represents the lifetime of the stack slot that holds the root
145 ///   `MatcherPos`. As described in `MatcherPosHandle`, the root `MatcherPos`
146 ///   structure is stored on the stack, but subsequent instances are put into
147 ///   the heap.
148 /// - `'tt` represents the lifetime of the token trees that this matcher
149 ///   position refers to.
150 ///
151 /// It is important to distinguish these two lifetimes because we have a
152 /// `SmallVec<TokenTreeOrTokenTreeSlice<'tt>>` below, and the destructor of
153 /// that is considered to possibly access the data from its elements (it lacks
154 /// a `#[may_dangle]` attribute). As a result, the compiler needs to know that
155 /// all the elements in that `SmallVec` strictly outlive the root stack slot
156 /// lifetime. By separating `'tt` from `'root`, we can show that.
157 #[derive(Clone)]
158 struct MatcherPos<'root, 'tt: 'root> {
159     /// The token or sequence of tokens that make up the matcher
160     top_elts: TokenTreeOrTokenTreeSlice<'tt>,
161
162     /// The position of the "dot" in this matcher
163     idx: usize,
164
165     /// The first span of source that the beginning of this matcher corresponds to. In other
166     /// words, the token in the source whose span is `sp_open` is matched against the first token of
167     /// the matcher.
168     sp_open: Span,
169
170     /// For each named metavar in the matcher, we keep track of token trees matched against the
171     /// metavar by the black box parser. In particular, there may be more than one match per
172     /// metavar if we are in a repetition (each repetition matches each of the variables).
173     /// Moreover, matchers and repetitions can be nested; the `matches` field is shared (hence the
174     /// `Rc`) among all "nested" matchers. `match_lo`, `match_cur`, and `match_hi` keep track of
175     /// the current position of the `self` matcher position in the shared `matches` list.
176     ///
177     /// Also, note that while we are descending into a sequence, matchers are given their own
178     /// `matches` vector. Only once we reach the end of a full repetition of the sequence do we add
179     /// all bound matches from the submatcher into the shared top-level `matches` vector. If `sep`
180     /// and `up` are `Some`, then `matches` is _not_ the shared top-level list. Instead, if one
181     /// wants the shared `matches`, one should use `up.matches`.
182     matches: Box<[Rc<NamedMatchVec>]>,
183     /// The position in `matches` corresponding to the first metavar in this matcher's sequence of
184     /// token trees. In other words, the first metavar in the first token of `top_elts` corresponds
185     /// to `matches[match_lo]`.
186     match_lo: usize,
187     /// The position in `matches` corresponding to the metavar we are currently trying to match
188     /// against the source token stream. `match_lo <= match_cur <= match_hi`.
189     match_cur: usize,
190     /// Similar to `match_lo` except `match_hi` is the position in `matches` of the _last_ metavar
191     /// in this matcher.
192     match_hi: usize,
193
194     // The following fields are used if we are matching a repetition. If we aren't, they should be
195     // `None`.
196
197     /// The KleeneOp of this sequence if we are in a repetition.
198     seq_op: Option<quoted::KleeneOp>,
199
200     /// The separator if we are in a repetition.
201     sep: Option<Token>,
202
203     /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
204     /// before we enter the sequence.
205     up: Option<MatcherPosHandle<'root, 'tt>>,
206
207     /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
208     /// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc
209     /// comment...
210     ///
211     /// When matching against matchers with nested delimited submatchers (e.g., `pat ( pat ( .. )
212     /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does
213     /// that where the bottom of the stack is the outermost matcher.
214     /// Also, throughout the comments, this "descent" is often referred to as "unzipping"...
215     stack: SmallVec<[MatcherTtFrame<'tt>; 1]>,
216 }
217
218 impl<'root, 'tt> MatcherPos<'root, 'tt> {
219     /// Add `m` as a named match for the `idx`-th metavar.
220     fn push_match(&mut self, idx: usize, m: NamedMatch) {
221         let matches = Rc::make_mut(&mut self.matches[idx]);
222         matches.push(m);
223     }
224 }
225
226 // Lots of MatcherPos instances are created at runtime. Allocating them on the
227 // heap is slow. Furthermore, using SmallVec<MatcherPos> to allocate them all
228 // on the stack is also slow, because MatcherPos is quite a large type and
229 // instances get moved around a lot between vectors, which requires lots of
230 // slow memcpy calls.
231 //
232 // Therefore, the initial MatcherPos is always allocated on the stack,
233 // subsequent ones (of which there aren't that many) are allocated on the heap,
234 // and this type is used to encapsulate both cases.
235 enum MatcherPosHandle<'root, 'tt: 'root> {
236     Ref(&'root mut MatcherPos<'root, 'tt>),
237     Box(Box<MatcherPos<'root, 'tt>>),
238 }
239
240 impl<'root, 'tt> Clone for MatcherPosHandle<'root, 'tt> {
241     // This always produces a new Box.
242     fn clone(&self) -> Self {
243         MatcherPosHandle::Box(match *self {
244             MatcherPosHandle::Ref(ref r) => Box::new((**r).clone()),
245             MatcherPosHandle::Box(ref b) => b.clone(),
246         })
247     }
248 }
249
250 impl<'root, 'tt> Deref for MatcherPosHandle<'root, 'tt> {
251     type Target = MatcherPos<'root, 'tt>;
252     fn deref(&self) -> &Self::Target {
253         match *self {
254             MatcherPosHandle::Ref(ref r) => r,
255             MatcherPosHandle::Box(ref b) => b,
256         }
257     }
258 }
259
260 impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> {
261     fn deref_mut(&mut self) -> &mut MatcherPos<'root, 'tt> {
262         match *self {
263             MatcherPosHandle::Ref(ref mut r) => r,
264             MatcherPosHandle::Box(ref mut b) => b,
265         }
266     }
267 }
268
269 /// Represents the possible results of an attempted parse.
270 pub enum ParseResult<T> {
271     /// Parsed successfully.
272     Success(T),
273     /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected
274     /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
275     Failure(syntax_pos::Span, Token, &'static str),
276     /// Fatal error (malformed macro?). Abort compilation.
277     Error(syntax_pos::Span, String),
278 }
279
280 /// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es.
281 /// This represents the mapping of metavars to the token trees they bind to.
282 pub type NamedParseResult = ParseResult<FxHashMap<Ident, Rc<NamedMatch>>>;
283
284 /// Count how many metavars are named in the given matcher `ms`.
285 pub fn count_names(ms: &[TokenTree]) -> usize {
286     ms.iter().fold(0, |count, elt| {
287         count + match *elt {
288             TokenTree::Sequence(_, ref seq) => seq.num_captures,
289             TokenTree::Delimited(_, ref delim) => count_names(&delim.tts),
290             TokenTree::MetaVar(..) => 0,
291             TokenTree::MetaVarDecl(..) => 1,
292             TokenTree::Token(..) => 0,
293         }
294     })
295 }
296
297 /// `len` `Vec`s (initially shared and empty) that will store matches of metavars.
298 fn create_matches(len: usize) -> Box<[Rc<NamedMatchVec>]> {
299     if len == 0 {
300         vec![]
301     } else {
302         let empty_matches = Rc::new(SmallVec::new());
303         vec![empty_matches; len]
304     }.into_boxed_slice()
305 }
306
307 /// Generate the top-level matcher position in which the "dot" is before the first token of the
308 /// matcher `ms` and we are going to start matching at the span `open` in the source.
309 fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherPos<'root, 'tt> {
310     let match_idx_hi = count_names(ms);
311     let matches = create_matches(match_idx_hi);
312     MatcherPos {
313         // Start with the top level matcher given to us
314         top_elts: TtSeq(ms), // "elts" is an abbr. for "elements"
315         // The "dot" is before the first token of the matcher
316         idx: 0,
317         // We start matching at the span `open` in the source code
318         sp_open: open,
319
320         // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`.
321         // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since
322         // we haven't actually matched anything yet.
323         matches,
324         match_lo: 0,
325         match_cur: 0,
326         match_hi: match_idx_hi,
327
328         // Haven't descended into any delimiters, so empty stack
329         stack: smallvec![],
330
331         // Haven't descended into any sequences, so both of these are `None`.
332         seq_op: None,
333         sep: None,
334         up: None,
335     }
336 }
337
338 /// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`:
339 /// so it is associated with a single ident in a parse, and all
340 /// `MatchedNonterminal`s in the `NamedMatch` have the same nonterminal type
341 /// (expr, item, etc). Each leaf in a single `NamedMatch` corresponds to a
342 /// single `token::MATCH_NONTERMINAL` in the `TokenTree` that produced it.
343 ///
344 /// The in-memory structure of a particular `NamedMatch` represents the match
345 /// that occurred when a particular subset of a matcher was applied to a
346 /// particular token tree.
347 ///
348 /// The width of each `MatchedSeq` in the `NamedMatch`, and the identity of
349 /// the `MatchedNonterminal`s, will depend on the token tree it was applied
350 /// to: each `MatchedSeq` corresponds to a single `TTSeq` in the originating
351 /// token tree. The depth of the `NamedMatch` structure will therefore depend
352 /// only on the nesting depth of `ast::TTSeq`s in the originating
353 /// token tree it was derived from.
354 #[derive(Debug, Clone)]
355 pub enum NamedMatch {
356     MatchedSeq(Rc<NamedMatchVec>, DelimSpan),
357     MatchedNonterminal(Rc<Nonterminal>),
358 }
359
360 /// Takes a sequence of token trees `ms` representing a matcher which successfully matched input
361 /// and an iterator of items that matched input and produces a `NamedParseResult`.
362 fn nameize<I: Iterator<Item = NamedMatch>>(
363     sess: &ParseSess,
364     ms: &[TokenTree],
365     mut res: I,
366 ) -> NamedParseResult {
367     // Recursively descend into each type of matcher (e.g., sequences, delimited, metavars) and make
368     // sure that each metavar has _exactly one_ binding. If a metavar does not have exactly one
369     // binding, then there is an error. If it does, then we insert the binding into the
370     // `NamedParseResult`.
371     fn n_rec<I: Iterator<Item = NamedMatch>>(
372         sess: &ParseSess,
373         m: &TokenTree,
374         res: &mut I,
375         ret_val: &mut FxHashMap<Ident, Rc<NamedMatch>>,
376     ) -> Result<(), (syntax_pos::Span, String)> {
377         match *m {
378             TokenTree::Sequence(_, ref seq) => for next_m in &seq.tts {
379                 n_rec(sess, next_m, res.by_ref(), ret_val)?
380             },
381             TokenTree::Delimited(_, ref delim) => for next_m in &delim.tts {
382                 n_rec(sess, next_m, res.by_ref(), ret_val)?;
383             },
384             TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => {
385                 if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
386                     return Err((span, "missing fragment specifier".to_string()));
387                 }
388             }
389             TokenTree::MetaVarDecl(sp, bind_name, _) => {
390                 match ret_val.entry(bind_name) {
391                     Vacant(spot) => {
392                         // FIXME(simulacrum): Don't construct Rc here
393                         spot.insert(Rc::new(res.next().unwrap()));
394                     }
395                     Occupied(..) => {
396                         return Err((sp, format!("duplicated bind name: {}", bind_name)))
397                     }
398                 }
399             }
400             TokenTree::MetaVar(..) | TokenTree::Token(..) => (),
401         }
402
403         Ok(())
404     }
405
406     let mut ret_val = FxHashMap::default();
407     for m in ms {
408         match n_rec(sess, m, res.by_ref(), &mut ret_val) {
409             Ok(_) => {}
410             Err((sp, msg)) => return Error(sp, msg),
411         }
412     }
413
414     Success(ret_val)
415 }
416
417 /// Generate an appropriate parsing failure message. For EOF, this is "unexpected end...". For
418 /// other tokens, this is "unexpected token...".
419 pub fn parse_failure_msg(tok: Token) -> String {
420     match tok {
421         token::Eof => "unexpected end of macro invocation".to_string(),
422         _ => format!(
423             "no rules expected the token `{}`",
424             pprust::token_to_string(&tok)
425         ),
426     }
427 }
428
429 /// Perform a token equality check, ignoring syntax context (that is, an unhygienic comparison)
430 fn token_name_eq(t1: &Token, t2: &Token) -> bool {
431     if let (Some((id1, is_raw1)), Some((id2, is_raw2))) = (t1.ident(), t2.ident()) {
432         id1.name == id2.name && is_raw1 == is_raw2
433     } else if let (Some(id1), Some(id2)) = (t1.lifetime(), t2.lifetime()) {
434         id1.name == id2.name
435     } else {
436         *t1 == *t2
437     }
438 }
439
440 /// Process the matcher positions of `cur_items` until it is empty. In the process, this will
441 /// produce more items in `next_items`, `eof_items`, and `bb_items`.
442 ///
443 /// For more info about the how this happens, see the module-level doc comments and the inline
444 /// comments of this function.
445 ///
446 /// # Parameters
447 ///
448 /// - `sess`: the parsing session into which errors are emitted.
449 /// - `cur_items`: the set of current items to be processed. This should be empty by the end of a
450 ///   successful execution of this function.
451 /// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
452 ///   the function `parse`.
453 /// - `eof_items`: the set of items that would be valid if this was the EOF.
454 /// - `bb_items`: the set of items that are waiting for the black-box parser.
455 /// - `token`: the current token of the parser.
456 /// - `span`: the `Span` in the source code corresponding to the token trees we are trying to match
457 ///   against the matcher positions in `cur_items`.
458 ///
459 /// # Returns
460 ///
461 /// A `ParseResult`. Note that matches are kept track of through the items generated.
462 fn inner_parse_loop<'root, 'tt>(
463     sess: &ParseSess,
464     cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
465     next_items: &mut Vec<MatcherPosHandle<'root, 'tt>>,
466     eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
467     bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
468     token: &Token,
469     span: syntax_pos::Span,
470 ) -> ParseResult<()> {
471     // Pop items from `cur_items` until it is empty.
472     while let Some(mut item) = cur_items.pop() {
473         // When unzipped trees end, remove them. This corresponds to backtracking out of a
474         // delimited submatcher into which we already descended. In backtracking out again, we need
475         // to advance the "dot" past the delimiters in the outer matcher.
476         while item.idx >= item.top_elts.len() {
477             match item.stack.pop() {
478                 Some(MatcherTtFrame { elts, idx }) => {
479                     item.top_elts = elts;
480                     item.idx = idx + 1;
481                 }
482                 None => break,
483             }
484         }
485
486         // Get the current position of the "dot" (`idx`) in `item` and the number of token trees in
487         // the matcher (`len`).
488         let idx = item.idx;
489         let len = item.top_elts.len();
490
491         // If `idx >= len`, then we are at or past the end of the matcher of `item`.
492         if idx >= len {
493             // We are repeating iff there is a parent. If the matcher is inside of a repetition,
494             // then we could be at the end of a sequence or at the beginning of the next
495             // repetition.
496             if item.up.is_some() {
497                 // At this point, regardless of whether there is a separator, we should add all
498                 // matches from the complete repetition of the sequence to the shared, top-level
499                 // `matches` list (actually, `up.matches`, which could itself not be the top-level,
500                 // but anyway...). Moreover, we add another item to `cur_items` in which the "dot"
501                 // is at the end of the `up` matcher. This ensures that the "dot" in the `up`
502                 // matcher is also advanced sufficiently.
503                 //
504                 // NOTE: removing the condition `idx == len` allows trailing separators.
505                 if idx == len {
506                     // Get the `up` matcher
507                     let mut new_pos = item.up.clone().unwrap();
508
509                     // Add matches from this repetition to the `matches` of `up`
510                     for idx in item.match_lo..item.match_hi {
511                         let sub = item.matches[idx].clone();
512                         let span = DelimSpan::from_pair(item.sp_open, span);
513                         new_pos.push_match(idx, MatchedSeq(sub, span));
514                     }
515
516                     // Move the "dot" past the repetition in `up`
517                     new_pos.match_cur = item.match_hi;
518                     new_pos.idx += 1;
519                     cur_items.push(new_pos);
520                 }
521
522                 // Check if we need a separator.
523                 if idx == len && item.sep.is_some() {
524                     // We have a separator, and it is the current token. We can advance past the
525                     // separator token.
526                     if item.sep
527                         .as_ref()
528                         .map(|sep| token_name_eq(token, sep))
529                         .unwrap_or(false)
530                     {
531                         item.idx += 1;
532                         next_items.push(item);
533                     }
534                 }
535                 // We don't need a separator. Move the "dot" back to the beginning of the matcher
536                 // and try to match again UNLESS we are only allowed to have _one_ repetition.
537                 else if item.seq_op != Some(quoted::KleeneOp::ZeroOrOne) {
538                     item.match_cur = item.match_lo;
539                     item.idx = 0;
540                     cur_items.push(item);
541                 }
542             }
543             // If we are not in a repetition, then being at the end of a matcher means that we have
544             // reached the potential end of the input.
545             else {
546                 eof_items.push(item);
547             }
548         }
549         // We are in the middle of a matcher.
550         else {
551             // Look at what token in the matcher we are trying to match the current token (`token`)
552             // against. Depending on that, we may generate new items.
553             match item.top_elts.get_tt(idx) {
554                 // Need to descend into a sequence
555                 TokenTree::Sequence(sp, seq) => {
556                     // Examine the case where there are 0 matches of this sequence
557                     if seq.op == quoted::KleeneOp::ZeroOrMore
558                         || seq.op == quoted::KleeneOp::ZeroOrOne
559                     {
560                         let mut new_item = item.clone();
561                         new_item.match_cur += seq.num_captures;
562                         new_item.idx += 1;
563                         for idx in item.match_cur..item.match_cur + seq.num_captures {
564                             new_item.push_match(idx, MatchedSeq(Rc::new(smallvec![]), sp));
565                         }
566                         cur_items.push(new_item);
567                     }
568
569                     let matches = create_matches(item.matches.len());
570                     cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos {
571                         stack: smallvec![],
572                         sep: seq.separator.clone(),
573                         seq_op: Some(seq.op),
574                         idx: 0,
575                         matches,
576                         match_lo: item.match_cur,
577                         match_cur: item.match_cur,
578                         match_hi: item.match_cur + seq.num_captures,
579                         up: Some(item),
580                         sp_open: sp.open,
581                         top_elts: Tt(TokenTree::Sequence(sp, seq)),
582                     })));
583                 }
584
585                 // We need to match a metavar (but the identifier is invalid)... this is an error
586                 TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => {
587                     if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
588                         return Error(span, "missing fragment specifier".to_string());
589                     }
590                 }
591
592                 // We need to match a metavar with a valid ident... call out to the black-box
593                 // parser by adding an item to `bb_items`.
594                 TokenTree::MetaVarDecl(_, _, id) => {
595                     // Built-in nonterminals never start with these tokens,
596                     // so we can eliminate them from consideration.
597                     if may_begin_with(&*id.as_str(), token) {
598                         bb_items.push(item);
599                     }
600                 }
601
602                 // We need to descend into a delimited submatcher or a doc comment. To do this, we
603                 // push the current matcher onto a stack and push a new item containing the
604                 // submatcher onto `cur_items`.
605                 //
606                 // At the beginning of the loop, if we reach the end of the delimited submatcher,
607                 // we pop the stack to backtrack out of the descent.
608                 seq @ TokenTree::Delimited(..) | seq @ TokenTree::Token(_, DocComment(..)) => {
609                     let lower_elts = mem::replace(&mut item.top_elts, Tt(seq));
610                     let idx = item.idx;
611                     item.stack.push(MatcherTtFrame {
612                         elts: lower_elts,
613                         idx,
614                     });
615                     item.idx = 0;
616                     cur_items.push(item);
617                 }
618
619                 // We just matched a normal token. We can just advance the parser.
620                 TokenTree::Token(_, ref t) if token_name_eq(t, token) => {
621                     item.idx += 1;
622                     next_items.push(item);
623                 }
624
625                 // There was another token that was not `token`... This means we can't add any
626                 // rules. NOTE that this is not necessarily an error unless _all_ items in
627                 // `cur_items` end up doing this. There may still be some other matchers that do
628                 // end up working out.
629                 TokenTree::Token(..) | TokenTree::MetaVar(..) => {}
630             }
631         }
632     }
633
634     // Yay a successful parse (so far)!
635     Success(())
636 }
637
638 /// Use the given sequence of token trees (`ms`) as a matcher. Match the given token stream `tts`
639 /// against it and return the match.
640 ///
641 /// # Parameters
642 ///
643 /// - `sess`: The session into which errors are emitted
644 /// - `tts`: The tokenstream we are matching against the pattern `ms`
645 /// - `ms`: A sequence of token trees representing a pattern against which we are matching
646 /// - `directory`: Information about the file locations (needed for the black-box parser)
647 /// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box
648 ///   parser)
649 pub fn parse(
650     sess: &ParseSess,
651     tts: TokenStream,
652     ms: &[TokenTree],
653     directory: Option<Directory<'_>>,
654     recurse_into_modules: bool,
655 ) -> NamedParseResult {
656     // Create a parser that can be used for the "black box" parts.
657     let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true);
658
659     // A queue of possible matcher positions. We initialize it with the matcher position in which
660     // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
661     // processes all of these possible matcher positions and produces possible next positions into
662     // `next_items`. After some post-processing, the contents of `next_items` replenish `cur_items`
663     // and we start over again.
664     //
665     // This MatcherPos instance is allocated on the stack. All others -- and
666     // there are frequently *no* others! -- are allocated on the heap.
667     let mut initial = initial_matcher_pos(ms, parser.span);
668     let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
669     let mut next_items = Vec::new();
670
671     loop {
672         // Matcher positions black-box parsed by parser.rs (`parser`)
673         let mut bb_items = SmallVec::new();
674
675         // Matcher positions that would be valid if the macro invocation was over now
676         let mut eof_items = SmallVec::new();
677         assert!(next_items.is_empty());
678
679         // Process `cur_items` until either we have finished the input or we need to get some
680         // parsing from the black-box parser done. The result is that `next_items` will contain a
681         // bunch of possible next matcher positions in `next_items`.
682         match inner_parse_loop(
683             sess,
684             &mut cur_items,
685             &mut next_items,
686             &mut eof_items,
687             &mut bb_items,
688             &parser.token,
689             parser.span,
690         ) {
691             Success(_) => {}
692             Failure(sp, tok, t) => return Failure(sp, tok, t),
693             Error(sp, msg) => return Error(sp, msg),
694         }
695
696         // inner parse loop handled all cur_items, so it's empty
697         assert!(cur_items.is_empty());
698
699         // We need to do some post processing after the `inner_parser_loop`.
700         //
701         // Error messages here could be improved with links to original rules.
702
703         // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
704         // either the parse is ambiguous (which should never happen) or there is a syntax error.
705         if token_name_eq(&parser.token, &token::Eof) {
706             if eof_items.len() == 1 {
707                 let matches = eof_items[0]
708                     .matches
709                     .iter_mut()
710                     .map(|dv| Rc::make_mut(dv).pop().unwrap());
711                 return nameize(sess, ms, matches);
712             } else if eof_items.len() > 1 {
713                 return Error(
714                     parser.span,
715                     "ambiguity: multiple successful parses".to_string(),
716                 );
717             } else {
718                 return Failure(
719                     if parser.span.is_dummy() {
720                         parser.span
721                     } else {
722                         sess.source_map().next_point(parser.span)
723                     },
724                     token::Eof,
725                     "missing tokens in macro arguments",
726                 );
727             }
728         }
729         // Performance hack: eof_items may share matchers via Rc with other things that we want
730         // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an
731         // unnecessary implicit clone later in Rc::make_mut.
732         drop(eof_items);
733
734         // Another possibility is that we need to call out to parse some rust nonterminal
735         // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
736         if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
737             let nts = bb_items
738                 .iter()
739                 .map(|item| match item.top_elts.get_tt(item.idx) {
740                     TokenTree::MetaVarDecl(_, bind, name) => format!("{} ('{}')", name, bind),
741                     _ => panic!(),
742                 })
743                 .collect::<Vec<String>>()
744                 .join(" or ");
745
746             return Error(
747                 parser.span,
748                 format!(
749                     "local ambiguity: multiple parsing options: {}",
750                     match next_items.len() {
751                         0 => format!("built-in NTs {}.", nts),
752                         1 => format!("built-in NTs {} or 1 other option.", nts),
753                         n => format!("built-in NTs {} or {} other options.", nts, n),
754                     }
755                 ),
756             );
757         }
758         // If there are no possible next positions AND we aren't waiting for the black-box parser,
759         // then there is a syntax error.
760         else if bb_items.is_empty() && next_items.is_empty() {
761             return Failure(
762                 parser.span,
763                 parser.token,
764                 "no rules expected this token in macro call",
765             );
766         }
767         // Dump all possible `next_items` into `cur_items` for the next iteration.
768         else if !next_items.is_empty() {
769             // Now process the next token
770             cur_items.extend(next_items.drain(..));
771             parser.bump();
772         }
773         // Finally, we have the case where we need to call the black-box parser to get some
774         // nonterminal.
775         else {
776             assert_eq!(bb_items.len(), 1);
777
778             let mut item = bb_items.pop().unwrap();
779             if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) {
780                 let match_cur = item.match_cur;
781                 item.push_match(
782                     match_cur,
783                     MatchedNonterminal(Rc::new(parse_nt(&mut parser, span, &ident.as_str()))),
784                 );
785                 item.idx += 1;
786                 item.match_cur += 1;
787             } else {
788                 unreachable!()
789             }
790             cur_items.push(item);
791         }
792
793         assert!(!cur_items.is_empty());
794     }
795 }
796
797 /// The token is an identifier, but not `_`.
798 /// We prohibit passing `_` to macros expecting `ident` for now.
799 fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
800     match *token {
801         token::Ident(ident, is_raw) if ident.name != keywords::Underscore.name() =>
802             Some((ident, is_raw)),
803         _ => None,
804     }
805 }
806
807 /// Checks whether a non-terminal may begin with a particular token.
808 ///
809 /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
810 /// token. Be conservative (return true) if not sure.
811 fn may_begin_with(name: &str, token: &Token) -> bool {
812     /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
813     fn may_be_ident(nt: &token::Nonterminal) -> bool {
814         match *nt {
815             token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) => false,
816             _ => true,
817         }
818     }
819
820     match name {
821         "expr" => token.can_begin_expr(),
822         "ty" => token.can_begin_type(),
823         "ident" => get_macro_ident(token).is_some(),
824         "literal" => token.can_begin_literal_or_bool(),
825         "vis" => match *token {
826             // The follow-set of :vis + "priv" keyword + interpolated
827             Token::Comma | Token::Ident(..) | Token::Interpolated(_) => true,
828             _ => token.can_begin_type(),
829         },
830         "block" => match *token {
831             Token::OpenDelim(token::Brace) => true,
832             Token::Interpolated(ref nt) => match nt.0 {
833                 token::NtItem(_)
834                 | token::NtPat(_)
835                 | token::NtTy(_)
836                 | token::NtIdent(..)
837                 | token::NtMeta(_)
838                 | token::NtPath(_)
839                 | token::NtVis(_) => false, // none of these may start with '{'.
840                 _ => true,
841             },
842             _ => false,
843         },
844         "path" | "meta" => match *token {
845             Token::ModSep | Token::Ident(..) => true,
846             Token::Interpolated(ref nt) => match nt.0 {
847                 token::NtPath(_) | token::NtMeta(_) => true,
848                 _ => may_be_ident(&nt.0),
849             },
850             _ => false,
851         },
852         "pat" => match *token {
853             Token::Ident(..) |               // box, ref, mut, and other identifiers (can stricten)
854             Token::OpenDelim(token::Paren) |    // tuple pattern
855             Token::OpenDelim(token::Bracket) |  // slice pattern
856             Token::BinOp(token::And) |          // reference
857             Token::BinOp(token::Minus) |        // negative literal
858             Token::AndAnd |                     // double reference
859             Token::Literal(..) |                // literal
860             Token::DotDot |                     // range pattern (future compat)
861             Token::DotDotDot |                  // range pattern (future compat)
862             Token::ModSep |                     // path
863             Token::Lt |                         // path (UFCS constant)
864             Token::BinOp(token::Shl) => true,   // path (double UFCS)
865             Token::Interpolated(ref nt) => may_be_ident(&nt.0),
866             _ => false,
867         },
868         "lifetime" => match *token {
869             Token::Lifetime(_) => true,
870             Token::Interpolated(ref nt) => match nt.0 {
871                 token::NtLifetime(_) | token::NtTT(_) => true,
872                 _ => false,
873             },
874             _ => false,
875         },
876         _ => match *token {
877             token::CloseDelim(_) => false,
878             _ => true,
879         },
880     }
881 }
882
883 /// A call to the "black-box" parser to parse some rust nonterminal.
884 ///
885 /// # Parameters
886 ///
887 /// - `p`: the "black-box" parser to use
888 /// - `sp`: the `Span` we want to parse
889 /// - `name`: the name of the metavar _matcher_ we want to match (e.g., `tt`, `ident`, `block`,
890 ///   etc...)
891 ///
892 /// # Returns
893 ///
894 /// The parsed nonterminal.
895 fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
896     if name == "tt" {
897         return token::NtTT(p.parse_token_tree());
898     }
899     // check at the beginning and the parser checks after each bump
900     p.process_potential_macro_variable();
901     match name {
902         "item" => match panictry!(p.parse_item()) {
903             Some(i) => token::NtItem(i),
904             None => {
905                 p.fatal("expected an item keyword").emit();
906                 FatalError.raise();
907             }
908         },
909         "block" => token::NtBlock(panictry!(p.parse_block())),
910         "stmt" => match panictry!(p.parse_stmt()) {
911             Some(s) => token::NtStmt(s),
912             None => {
913                 p.fatal("expected a statement").emit();
914                 FatalError.raise();
915             }
916         },
917         "pat" => token::NtPat(panictry!(p.parse_pat(None))),
918         "expr" => token::NtExpr(panictry!(p.parse_expr())),
919         "literal" => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())),
920         "ty" => token::NtTy(panictry!(p.parse_ty())),
921         // this could be handled like a token, since it is one
922         "ident" => if let Some((ident, is_raw)) = get_macro_ident(&p.token) {
923             let span = p.span;
924             p.bump();
925             token::NtIdent(Ident::new(ident.name, span), is_raw)
926         } else {
927             let token_str = pprust::token_to_string(&p.token);
928             p.fatal(&format!("expected ident, found {}", &token_str)).emit();
929             FatalError.raise()
930         }
931         "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
932         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
933         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
934         "lifetime" => if p.check_lifetime() {
935             token::NtLifetime(p.expect_lifetime().ident)
936         } else {
937             let token_str = pprust::token_to_string(&p.token);
938             p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit();
939             FatalError.raise();
940         }
941         // this is not supposed to happen, since it has been checked
942         // when compiling the macro.
943         _ => p.span_bug(sp, "invalid fragment specifier"),
944     }
945 }