summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/mbe/src/expander
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/mbe/src/expander')
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs41
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs74
2 files changed, 72 insertions, 43 deletions
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
index 88eae136f..f4ea9e5c8 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -67,6 +67,7 @@ use syntax::SmolStr;
use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
parser::{MetaVarKind, Op, RepeatKind, Separator},
+ tt,
tt_iter::TtIter,
ExpandError, MetaTemplate, ValueResult,
};
@@ -75,7 +76,8 @@ impl Bindings {
fn push_optional(&mut self, name: &SmolStr) {
// FIXME: Do we have a better way to represent an empty token ?
// Insert an empty subtree for empty token
- let tt = tt::Subtree::default().into();
+ let tt =
+ tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![] }.into();
self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
}
@@ -462,9 +464,9 @@ fn match_loop_inner<'t>(
}
OpDelimited::Op(Op::Subtree { tokens, delimiter }) => {
if let Ok(subtree) = src.clone().expect_subtree() {
- if subtree.delimiter_kind() == delimiter.map(|it| it.kind) {
+ if subtree.delimiter.kind == delimiter.kind {
item.stack.push(item.dot);
- item.dot = tokens.iter_delimited(delimiter.as_ref());
+ item.dot = tokens.iter_delimited(Some(delimiter));
cur_items.push(item);
}
}
@@ -663,8 +665,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
}
res.add_err(ExpandError::LeftoverTokens);
- if let Some(error_reover_item) = error_recover_item {
- res.bindings = bindings_builder.build(&error_reover_item);
+ if let Some(error_recover_item) = error_recover_item {
+ res.bindings = bindings_builder.build(&error_recover_item);
}
return res;
}
@@ -782,7 +784,7 @@ fn match_meta_var(kind: MetaVarKind, input: &mut TtIter<'_>) -> ExpandResult<Opt
match neg {
None => lit.into(),
Some(neg) => tt::TokenTree::Subtree(tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::unspecified(),
token_trees: vec![neg, lit.into()],
}),
}
@@ -810,7 +812,11 @@ fn collect_vars(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate)
}
impl MetaTemplate {
fn iter_delimited<'a>(&'a self, delimited: Option<&'a tt::Delimiter>) -> OpDelimitedIter<'a> {
- OpDelimitedIter { inner: &self.0, idx: 0, delimited }
+ OpDelimitedIter {
+ inner: &self.0,
+ idx: 0,
+ delimited: delimited.unwrap_or(&tt::Delimiter::UNSPECIFIED),
+ }
}
}
@@ -824,20 +830,21 @@ enum OpDelimited<'a> {
#[derive(Debug, Clone, Copy)]
struct OpDelimitedIter<'a> {
inner: &'a [Op],
- delimited: Option<&'a tt::Delimiter>,
+ delimited: &'a tt::Delimiter,
idx: usize,
}
impl<'a> OpDelimitedIter<'a> {
fn is_eof(&self) -> bool {
- let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
+ let len = self.inner.len()
+ + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
self.idx >= len
}
fn peek(&self) -> Option<OpDelimited<'a>> {
- match self.delimited {
- None => self.inner.get(self.idx).map(OpDelimited::Op),
- Some(_) => match self.idx {
+ match self.delimited.kind {
+ tt::DelimiterKind::Invisible => self.inner.get(self.idx).map(OpDelimited::Op),
+ _ => match self.idx {
0 => Some(OpDelimited::Open),
i if i == self.inner.len() + 1 => Some(OpDelimited::Close),
i => self.inner.get(i - 1).map(OpDelimited::Op),
@@ -860,7 +867,8 @@ impl<'a> Iterator for OpDelimitedIter<'a> {
}
fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
+ let len = self.inner.len()
+ + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
let remain = len.saturating_sub(self.idx);
(remain, Some(remain))
}
@@ -904,7 +912,10 @@ impl<'a> TtIter<'a> {
} else {
let puncts = self.expect_glued_punct()?;
let token_trees = puncts.into_iter().map(|p| tt::Leaf::Punct(p).into()).collect();
- Ok(tt::TokenTree::Subtree(tt::Subtree { delimiter: None, token_trees }))
+ Ok(tt::TokenTree::Subtree(tt::Subtree {
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees,
+ }))
}
} else {
self.next().ok_or(()).cloned()
@@ -919,7 +930,7 @@ impl<'a> TtIter<'a> {
let ident = self.expect_ident_or_underscore()?;
Ok(tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::unspecified(),
token_trees: vec![
tt::Leaf::Punct(*punct).into(),
tt::Leaf::Ident(ident.clone()).into(),
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
index db0d327bf..dffb40d4b 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -2,11 +2,11 @@
//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
use syntax::SmolStr;
-use tt::{Delimiter, Subtree};
use crate::{
expander::{Binding, Bindings, Fragment},
parser::{MetaVarKind, Op, RepeatKind, Separator},
+ tt::{self, Delimiter},
ExpandError, ExpandResult, MetaTemplate,
};
@@ -44,22 +44,23 @@ impl Bindings {
Binding::Missing(it) => Ok(match it {
MetaVarKind::Stmt => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
char: ';',
spacing: tt::Spacing::Alone,
})))
}
MetaVarKind::Block => Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
kind: tt::DelimiterKind::Brace,
- }),
+ },
token_trees: vec![],
})),
// FIXME: Meta and Item should get proper defaults
MetaVarKind::Meta | MetaVarKind::Item | MetaVarKind::Tt | MetaVarKind::Vis => {
Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::UNSPECIFIED,
token_trees: vec![],
}))
}
@@ -71,19 +72,19 @@ impl Bindings {
| MetaVarKind::Ident => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: SmolStr::new_inline("missing"),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})))
}
MetaVarKind::Lifetime => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: SmolStr::new_inline("'missing"),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})))
}
MetaVarKind::Literal => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: SmolStr::new_inline("\"missing\""),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})))
}
}),
@@ -138,12 +139,12 @@ fn expand_subtree(
Op::Ident(it) => arena.push(tt::Leaf::from(it.clone()).into()),
Op::Punct(puncts) => {
for punct in puncts {
- arena.push(tt::Leaf::from(punct.clone()).into());
+ arena.push(tt::Leaf::from(*punct).into());
}
}
Op::Subtree { tokens, delimiter } => {
let ExpandResult { value: tt, err: e } =
- expand_subtree(ctx, tokens, *delimiter, arena);
+ expand_subtree(ctx, tokens, Some(*delimiter), arena);
err = err.or(e);
arena.push(tt.into());
}
@@ -170,7 +171,7 @@ fn expand_subtree(
arena.push(
tt::Leaf::Literal(tt::Literal {
text: index.to_string().into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})
.into(),
);
@@ -179,7 +180,13 @@ fn expand_subtree(
}
// drain the elements added in this instance of expand_subtree
let tts = arena.drain(start_elements..).collect();
- ExpandResult { value: tt::Subtree { delimiter, token_trees: tts }, err }
+ ExpandResult {
+ value: tt::Subtree {
+ delimiter: delimiter.unwrap_or_else(tt::Delimiter::unspecified),
+ token_trees: tts,
+ },
+ err,
+ }
}
fn expand_var(ctx: &mut ExpandCtx<'_>, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
@@ -201,18 +208,25 @@ fn expand_var(ctx: &mut ExpandCtx<'_>, v: &SmolStr, id: tt::TokenId) -> ExpandRe
// ```
// We just treat it a normal tokens
let tt = tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::UNSPECIFIED,
token_trees: vec![
- tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
- tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
+ tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id })
+ .into(),
+ tt::Leaf::from(tt::Ident { text: v.clone(), span: id }).into(),
],
}
.into();
ExpandResult::ok(Fragment::Tokens(tt))
} else {
ctx.bindings.get(v, &mut ctx.nesting).map_or_else(
- |e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
- |it| ExpandResult::ok(it),
+ |e| ExpandResult {
+ value: Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees: vec![],
+ })),
+ err: Some(e),
+ },
+ ExpandResult::ok,
)
}
}
@@ -249,7 +263,10 @@ fn expand_repeat(
ctx
);
return ExpandResult {
- value: Fragment::Tokens(Subtree::default().into()),
+ value: Fragment::Tokens(
+ tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![] }
+ .into(),
+ ),
err: Some(ExpandError::LimitExceeded),
};
}
@@ -258,7 +275,7 @@ fn expand_repeat(
continue;
}
- t.delimiter = None;
+ t.delimiter = tt::Delimiter::unspecified();
push_subtree(&mut buf, t);
if let Some(sep) = separator {
@@ -292,7 +309,7 @@ fn expand_repeat(
// Check if it is a single token subtree without any delimiter
// e.g {Delimiter:None> ['>'] /Delimiter:None>}
- let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
+ let tt = tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: buf }.into();
if RepeatKind::OneOrMore == kind && counter == 0 {
return ExpandResult {
@@ -307,11 +324,12 @@ fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
match fragment {
Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
Fragment::Expr(tt::TokenTree::Subtree(mut tt)) => {
- if tt.delimiter.is_none() {
- tt.delimiter = Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ if tt.delimiter.kind == tt::DelimiterKind::Invisible {
+ tt.delimiter = tt::Delimiter {
+ open: tt::TokenId::UNSPECIFIED,
+ close: tt::TokenId::UNSPECIFIED,
kind: tt::DelimiterKind::Parenthesis,
- })
+ };
}
buf.push(tt.into())
}
@@ -320,8 +338,8 @@ fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
}
fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
- match tt.delimiter {
- None => buf.extend(tt.token_trees),
- Some(_) => buf.push(tt.into()),
+ match tt.delimiter.kind {
+ tt::DelimiterKind::Invisible => buf.extend(tt.token_trees),
+ _ => buf.push(tt.into()),
}
}