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.rs | 35 |
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; } |