diff options
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 50 |
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 | |||
582 | fn 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 | |||
589 | fn 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 | } | ||