}
impl Match {
- pub(super) fn add_err(&mut self, err: ExpandError) {
+ fn add_err(&mut self, err: ExpandError) {
let prev_err = self.err.take();
self.err = prev_err.or(Some(err));
self.err_count += 1;
/// Matching errors are added to the `Match`.
pub(super) fn match_(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
- assert!(pattern.delimiter == None);
-
let mut res = Match::default();
let mut src = TtIter::new(src);
- match_subtree(&mut res, pattern, &mut src);
+ match_tokens(&mut res, pattern, &mut src);
if src.len() > 0 {
res.unmatched_tts += src.len();
res
}
-fn match_subtree(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) {
+fn match_tokens(res: &mut Match, pattern: &MetaTemplate, src: &mut TtIter) {
for op in pattern.iter() {
match op {
Op::Leaf(lhs) => {
- let rhs = match src.expect_leaf() {
- Ok(l) => l,
- Err(()) => {
- res.add_err(err!("expected leaf: `{}`", lhs));
- continue;
- }
- };
- match (lhs, rhs) {
- (
- tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
- tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
- ) if lhs == rhs => (),
- (
- tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
- tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
- ) if lhs == rhs => (),
- (
- tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
- tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
- ) if lhs == rhs => (),
- _ => {
- res.add_err(ExpandError::UnexpectedToken);
- }
+ if let Err(err) = match_leaf(lhs, src) {
+ res.add_err(err);
+ continue;
}
}
- Op::Subtree(lhs) => {
+ Op::Subtree { tokens, delimiter: delim } => {
let rhs = match src.expect_subtree() {
Ok(s) => s,
Err(()) => {
continue;
}
};
- if lhs.delimiter_kind() != rhs.delimiter_kind() {
+ if delim.map(|it| it.kind) != rhs.delimiter_kind() {
res.add_err(err!("mismatched delimiter"));
continue;
}
let mut src = TtIter::new(rhs);
- match_subtree(res, lhs, &mut src);
+ match_tokens(res, tokens, &mut src);
if src.len() > 0 {
res.add_err(err!("leftover tokens"));
}
res.add_err(err);
}
}
- Op::Repeat { subtree, kind, separator } => {
+ Op::Repeat { tokens: subtree, kind, separator } => {
match_repeat(res, subtree, *kind, separator, src);
}
}
}
}
-pub(super) fn match_repeat(
+fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter) -> Result<(), ExpandError> {
+ let rhs = match src.expect_leaf() {
+ Ok(l) => l,
+ Err(()) => {
+ return Err(err!("expected leaf: `{}`", lhs));
+ }
+ };
+ match (lhs, rhs) {
+ (
+ tt::Leaf::Punct(tt::Punct { char: lhs, .. }),
+ tt::Leaf::Punct(tt::Punct { char: rhs, .. }),
+ ) if lhs == rhs => (),
+ (
+ tt::Leaf::Ident(tt::Ident { text: lhs, .. }),
+ tt::Leaf::Ident(tt::Ident { text: rhs, .. }),
+ ) if lhs == rhs => (),
+ (
+ tt::Leaf::Literal(tt::Literal { text: lhs, .. }),
+ tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
+ ) if lhs == rhs => (),
+ _ => {
+ return Err(ExpandError::UnexpectedToken);
+ }
+ }
+
+ Ok(())
+}
+
+fn match_repeat(
res: &mut Match,
pattern: &MetaTemplate,
kind: RepeatKind,
}
let mut nested = Match::default();
- match_subtree(&mut nested, pattern, &mut fork);
+ match_tokens(&mut nested, pattern, &mut fork);
if nested.err.is_none() {
limit -= 1;
if limit == 0 {
match op {
Op::Var { name, .. } => buf.push(name.clone()),
Op::Leaf(_) => (),
- Op::Subtree(subtree) => collect_vars(buf, subtree),
- Op::Repeat { subtree, .. } => collect_vars(buf, subtree),
+ Op::Subtree { tokens, .. } => collect_vars(buf, tokens),
+ Op::Repeat { tokens, .. } => collect_vars(buf, tokens),
}
}
}
ok
}
- pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
+ fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> {
match self.peek_n(0) {
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => {
return self.expect_lifetime();
}
}
- pub(crate) fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> {
+ fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> {
let punct = self.expect_punct()?;
if punct.char != '\'' {
return Err(());
.into())
}
- pub(crate) fn expect_fragment(
+ fn expect_fragment(
&mut self,
fragment_kind: parser::FragmentKind,
) -> ExpandResult<Option<tt::TokenTree>> {
- pub(crate) struct OffsetTokenSink<'a> {
- pub(crate) cursor: Cursor<'a>,
- pub(crate) error: bool,
+ struct OffsetTokenSink<'a> {
+ cursor: Cursor<'a>,
+ error: bool,
}
impl<'a> TreeSink for OffsetTokenSink<'a> {
ExpandResult { value: res, err }
}
- pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
+ fn eat_vis(&mut self) -> Option<tt::TokenTree> {
let mut fork = self.clone();
match fork.expect_fragment(Visibility) {
ExpandResult { value: tt, err: None } => {
}
}
- pub(crate) fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> {
+ fn eat_char(&mut self, c: char) -> Option<tt::TokenTree> {
let mut fork = self.clone();
match fork.expect_char(c) {
Ok(_) => {
//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
use syntax::SmolStr;
+use tt::Delimiter;
use super::ExpandResult;
use crate::{
template: &MetaTemplate,
bindings: &Bindings,
) -> ExpandResult<tt::Subtree> {
- assert!(template.delimiter == None);
let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
let mut arena: Vec<tt::TokenTree> = Vec::new();
- expand_subtree(&mut ctx, template, &mut arena)
+ expand_subtree(&mut ctx, template, None, &mut arena)
}
#[derive(Debug)]
fn expand_subtree(
ctx: &mut ExpandCtx,
template: &MetaTemplate,
+ delimiter: Option<Delimiter>,
arena: &mut Vec<tt::TokenTree>,
) -> ExpandResult<tt::Subtree> {
// remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
for op in template.iter() {
match op {
Op::Leaf(tt) => arena.push(tt.clone().into()),
- Op::Subtree(tt) => {
- let ExpandResult { value: tt, err: e } = expand_subtree(ctx, &tt, arena);
+ Op::Subtree { tokens, delimiter } => {
+ let ExpandResult { value: tt, err: e } =
+ expand_subtree(ctx, &tokens, *delimiter, arena);
err = err.or(e);
arena.push(tt.into());
}
err = err.or(e);
push_fragment(arena, fragment);
}
- Op::Repeat { subtree, kind, separator } => {
+ Op::Repeat { tokens: subtree, kind, separator } => {
let ExpandResult { value: fragment, err: e } =
expand_repeat(ctx, subtree, *kind, separator, arena);
err = err.or(e);
}
// drain the elements added in this instance of expand_subtree
let tts = arena.drain(start_elements..arena.len()).collect();
- ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err }
+ ExpandResult { value: tt::Subtree { delimiter, token_trees: tts }, err }
}
fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
let mut counter = 0;
loop {
- let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, arena);
+ let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, None, arena);
let nesting_state = ctx.nesting.last_mut().unwrap();
if nesting_state.at_end || !nesting_state.hit {
break;
}
#[derive(Clone, Debug, PartialEq, Eq)]
-struct MetaTemplate {
- delimiter: Option<Delimiter>,
- tokens: Vec<Op>,
-}
+struct MetaTemplate(Vec<Op>);
impl<'a> MetaTemplate {
fn iter(&self) -> impl Iterator<Item = &Op> {
- self.tokens.iter()
- }
-
- fn delimiter_kind(&self) -> Option<DelimiterKind> {
- self.delimiter.map(|it| it.kind)
+ self.0.iter()
}
}
.expect_subtree()
.map_err(|()| ParseError::Expected("expected subtree".to_string()))?;
- let lhs = MetaTemplate { tokens: parse_pattern(&lhs)?, delimiter: None };
- let rhs = MetaTemplate { tokens: parse_template(&rhs)?, delimiter: None };
+ let lhs = MetaTemplate(parse_pattern(&lhs)?);
+ let rhs = MetaTemplate(parse_template(&rhs)?);
Ok(crate::Rule { lhs, rhs })
}
fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
for op in pattern.iter() {
match op {
- Op::Subtree(subtree) => validate(&subtree)?,
- Op::Repeat { subtree, separator, .. } => {
+ Op::Subtree { tokens, .. } => validate(&tokens)?,
+ Op::Repeat { tokens: subtree, separator, .. } => {
// Checks that no repetition which could match an empty token
// https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
)
}
Op::Leaf(_) => {}
- Op::Subtree(_) => {}
+ Op::Subtree { .. } => {}
}
false
}) {
use smallvec::SmallVec;
use syntax::SmolStr;
+use tt::Delimiter;
use crate::{tt_iter::TtIter, MetaTemplate, ParseError};
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum Op {
Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
- Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
+ Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
Leaf(tt::Leaf),
- Subtree(MetaTemplate),
+ Subtree { tokens: MetaTemplate, delimiter: Option<Delimiter> },
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
match second {
tt::TokenTree::Subtree(subtree) => {
let (separator, kind) = parse_repeat(src)?;
- let delimiter = subtree.delimiter;
let tokens = parse_inner(&subtree, mode)
.into_iter()
.collect::<Result<Vec<Op>, ParseError>>()?;
- let subtree = MetaTemplate { tokens, delimiter };
- Op::Repeat { subtree, separator, kind }
+ Op::Repeat { tokens: MetaTemplate(tokens), separator, kind }
}
tt::TokenTree::Leaf(leaf) => match leaf {
tt::Leaf::Punct(punct) => {
}
tt::TokenTree::Leaf(tt) => Op::Leaf(tt.clone()),
tt::TokenTree::Subtree(subtree) => {
- let delimiter = subtree.delimiter;
let tokens =
parse_inner(&subtree, mode).into_iter().collect::<Result<Vec<Op>, ParseError>>()?;
-
- let subtree = MetaTemplate { tokens, delimiter };
- Op::Subtree(subtree)
+ Op::Subtree { tokens: MetaTemplate(tokens), delimiter: subtree.delimiter }
}
};
Ok(res)