aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs67
-rw-r--r--crates/ra_mbe/src/tests.rs2
2 files changed, 37 insertions, 32 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 5fb8414b3..1328e4349 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -11,40 +11,45 @@ use rustc_hash::FxHashMap;
11use crate::{ExpandError, ExpandResult}; 11use crate::{ExpandError, ExpandResult};
12 12
13pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> ExpandResult<tt::Subtree> { 13pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> ExpandResult<tt::Subtree> {
14 let (mut result, mut unmatched_tokens, mut unmatched_patterns, mut err) = ( 14 expand_rules(&rules.rules, input)
15 tt::Subtree::default(), 15}
16 usize::max_value(), 16
17 usize::max_value(), 17fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::Subtree> {
18 Some(ExpandError::NoMatchingRule), 18 let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
19 ); 19 let mut err = Some(ExpandError::NoMatchingRule);
20 for rule in &rules.rules { 20 for rule in rules {
21 let ((res, tokens, patterns), e) = expand_rule(rule, input); 21 let (new_match, bindings_err) = matcher::match_(&rule.lhs, input);
22 if e.is_none() { 22 if bindings_err.is_none() {
23 // if we find a rule that applies without errors, we're done 23 // if we find a rule that applies without errors, we're done
24 return (res, None); 24 eprintln!("match without errors: {:?}", new_match);
25 let (res, transcribe_err) = transcriber::transcribe(&rule.rhs, &new_match.bindings);
26 eprintln!("transcribe_err = {:?}", transcribe_err);
27 if transcribe_err.is_none() {
28 return (res, None);
29 }
25 } 30 }
26 // use the rule if we matched more tokens, or had fewer patterns left 31 // use the rule if we matched more tokens, or had fewer patterns left
27 if tokens < unmatched_tokens || tokens == unmatched_tokens && patterns < unmatched_patterns 32 if let Some((prev_match, _)) = &match_ {
28 { 33 if new_match.unmatched_tokens < prev_match.unmatched_tokens
29 result = res; 34 || new_match.unmatched_tokens == prev_match.unmatched_tokens
30 err = e; 35 && new_match.unmatched_patterns < prev_match.unmatched_patterns
31 unmatched_tokens = tokens; 36 || err.is_some() && bindings_err.is_none()
32 unmatched_patterns = patterns; 37 {
38 match_ = Some((new_match, rule));
39 err = bindings_err;
40 }
41 } else {
42 match_ = Some((new_match, rule));
43 err = bindings_err;
33 } 44 }
34 } 45 }
35 (result, err) 46 if let Some((match_, rule)) = match_ {
36} 47 // if we got here, there was no match without errors
37 48 let (result, transcribe_err) = transcriber::transcribe(&rule.rhs, &match_.bindings);
38fn expand_rule( 49 (result, err.or(transcribe_err))
39 rule: &crate::Rule, 50 } else {
40 input: &tt::Subtree, 51 (tt::Subtree::default(), err)
41) -> ExpandResult<(tt::Subtree, usize, usize)> { 52 }
42 let (match_result, bindings_err) = matcher::match_(&rule.lhs, input);
43 let (res, transcribe_err) = transcriber::transcribe(&rule.rhs, &match_result.bindings);
44 (
45 (res, match_result.unmatched_tokens, match_result.unmatched_patterns),
46 bindings_err.or(transcribe_err),
47 )
48} 53}
49 54
50/// The actual algorithm for expansion is not too hard, but is pretty tricky. 55/// The actual algorithm for expansion is not too hard, but is pretty tricky.
@@ -167,7 +172,7 @@ mod tests {
167 let (invocation_tt, _) = 172 let (invocation_tt, _) =
168 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 173 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
169 174
170 let expanded = expand_rule(&rules.rules[0], &invocation_tt); 175 let expanded = expand_rules(&rules.rules, &invocation_tt);
171 ((expanded.0).0, expanded.1) 176 (expanded.0, expanded.1)
172 } 177 }
173} 178}
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 4d3140fa9..faf88c1b1 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -1663,5 +1663,5 @@ fn test_expand_bad_literal() {
1663 macro_rules! foo { ($i:literal) => {}; } 1663 macro_rules! foo { ($i:literal) => {}; }
1664 "#, 1664 "#,
1665 ) 1665 )
1666 .assert_expand_err(r#"foo!(&k");"#, &ExpandError::NoMatchingRule); 1666 .assert_expand_err(r#"foo!(&k");"#, &ExpandError::BindingError("".to_string()));
1667} 1667}