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.rs169
1 files changed, 83 insertions, 86 deletions
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 0cec4e70da..b20d5579ca 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -59,17 +59,17 @@
//! eof: [a $( a )* a b ยท]
//! ```
-use std::rc::Rc;
+use std::{rc::Rc, sync::Arc};
use smallvec::{smallvec, SmallVec};
use span::{Edition, Span};
use syntax::SmolStr;
-use tt::DelimSpan;
+use tt::{iter::TtIter, DelimSpan};
use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
+ expect_fragment,
parser::{MetaVarKind, Op, RepeatKind, Separator},
- tt_iter::TtIter,
ExpandError, MetaTemplate, ValueResult,
};
@@ -315,7 +315,7 @@ struct MatchState<'t> {
up: Option<Box<MatchState<'t>>>,
/// The separator if we are in a repetition.
- sep: Option<Separator>,
+ sep: Option<Arc<Separator>>,
/// The KleeneOp of this sequence if we are in a repetition.
sep_kind: Option<RepeatKind>,
@@ -406,7 +406,7 @@ fn match_loop_inner<'t>(
if item.sep.is_some() && !item.sep_matched {
let sep = item.sep.as_ref().unwrap();
let mut fork = src.clone();
- if fork.expect_separator(sep) {
+ if expect_separator(&mut fork, sep) {
// HACK: here we use `meta_result` to pass `TtIter` back to caller because
// it might have been advanced multiple times. `ValueResult` is
// insignificant.
@@ -746,7 +746,7 @@ fn match_meta_var(
) -> ExpandResult<Option<Fragment>> {
let fragment = match kind {
MetaVarKind::Path => {
- return input.expect_fragment(parser::PrefixEntryPoint::Path, edition).map(|it| {
+ return expect_fragment(input, parser::PrefixEntryPoint::Path, edition).map(|it| {
it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
});
}
@@ -765,7 +765,7 @@ fn match_meta_var(
}
_ => {}
};
- return input.expect_fragment(parser::PrefixEntryPoint::Expr, edition).map(|tt| {
+ return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition).map(|tt| {
tt.map(|tt| match tt {
tt::TokenTree::Leaf(leaf) => tt::Subtree {
delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
@@ -787,14 +787,13 @@ fn match_meta_var(
.expect_ident()
.map(|ident| tt::Leaf::from(ident.clone()).into())
.map_err(|()| ExpandError::binding_error("expected ident")),
- MetaVarKind::Tt => input
- .expect_tt()
- .map_err(|()| ExpandError::binding_error("expected token tree")),
- MetaVarKind::Lifetime => input
- .expect_lifetime()
+ MetaVarKind::Tt => {
+ expect_tt(input).map_err(|()| ExpandError::binding_error("expected token tree"))
+ }
+ MetaVarKind::Lifetime => expect_lifetime(input)
.map_err(|()| ExpandError::binding_error("expected lifetime")),
MetaVarKind::Literal => {
- let neg = input.eat_char('-');
+ let neg = eat_char(input, '-');
input
.expect_literal()
.map(|literal| {
@@ -822,7 +821,7 @@ fn match_meta_var(
MetaVarKind::Item => parser::PrefixEntryPoint::Item,
MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
};
- input.expect_fragment(fragment, edition).map(|it| it.map(Fragment::Tokens))
+ expect_fragment(input, fragment, edition).map(|it| it.map(Fragment::Tokens))
}
fn collect_vars(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate) {
@@ -905,86 +904,84 @@ impl<'a> Iterator for OpDelimitedIter<'a> {
}
}
-impl TtIter<'_, Span> {
- fn expect_separator(&mut self, separator: &Separator) -> bool {
- let mut fork = self.clone();
- let ok = match separator {
- Separator::Ident(lhs) => match fork.expect_ident_or_underscore() {
- Ok(rhs) => rhs.text == lhs.text,
- Err(_) => false,
- },
- Separator::Literal(lhs) => match fork.expect_literal() {
- Ok(rhs) => match rhs {
- tt::Leaf::Literal(rhs) => rhs.text == lhs.text,
- tt::Leaf::Ident(rhs) => rhs.text == lhs.text,
- tt::Leaf::Punct(_) => false,
- },
- Err(_) => false,
+fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) -> bool {
+ let mut fork = iter.clone();
+ let ok = match separator {
+ Separator::Ident(lhs) => match fork.expect_ident_or_underscore() {
+ Ok(rhs) => rhs.text == lhs.text,
+ Err(_) => false,
+ },
+ Separator::Literal(lhs) => match fork.expect_literal() {
+ Ok(rhs) => match rhs {
+ tt::Leaf::Literal(rhs) => rhs.text == lhs.text,
+ tt::Leaf::Ident(rhs) => rhs.text == lhs.text,
+ tt::Leaf::Punct(_) => false,
},
- Separator::Puncts(lhs) => match fork.expect_glued_punct() {
- Ok(rhs) => {
- let lhs = lhs.iter().map(|it| it.char);
- let rhs = rhs.iter().map(|it| it.char);
- lhs.eq(rhs)
- }
- Err(_) => false,
- },
- };
- if ok {
- *self = fork;
- }
- ok
- }
-
- fn expect_tt(&mut self) -> Result<tt::TokenTree<Span>, ()> {
- if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = self.peek_n(0) {
- if punct.char == '\'' {
- self.expect_lifetime()
- } else {
- let puncts = self.expect_glued_punct()?;
- let delimiter = tt::Delimiter {
- open: puncts.first().unwrap().span,
- close: puncts.last().unwrap().span,
- kind: tt::DelimiterKind::Invisible,
- };
- let token_trees = puncts.into_iter().map(|p| tt::Leaf::Punct(p).into()).collect();
- Ok(tt::TokenTree::Subtree(tt::Subtree { delimiter, token_trees }))
+ Err(_) => false,
+ },
+ Separator::Puncts(lhs) => match fork.expect_glued_punct() {
+ Ok(rhs) => {
+ let lhs = lhs.iter().map(|it| it.char);
+ let rhs = rhs.iter().map(|it| it.char);
+ lhs.eq(rhs)
}
- } else {
- self.next().ok_or(()).cloned()
- }
+ Err(_) => false,
+ },
+ };
+ if ok {
+ *iter = fork;
}
+ ok
+}
- fn expect_lifetime(&mut self) -> Result<tt::TokenTree<Span>, ()> {
- let punct = self.expect_single_punct()?;
- if punct.char != '\'' {
- return Err(());
- }
- let ident = self.expect_ident_or_underscore()?;
-
- Ok(tt::Subtree {
- delimiter: tt::Delimiter {
- open: punct.span,
- close: ident.span,
+fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<tt::TokenTree<S>, ()> {
+ if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = iter.peek_n(0) {
+ if punct.char == '\'' {
+ expect_lifetime(iter)
+ } else {
+ let puncts = iter.expect_glued_punct()?;
+ let delimiter = tt::Delimiter {
+ open: puncts.first().unwrap().span,
+ close: puncts.last().unwrap().span,
kind: tt::DelimiterKind::Invisible,
- },
- token_trees: Box::new([
- tt::Leaf::Punct(*punct).into(),
- tt::Leaf::Ident(ident.clone()).into(),
- ]),
+ };
+ let token_trees = puncts.into_iter().map(|p| tt::Leaf::Punct(p).into()).collect();
+ Ok(tt::TokenTree::Subtree(tt::Subtree { delimiter, token_trees }))
}
- .into())
+ } else {
+ iter.next().ok_or(()).cloned()
}
+}
- fn eat_char(&mut self, c: char) -> Option<tt::TokenTree<Span>> {
- let mut fork = self.clone();
- match fork.expect_char(c) {
- Ok(_) => {
- let tt = self.next().cloned();
- *self = fork;
- tt
- }
- Err(_) => None,
+fn expect_lifetime<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<tt::TokenTree<S>, ()> {
+ let punct = iter.expect_single_punct()?;
+ if punct.char != '\'' {
+ return Err(());
+ }
+ let ident = iter.expect_ident_or_underscore()?;
+
+ Ok(tt::Subtree {
+ delimiter: tt::Delimiter {
+ open: punct.span,
+ close: ident.span,
+ kind: tt::DelimiterKind::Invisible,
+ },
+ token_trees: Box::new([
+ tt::Leaf::Punct(*punct).into(),
+ tt::Leaf::Ident(ident.clone()).into(),
+ ]),
+ }
+ .into())
+}
+
+fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) -> Option<tt::TokenTree<S>> {
+ let mut fork = iter.clone();
+ match fork.expect_char(c) {
+ Ok(_) => {
+ let tt = iter.next().cloned();
+ *iter = fork;
+ tt
}
+ Err(_) => None,
}
}