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 | 72 |
1 files changed, 51 insertions, 21 deletions
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs index 5f1815304e..afdbbef231 100644 --- a/crates/mbe/src/parser.rs +++ b/crates/mbe/src/parser.rs @@ -25,23 +25,26 @@ pub(crate) struct MetaTemplate<S>(pub(crate) Box<[Op<S>]>); impl<S: Span> MetaTemplate<S> { pub(crate) fn parse_pattern(pattern: &tt::Subtree<S>) -> Result<Self, ParseError> { - MetaTemplate::parse(pattern, Mode::Pattern) + MetaTemplate::parse(pattern, Mode::Pattern, false) } - pub(crate) fn parse_template(template: &tt::Subtree<S>) -> Result<Self, ParseError> { - MetaTemplate::parse(template, Mode::Template) + pub(crate) fn parse_template( + template: &tt::Subtree<S>, + new_meta_vars: bool, + ) -> Result<Self, ParseError> { + MetaTemplate::parse(template, Mode::Template, new_meta_vars) } pub(crate) fn iter(&self) -> impl Iterator<Item = &Op<S>> { self.0.iter() } - fn parse(tt: &tt::Subtree<S>, mode: Mode) -> Result<Self, ParseError> { + fn parse(tt: &tt::Subtree<S>, mode: Mode, new_meta_vars: bool) -> Result<Self, ParseError> { let mut src = TtIter::new(tt); let mut res = Vec::new(); while let Some(first) = src.peek_n(0) { - let op = next_op(first, &mut src, mode)?; + let op = next_op(first, &mut src, mode, new_meta_vars)?; res.push(op); } @@ -51,13 +54,35 @@ impl<S: Span> MetaTemplate<S> { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum Op<S> { - Var { name: SmolStr, kind: Option<MetaVarKind>, id: S }, - Ignore { name: SmolStr, id: S }, - Index { depth: usize }, - Length { depth: usize }, - Count { name: SmolStr, depth: usize }, - Repeat { tokens: MetaTemplate<S>, kind: RepeatKind, separator: Option<Separator<S>> }, - Subtree { tokens: MetaTemplate<S>, delimiter: tt::Delimiter<S> }, + Var { + name: SmolStr, + kind: Option<MetaVarKind>, + id: S, + }, + Ignore { + name: SmolStr, + id: S, + }, + Index { + depth: usize, + }, + Length { + depth: usize, + }, + Count { + name: SmolStr, + // FIXME: `usize`` once we drop support for 1.76 + depth: Option<usize>, + }, + Repeat { + tokens: MetaTemplate<S>, + kind: RepeatKind, + separator: Option<Separator<S>>, + }, + Subtree { + tokens: MetaTemplate<S>, + delimiter: tt::Delimiter<S>, + }, Literal(tt::Literal<S>), Punct(SmallVec<[tt::Punct<S>; 3]>), Ident(tt::Ident<S>), @@ -123,6 +148,7 @@ fn next_op<S: Span>( first_peeked: &tt::TokenTree<S>, src: &mut TtIter<'_, S>, mode: Mode, + new_meta_vars: bool, ) -> Result<Op<S>, ParseError> { let res = match first_peeked { tt::TokenTree::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => { @@ -136,14 +162,14 @@ fn next_op<S: Span>( tt::TokenTree::Subtree(subtree) => match subtree.delimiter.kind { tt::DelimiterKind::Parenthesis => { let (separator, kind) = parse_repeat(src)?; - let tokens = MetaTemplate::parse(subtree, mode)?; + let tokens = MetaTemplate::parse(subtree, mode, new_meta_vars)?; Op::Repeat { tokens, separator, kind } } tt::DelimiterKind::Brace => match mode { Mode::Template => { - parse_metavar_expr(&mut TtIter::new(subtree)).map_err(|()| { - ParseError::unexpected("invalid metavariable expression") - })? + parse_metavar_expr(new_meta_vars, &mut TtIter::new(subtree)).map_err( + |()| ParseError::unexpected("invalid metavariable expression"), + )? } Mode::Pattern => { return Err(ParseError::unexpected( @@ -207,7 +233,7 @@ fn next_op<S: Span>( tt::TokenTree::Subtree(subtree) => { src.next().expect("first token already peeked"); - let tokens = MetaTemplate::parse(subtree, mode)?; + let tokens = MetaTemplate::parse(subtree, mode, new_meta_vars)?; Op::Subtree { tokens, delimiter: subtree.delimiter } } }; @@ -288,7 +314,7 @@ fn parse_repeat<S: Span>( Err(ParseError::InvalidRepeat) } -fn parse_metavar_expr<S: Span>(src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> { +fn parse_metavar_expr<S: Span>(new_meta_vars: bool, src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> { let func = src.expect_ident()?; let args = src.expect_subtree()?; @@ -300,16 +326,20 @@ fn parse_metavar_expr<S: Span>(src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> { let op = match &*func.text { "ignore" => { - args.expect_dollar()?; + if new_meta_vars { + args.expect_dollar()?; + } let ident = args.expect_ident()?; Op::Ignore { name: ident.text.clone(), id: ident.span } } "index" => Op::Index { depth: parse_depth(&mut args)? }, "length" => Op::Length { depth: parse_depth(&mut args)? }, "count" => { - args.expect_dollar()?; + if new_meta_vars { + args.expect_dollar()?; + } let ident = args.expect_ident()?; - let depth = if try_eat_comma(&mut args) { parse_depth(&mut args)? } else { 0 }; + let depth = if try_eat_comma(&mut args) { Some(parse_depth(&mut args)?) } else { None }; Op::Count { name: ident.text.clone(), depth } } _ => return Err(()), |