Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/parser.rs')
-rw-r--r--crates/mbe/src/parser.rs35
1 files changed, 24 insertions, 11 deletions
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index bbe00f0afc..5c499c06b1 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -1,11 +1,14 @@
//! Parser recognizes special macro syntax, `$var` and `$(repeat)*`, in token
//! trees.
-use smallvec::{smallvec, SmallVec};
+use std::sync::Arc;
+
+use arrayvec::ArrayVec;
use span::{Edition, Span, SyntaxContextId};
use syntax::SmolStr;
+use tt::iter::TtIter;
-use crate::{tt_iter::TtIter, ParseError};
+use crate::ParseError;
/// Consider
///
@@ -86,14 +89,14 @@ pub(crate) enum Op {
Repeat {
tokens: MetaTemplate,
kind: RepeatKind,
- separator: Option<Separator>,
+ separator: Option<Arc<Separator>>,
},
Subtree {
tokens: MetaTemplate,
delimiter: tt::Delimiter<Span>,
},
Literal(tt::Literal<Span>),
- Punct(SmallVec<[tt::Punct<Span>; 3]>),
+ Punct(Box<ArrayVec<tt::Punct<Span>, 3>>),
Ident(tt::Ident<Span>),
}
@@ -126,7 +129,7 @@ pub(crate) enum MetaVarKind {
pub(crate) enum Separator {
Literal(tt::Literal<Span>),
Ident(tt::Ident<Span>),
- Puncts(SmallVec<[tt::Punct<Span>; 3]>),
+ Puncts(ArrayVec<tt::Punct<Span>, 3>),
}
// Note that when we compare a Separator, we just care about its textual value.
@@ -165,7 +168,13 @@ fn next_op(
src.next().expect("first token already peeked");
// Note that the '$' itself is a valid token inside macro_rules.
let second = match src.next() {
- None => return Ok(Op::Punct(smallvec![*p])),
+ None => {
+ return Ok(Op::Punct({
+ let mut res = ArrayVec::new();
+ res.push(*p);
+ Box::new(res)
+ }))
+ }
Some(it) => it,
};
match second {
@@ -173,7 +182,7 @@ fn next_op(
tt::DelimiterKind::Parenthesis => {
let (separator, kind) = parse_repeat(src)?;
let tokens = MetaTemplate::parse(edition, subtree, mode, new_meta_vars)?;
- Op::Repeat { tokens, separator, kind }
+ Op::Repeat { tokens, separator: separator.map(Arc::new), kind }
}
tt::DelimiterKind::Brace => match mode {
Mode::Template => {
@@ -216,7 +225,11 @@ fn next_op(
"`$$` is not allowed on the pattern side",
))
}
- Mode::Template => Op::Punct(smallvec![*punct]),
+ Mode::Template => Op::Punct({
+ let mut res = ArrayVec::new();
+ res.push(*punct);
+ Box::new(res)
+ }),
},
tt::Leaf::Punct(_) | tt::Leaf::Literal(_) => {
return Err(ParseError::expected("expected ident"))
@@ -238,7 +251,7 @@ fn next_op(
tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => {
// There's at least one punct so this shouldn't fail.
let puncts = src.expect_glued_punct().unwrap();
- Op::Punct(puncts)
+ Op::Punct(Box::new(puncts))
}
tt::TokenTree::Subtree(subtree) => {
@@ -290,7 +303,7 @@ fn is_boolean_literal(lit: &tt::Literal<Span>) -> bool {
}
fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, RepeatKind), ParseError> {
- let mut separator = Separator::Puncts(SmallVec::new());
+ let mut separator = Separator::Puncts(ArrayVec::new());
for tt in src {
let tt = match tt {
tt::TokenTree::Leaf(leaf) => leaf,
@@ -312,7 +325,7 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
'+' => RepeatKind::OneOrMore,
'?' => RepeatKind::ZeroOrOne,
_ => match &mut separator {
- Separator::Puncts(puncts) if puncts.len() != 3 => {
+ Separator::Puncts(puncts) if puncts.len() < 3 => {
puncts.push(*punct);
continue;
}