mbe/expander/
matcher.rs

1//! An NFA-based parser, which is porting from rustc mbe parsing code
2//!
3//! See <https://github.com/rust-lang/rust/blob/70b18bc2cbac4712020019f5bf57c00905373205/compiler/rustc_expand/src/mbe/macro_parser.rs>
4//! Here is a quick intro to how the parser works, copied from rustc:
5//!
6//! A 'position' is a dot in the middle of a matcher, usually represented as a
7//! dot. For example `· a $( a )* a b` is a position, as is `a $( · a )* a b`.
8//!
9//! The parser walks through the input a character at a time, maintaining a list
10//! of threads consistent with the current position in the input string: `cur_items`.
11//!
12//! As it processes them, it fills up `eof_items` with threads that would be valid if
13//! the macro invocation is now over, `bb_items` with threads that are waiting on
14//! a Rust non-terminal like `$e:expr`, and `next_items` with threads that are waiting
15//! on a particular token. Most of the logic concerns moving the · through the
16//! repetitions indicated by Kleene stars. The rules for moving the · without
17//! consuming any input are called epsilon transitions. It only advances or calls
18//! out to the real Rust parser when no `cur_items` threads remain.
19//!
20//! Example:
21//!
22//! ```text, ignore
23//! Start parsing a a a a b against [· a $( a )* a b].
24//!
25//! Remaining input: a a a a b
26//! next: [· a $( a )* a b]
27//!
28//! - - - Advance over an a. - - -
29//!
30//! Remaining input: a a a b
31//! cur: [a · $( a )* a b]
32//! Descend/Skip (first item).
33//! next: [a $( · a )* a b]  [a $( a )* · a b].
34//!
35//! - - - Advance over an a. - - -
36//!
37//! Remaining input: a a b
38//! cur: [a $( a · )* a b]  [a $( a )* a · b]
39//! Follow epsilon transition: Finish/Repeat (first item)
40//! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
41//!
42//! - - - Advance over an a. - - - (this looks exactly like the last step)
43//!
44//! Remaining input: a b
45//! cur: [a $( a · )* a b]  [a $( a )* a · b]
46//! Follow epsilon transition: Finish/Repeat (first item)
47//! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
48//!
49//! - - - Advance over an a. - - - (this looks exactly like the last step)
50//!
51//! Remaining input: b
52//! cur: [a $( a · )* a b]  [a $( a )* a · b]
53//! Follow epsilon transition: Finish/Repeat (first item)
54//! next: [a $( a )* · a b]  [a $( · a )* a b]  [a $( a )* a · b]
55//!
56//! - - - Advance over a b. - - -
57//!
58//! Remaining input: ''
59//! eof: [a $( a )* a b ·]
60//! ```
61
62use std::{rc::Rc, sync::Arc};
63
64use intern::{Symbol, sym};
65use smallvec::{SmallVec, smallvec};
66use span::Span;
67use tt::{
68    DelimSpan,
69    iter::{TtElement, TtIter},
70};
71
72use crate::{
73    ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
74    expander::{Binding, Bindings, ExpandResult, Fragment},
75    expect_fragment,
76    parser::{ExprKind, MetaVarKind, Op, RepeatKind, Separator},
77};
78
79impl<'a> Bindings<'a> {
80    fn push_optional(&mut self, name: Symbol) {
81        self.inner.insert(name, Binding::Fragment(Fragment::Empty));
82    }
83
84    fn push_empty(&mut self, name: Symbol) {
85        self.inner.insert(name, Binding::Empty);
86    }
87
88    fn bindings(&self) -> impl Iterator<Item = &Binding<'a>> {
89        self.inner.values()
90    }
91}
92
93#[derive(Clone, Default, Debug)]
94pub(super) struct Match<'a> {
95    pub(super) bindings: Bindings<'a>,
96    /// We currently just keep the first error and count the rest to compare matches.
97    pub(super) err: Option<ExpandError>,
98    pub(super) err_count: usize,
99    /// How many top-level token trees were left to match.
100    pub(super) unmatched_tts: usize,
101    /// The number of bound variables
102    pub(super) bound_count: usize,
103}
104
105impl Match<'_> {
106    fn add_err(&mut self, err: ExpandError) {
107        let prev_err = self.err.take();
108        self.err = prev_err.or(Some(err));
109        self.err_count += 1;
110    }
111}
112
113/// Matching errors are added to the `Match`.
114pub(super) fn match_<'t>(
115    db: &dyn salsa::Database,
116    pattern: &'t MetaTemplate,
117    input: &'t tt::TopSubtree<Span>,
118) -> Match<'t> {
119    let mut res = match_loop(db, pattern, input);
120    res.bound_count = count(res.bindings.bindings());
121    return res;
122
123    fn count<'a>(bindings: impl Iterator<Item = &'a Binding<'a>>) -> usize {
124        bindings
125            .map(|it| match it {
126                Binding::Fragment(_) => 1,
127                Binding::Empty => 1,
128                Binding::Missing(_) => 1,
129                Binding::Nested(it) => count(it.iter()),
130            })
131            .sum()
132    }
133}
134
135#[derive(Debug, Clone)]
136enum BindingKind<'a> {
137    Empty(Symbol),
138    Optional(Symbol),
139    Fragment(Symbol, Fragment<'a>),
140    Missing(Symbol, MetaVarKind),
141    Nested(usize, usize),
142}
143
144#[derive(Debug, Clone)]
145struct BindingsIdx(usize, usize);
146
147#[derive(Debug, Clone)]
148enum LinkNode<T> {
149    Node(T),
150    Parent { idx: usize, len: usize },
151}
152
153#[derive(Default)]
154struct BindingsBuilder<'a> {
155    nodes: Vec<Vec<LinkNode<Rc<BindingKind<'a>>>>>,
156    nested: Vec<Vec<LinkNode<usize>>>,
157}
158
159impl<'a> BindingsBuilder<'a> {
160    fn alloc(&mut self) -> BindingsIdx {
161        let idx = self.nodes.len();
162        self.nodes.push(Vec::new());
163        let nidx = self.nested.len();
164        self.nested.push(Vec::new());
165        BindingsIdx(idx, nidx)
166    }
167
168    fn copy(&mut self, bindings: &BindingsIdx) -> BindingsIdx {
169        let idx = copy_parent(bindings.0, &mut self.nodes);
170        let nidx = copy_parent(bindings.1, &mut self.nested);
171        return BindingsIdx(idx, nidx);
172
173        fn copy_parent<T>(idx: usize, target: &mut Vec<Vec<LinkNode<T>>>) -> usize
174        where
175            T: Clone,
176        {
177            let new_idx = target.len();
178            let len = target[idx].len();
179            if len < 4 {
180                target.push(target[idx].clone())
181            } else {
182                target.push(vec![LinkNode::Parent { idx, len }]);
183            }
184            new_idx
185        }
186    }
187
188    fn push_empty(&mut self, idx: &mut BindingsIdx, var: &Symbol) {
189        self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone()))));
190    }
191
192    fn push_optional(&mut self, idx: &mut BindingsIdx, var: &Symbol) {
193        self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone()))));
194    }
195
196    fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &Symbol, fragment: Fragment<'a>) {
197        self.nodes[idx.0]
198            .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
199    }
200
201    fn push_missing(&mut self, idx: &mut BindingsIdx, var: &Symbol, kind: MetaVarKind) {
202        self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Missing(var.clone(), kind))));
203    }
204
205    fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) {
206        let BindingsIdx(idx, nidx) = self.copy(child);
207        self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx))));
208    }
209
210    fn push_default(&mut self, idx: &mut BindingsIdx) {
211        self.nested[idx.1].push(LinkNode::Node(idx.0));
212        let new_idx = self.nodes.len();
213        self.nodes.push(Vec::new());
214        idx.0 = new_idx;
215    }
216
217    fn build(self, idx: &BindingsIdx) -> Bindings<'a> {
218        self.build_inner(&self.nodes[idx.0])
219    }
220
221    fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind<'a>>>]) -> Bindings<'a> {
222        let mut bindings = Bindings::default();
223        let mut nodes = Vec::new();
224        self.collect_nodes(link_nodes, &mut nodes);
225
226        for cmd in nodes {
227            match cmd {
228                BindingKind::Empty(name) => {
229                    bindings.push_empty(name.clone());
230                }
231                BindingKind::Optional(name) => {
232                    bindings.push_optional(name.clone());
233                }
234                BindingKind::Fragment(name, fragment) => {
235                    bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone()));
236                }
237                BindingKind::Missing(name, kind) => {
238                    bindings.inner.insert(name.clone(), Binding::Missing(*kind));
239                }
240                BindingKind::Nested(idx, nested_idx) => {
241                    let mut nested_nodes = Vec::new();
242                    self.collect_nested(*idx, *nested_idx, &mut nested_nodes);
243
244                    for (idx, iter) in nested_nodes.into_iter().enumerate() {
245                        for (key, value) in &iter.inner {
246                            let bindings = bindings
247                                .inner
248                                .entry(key.clone())
249                                .or_insert_with(|| Binding::Nested(Vec::new()));
250
251                            if let Binding::Nested(it) = bindings {
252                                // insert empty nested bindings before this one
253                                while it.len() < idx {
254                                    it.push(Binding::Nested(Vec::new()));
255                                }
256                                it.push(value.clone());
257                            }
258                        }
259                    }
260                }
261            }
262        }
263
264        bindings
265    }
266
267    fn collect_nested_ref<'b>(
268        &'b self,
269        id: usize,
270        len: usize,
271        nested_refs: &mut Vec<&'b [LinkNode<Rc<BindingKind<'a>>>]>,
272    ) {
273        self.nested[id].iter().take(len).for_each(|it| match it {
274            LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
275            LinkNode::Parent { idx, len } => self.collect_nested_ref(*idx, *len, nested_refs),
276        });
277    }
278
279    fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings<'a>>) {
280        let last = &self.nodes[idx];
281        let mut nested_refs: Vec<&[_]> = Vec::new();
282        self.nested[nested_idx].iter().for_each(|it| match *it {
283            LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]),
284            LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs),
285        });
286        nested_refs.push(last);
287        nested.extend(nested_refs.into_iter().map(|iter| self.build_inner(iter)));
288    }
289
290    fn collect_nodes_ref<'b>(
291        &'b self,
292        id: usize,
293        len: usize,
294        nodes: &mut Vec<&'b BindingKind<'a>>,
295    ) {
296        self.nodes[id].iter().take(len).for_each(|it| match it {
297            LinkNode::Node(it) => nodes.push(it),
298            LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
299        });
300    }
301
302    fn collect_nodes<'b>(
303        &'b self,
304        link_nodes: &'b [LinkNode<Rc<BindingKind<'a>>>],
305        nodes: &mut Vec<&'b BindingKind<'a>>,
306    ) {
307        link_nodes.iter().for_each(|it| match it {
308            LinkNode::Node(it) => nodes.push(it),
309            LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
310        });
311    }
312}
313
314#[derive(Debug, Clone)]
315struct MatchState<'t> {
316    /// The position of the "dot" in this matcher
317    dot: OpDelimitedIter<'t>,
318
319    /// Token subtree stack
320    /// When matching against matchers with nested delimited submatchers (e.g., `pat ( pat ( .. )
321    /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does
322    /// that where the bottom of the stack is the outermost matcher.
323    stack: SmallVec<[OpDelimitedIter<'t>; 4]>,
324
325    /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
326    /// before we enter the repetition.
327    up: Option<Box<MatchState<'t>>>,
328
329    /// The separator if we are in a repetition.
330    sep: Option<Arc<Separator>>,
331
332    /// The KleeneOp of this sequence if we are in a repetition.
333    sep_kind: Option<RepeatKind>,
334
335    /// Whether we already matched separator token.
336    sep_matched: bool,
337
338    /// Matched meta variables bindings
339    bindings: BindingsIdx,
340
341    /// Cached result of meta variable parsing
342    meta_result: Option<(TtIter<'t, Span>, ExpandResult<Option<Fragment<'t>>>)>,
343
344    /// Is error occurred in this state, will `poised` to "parent"
345    is_error: bool,
346}
347
348/// Process the matcher positions of `cur_items` until it is empty. In the process, this will
349/// produce more items in `next_items`, `eof_items`, and `bb_items`.
350///
351/// For more info about the how this happens, see the module-level doc comments and the inline
352/// comments of this function.
353///
354/// # Parameters
355///
356/// - `src`: the current token of the parser.
357/// - `stack`: the "parent" frames of the token tree
358/// - `res`: the match result to store errors
359/// - `cur_items`: the set of current items to be processed. This should be empty by the end of a
360///   successful execution of this function.
361/// - `next_items`: the set of newly generated items. These are used to replenish `cur_items` in
362///   the function `parse`.
363/// - `eof_items`: the set of items that would be valid if this was the EOF.
364/// - `bb_items`: the set of items that are waiting for the black-box parser.
365/// - `error_items`: the set of items in errors, used for error-resilient parsing
366#[inline]
367fn match_loop_inner<'t>(
368    db: &dyn salsa::Database,
369    src: TtIter<'t, Span>,
370    stack: &[TtIter<'t, Span>],
371    res: &mut Match<'t>,
372    bindings_builder: &mut BindingsBuilder<'t>,
373    cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
374    bb_items: &mut SmallVec<[MatchState<'t>; 1]>,
375    next_items: &mut Vec<MatchState<'t>>,
376    eof_items: &mut SmallVec<[MatchState<'t>; 1]>,
377    error_items: &mut SmallVec<[MatchState<'t>; 1]>,
378    delim_span: tt::DelimSpan<Span>,
379) {
380    macro_rules! try_push {
381        ($items: expr, $it:expr) => {
382            if $it.is_error {
383                error_items.push($it);
384            } else {
385                $items.push($it);
386            }
387        };
388    }
389
390    while let Some(mut item) = cur_items.pop() {
391        while item.dot.is_eof() {
392            match item.stack.pop() {
393                Some(frame) => {
394                    item.dot = frame;
395                    item.dot.next();
396                }
397                None => break,
398            }
399        }
400        let op = match item.dot.peek() {
401            None => {
402                // We are at or past the end of the matcher of `item`.
403                if let Some(up) = &item.up {
404                    if !item.sep_matched {
405                        // Get the `up` matcher
406                        let mut new_pos = (**up).clone();
407                        new_pos.bindings = bindings_builder.copy(&new_pos.bindings);
408                        // Add matches from this repetition to the `matches` of `up`
409                        bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings);
410
411                        // Move the "dot" past the repetition in `up`
412                        new_pos.dot.next();
413                        new_pos.is_error = new_pos.is_error || item.is_error;
414                        cur_items.push(new_pos);
415                    }
416
417                    // Check if we need a separator.
418                    if item.sep.is_some() && !item.sep_matched {
419                        let sep = item.sep.as_ref().unwrap();
420                        let mut fork = src.clone();
421                        if expect_separator(&mut fork, sep) {
422                            // HACK: here we use `meta_result` to pass `TtIter` back to caller because
423                            // it might have been advanced multiple times. `ValueResult` is
424                            // insignificant.
425                            item.meta_result = Some((fork, ValueResult::ok(None)));
426                            item.dot.next();
427                            // item.sep_parsed = Some(sep_len);
428                            item.sep_matched = true;
429                            try_push!(next_items, item);
430                        }
431                    }
432                    // We don't need a separator. Move the "dot" back to the beginning of the matcher
433                    // and try to match again UNLESS we are only allowed to have _one_ repetition.
434                    else if item.sep_kind != Some(RepeatKind::ZeroOrOne) {
435                        item.dot = item.dot.reset();
436                        item.sep_matched = false;
437                        bindings_builder.push_default(&mut item.bindings);
438                        cur_items.push(item);
439                    }
440                } else {
441                    // If we are not in a repetition, then being at the end of a matcher means that we have
442                    // reached the potential end of the input.
443                    try_push!(eof_items, item);
444                }
445                continue;
446            }
447            Some(it) => it,
448        };
449
450        // We are in the middle of a matcher.
451        match op {
452            OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => {
453                if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) {
454                    let mut new_item = item.clone();
455                    new_item.bindings = bindings_builder.copy(&new_item.bindings);
456                    new_item.dot.next();
457                    collect_vars(
458                        &mut |s| {
459                            bindings_builder.push_empty(&mut new_item.bindings, &s);
460                        },
461                        tokens,
462                    );
463                    cur_items.push(new_item);
464                }
465                cur_items.push(MatchState {
466                    dot: tokens.iter_delimited(delim_span),
467                    stack: Default::default(),
468                    up: Some(Box::new(item)),
469                    sep: separator.clone(),
470                    sep_kind: Some(*kind),
471                    sep_matched: false,
472                    bindings: bindings_builder.alloc(),
473                    meta_result: None,
474                    is_error: false,
475                })
476            }
477            OpDelimited::Op(Op::Subtree { tokens, delimiter }) => {
478                if let Ok((subtree, _)) = src.clone().expect_subtree()
479                    && subtree.delimiter.kind == delimiter.kind
480                {
481                    item.stack.push(item.dot);
482                    item.dot = tokens.iter_delimited_with(*delimiter);
483                    cur_items.push(item);
484                }
485            }
486            OpDelimited::Op(Op::Var { kind, name, .. }) => {
487                if let &Some(kind) = kind {
488                    let mut fork = src.clone();
489                    let match_res = match_meta_var(db, kind, &mut fork, delim_span);
490                    match match_res.err {
491                        None => {
492                            // Some meta variables are optional (e.g. vis)
493                            if !match_res.value.is_empty() {
494                                item.meta_result = Some((fork, match_res.map(Some)));
495                                try_push!(bb_items, item);
496                            } else {
497                                bindings_builder.push_optional(&mut item.bindings, name);
498                                item.dot.next();
499                                cur_items.push(item);
500                            }
501                        }
502                        Some(err) => {
503                            res.add_err(err);
504                            if !match_res.value.is_empty() {
505                                bindings_builder.push_fragment(
506                                    &mut item.bindings,
507                                    name,
508                                    match_res.value,
509                                )
510                            } else {
511                                bindings_builder.push_missing(&mut item.bindings, name, kind)
512                            }
513                            item.is_error = true;
514                            error_items.push(item);
515                        }
516                    }
517                }
518            }
519            OpDelimited::Op(Op::Literal(lhs)) => {
520                if let Ok(rhs) = src.clone().expect_leaf() {
521                    if matches!(rhs, tt::Leaf::Literal(it) if it.symbol == lhs.symbol) {
522                        item.dot.next();
523                    } else {
524                        res.add_err(ExpandError::new(
525                            *rhs.span(),
526                            ExpandErrorKind::UnexpectedToken,
527                        ));
528                        item.is_error = true;
529                    }
530                } else {
531                    res.add_err(ExpandError::binding_error(
532                        src.clone().next().map_or(delim_span.close, |it| it.first_span()),
533                        format!("expected literal: `{lhs}`"),
534                    ));
535                    item.is_error = true;
536                }
537                try_push!(next_items, item);
538            }
539            OpDelimited::Op(Op::Ident(lhs)) => {
540                if let Ok(rhs) = src.clone().expect_leaf() {
541                    if matches!(rhs, tt::Leaf::Ident(it) if it.sym == lhs.sym) {
542                        item.dot.next();
543                    } else {
544                        res.add_err(ExpandError::new(
545                            *rhs.span(),
546                            ExpandErrorKind::UnexpectedToken,
547                        ));
548                        item.is_error = true;
549                    }
550                } else {
551                    res.add_err(ExpandError::binding_error(
552                        src.clone().next().map_or(delim_span.close, |it| it.first_span()),
553                        format!("expected ident: `{lhs}`"),
554                    ));
555                    item.is_error = true;
556                }
557                try_push!(next_items, item);
558            }
559            OpDelimited::Op(Op::Punct(lhs)) => {
560                let mut fork = src.clone();
561                let error = if let Ok(rhs) = fork.expect_glued_punct() {
562                    let first_is_single_quote = rhs[0].char == '\'';
563                    let lhs = lhs.iter().map(|it| it.char);
564                    let rhs_ = rhs.iter().map(|it| it.char);
565                    if lhs.clone().eq(rhs_) {
566                        // HACK: here we use `meta_result` to pass `TtIter` back to caller because
567                        // it might have been advanced multiple times. `ValueResult` is
568                        // insignificant.
569                        item.meta_result = Some((fork, ValueResult::ok(None)));
570                        item.dot.next();
571                        next_items.push(item);
572                        continue;
573                    }
574
575                    if first_is_single_quote {
576                        // If the first punct token is a single quote, that's a part of a lifetime
577                        // ident, not a punct.
578                        ExpandError::new(
579                            rhs.get(1).map_or(rhs[0].span, |it| it.span),
580                            ExpandErrorKind::UnexpectedToken,
581                        )
582                    } else {
583                        let lhs = lhs.collect::<String>();
584                        ExpandError::binding_error(rhs[0].span, format!("expected punct: `{lhs}`"))
585                    }
586                } else {
587                    ExpandError::new(
588                        src.clone().next().map_or(delim_span.close, |it| it.first_span()),
589                        ExpandErrorKind::UnexpectedToken,
590                    )
591                };
592
593                res.add_err(error);
594                item.is_error = true;
595                error_items.push(item);
596            }
597            OpDelimited::Op(
598                Op::Ignore { .. }
599                | Op::Index { .. }
600                | Op::Count { .. }
601                | Op::Len { .. }
602                | Op::Concat { .. },
603            ) => {
604                stdx::never!("metavariable expression in lhs found");
605            }
606            OpDelimited::Open => {
607                if matches!(src.peek(), Some(TtElement::Subtree(..))) {
608                    item.dot.next();
609                    try_push!(next_items, item);
610                }
611            }
612            OpDelimited::Close => {
613                let is_delim_closed = src.is_empty() && !stack.is_empty();
614                if is_delim_closed {
615                    item.dot.next();
616                    try_push!(next_items, item);
617                }
618            }
619        }
620    }
621}
622
623fn match_loop<'t>(
624    db: &dyn salsa::Database,
625    pattern: &'t MetaTemplate,
626    src: &'t tt::TopSubtree<Span>,
627) -> Match<'t> {
628    let span = src.top_subtree().delimiter.delim_span();
629    let mut src = src.iter();
630    let mut stack: SmallVec<[TtIter<'_, Span>; 1]> = SmallVec::new();
631    let mut res = Match::default();
632    let mut error_recover_item = None;
633
634    let mut bindings_builder = BindingsBuilder::default();
635
636    let mut cur_items = smallvec![MatchState {
637        dot: pattern.iter_delimited(span),
638        stack: Default::default(),
639        up: None,
640        sep: None,
641        sep_kind: None,
642        sep_matched: false,
643        bindings: bindings_builder.alloc(),
644        is_error: false,
645        meta_result: None,
646    }];
647
648    let mut next_items = vec![];
649
650    loop {
651        let mut bb_items = SmallVec::new();
652        let mut eof_items = SmallVec::new();
653        let mut error_items = SmallVec::new();
654
655        stdx::always!(next_items.is_empty());
656
657        match_loop_inner(
658            db,
659            src.clone(),
660            &stack,
661            &mut res,
662            &mut bindings_builder,
663            &mut cur_items,
664            &mut bb_items,
665            &mut next_items,
666            &mut eof_items,
667            &mut error_items,
668            span,
669        );
670        stdx::always!(cur_items.is_empty());
671
672        if !error_items.is_empty() {
673            error_recover_item = error_items.pop().map(|it| it.bindings);
674        } else if let [state, ..] = &*eof_items {
675            error_recover_item = Some(state.bindings.clone());
676        }
677
678        // We need to do some post processing after the `match_loop_inner`.
679        // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
680        // either the parse is ambiguous (which should never happen) or there is a syntax error.
681        if src.is_empty() && stack.is_empty() {
682            if let [state] = &*eof_items {
683                // remove all errors, because it is the correct answer !
684                res = Match::default();
685                res.bindings = bindings_builder.build(&state.bindings);
686            } else {
687                // Error recovery
688                if let Some(item) = error_recover_item {
689                    res.bindings = bindings_builder.build(&item);
690                }
691                res.add_err(ExpandError::new(span.open, ExpandErrorKind::UnexpectedToken));
692            }
693            return res;
694        }
695
696        // If there are no possible next positions AND we aren't waiting for the black-box parser,
697        // then there is a syntax error.
698        //
699        // Another possibility is that we need to call out to parse some rust nonterminal
700        // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
701        let has_leftover_tokens = (bb_items.is_empty() && next_items.is_empty())
702            || !(bb_items.is_empty() || next_items.is_empty())
703            || bb_items.len() > 1;
704        if has_leftover_tokens {
705            res.unmatched_tts += src.remaining().flat_tokens().len();
706            res.add_err(ExpandError::new(span.open, ExpandErrorKind::LeftoverTokens));
707
708            if let Some(error_recover_item) = error_recover_item {
709                res.bindings = bindings_builder.build(&error_recover_item);
710            }
711            return res;
712        }
713        // Dump all possible `next_items` into `cur_items` for the next iteration.
714        else if !next_items.is_empty() {
715            if let Some((iter, _)) = next_items[0].meta_result.take() {
716                // We've matched a possibly "glued" punct. The matched punct (hence
717                // `meta_result` also) must be the same for all items.
718                // FIXME: If there are multiple items, it's definitely redundant (and it's hacky!
719                // `meta_result` isn't supposed to be used this way).
720
721                // We already bumped, so no need to call `.next()` like in the other branch.
722                src = iter;
723                for item in next_items.iter_mut() {
724                    item.meta_result = None;
725                }
726            } else {
727                match src.next() {
728                    Some(TtElement::Subtree(_, subtree_iter)) => {
729                        stack.push(src.clone());
730                        src = subtree_iter;
731                    }
732                    None => {
733                        if let Some(iter) = stack.pop() {
734                            src = iter;
735                        }
736                    }
737                    _ => (),
738                }
739            }
740            // Now process the next token
741            cur_items.extend(next_items.drain(..));
742        }
743        // Finally, we have the case where we need to call the black-box parser to get some
744        // nonterminal.
745        else {
746            stdx::always!(bb_items.len() == 1);
747            let mut item = bb_items.pop().unwrap();
748
749            if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() {
750                let (iter, match_res) = item.meta_result.take().unwrap();
751                match match_res.value {
752                    Some(fragment) => {
753                        bindings_builder.push_fragment(&mut item.bindings, name, fragment);
754                    }
755                    None if match_res.err.is_none() => {
756                        bindings_builder.push_optional(&mut item.bindings, name);
757                    }
758                    None => {}
759                }
760                if let Some(err) = match_res.err {
761                    res.add_err(err);
762                }
763                src = iter.clone();
764                item.dot.next();
765            } else {
766                unreachable!()
767            }
768            cur_items.push(item);
769        }
770        stdx::always!(!cur_items.is_empty());
771    }
772}
773
774fn match_meta_var<'t>(
775    db: &dyn salsa::Database,
776    kind: MetaVarKind,
777    input: &mut TtIter<'t, Span>,
778    delim_span: DelimSpan<Span>,
779) -> ExpandResult<Fragment<'t>> {
780    let fragment = match kind {
781        MetaVarKind::Path => {
782            return expect_fragment(db, input, parser::PrefixEntryPoint::Path, delim_span)
783                .map(Fragment::Path);
784        }
785        MetaVarKind::Expr(expr) => {
786            // `expr_2021` should not match underscores, let expressions, or inline const.
787            // The latter two are for [backwards compatibility][0].
788            // And `expr` also should not contain let expressions but may contain the other two
789            // since `Edition2024`.
790            // HACK: Macro expansion should not be done using "rollback and try another alternative".
791            // rustc [explicitly checks the next token][1].
792            // [0]: https://github.com/rust-lang/rust/issues/86730
793            // [1]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576
794            match input.peek() {
795                Some(TtElement::Leaf(tt::Leaf::Ident(it))) => {
796                    let is_err = if it.is_raw.no() && matches!(expr, ExprKind::Expr2021) {
797                        it.sym == sym::underscore || it.sym == sym::let_ || it.sym == sym::const_
798                    } else {
799                        it.sym == sym::let_
800                    };
801                    if is_err {
802                        return ExpandResult::only_err(ExpandError::new(
803                            it.span,
804                            ExpandErrorKind::NoMatchingRule,
805                        ));
806                    }
807                }
808                _ => {}
809            };
810            return expect_fragment(db, input, parser::PrefixEntryPoint::Expr, delim_span)
811                .map(Fragment::Expr);
812        }
813        MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
814            let span = input.next_span();
815            let savepoint = input.savepoint();
816            let err = match kind {
817                MetaVarKind::Ident => input.expect_ident().map(drop).map_err(|()| {
818                    ExpandError::binding_error(span.unwrap_or(delim_span.close), "expected ident")
819                }),
820                MetaVarKind::Tt => expect_tt(input).map_err(|()| {
821                    ExpandError::binding_error(
822                        span.unwrap_or(delim_span.close),
823                        "expected token tree",
824                    )
825                }),
826                MetaVarKind::Lifetime => expect_lifetime(input).map(drop).map_err(|()| {
827                    ExpandError::binding_error(
828                        span.unwrap_or(delim_span.close),
829                        "expected lifetime",
830                    )
831                }),
832                MetaVarKind::Literal => {
833                    eat_char(input, '-');
834                    input.expect_literal().map(drop).map_err(|()| {
835                        ExpandError::binding_error(
836                            span.unwrap_or(delim_span.close),
837                            "expected literal",
838                        )
839                    })
840                }
841                _ => unreachable!(),
842            }
843            .err();
844            let tt_result = input.from_savepoint(savepoint);
845            return ValueResult { value: Fragment::Tokens(tt_result), err };
846        }
847        MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
848        MetaVarKind::Pat => parser::PrefixEntryPoint::PatTop,
849        MetaVarKind::PatParam => parser::PrefixEntryPoint::Pat,
850        MetaVarKind::Stmt => parser::PrefixEntryPoint::Stmt,
851        MetaVarKind::Block => parser::PrefixEntryPoint::Block,
852        MetaVarKind::Meta => parser::PrefixEntryPoint::MetaItem,
853        MetaVarKind::Item => parser::PrefixEntryPoint::Item,
854        MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
855    };
856    expect_fragment(db, input, fragment, delim_span).map(Fragment::Tokens)
857}
858
859fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {
860    for op in pattern.iter() {
861        match op {
862            Op::Var { name, .. } => collector_fun(name.clone()),
863            Op::Subtree { tokens, .. } => collect_vars(collector_fun, tokens),
864            Op::Repeat { tokens, .. } => collect_vars(collector_fun, tokens),
865            Op::Literal(_) | Op::Ident(_) | Op::Punct(_) => {}
866            Op::Ignore { .. }
867            | Op::Index { .. }
868            | Op::Count { .. }
869            | Op::Len { .. }
870            | Op::Concat { .. } => {
871                stdx::never!("metavariable expression in lhs found");
872            }
873        }
874    }
875}
876impl MetaTemplate {
877    fn iter_delimited_with(&self, delimiter: tt::Delimiter<Span>) -> OpDelimitedIter<'_> {
878        OpDelimitedIter { inner: &self.0, idx: 0, delimited: delimiter }
879    }
880    fn iter_delimited(&self, span: tt::DelimSpan<Span>) -> OpDelimitedIter<'_> {
881        OpDelimitedIter {
882            inner: &self.0,
883            idx: 0,
884            delimited: tt::Delimiter::invisible_delim_spanned(span),
885        }
886    }
887}
888
889#[derive(Debug, Clone, Copy)]
890enum OpDelimited<'a> {
891    Op(&'a Op),
892    Open,
893    Close,
894}
895
896#[derive(Debug, Clone, Copy)]
897struct OpDelimitedIter<'a> {
898    inner: &'a [Op],
899    delimited: tt::Delimiter<Span>,
900    idx: usize,
901}
902
903impl<'a> OpDelimitedIter<'a> {
904    fn is_eof(&self) -> bool {
905        let len = self.inner.len()
906            + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
907        self.idx >= len
908    }
909
910    fn peek(&self) -> Option<OpDelimited<'a>> {
911        match self.delimited.kind {
912            tt::DelimiterKind::Invisible => self.inner.get(self.idx).map(OpDelimited::Op),
913            _ => match self.idx {
914                0 => Some(OpDelimited::Open),
915                i if i == self.inner.len() + 1 => Some(OpDelimited::Close),
916                i => self.inner.get(i - 1).map(OpDelimited::Op),
917            },
918        }
919    }
920
921    fn reset(&self) -> Self {
922        Self { inner: self.inner, idx: 0, delimited: self.delimited }
923    }
924}
925
926impl<'a> Iterator for OpDelimitedIter<'a> {
927    type Item = OpDelimited<'a>;
928
929    fn next(&mut self) -> Option<Self::Item> {
930        let res = self.peek();
931        self.idx += 1;
932        res
933    }
934
935    fn size_hint(&self) -> (usize, Option<usize>) {
936        let len = self.inner.len()
937            + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
938        let remain = len.saturating_sub(self.idx);
939        (remain, Some(remain))
940    }
941}
942
943fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) -> bool {
944    let mut fork = iter.clone();
945    let ok = match separator {
946        Separator::Ident(lhs) => match fork.expect_ident_or_underscore() {
947            Ok(rhs) => rhs.sym == lhs.sym,
948            Err(_) => false,
949        },
950        Separator::Literal(lhs) => match fork.expect_literal() {
951            Ok(rhs) => match rhs {
952                tt::Leaf::Literal(rhs) => rhs.symbol == lhs.symbol,
953                tt::Leaf::Ident(rhs) => rhs.sym == lhs.symbol,
954                tt::Leaf::Punct(_) => false,
955            },
956            Err(_) => false,
957        },
958        Separator::Puncts(lhs) => match fork.expect_glued_punct() {
959            Ok(rhs) => {
960                let lhs = lhs.iter().map(|it| it.char);
961                let rhs = rhs.iter().map(|it| it.char);
962                lhs.eq(rhs)
963            }
964            Err(_) => false,
965        },
966        Separator::Lifetime(_punct, ident) => match expect_lifetime(&mut fork) {
967            Ok(lifetime) => lifetime.sym == ident.sym,
968            Err(_) => false,
969        },
970    };
971    if ok {
972        *iter = fork;
973    }
974    ok
975}
976
977fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
978    if let Some(TtElement::Leaf(tt::Leaf::Punct(punct))) = iter.peek() {
979        if punct.char == '\'' {
980            expect_lifetime(iter)?;
981        } else {
982            iter.expect_glued_punct()?;
983        }
984    } else {
985        iter.next().ok_or(())?;
986    }
987    Ok(())
988}
989
990fn expect_lifetime<'a, S: Copy>(iter: &mut TtIter<'a, S>) -> Result<&'a tt::Ident<S>, ()> {
991    let punct = iter.expect_single_punct()?;
992    if punct.char != '\'' {
993        return Err(());
994    }
995    iter.expect_ident_or_underscore()
996}
997
998fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) {
999    if matches!(iter.peek(), Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char, .. }))) if *char == c)
1000    {
1001        iter.next().expect("already peeked");
1002    }
1003}