aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs45
1 files changed, 23 insertions, 22 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 1b579f319..361b1e404 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -107,13 +107,19 @@ impl Bindings {
107 } 107 }
108 } 108 }
109 109
110 fn push_nested(&mut self, nested: Bindings) -> Result<(), ExpandError> { 110 fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> {
111 for (key, value) in nested.inner { 111 for (key, value) in nested.inner {
112 if !self.inner.contains_key(&key) { 112 if !self.inner.contains_key(&key) {
113 self.inner.insert(key.clone(), Binding::Nested(Vec::new())); 113 self.inner.insert(key.clone(), Binding::Nested(Vec::new()));
114 } 114 }
115 match self.inner.get_mut(&key) { 115 match self.inner.get_mut(&key) {
116 Some(Binding::Nested(it)) => it.push(value), 116 Some(Binding::Nested(it)) => {
117 // insert empty nested bindings before this one
118 while it.len() < idx {
119 it.push(Binding::Nested(vec![]));
120 }
121 it.push(value);
122 }
117 _ => { 123 _ => {
118 return Err(ExpandError::BindingError(format!( 124 return Err(ExpandError::BindingError(format!(
119 "could not find binding `{}`", 125 "could not find binding `{}`",
@@ -178,10 +184,6 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
178 input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone(); 184 input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone();
179 res.inner.insert(text.clone(), Binding::Simple(meta.into())); 185 res.inner.insert(text.clone(), Binding::Simple(meta.into()));
180 } 186 }
181 // FIXME:
182 // Enable followiing code when everything is fixed
183 // At least we can dogfood itself to not stackoverflow
184 //
185 "tt" => { 187 "tt" => {
186 let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone(); 188 let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone();
187 res.inner.insert(text.clone(), Binding::Simple(token.into())); 189 res.inner.insert(text.clone(), Binding::Simple(token.into()));
@@ -252,7 +254,6 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
252 loop { 254 loop {
253 match match_lhs(subtree, input) { 255 match match_lhs(subtree, input) {
254 Ok(nested) => { 256 Ok(nested) => {
255 counter += 1;
256 limit -= 1; 257 limit -= 1;
257 if limit == 0 { 258 if limit == 0 {
258 log::warn!("match_lhs excced in repeat pattern exceed limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", subtree, input, kind, separator); 259 log::warn!("match_lhs excced in repeat pattern exceed limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", subtree, input, kind, separator);
@@ -260,7 +261,8 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
260 } 261 }
261 262
262 memento = input.save(); 263 memento = input.save();
263 res.push_nested(nested)?; 264 res.push_nested(counter, nested)?;
265 counter += 1;
264 if counter == 1 { 266 if counter == 1 {
265 if let crate::RepeatKind::ZeroOrOne = kind { 267 if let crate::RepeatKind::ZeroOrOne = kind {
266 break; 268 break;
@@ -268,20 +270,9 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
268 } 270 }
269 271
270 if let Some(separator) = separator { 272 if let Some(separator) = separator {
271 use crate::Separator::*;
272
273 if !input 273 if !input
274 .eat_seperator() 274 .eat_seperator()
275 .map(|sep| match (sep, separator) { 275 .map(|sep| sep == *separator)
276 (Ident(ref a), Ident(ref b)) => a.text == b.text,
277 (Literal(ref a), Literal(ref b)) => a.text == b.text,
278 (Puncts(ref a), Puncts(ref b)) if a.len() == b.len() => {
279 let a_iter = a.iter().map(|a| a.char);
280 let b_iter = b.iter().map(|b| b.char);
281 a_iter.eq(b_iter)
282 }
283 _ => false,
284 })
285 .unwrap_or(false) 276 .unwrap_or(false)
286 { 277 {
287 input.rollback(memento); 278 input.rollback(memento);
@@ -372,14 +363,23 @@ fn expand_tt(
372 let mut has_seps = 0; 363 let mut has_seps = 0;
373 let mut counter = 0; 364 let mut counter = 0;
374 365
366 // We store the old var expanded value, and restore it later
367 // It is because before this `$repeat`,
368 // it is possible some variables already expanad in the same subtree
369 //
370 // `some_var_expanded` keep check if the deeper subtree has expanded variables
375 let mut some_var_expanded = false; 371 let mut some_var_expanded = false;
372 let old_var_expanded = ctx.var_expanded;
376 ctx.var_expanded = false; 373 ctx.var_expanded = false;
377 374
378 while let Ok(t) = expand_subtree(&repeat.subtree, ctx) { 375 while let Ok(t) = expand_subtree(&repeat.subtree, ctx) {
379 // if no var expaned in the child, we count it as a fail 376 // if no var expanded in the child, we count it as a fail
380 if !ctx.var_expanded { 377 if !ctx.var_expanded {
381 break; 378 break;
382 } 379 }
380
381 // Reset `ctx.var_expandeded` to see if there is other expanded variable
382 // in the next matching
383 some_var_expanded = true; 383 some_var_expanded = true;
384 ctx.var_expanded = false; 384 ctx.var_expanded = false;
385 385
@@ -423,7 +423,8 @@ fn expand_tt(
423 } 423 }
424 } 424 }
425 425
426 ctx.var_expanded = some_var_expanded; 426 // Restore the `var_expanded` by combining old one and the new one
427 ctx.var_expanded = some_var_expanded || old_var_expanded;
427 428
428 ctx.nesting.pop().unwrap(); 429 ctx.nesting.pop().unwrap();
429 for _ in 0..has_seps { 430 for _ in 0..has_seps {