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.rs50
1 files changed, 28 insertions, 22 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 01641fdee..08b0519d2 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -339,21 +339,13 @@ fn expand_subtree(
339 template: &crate::Subtree, 339 template: &crate::Subtree,
340 ctx: &mut ExpandCtx, 340 ctx: &mut ExpandCtx,
341) -> Result<tt::Subtree, ExpandError> { 341) -> Result<tt::Subtree, ExpandError> {
342 let token_trees = template 342 let mut buf: Vec<tt::TokenTree> = Vec::new();
343 .token_trees 343 for tt in template.token_trees.iter() {
344 .iter() 344 let tt = expand_tt(tt, ctx)?;
345 .map(|it| expand_tt(it, ctx)) 345 push_tt(&mut buf, tt);
346 .filter(|it| { 346 }
347 // Filter empty subtree
348 if let Ok(tt::TokenTree::Subtree(subtree)) = it {
349 subtree.delimiter != tt::Delimiter::None || !subtree.token_trees.is_empty()
350 } else {
351 true
352 }
353 })
354 .collect::<Result<Vec<_>, ExpandError>>()?;
355 347
356 Ok(tt::Subtree { token_trees, delimiter: template.delimiter }) 348 Ok(tt::Subtree { delimiter: template.delimiter, token_trees: buf })
357} 349}
358 350
359/// Reduce single token subtree to single token 351/// Reduce single token subtree to single token
@@ -377,7 +369,7 @@ fn expand_tt(
377 let res: tt::TokenTree = match template { 369 let res: tt::TokenTree = match template {
378 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(), 370 crate::TokenTree::Subtree(subtree) => expand_subtree(subtree, ctx)?.into(),
379 crate::TokenTree::Repeat(repeat) => { 371 crate::TokenTree::Repeat(repeat) => {
380 let mut token_trees: Vec<tt::TokenTree> = Vec::new(); 372 let mut buf: Vec<tt::TokenTree> = Vec::new();
381 ctx.nesting.push(0); 373 ctx.nesting.push(0);
382 // Dirty hack to make macro-expansion terminate. 374 // Dirty hack to make macro-expansion terminate.
383 // This should be replaced by a propper macro-by-example implementation 375 // This should be replaced by a propper macro-by-example implementation
@@ -418,23 +410,23 @@ fn expand_tt(
418 410
419 let idx = ctx.nesting.pop().unwrap(); 411 let idx = ctx.nesting.pop().unwrap();
420 ctx.nesting.push(idx + 1); 412 ctx.nesting.push(idx + 1);
421 token_trees.push(reduce_single_token(t)); 413 push_subtree(&mut buf, t);
422 414
423 if let Some(ref sep) = repeat.separator { 415 if let Some(ref sep) = repeat.separator {
424 match sep { 416 match sep {
425 crate::Separator::Ident(ident) => { 417 crate::Separator::Ident(ident) => {
426 has_seps = 1; 418 has_seps = 1;
427 token_trees.push(tt::Leaf::from(ident.clone()).into()); 419 buf.push(tt::Leaf::from(ident.clone()).into());
428 } 420 }
429 crate::Separator::Literal(lit) => { 421 crate::Separator::Literal(lit) => {
430 has_seps = 1; 422 has_seps = 1;
431 token_trees.push(tt::Leaf::from(lit.clone()).into()); 423 buf.push(tt::Leaf::from(lit.clone()).into());
432 } 424 }
433 425
434 crate::Separator::Puncts(puncts) => { 426 crate::Separator::Puncts(puncts) => {
435 has_seps = puncts.len(); 427 has_seps = puncts.len();
436 for punct in puncts { 428 for punct in puncts {
437 token_trees.push(tt::Leaf::from(*punct).into()); 429 buf.push(tt::Leaf::from(*punct).into());
438 } 430 }
439 } 431 }
440 } 432 }
@@ -450,16 +442,16 @@ fn expand_tt(
450 442
451 ctx.nesting.pop().unwrap(); 443 ctx.nesting.pop().unwrap();
452 for _ in 0..has_seps { 444 for _ in 0..has_seps {
453 token_trees.pop(); 445 buf.pop();
454 } 446 }
455 447
456 if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 { 448 if crate::RepeatKind::OneOrMore == repeat.kind && counter == 0 {
457 return Err(ExpandError::UnexpectedToken); 449 return Err(ExpandError::UnexpectedToken);
458 } 450 }
459 451
460 // Check if it is a singel token subtree without any delimiter 452 // Check if it is a single token subtree without any delimiter
461 // e.g {Delimiter:None> ['>'] /Delimiter:None>} 453 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
462 reduce_single_token(tt::Subtree { token_trees, delimiter: tt::Delimiter::None }) 454 reduce_single_token(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: buf })
463 } 455 }
464 crate::TokenTree::Leaf(leaf) => match leaf { 456 crate::TokenTree::Leaf(leaf) => match leaf {
465 crate::Leaf::Ident(ident) => { 457 crate::Leaf::Ident(ident) => {
@@ -586,3 +578,17 @@ mod tests {
586 expand_rule(&rules.rules[0], &invocation_tt) 578 expand_rule(&rules.rules[0], &invocation_tt)
587 } 579 }
588} 580}
581
582fn push_tt(buf: &mut Vec<tt::TokenTree>, tt: tt::TokenTree) {
583 match tt {
584 tt::TokenTree::Subtree(tt) => push_subtree(buf, tt),
585 _ => buf.push(tt),
586 }
587}
588
589fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
590 match tt.delimiter {
591 tt::Delimiter::None => buf.extend(tt.token_trees),
592 _ => buf.push(tt.into()),
593 }
594}