Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/expander/matcher.rs')
-rw-r--r--crates/mbe/src/expander/matcher.rs91
1 files changed, 48 insertions, 43 deletions
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 189efcd15c..8f6627a60f 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -63,7 +63,6 @@ use std::{rc::Rc, sync::Arc};
use intern::{Symbol, sym};
use smallvec::{SmallVec, smallvec};
-use span::{Edition, Span};
use tt::{
DelimSpan,
iter::{TtElement, TtIter},
@@ -71,7 +70,7 @@ use tt::{
use crate::{
ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
- expander::{Binding, Bindings, ExpandResult, Fragment},
+ expander::{Binding, Bindings, ExpandResult, Fragment, TokensOrigin},
expect_fragment,
parser::{ExprKind, MetaVarKind, Op, RepeatKind, Separator},
};
@@ -112,11 +111,11 @@ impl Match<'_> {
/// Matching errors are added to the `Match`.
pub(super) fn match_<'t>(
+ db: &dyn salsa::Database,
pattern: &'t MetaTemplate,
- input: &'t tt::TopSubtree<Span>,
- edition: Edition,
+ input: &'t tt::TopSubtree,
) -> Match<'t> {
- let mut res = match_loop(pattern, input, edition);
+ let mut res = match_loop(db, pattern, input);
res.bound_count = count(res.bindings.bindings());
return res;
@@ -339,7 +338,7 @@ struct MatchState<'t> {
bindings: BindingsIdx,
/// Cached result of meta variable parsing
- meta_result: Option<(TtIter<'t, Span>, ExpandResult<Option<Fragment<'t>>>)>,
+ meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment<'t>>>)>,
/// Is error occurred in this state, will `poised` to "parent"
is_error: bool,
@@ -365,8 +364,9 @@ struct MatchState<'t> {
/// - `error_items`: the set of items in errors, used for error-resilient parsing
#[inline]
fn match_loop_inner<'t>(
- src: TtIter<'t, Span>,
- stack: &[TtIter<'t, Span>],
+ db: &dyn salsa::Database,
+ src: TtIter<'t>,
+ stack: &[TtIter<'t>],
res: &mut Match<'t>,
bindings_builder: &mut BindingsBuilder<'t>,
cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
@@ -374,8 +374,7 @@ fn match_loop_inner<'t>(
next_items: &mut Vec<MatchState<'t>>,
eof_items: &mut SmallVec<[MatchState<'t>; 1]>,
error_items: &mut SmallVec<[MatchState<'t>; 1]>,
- delim_span: tt::DelimSpan<Span>,
- edition: Edition,
+ delim_span: tt::DelimSpan,
) {
macro_rules! try_push {
($items: expr, $it:expr) => {
@@ -486,7 +485,7 @@ fn match_loop_inner<'t>(
OpDelimited::Op(Op::Var { kind, name, .. }) => {
if let &Some(kind) = kind {
let mut fork = src.clone();
- let match_res = match_meta_var(kind, &mut fork, delim_span, edition);
+ let match_res = match_meta_var(db, kind, &mut fork, delim_span);
match match_res.err {
None => {
// Some meta variables are optional (e.g. vis)
@@ -518,7 +517,8 @@ fn match_loop_inner<'t>(
}
OpDelimited::Op(Op::Literal(lhs)) => {
if let Ok(rhs) = src.clone().expect_leaf() {
- if matches!(rhs, tt::Leaf::Literal(it) if it.symbol == lhs.symbol) {
+ if matches!(&rhs, tt::Leaf::Literal(it) if it.text_and_suffix == lhs.text_and_suffix)
+ {
item.dot.next();
} else {
res.add_err(ExpandError::new(
@@ -538,7 +538,7 @@ fn match_loop_inner<'t>(
}
OpDelimited::Op(Op::Ident(lhs)) => {
if let Ok(rhs) = src.clone().expect_leaf() {
- if matches!(rhs, tt::Leaf::Ident(it) if it.sym == lhs.sym) {
+ if matches!(&rhs, tt::Leaf::Ident(it) if it.sym == lhs.sym) {
item.dot.next();
} else {
res.add_err(ExpandError::new(
@@ -621,13 +621,13 @@ fn match_loop_inner<'t>(
}
fn match_loop<'t>(
+ db: &dyn salsa::Database,
pattern: &'t MetaTemplate,
- src: &'t tt::TopSubtree<Span>,
- edition: Edition,
+ src: &'t tt::TopSubtree,
) -> Match<'t> {
let span = src.top_subtree().delimiter.delim_span();
let mut src = src.iter();
- let mut stack: SmallVec<[TtIter<'_, Span>; 1]> = SmallVec::new();
+ let mut stack: SmallVec<[TtIter<'_>; 1]> = SmallVec::new();
let mut res = Match::default();
let mut error_recover_item = None;
@@ -655,6 +655,7 @@ fn match_loop<'t>(
stdx::always!(next_items.is_empty());
match_loop_inner(
+ db,
src.clone(),
&stack,
&mut res,
@@ -665,7 +666,6 @@ fn match_loop<'t>(
&mut eof_items,
&mut error_items,
span,
- edition,
);
stdx::always!(cur_items.is_empty());
@@ -702,7 +702,7 @@ fn match_loop<'t>(
|| !(bb_items.is_empty() || next_items.is_empty())
|| bb_items.len() > 1;
if has_leftover_tokens {
- res.unmatched_tts += src.remaining().flat_tokens().len();
+ res.unmatched_tts += src.remaining().len();
res.add_err(ExpandError::new(span.open, ExpandErrorKind::LeftoverTokens));
if let Some(error_recover_item) = error_recover_item {
@@ -772,14 +772,14 @@ fn match_loop<'t>(
}
fn match_meta_var<'t>(
+ db: &dyn salsa::Database,
kind: MetaVarKind,
- input: &mut TtIter<'t, Span>,
- delim_span: DelimSpan<Span>,
- edition: Edition,
+ input: &mut TtIter<'t>,
+ delim_span: DelimSpan,
) -> ExpandResult<Fragment<'t>> {
let fragment = match kind {
MetaVarKind::Path => {
- return expect_fragment(input, parser::PrefixEntryPoint::Path, edition, delim_span)
+ return expect_fragment(db, input, parser::PrefixEntryPoint::Path, delim_span)
.map(Fragment::Path);
}
MetaVarKind::Expr(expr) => {
@@ -807,7 +807,7 @@ fn match_meta_var<'t>(
}
_ => {}
};
- return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition, delim_span)
+ return expect_fragment(db, input, parser::PrefixEntryPoint::Expr, delim_span)
.map(Fragment::Expr);
}
MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
@@ -842,18 +842,23 @@ fn match_meta_var<'t>(
}
.err();
let tt_result = input.from_savepoint(savepoint);
- return ValueResult { value: Fragment::Tokens(tt_result), err };
+ return ValueResult {
+ value: Fragment::Tokens { tree: tt_result, origin: TokensOrigin::Raw },
+ err,
+ };
}
- MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
- MetaVarKind::Pat => parser::PrefixEntryPoint::PatTop,
- MetaVarKind::PatParam => parser::PrefixEntryPoint::Pat,
- MetaVarKind::Stmt => parser::PrefixEntryPoint::Stmt,
- MetaVarKind::Block => parser::PrefixEntryPoint::Block,
- MetaVarKind::Meta => parser::PrefixEntryPoint::MetaItem,
- MetaVarKind::Item => parser::PrefixEntryPoint::Item,
- MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
+ MetaVarKind::Ty => (parser::PrefixEntryPoint::Ty, TokensOrigin::Ast),
+ MetaVarKind::Pat => (parser::PrefixEntryPoint::PatTop, TokensOrigin::Ast),
+ MetaVarKind::PatParam => (parser::PrefixEntryPoint::Pat, TokensOrigin::Ast),
+ MetaVarKind::Stmt => (parser::PrefixEntryPoint::Stmt, TokensOrigin::Ast),
+ MetaVarKind::Block => (parser::PrefixEntryPoint::Block, TokensOrigin::Ast),
+ MetaVarKind::Meta => (parser::PrefixEntryPoint::MetaItem, TokensOrigin::Ast),
+ MetaVarKind::Item => (parser::PrefixEntryPoint::Item, TokensOrigin::Ast),
+ MetaVarKind::Vis => (parser::PrefixEntryPoint::Vis, TokensOrigin::Ast),
};
- expect_fragment(input, fragment, edition, delim_span).map(Fragment::Tokens)
+ let (entry_point, origin) = fragment;
+ expect_fragment(db, input, entry_point, delim_span)
+ .map(|tree| Fragment::Tokens { tree, origin })
}
fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {
@@ -874,10 +879,10 @@ fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate)
}
}
impl MetaTemplate {
- fn iter_delimited_with(&self, delimiter: tt::Delimiter<Span>) -> OpDelimitedIter<'_> {
+ fn iter_delimited_with(&self, delimiter: tt::Delimiter) -> OpDelimitedIter<'_> {
OpDelimitedIter { inner: &self.0, idx: 0, delimited: delimiter }
}
- fn iter_delimited(&self, span: tt::DelimSpan<Span>) -> OpDelimitedIter<'_> {
+ fn iter_delimited(&self, span: tt::DelimSpan) -> OpDelimitedIter<'_> {
OpDelimitedIter {
inner: &self.0,
idx: 0,
@@ -896,7 +901,7 @@ enum OpDelimited<'a> {
#[derive(Debug, Clone, Copy)]
struct OpDelimitedIter<'a> {
inner: &'a [Op],
- delimited: tt::Delimiter<Span>,
+ delimited: tt::Delimiter,
idx: usize,
}
@@ -940,7 +945,7 @@ impl<'a> Iterator for OpDelimitedIter<'a> {
}
}
-fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) -> bool {
+fn expect_separator(iter: &mut TtIter<'_>, separator: &Separator) -> bool {
let mut fork = iter.clone();
let ok = match separator {
Separator::Ident(lhs) => match fork.expect_ident_or_underscore() {
@@ -949,8 +954,8 @@ fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) ->
},
Separator::Literal(lhs) => match fork.expect_literal() {
Ok(rhs) => match rhs {
- tt::Leaf::Literal(rhs) => rhs.symbol == lhs.symbol,
- tt::Leaf::Ident(rhs) => rhs.sym == lhs.symbol,
+ tt::Leaf::Literal(rhs) => rhs.text_and_suffix == lhs.text_and_suffix,
+ tt::Leaf::Ident(rhs) => rhs.sym == lhs.text_and_suffix,
tt::Leaf::Punct(_) => false,
},
Err(_) => false,
@@ -974,7 +979,7 @@ fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) ->
ok
}
-fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
+fn expect_tt(iter: &mut TtIter<'_>) -> Result<(), ()> {
if let Some(TtElement::Leaf(tt::Leaf::Punct(punct))) = iter.peek() {
if punct.char == '\'' {
expect_lifetime(iter)?;
@@ -987,7 +992,7 @@ fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
Ok(())
}
-fn expect_lifetime<'a, S: Copy>(iter: &mut TtIter<'a, S>) -> Result<&'a tt::Ident<S>, ()> {
+fn expect_lifetime<'a>(iter: &mut TtIter<'a>) -> Result<tt::Ident, ()> {
let punct = iter.expect_single_punct()?;
if punct.char != '\'' {
return Err(());
@@ -995,8 +1000,8 @@ fn expect_lifetime<'a, S: Copy>(iter: &mut TtIter<'a, S>) -> Result<&'a tt::Iden
iter.expect_ident_or_underscore()
}
-fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) {
- if matches!(iter.peek(), Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char, .. }))) if *char == c)
+fn eat_char(iter: &mut TtIter<'_>, c: char) {
+ if matches!(iter.peek(), Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char, .. }))) if char == c)
{
iter.next().expect("already peeked");
}