From 299d97b6d98cec673ff056c188ac45a17febc7d4 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 24 Apr 2019 23:01:32 +0800 Subject: Add handling `token` seperator in mbe --- crates/ra_mbe/src/mbe_expander.rs | 49 +++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'crates/ra_mbe/src/mbe_expander.rs') diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 91b6db522..7411dd8b1 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs @@ -196,6 +196,7 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result { let literal = input.eat_literal().ok_or(ExpandError::UnexpectedToken)?.clone(); + res.inner.insert( text.clone(), Binding::Simple(tt::Leaf::from(literal).into()), @@ -210,7 +211,7 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result { - if input.eat_punct() != Some(punct) { + if !input.eat_punct().map(|p| p.char == punct.char).unwrap_or(false) { return Err(ExpandError::UnexpectedToken); } } @@ -246,8 +247,23 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result a.text == b.text, + (Literal(ref a), Literal(ref b)) => a.text == b.text, + (Puncts(ref a), Puncts(ref b)) if a.len() == b.len() => { + let a_iter = a.iter().map(|a| a.char); + let b_iter = b.iter().map(|b| b.char); + a_iter.eq(b_iter) + } + _ => false, + }) + .unwrap_or(false) + { input.rollback(memento); break; } @@ -328,7 +344,7 @@ fn expand_tt( // Dirty hack to make macro-expansion terminate. // This should be replaced by a propper macro-by-example implementation let mut limit = 128; - let mut has_sep = false; + let mut has_seps = 0; while let Ok(t) = expand_subtree(&repeat.subtree, bindings, nesting) { limit -= 1; @@ -339,15 +355,28 @@ fn expand_tt( nesting.push(idx + 1); token_trees.push(reduce_single_token(t).into()); - if let Some(sep) = repeat.separator { - let punct = - tt::Leaf::from(tt::Punct { char: sep, spacing: tt::Spacing::Alone }); - token_trees.push(punct.into()); - has_sep = true; + if let Some(ref sep) = repeat.separator { + match sep { + crate::Separator::Ident(ident) => { + has_seps = 1; + token_trees.push(tt::Leaf::from(ident.clone()).into()); + } + crate::Separator::Literal(lit) => { + has_seps = 1; + token_trees.push(tt::Leaf::from(lit.clone()).into()); + } + + crate::Separator::Puncts(puncts) => { + has_seps = puncts.len(); + for punct in puncts { + token_trees.push(tt::Leaf::from(*punct).into()); + } + } + } } } nesting.pop().unwrap(); - if has_sep { + for _ in 0..has_seps { token_trees.pop(); } -- cgit v1.2.3