Skip to main content

rustc_expand/mbe/
macro_parser.rs

1//! This is an NFA-based parser, which calls out to the main Rust parser for named non-terminals
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//! matcher positions, 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 "matcher position" (a.k.a. "position" or "mp") is a dot in the middle of a matcher, usually
18//! written as a `·`. For example `· a $( a )* a b` is one, as is `a $( · a )* a b`.
19//!
20//! The parser walks through the input a token at a time, maintaining a list
21//! of threads consistent with the current position in the input string: `cur_mps`.
22//!
23//! As it processes them, it fills up `eof_mps` with threads that would be valid if
24//! the macro invocation is now over, `bb_mps` with threads that are waiting on
25//! a Rust non-terminal like `$e:expr`, and `next_mps` 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_mps` 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 position).
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 position)
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 position)
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 position)
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
73use std::borrow::Cow;
74use std::fmt::Display;
75use std::ops::ControlFlow;
76use std::rc::Rc;
77
78pub(crate) use NamedMatch::*;
79pub(crate) use ParseResult::*;
80use rustc_ast::token::{self, DocComment, NonterminalKind, Token, TokenKind};
81use rustc_data_structures::fx::FxHashMap;
82use rustc_errors::{Diag, ErrorGuaranteed};
83use rustc_parse::parser::{ParseNtResult, Parser, token_descr};
84use rustc_span::{Ident, MacroRulesNormalizedIdent, Span};
85
86use crate::mbe::macro_rules::Tracker;
87use crate::mbe::{KleeneOp, TokenTree};
88
89/// A unit within a matcher that a `MatcherPos` can refer to. Similar to (and derived from)
90/// `mbe::TokenTree`, but designed specifically for fast and easy traversal during matching.
91/// Notable differences to `mbe::TokenTree`:
92/// - It is non-recursive, i.e. there is no nesting.
93/// - The end pieces of each sequence (the separator, if present, and the Kleene op) are
94///   represented explicitly, as is the very end of the matcher.
95///
96/// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves
97/// simply incrementing the current matcher position index by one.
98#[derive(#[automatically_derived]
impl ::core::fmt::Debug for MatcherLoc {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Token { token: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Token",
                    "token", &__self_0),
            Self::Delimited =>
                ::core::fmt::Formatter::write_str(f, "Delimited"),
            Self::Sequence {
                op: __self_0,
                num_metavar_decls: __self_1,
                idx_first_after: __self_2,
                next_metavar: __self_3,
                seq_depth: __self_4 } =>
                ::core::fmt::Formatter::debug_struct_field5_finish(f,
                    "Sequence", "op", __self_0, "num_metavar_decls", __self_1,
                    "idx_first_after", __self_2, "next_metavar", __self_3,
                    "seq_depth", &__self_4),
            Self::SequenceKleeneOpNoSep { op: __self_0, idx_first: __self_1 }
                =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "SequenceKleeneOpNoSep", "op", __self_0, "idx_first",
                    &__self_1),
            Self::SequenceSep { separator: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "SequenceSep", "separator", &__self_0),
            Self::SequenceKleeneOpAfterSep { idx_first: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "SequenceKleeneOpAfterSep", "idx_first", &__self_0),
            Self::MetaVarDecl {
                span: __self_0,
                bind: __self_1,
                kind: __self_2,
                next_metavar: __self_3,
                seq_depth: __self_4 } =>
                ::core::fmt::Formatter::debug_struct_field5_finish(f,
                    "MetaVarDecl", "span", __self_0, "bind", __self_1, "kind",
                    __self_2, "next_metavar", __self_3, "seq_depth", &__self_4),
            Self::Eof => ::core::fmt::Formatter::write_str(f, "Eof"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for MatcherLoc { }
#[automatically_derived]
impl ::core::cmp::PartialEq for MatcherLoc {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Token { token: __self_0 }, Self::Token {
                    token: __arg1_0 }) => __self_0 == __arg1_0,
                (Self::Sequence {
                    op: __self_0,
                    num_metavar_decls: __self_1,
                    idx_first_after: __self_2,
                    next_metavar: __self_3,
                    seq_depth: __self_4 }, Self::Sequence {
                    op: __arg1_0,
                    num_metavar_decls: __arg1_1,
                    idx_first_after: __arg1_2,
                    next_metavar: __arg1_3,
                    seq_depth: __arg1_4 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                                __self_2 == __arg1_2 && __self_3 == __arg1_3 &&
                        __self_4 == __arg1_4,
                (Self::SequenceKleeneOpNoSep {
                    op: __self_0, idx_first: __self_1 },
                    Self::SequenceKleeneOpNoSep {
                    op: __arg1_0, idx_first: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (Self::SequenceSep { separator: __self_0 },
                    Self::SequenceSep { separator: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                (Self::SequenceKleeneOpAfterSep { idx_first: __self_0 },
                    Self::SequenceKleeneOpAfterSep { idx_first: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                (Self::MetaVarDecl {
                    span: __self_0,
                    bind: __self_1,
                    kind: __self_2,
                    next_metavar: __self_3,
                    seq_depth: __self_4 }, Self::MetaVarDecl {
                    span: __arg1_0,
                    bind: __arg1_1,
                    kind: __arg1_2,
                    next_metavar: __arg1_3,
                    seq_depth: __arg1_4 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                                __self_2 == __arg1_2 && __self_3 == __arg1_3 &&
                        __self_4 == __arg1_4,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::clone::Clone for MatcherLoc {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Token { token: __self_0 } =>
                Self::Token { token: ::core::clone::Clone::clone(__self_0) },
            Self::Delimited => Self::Delimited,
            Self::Sequence {
                op: __self_0,
                num_metavar_decls: __self_1,
                idx_first_after: __self_2,
                next_metavar: __self_3,
                seq_depth: __self_4 } =>
                Self::Sequence {
                    op: ::core::clone::Clone::clone(__self_0),
                    num_metavar_decls: ::core::clone::Clone::clone(__self_1),
                    idx_first_after: ::core::clone::Clone::clone(__self_2),
                    next_metavar: ::core::clone::Clone::clone(__self_3),
                    seq_depth: ::core::clone::Clone::clone(__self_4),
                },
            Self::SequenceKleeneOpNoSep { op: __self_0, idx_first: __self_1 }
                =>
                Self::SequenceKleeneOpNoSep {
                    op: ::core::clone::Clone::clone(__self_0),
                    idx_first: ::core::clone::Clone::clone(__self_1),
                },
            Self::SequenceSep { separator: __self_0 } =>
                Self::SequenceSep {
                    separator: ::core::clone::Clone::clone(__self_0),
                },
            Self::SequenceKleeneOpAfterSep { idx_first: __self_0 } =>
                Self::SequenceKleeneOpAfterSep {
                    idx_first: ::core::clone::Clone::clone(__self_0),
                },
            Self::MetaVarDecl {
                span: __self_0,
                bind: __self_1,
                kind: __self_2,
                next_metavar: __self_3,
                seq_depth: __self_4 } =>
                Self::MetaVarDecl {
                    span: ::core::clone::Clone::clone(__self_0),
                    bind: ::core::clone::Clone::clone(__self_1),
                    kind: ::core::clone::Clone::clone(__self_2),
                    next_metavar: ::core::clone::Clone::clone(__self_3),
                    seq_depth: ::core::clone::Clone::clone(__self_4),
                },
            Self::Eof => Self::Eof,
        }
    }
}Clone)]
99pub(crate) enum MatcherLoc {
100    Token {
101        token: Token,
102    },
103    Delimited,
104    Sequence {
105        op: KleeneOp,
106        num_metavar_decls: usize,
107        idx_first_after: usize,
108        next_metavar: usize,
109        seq_depth: usize,
110    },
111    SequenceKleeneOpNoSep {
112        op: KleeneOp,
113        idx_first: usize,
114    },
115    SequenceSep {
116        separator: Token,
117    },
118    SequenceKleeneOpAfterSep {
119        idx_first: usize,
120    },
121    MetaVarDecl {
122        span: Span,
123        bind: Ident,
124        kind: NonterminalKind,
125        next_metavar: usize,
126        seq_depth: usize,
127    },
128    Eof,
129}
130
131impl MatcherLoc {
132    pub(super) fn span(&self) -> Option<Span> {
133        match self {
134            MatcherLoc::Token { token } => Some(token.span),
135            MatcherLoc::Delimited => None,
136            MatcherLoc::Sequence { .. } => None,
137            MatcherLoc::SequenceKleeneOpNoSep { .. } => None,
138            MatcherLoc::SequenceSep { .. } => None,
139            MatcherLoc::SequenceKleeneOpAfterSep { .. } => None,
140            MatcherLoc::MetaVarDecl { span, .. } => Some(*span),
141            MatcherLoc::Eof => None,
142        }
143    }
144}
145
146impl Display for MatcherLoc {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        match self {
149            MatcherLoc::Token { token } | MatcherLoc::SequenceSep { separator: token } => {
150                f.write_fmt(format_args!("{0}", token_descr(token)))write!(f, "{}", token_descr(token))
151            }
152            MatcherLoc::MetaVarDecl { bind, kind, .. } => {
153                f.write_fmt(format_args!("meta-variable `${0}:{1}`", bind, kind))write!(f, "meta-variable `${bind}:{kind}`")
154            }
155            MatcherLoc::Eof => f.write_str("end of macro"),
156
157            // These are not printed in the diagnostic
158            MatcherLoc::Delimited => f.write_str("delimiter"),
159            MatcherLoc::Sequence { .. } => f.write_str("sequence start"),
160            MatcherLoc::SequenceKleeneOpNoSep { .. } => f.write_str("sequence end"),
161            MatcherLoc::SequenceKleeneOpAfterSep { .. } => f.write_str("sequence end"),
162        }
163    }
164}
165
166pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
167    fn inner(
168        tts: &[TokenTree],
169        locs: &mut Vec<MatcherLoc>,
170        next_metavar: &mut usize,
171        seq_depth: usize,
172    ) {
173        for tt in tts {
174            match tt {
175                TokenTree::Token(token) => {
176                    locs.push(MatcherLoc::Token { token: *token });
177                }
178                TokenTree::Delimited(span, _, delimited) => {
179                    let open_token = Token::new(delimited.delim.as_open_token_kind(), span.open);
180                    let close_token = Token::new(delimited.delim.as_close_token_kind(), span.close);
181
182                    locs.push(MatcherLoc::Delimited);
183                    locs.push(MatcherLoc::Token { token: open_token });
184                    inner(&delimited.tts, locs, next_metavar, seq_depth);
185                    locs.push(MatcherLoc::Token { token: close_token });
186                }
187                TokenTree::Sequence(_, seq) => {
188                    // We can't determine `idx_first_after` and construct the final
189                    // `MatcherLoc::Sequence` until after `inner()` is called and the sequence end
190                    // pieces are processed. So we push a dummy value (`Eof` is cheapest to
191                    // construct) now, and overwrite it with the proper value below.
192                    let dummy = MatcherLoc::Eof;
193                    locs.push(dummy);
194
195                    let next_metavar_orig = *next_metavar;
196                    let op = seq.kleene.op;
197                    let idx_first = locs.len();
198                    let idx_seq = idx_first - 1;
199                    inner(&seq.tts, locs, next_metavar, seq_depth + 1);
200
201                    if let Some(separator) = seq.separator {
202                        locs.push(MatcherLoc::SequenceSep { separator });
203                        locs.push(MatcherLoc::SequenceKleeneOpAfterSep { idx_first });
204                    } else {
205                        locs.push(MatcherLoc::SequenceKleeneOpNoSep { op, idx_first });
206                    }
207
208                    // Overwrite the dummy value pushed above with the proper value.
209                    locs[idx_seq] = MatcherLoc::Sequence {
210                        op,
211                        num_metavar_decls: seq.num_captures,
212                        idx_first_after: locs.len(),
213                        next_metavar: next_metavar_orig,
214                        seq_depth,
215                    };
216                }
217                &TokenTree::MetaVarDecl { span, name: bind, kind } => {
218                    locs.push(MatcherLoc::MetaVarDecl {
219                        span,
220                        bind,
221                        kind,
222                        next_metavar: *next_metavar,
223                        seq_depth,
224                    });
225                    *next_metavar += 1;
226                }
227                TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
228            }
229        }
230    }
231
232    let mut locs = ::alloc::vec::Vec::new()vec![];
233    let mut next_metavar = 0;
234    inner(matcher, &mut locs, &mut next_metavar, /* seq_depth */ 0);
235
236    // A final entry is needed for eof.
237    locs.push(MatcherLoc::Eof);
238
239    locs
240}
241
242/// A single matcher position, representing the state of matching.
243#[derive(#[automatically_derived]
impl ::core::fmt::Debug for MatcherPos {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "MatcherPos",
            "idx", &self.idx, "matches", &&self.matches)
    }
}Debug)]
244struct MatcherPos {
245    /// The index into `TtParser::locs`, which represents the "dot".
246    idx: usize,
247
248    /// The matches made against metavar decls so far. On a successful match, this vector ends up
249    /// with one element per metavar decl in the matcher. Each element records token trees matched
250    /// against the relevant metavar by the black box parser. An element will be a `MatchedSeq` if
251    /// the corresponding metavar decl is within a sequence.
252    ///
253    /// It is critical to performance that this is an `Rc`, because it gets cloned frequently when
254    /// processing sequences. Mostly for sequence-ending possibilities that must be tried but end
255    /// up failing.
256    matches: Rc<Vec<NamedMatch>>,
257}
258
259// This type is used a lot. Make sure it doesn't unintentionally get bigger.
260#[cfg(target_pointer_width = "64")]
261const _: [(); 16] = [(); ::std::mem::size_of::<MatcherPos>()];rustc_data_structures::static_assert_size!(MatcherPos, 16);
262
263impl MatcherPos {
264    /// Adds `m` as a named match for the `metavar_idx`-th metavar. There are only two call sites,
265    /// and both are hot enough to be always worth inlining.
266    #[inline(always)]
267    fn push_match(&mut self, metavar_idx: usize, seq_depth: usize, m: NamedMatch) {
268        let matches = Rc::make_mut(&mut self.matches);
269        match seq_depth {
270            0 => {
271                // We are not within a sequence. Just append `m`.
272                {
    match (&metavar_idx, &matches.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(metavar_idx, matches.len());
273                matches.push(m);
274            }
275            _ => {
276                // We are within a sequence. Find the final `MatchedSeq` at the appropriate depth
277                // and append `m` to its vector.
278                let mut curr = &mut matches[metavar_idx];
279                for _ in 0..seq_depth - 1 {
280                    match curr {
281                        MatchedSeq(seq) => curr = seq.last_mut().unwrap(),
282                        _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
283                    }
284                }
285                match curr {
286                    MatchedSeq(seq) => seq.push(m),
287                    _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
288                }
289            }
290        }
291    }
292}
293
294/// Represents the possible results of an attempted parse.
295#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ParseResult<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Success(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Success", &__self_0),
            Self::Failure => ::core::fmt::Formatter::write_str(f, "Failure"),
            Self::Ambiguity =>
                ::core::fmt::Formatter::write_str(f, "Ambiguity"),
            Self::ErrorReported(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ErrorReported", &__self_0),
        }
    }
}Debug)]
296pub(crate) enum ParseResult<T> {
297    /// Parsed successfully.
298    Success(T),
299    /// Arm failed to match.
300    ///
301    /// [`Tracker::failure()`] will be called beforehand.
302    Failure,
303    /// The input could be parsed in multiple distinct ways.
304    ///
305    /// [`Tracker::ambiguity()`] will be called beforehand.
306    Ambiguity,
307    ErrorReported(ErrorGuaranteed),
308}
309
310/// A `ParseResult` where the `Success` variant contains a mapping of
311/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
312/// of metavars to the token trees they bind to.
313pub(crate) type NamedParseResult = ParseResult<NamedMatches>;
314
315/// Contains a mapping of `MacroRulesNormalizedIdent`s to `NamedMatch`es.
316/// This represents the mapping of metavars to the token trees they bind to.
317pub(crate) type NamedMatches = FxHashMap<MacroRulesNormalizedIdent, NamedMatch>;
318
319/// Count how many metavars declarations are in `matcher`.
320pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
321    matcher
322        .iter()
323        .map(|tt| match tt {
324            TokenTree::MetaVarDecl { .. } => 1,
325            TokenTree::Sequence(_, seq) => seq.num_captures,
326            TokenTree::Delimited(.., delim) => count_metavar_decls(&delim.tts),
327            TokenTree::Token(..) => 0,
328            TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
329        })
330        .sum()
331}
332
333/// `NamedMatch` is a pattern-match result for a single metavar. All
334/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
335/// (expr, item, etc).
336///
337/// The in-memory structure of a particular `NamedMatch` represents the match
338/// that occurred when a particular subset of a matcher was applied to a
339/// particular token tree.
340///
341/// The width of each `MatchedSeq` in the `NamedMatch`, and the identity of
342/// the `MatchedNtNonTts`s, will depend on the token tree it was applied
343/// to: each `MatchedSeq` corresponds to a single repetition in the originating
344/// token tree. The depth of the `NamedMatch` structure will therefore depend
345/// only on the nesting depth of repetitions in the originating token tree it
346/// was derived from.
347///
348/// In layperson's terms: `NamedMatch` will form a tree representing nested matches of a particular
349/// meta variable. For example, if we are matching the following macro against the following
350/// invocation...
351///
352/// ```rust
353/// macro_rules! foo {
354///   ($($($x:ident),+);+) => {}
355/// }
356///
357/// foo!(a, b, c, d; a, b, c, d, e);
358/// ```
359///
360/// Then, the tree will have the following shape:
361///
362/// ```ignore (private-internal)
363/// # use NamedMatch::*;
364/// MatchedSeq([
365///   MatchedSeq([
366///     MatchedNonterminal(a),
367///     MatchedNonterminal(b),
368///     MatchedNonterminal(c),
369///     MatchedNonterminal(d),
370///   ]),
371///   MatchedSeq([
372///     MatchedNonterminal(a),
373///     MatchedNonterminal(b),
374///     MatchedNonterminal(c),
375///     MatchedNonterminal(d),
376///     MatchedNonterminal(e),
377///   ])
378/// ])
379/// ```
380#[derive(#[automatically_derived]
impl ::core::fmt::Debug for NamedMatch {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::MatchedSeq(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MatchedSeq", &__self_0),
            Self::MatchedSingle(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MatchedSingle", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for NamedMatch {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::MatchedSeq(__self_0) =>
                Self::MatchedSeq(::core::clone::Clone::clone(__self_0)),
            Self::MatchedSingle(__self_0) =>
                Self::MatchedSingle(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)]
381pub(crate) enum NamedMatch {
382    MatchedSeq(Vec<NamedMatch>),
383    MatchedSingle(ParseNtResult),
384}
385
386impl NamedMatch {
387    pub(super) fn is_repeatable(&self) -> bool {
388        match self {
389            NamedMatch::MatchedSeq(_) => true,
390            NamedMatch::MatchedSingle(_) => false,
391        }
392    }
393}
394
395/// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
396fn token_name_eq(t1: &Token, t2: &Token) -> bool {
397    if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) {
398        ident1.name == ident2.name && is_raw1 == is_raw2
399    } else if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) =
400        (t1.lifetime(), t2.lifetime())
401    {
402        ident1.name == ident2.name && is_raw1 == is_raw2
403    } else {
404        // Note: we SHOULD NOT use `t1.kind == t2.kind` here, and we should instead compare the
405        // tokens using the special comparison logic below.
406        // It makes sure that variants containing `InvisibleOrigin` will
407        // never compare equal to one another.
408        //
409        // When we had AST-based nonterminals we couldn't compare them, and the
410        // old `Nonterminal` type had an `eq` that always returned false,
411        // resulting in this restriction:
412        // <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment>
413        // This comparison logic emulates that behaviour. We could consider lifting this
414        // restriction now but there are still cases involving invisible
415        // delimiters that make it harder than it first appears.
416        match (t1.kind, t2.kind) {
417            (TokenKind::OpenInvisible(_) | TokenKind::CloseInvisible(_), _)
418            | (_, TokenKind::OpenInvisible(_) | TokenKind::CloseInvisible(_)) => false,
419            (a, b) => a == b,
420        }
421    }
422}
423
424// Note: the vectors could be created and dropped within `parse_tt`, but to avoid excess
425// allocations we have a single vector for each kind that is cleared and reused repeatedly.
426pub(crate) struct TtParser {
427    /// The set of current mps to be processed. This should be empty by the end of a successful
428    /// execution of `parse_tt_inner`.
429    cur_mps: Vec<MatcherPos>,
430
431    /// The set of newly generated mps. These are used to replenish `cur_mps` in the function
432    /// `parse_tt`.
433    next_mps: Vec<MatcherPos>,
434
435    /// Pre-allocate an empty match array, so it can be cloned cheaply for macros with many rules
436    /// that have no metavars.
437    empty_matches: Rc<Vec<NamedMatch>>,
438
439    /// Whether an ambiguity error has occurred.
440    found_ambiguity: bool,
441}
442
443impl TtParser {
444    pub(super) fn new() -> TtParser {
445        TtParser {
446            cur_mps: ::alloc::vec::Vec::new()vec![],
447            next_mps: ::alloc::vec::Vec::new()vec![],
448            empty_matches: Rc::new(::alloc::vec::Vec::new()vec![]),
449            found_ambiguity: false,
450        }
451    }
452
453    pub(super) fn has_no_remaining_items_for_step(&self) -> bool {
454        self.cur_mps.is_empty()
455    }
456
457    /// Process the matcher positions of `cur_mps` until it is empty. In the process, this will
458    /// produce more mps in `next_mps` and `bb_mps`.
459    ///
460    /// # Returns
461    ///
462    /// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept
463    /// track of through the mps generated.
464    fn parse_tt_inner<'matcher, T: Tracker<'matcher>>(
465        &mut self,
466        parser: &mut Cow<'_, Parser<'_>>,
467        matcher: &'matcher [MatcherLoc],
468        track: &mut T,
469    ) -> Option<NamedParseResult> {
470        while let Some(mp) = self.cur_mps.pop() {
471            if let Some(result) = self.match_one(parser, matcher, mp, track, false) {
472                return Some(result);
473            }
474        }
475
476        // FIXME: Error messages here could be improved with links to original rules.
477
478        if self.next_mps.is_empty() {
479            // There are no possible next positions: syntax error.
480            track.failure(parser);
481            return Some(Failure);
482        }
483
484        // Dump all possible `next_mps` into `cur_mps` for the next iteration. Then
485        // process the next token.
486        self.cur_mps.append(&mut self.next_mps);
487        parser.to_mut().bump();
488
489        None
490    }
491
492    /// Match a single [`MatcherPos`].
493    ///
494    /// If a meta-variable is encountered and `checking_for_ambiguity` is `false`, `cur_mps` will be
495    /// drained to eagerly check for ambiguity, and `parser` will be modified.
496    #[inline(always)] // must be inlined in `parse_tt_inner()`
497    fn match_one<'matcher, T: Tracker<'matcher>>(
498        &mut self,
499        parser: &mut Cow<'_, Parser<'_>>,
500        matcher: &'matcher [MatcherLoc],
501        mut mp: MatcherPos,
502        track: &mut T,
503        checking_for_ambiguity: bool,
504    ) -> Option<NamedParseResult> {
505        let matcher_loc = &matcher[mp.idx];
506        track.before_match_loc(self, matcher_loc);
507        let token = &parser.token;
508
509        match matcher_loc {
510            MatcherLoc::Token { token: t } => {
511                // If it's a doc comment, we just ignore it and move on to the next tt in the
512                // matcher. This is a bug, but #95267 showed that existing programs rely on this
513                // behaviour, and changing it would require some care and a transition period.
514                //
515                // If the token matches, we can just advance the parser.
516                //
517                // Otherwise, this match has failed, there is nothing to do, and hopefully another
518                // mp in `cur_mps` will match.
519                if #[allow(non_exhaustive_omitted_patterns)] match t {
    Token { kind: DocComment(..), .. } => true,
    _ => false,
}matches!(t, Token { kind: DocComment(..), .. }) {
520                    mp.idx += 1;
521                    self.cur_mps.push(mp);
522                } else if token_name_eq(t, token) {
523                    track.matched_one(parser, mp.idx);
524                    mp.idx += 1;
525                    self.next_mps.push(mp);
526                }
527            }
528            MatcherLoc::Delimited => {
529                // Entering the delimiter is trivial.
530                mp.idx += 1;
531                self.cur_mps.push(mp);
532            }
533            &MatcherLoc::Sequence {
534                op,
535                num_metavar_decls,
536                idx_first_after,
537                next_metavar,
538                seq_depth,
539            } => {
540                // Install an empty vec for each metavar within the sequence.
541                for metavar_idx in next_metavar..next_metavar + num_metavar_decls {
542                    mp.push_match(metavar_idx, seq_depth, MatchedSeq(::alloc::vec::Vec::new()vec![]));
543                }
544
545                if #[allow(non_exhaustive_omitted_patterns)] match op {
    KleeneOp::ZeroOrMore | KleeneOp::ZeroOrOne => true,
    _ => false,
}matches!(op, KleeneOp::ZeroOrMore | KleeneOp::ZeroOrOne) {
546                    // Try zero matches of this sequence, by skipping over it.
547                    self.cur_mps
548                        .push(MatcherPos { idx: idx_first_after, matches: Rc::clone(&mp.matches) });
549                }
550
551                // Try one or more matches of this sequence, by entering it.
552                mp.idx += 1;
553                self.cur_mps.push(mp);
554            }
555            &MatcherLoc::SequenceKleeneOpNoSep { op, idx_first } => {
556                // We are past the end of a sequence with no separator. Try ending the sequence. If
557                // that's not possible, `ending_mp` will fail quietly when it is processed next time
558                // around the loop.
559                let ending_mp = MatcherPos {
560                    idx: mp.idx + 1, // +1 skips the Kleene op
561                    matches: Rc::clone(&mp.matches),
562                };
563                self.cur_mps.push(ending_mp);
564
565                if op != KleeneOp::ZeroOrOne {
566                    // Try another repetition.
567                    mp.idx = idx_first;
568                    self.cur_mps.push(mp);
569                }
570            }
571            MatcherLoc::SequenceSep { separator } => {
572                // We are past the end of a sequence with a separator but we haven't seen the
573                // separator yet. Try ending the sequence. If that's not possible, `ending_mp` will
574                // fail quietly when it is processed next time around the loop.
575                let ending_mp = MatcherPos {
576                    idx: mp.idx + 2, // +2 skips the separator and the Kleene op
577                    matches: Rc::clone(&mp.matches),
578                };
579                self.cur_mps.push(ending_mp);
580
581                if token_name_eq(token, separator) {
582                    // The separator matches the current token. Advance past it.
583                    track.matched_one(parser, mp.idx);
584                    mp.idx += 1;
585                    self.next_mps.push(mp);
586                }
587            }
588            &MatcherLoc::SequenceKleeneOpAfterSep { idx_first } => {
589                // We are past the sequence separator. This can't be a `?` Kleene op, because they
590                // don't permit separators. Try another repetition.
591                mp.idx = idx_first;
592                self.cur_mps.push(mp);
593            }
594            &MatcherLoc::MetaVarDecl { kind, next_metavar, seq_depth, .. } => {
595                // Built-in nonterminals never start with these tokens, so we can eliminate them
596                // from consideration. We use the span of the metavariable declaration to determine
597                // any edition-specific matching behavior for non-terminals.
598                if !Parser::nonterminal_may_begin_with(kind, token) {
599                    return None;
600                }
601
602                // EOF tokens would cause unexpected processing in `match_one()`.
603                if true {
    if !(parser.token != token::Eof) {
        {
            ::core::panicking::panic_fmt(format_args!("{0:?} should not accept EOF tokens",
                    kind));
        }
    };
};debug_assert!(parser.token != token::Eof, "{kind:?} should not accept EOF tokens");
604
605                track.matched_one(parser, mp.idx);
606
607                if let ControlFlow::Break(result) =
608                    self.check_for_ambiguity(parser, matcher, track, checking_for_ambiguity)
609                {
610                    return result;
611                }
612
613                // We use the span of the metavariable declaration to determine any
614                // edition-specific matching behavior for non-terminals.
615                let nt = match parser.to_mut().parse_nonterminal(kind) {
616                    Err(err) => return Some(self.nt_parsing_error(matcher_loc, err)),
617                    Ok(nt) => nt,
618                };
619                mp.push_match(next_metavar, seq_depth, MatchedSingle(nt));
620
621                mp.idx += 1;
622                self.cur_mps.push(mp);
623            }
624            MatcherLoc::Eof => {
625                // We are past the matcher's end, and not in a sequence. Try to end things.
626                if true {
    {
        match (&mp.idx, &(matcher.len() - 1)) {
            (left_val, right_val) => {
                if !(*left_val == *right_val) {
                    let kind = ::core::panicking::AssertKind::Eq;
                    ::core::panicking::assert_failed(kind, &*left_val,
                        &*right_val, ::core::option::Option::None);
                }
            }
        }
    };
};debug_assert_eq!(mp.idx, matcher.len() - 1);
627
628                if *token != token::Eof {
629                    return None;
630                }
631
632                track.matched_one(parser, mp.idx);
633
634                if let ControlFlow::Break(result) =
635                    self.check_for_ambiguity(parser, matcher, track, checking_for_ambiguity)
636                {
637                    return result;
638                }
639
640                let matches = Rc::unwrap_or_clone(mp.matches).into_iter();
641                return Some(Success(self.nameize(matcher, matches)));
642            }
643        }
644
645        None
646    }
647
648    /// Look for ambiguity before parsing a non-terminal.
649    ///
650    /// - When `checking_for_ambiguity`: immediately an ambiguity error.
651    /// - Otherwise: eagerly consumes [`Self::cur_mps`] to check for ambiguity.
652    ///
653    /// If [`ControlFlow::Continue`] is returned, ambiguity has not been detected.
654    fn check_for_ambiguity<'matcher, R, T: Tracker<'matcher>>(
655        &mut self,
656        parser: &mut Cow<'_, Parser<'_>>,
657        matcher: &'matcher [MatcherLoc],
658        track: &mut T,
659        checking_for_ambiguity: bool,
660    ) -> ControlFlow<Option<ParseResult<R>>> {
661        if checking_for_ambiguity {
662            // This was called in the context of a _different_ `MatcherLoc` that was about to be
663            // matched. Prevent the caller from doing more work, but don't prepare the actual error
664            // yet; let the outer `check_for_ambiguity()` do that.
665            self.found_ambiguity = true;
666            return ControlFlow::Break(None);
667        }
668
669        if !!self.found_ambiguity {
    ::core::panicking::panic("assertion failed: !self.found_ambiguity")
};assert!(!self.found_ambiguity);
670
671        // Consume all pending mps at the current input position.
672        while let Some(mp) = self.cur_mps.pop() {
673            let result = self.match_one(parser, matcher, mp, track, true);
674            // A result cannot be returned when `check_for_ambiguity` is `true`.
675            if !result.is_none() {
    ::core::panicking::panic("assertion failed: result.is_none()")
};assert!(result.is_none());
676        }
677
678        if std::mem::take(&mut self.found_ambiguity) || !self.next_mps.is_empty() {
679            track.ambiguity(parser);
680            ControlFlow::Break(Some(Ambiguity))
681        } else {
682            ControlFlow::Continue(())
683        }
684    }
685
686    /// Match the token stream from `parser` against `matcher`.
687    pub(super) fn parse_tt<'matcher, T: Tracker<'matcher>>(
688        &mut self,
689        parser: &mut Cow<'_, Parser<'_>>,
690        matcher: &'matcher [MatcherLoc],
691        track: &mut T,
692    ) -> NamedParseResult {
693        // A queue of possible matcher positions. We initialize it with the matcher position in
694        // which the "dot" is before the first token of the first token tree in `matcher`.
695        // `parse_tt_inner` then processes all of these possible matcher positions and produces
696        // possible next positions into `next_mps`. After some post-processing, the contents of
697        // `next_mps` replenish `cur_mps` and we start over again.
698        self.cur_mps.clear();
699        self.cur_mps.push(MatcherPos { idx: 0, matches: Rc::clone(&self.empty_matches) });
700
701        loop {
702            if !!self.cur_mps.is_empty() {
    ::core::panicking::panic("assertion failed: !self.cur_mps.is_empty()")
};assert!(!self.cur_mps.is_empty());
703            self.next_mps.clear();
704
705            // Parse all mps at the current input position, then progress the parser.
706            let res = self.parse_tt_inner(parser, matcher, track);
707
708            if let Some(res) = res {
709                return res;
710            }
711        }
712    }
713
714    fn nt_parsing_error<R>(&self, loc: &MatcherLoc, err: Diag<'_>) -> ParseResult<R> {
715        let &MatcherLoc::MetaVarDecl { span, kind, .. } = loc else { ::core::panicking::panic("internal error: entered unreachable code")unreachable!() };
716        let guar = err
717            .with_span_label(
718                span,
719                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("while parsing argument for this `{0}` macro fragment",
                kind))
    })format!("while parsing argument for this `{kind}` macro fragment"),
720            )
721            .emit_err();
722        ErrorReported(guar)
723    }
724
725    fn nameize<I: Iterator<Item = NamedMatch>>(
726        &self,
727        matcher: &[MatcherLoc],
728        mut res: I,
729    ) -> NamedMatches {
730        // Make that each metavar has _exactly one_ binding. If so, insert the binding into the
731        // `NamedParseResult`. Otherwise, it's an error.
732        let mut ret_val = FxHashMap::default();
733        for loc in matcher {
734            if let &MatcherLoc::MetaVarDecl { bind, .. } = loc
735                && ret_val
736                    .insert(MacroRulesNormalizedIdent::new(bind), res.next().unwrap())
737                    .is_some()
738            {
739                // Duplicate binds are checked for when the macro definition is processed,
740                // and should have prevented the definition from ever being used.
741                {
    ::core::panicking::panic_fmt(format_args!("duplicate meta-variable binding went undetected at macro definition"));
}panic!("duplicate meta-variable binding went undetected at macro definition")
742            }
743        }
744        ret_val
745    }
746}