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.rs88
1 files changed, 43 insertions, 45 deletions
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index b55edf4a5e..16d55492a0 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
use arrayvec::ArrayVec;
use intern::{sym, Symbol};
use span::{Edition, Span, SyntaxContextId};
-use tt::iter::TtIter;
+use tt::iter::{TtElement, TtIter};
use crate::ParseError;
@@ -29,14 +29,14 @@ pub(crate) struct MetaTemplate(pub(crate) Box<[Op]>);
impl MetaTemplate {
pub(crate) fn parse_pattern(
edition: impl Copy + Fn(SyntaxContextId) -> Edition,
- pattern: &tt::Subtree<Span>,
+ pattern: TtIter<'_, Span>,
) -> Result<Self, ParseError> {
MetaTemplate::parse(edition, pattern, Mode::Pattern)
}
pub(crate) fn parse_template(
edition: impl Copy + Fn(SyntaxContextId) -> Edition,
- template: &tt::Subtree<Span>,
+ template: TtIter<'_, Span>,
) -> Result<Self, ParseError> {
MetaTemplate::parse(edition, template, Mode::Template)
}
@@ -47,13 +47,11 @@ impl MetaTemplate {
fn parse(
edition: impl Copy + Fn(SyntaxContextId) -> Edition,
- tt: &tt::Subtree<Span>,
+ mut src: TtIter<'_, Span>,
mode: Mode,
) -> Result<Self, ParseError> {
- let mut src = TtIter::new(tt);
-
let mut res = Vec::new();
- while let Some(first) = src.peek_n(0) {
+ while let Some(first) = src.peek() {
let op = next_op(edition, first, &mut src, mode)?;
res.push(op);
}
@@ -182,12 +180,12 @@ enum Mode {
fn next_op(
edition: impl Copy + Fn(SyntaxContextId) -> Edition,
- first_peeked: &tt::TokenTree<Span>,
+ first_peeked: TtElement<'_, Span>,
src: &mut TtIter<'_, Span>,
mode: Mode,
) -> Result<Op, ParseError> {
let res = match first_peeked {
- tt::TokenTree::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => {
+ TtElement::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => {
src.next().expect("first token already peeked");
// Note that the '$' itself is a valid token inside macro_rules.
let second = match src.next() {
@@ -201,18 +199,16 @@ fn next_op(
Some(it) => it,
};
match second {
- tt::TokenTree::Subtree(subtree) => match subtree.delimiter.kind {
+ TtElement::Subtree(subtree, mut subtree_iter) => match subtree.delimiter.kind {
tt::DelimiterKind::Parenthesis => {
let (separator, kind) = parse_repeat(src)?;
- let tokens = MetaTemplate::parse(edition, subtree, mode)?;
+ let tokens = MetaTemplate::parse(edition, subtree_iter, mode)?;
Op::Repeat { tokens, separator: separator.map(Arc::new), kind }
}
tt::DelimiterKind::Brace => match mode {
- Mode::Template => {
- parse_metavar_expr(&mut TtIter::new(subtree)).map_err(|()| {
- ParseError::unexpected("invalid metavariable expression")
- })?
- }
+ Mode::Template => parse_metavar_expr(&mut subtree_iter).map_err(|()| {
+ ParseError::unexpected("invalid metavariable expression")
+ })?,
Mode::Pattern => {
return Err(ParseError::unexpected(
"`${}` metavariable expressions are not allowed in matchers",
@@ -225,7 +221,7 @@ fn next_op(
))
}
},
- tt::TokenTree::Leaf(leaf) => match leaf {
+ TtElement::Leaf(leaf) => match leaf {
tt::Leaf::Ident(ident) if ident.sym == sym::crate_ => {
// We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
Op::Ident(tt::Ident {
@@ -265,25 +261,25 @@ fn next_op(
}
}
- tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => {
+ TtElement::Leaf(tt::Leaf::Literal(it)) => {
src.next().expect("first token already peeked");
Op::Literal(it.clone())
}
- tt::TokenTree::Leaf(tt::Leaf::Ident(it)) => {
+ TtElement::Leaf(tt::Leaf::Ident(it)) => {
src.next().expect("first token already peeked");
Op::Ident(it.clone())
}
- tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => {
+ TtElement::Leaf(tt::Leaf::Punct(_)) => {
// There's at least one punct so this shouldn't fail.
let puncts = src.expect_glued_punct().unwrap();
Op::Punct(Box::new(puncts))
}
- tt::TokenTree::Subtree(subtree) => {
+ TtElement::Subtree(subtree, subtree_iter) => {
src.next().expect("first token already peeked");
- let tokens = MetaTemplate::parse(edition, subtree, mode)?;
+ let tokens = MetaTemplate::parse(edition, subtree_iter, mode)?;
Op::Subtree { tokens, delimiter: subtree.delimiter }
}
};
@@ -343,8 +339,8 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
let mut separator = Separator::Puncts(ArrayVec::new());
for tt in src {
let tt = match tt {
- tt::TokenTree::Leaf(leaf) => leaf,
- tt::TokenTree::Subtree(_) => return Err(ParseError::InvalidRepeat),
+ TtElement::Leaf(leaf) => leaf,
+ TtElement::Subtree(..) => return Err(ParseError::InvalidRepeat),
};
let has_sep = match &separator {
Separator::Puncts(puncts) => !puncts.is_empty(),
@@ -378,37 +374,39 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
let func = src.expect_ident()?;
- let args = src.expect_subtree()?;
+ let (args, mut args_iter) = src.expect_subtree()?;
if args.delimiter.kind != tt::DelimiterKind::Parenthesis {
return Err(());
}
- let mut args = TtIter::new(args);
-
let op = match &func.sym {
s if sym::ignore == *s => {
- args.expect_dollar()?;
- let ident = args.expect_ident()?;
+ args_iter.expect_dollar()?;
+ let ident = args_iter.expect_ident()?;
Op::Ignore { name: ident.sym.clone(), id: ident.span }
}
- s if sym::index == *s => Op::Index { depth: parse_depth(&mut args)? },
- s if sym::len == *s => Op::Len { depth: parse_depth(&mut args)? },
+ s if sym::index == *s => Op::Index { depth: parse_depth(&mut args_iter)? },
+ s if sym::len == *s => Op::Len { depth: parse_depth(&mut args_iter)? },
s if sym::count == *s => {
- args.expect_dollar()?;
- let ident = args.expect_ident()?;
- let depth = if try_eat_comma(&mut args) { Some(parse_depth(&mut args)?) } else { None };
+ args_iter.expect_dollar()?;
+ let ident = args_iter.expect_ident()?;
+ let depth = if try_eat_comma(&mut args_iter) {
+ Some(parse_depth(&mut args_iter)?)
+ } else {
+ None
+ };
Op::Count { name: ident.sym.clone(), depth }
}
s if sym::concat == *s => {
let mut elements = Vec::new();
- while let Some(next) = args.peek_n(0) {
- let element = if let tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) = next {
- args.next().expect("already peeked");
+ while let Some(next) = args_iter.peek() {
+ let element = if let TtElement::Leaf(tt::Leaf::Literal(lit)) = next {
+ args_iter.next().expect("already peeked");
ConcatMetaVarExprElem::Literal(lit.clone())
} else {
- let is_var = try_eat_dollar(&mut args);
- let ident = args.expect_ident_or_underscore()?.clone();
+ let is_var = try_eat_dollar(&mut args_iter);
+ let ident = args_iter.expect_ident_or_underscore()?.clone();
if is_var {
ConcatMetaVarExprElem::Var(ident)
@@ -417,8 +415,8 @@ fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
}
};
elements.push(element);
- if args.peek_n(0).is_some() {
- args.expect_comma()?;
+ if !args_iter.is_empty() {
+ args_iter.expect_comma()?;
}
}
if elements.len() < 2 {
@@ -429,7 +427,7 @@ fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
_ => return Err(()),
};
- if args.next().is_some() {
+ if args_iter.next().is_some() {
return Err(());
}
@@ -437,7 +435,7 @@ fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
}
fn parse_depth(src: &mut TtIter<'_, Span>) -> Result<usize, ()> {
- if src.len() == 0 {
+ if src.is_empty() {
Ok(0)
} else if let tt::Leaf::Literal(tt::Literal { symbol: text, suffix: None, .. }) =
src.expect_literal()?
@@ -450,7 +448,7 @@ fn parse_depth(src: &mut TtIter<'_, Span>) -> Result<usize, ()> {
}
fn try_eat_comma(src: &mut TtIter<'_, Span>) -> bool {
- if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))) = src.peek_n(0) {
+ if let Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))) = src.peek() {
let _ = src.next();
return true;
}
@@ -458,7 +456,7 @@ fn try_eat_comma(src: &mut TtIter<'_, Span>) -> bool {
}
fn try_eat_dollar(src: &mut TtIter<'_, Span>) -> bool {
- if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '$', .. }))) = src.peek_n(0) {
+ if let Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char: '$', .. }))) = src.peek() {
let _ = src.next();
return true;
}