diff options
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 67 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 2 |
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; | |||
11 | use crate::{ExpandError, ExpandResult}; | 11 | use crate::{ExpandError, ExpandResult}; |
12 | 12 | ||
13 | pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> ExpandResult<tt::Subtree> { | 13 | pub(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(), | 17 | fn 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); | |
38 | fn 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(¯o_invocation.token_tree().unwrap()).unwrap(); | 173 | ast_to_token_tree(¯o_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 | } |