aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs22
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs112
2 files changed, 76 insertions, 58 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 3c00e3b64..7adb70d45 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -16,10 +16,15 @@ pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> ExpandRe
16 16
17fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::Subtree> { 17fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::Subtree> {
18 let mut match_: Option<(matcher::Match, &crate::Rule)> = None; 18 let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
19 let mut err = Some(ExpandError::NoMatchingRule);
20 for rule in rules { 19 for rule in rules {
21 let ExpandResult(new_match, bindings_err) = matcher::match_(&rule.lhs, input); 20 let new_match = match matcher::match_(&rule.lhs, input) {
22 if bindings_err.is_none() { 21 Ok(m) => m,
22 Err(_e) => {
23 // error in pattern parsing
24 continue;
25 }
26 };
27 if new_match.err.is_none() {
23 // If we find a rule that applies without errors, we're done. 28 // If we find a rule that applies without errors, we're done.
24 // Unconditionally returning the transcription here makes the 29 // Unconditionally returning the transcription here makes the
25 // `test_repeat_bad_var` test fail. 30 // `test_repeat_bad_var` test fail.
@@ -32,25 +37,22 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::
32 // Use the rule if we matched more tokens, or had fewer patterns left, 37 // Use the rule if we matched more tokens, or had fewer patterns left,
33 // or had no error 38 // or had no error
34 if let Some((prev_match, _)) = &match_ { 39 if let Some((prev_match, _)) = &match_ {
35 if (new_match.unmatched_tokens, new_match.unmatched_patterns) 40 if (new_match.unmatched_tts, new_match.err_count)
36 < (prev_match.unmatched_tokens, prev_match.unmatched_patterns) 41 < (prev_match.unmatched_tts, prev_match.err_count)
37 || err.is_some() && bindings_err.is_none()
38 { 42 {
39 match_ = Some((new_match, rule)); 43 match_ = Some((new_match, rule));
40 err = bindings_err;
41 } 44 }
42 } else { 45 } else {
43 match_ = Some((new_match, rule)); 46 match_ = Some((new_match, rule));
44 err = bindings_err;
45 } 47 }
46 } 48 }
47 if let Some((match_, rule)) = match_ { 49 if let Some((match_, rule)) = match_ {
48 // if we got here, there was no match without errors 50 // if we got here, there was no match without errors
49 let ExpandResult(result, transcribe_err) = 51 let ExpandResult(result, transcribe_err) =
50 transcriber::transcribe(&rule.rhs, &match_.bindings); 52 transcriber::transcribe(&rule.rhs, &match_.bindings);
51 ExpandResult(result, err.or(transcribe_err)) 53 ExpandResult(result, match_.err.or(transcribe_err))
52 } else { 54 } else {
53 ExpandResult(tt::Subtree::default(), err) 55 ExpandResult(tt::Subtree::default(), Some(ExpandError::NoMatchingRule))
54 } 56 }
55} 57}
56 58
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs
index 22fb5d74c..2579382da 100644
--- a/crates/ra_mbe/src/mbe_expander/matcher.rs
+++ b/crates/ra_mbe/src/mbe_expander/matcher.rs
@@ -62,24 +62,41 @@ macro_rules! err {
62#[derive(Debug, Default)] 62#[derive(Debug, Default)]
63pub(super) struct Match { 63pub(super) struct Match {
64 pub bindings: Bindings, 64 pub bindings: Bindings,
65 pub unmatched_tokens: usize, 65 /// We currently just keep the first error and count the rest to compare matches.
66 pub unmatched_patterns: usize, 66 pub err: Option<ExpandError>,
67 pub err_count: usize,
68 /// How many top-level token trees were left to match.
69 pub unmatched_tts: usize,
67} 70}
68 71
69pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult<Match> { 72impl Match {
73 pub fn add_err(&mut self, err: ExpandError) {
74 let prev_err = self.err.take();
75 self.err = prev_err.or(Some(err));
76 self.err_count += 1;
77 }
78}
79
80// General note: These functions have two channels to return errors, a `Result`
81// return value and the `&mut Match`. The returned Result is for pattern parsing
82// errors; if a branch of the macro definition doesn't parse, it doesn't make
83// sense to try using it. Matching errors are added to the `Match`. It might
84// make sense to make pattern parsing a separate step?
85
86pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Match, ExpandError> {
70 assert!(pattern.delimiter == None); 87 assert!(pattern.delimiter == None);
71 88
72 let mut res = Match::default(); 89 let mut res = Match::default();
73 let mut src = TtIter::new(src); 90 let mut src = TtIter::new(src);
74 91
75 let mut err = match_subtree(&mut res, pattern, &mut src).err(); 92 match_subtree(&mut res, pattern, &mut src)?;
76 93
77 res.unmatched_tokens += src.len(); 94 if src.len() > 0 {
78 if src.len() > 0 && err.is_none() { 95 res.unmatched_tts += src.len();
79 err = Some(err!("leftover tokens")); 96 res.add_err(err!("leftover tokens"));
80 } 97 }
81 98
82 ExpandResult(res, err) 99 Ok(res)
83} 100}
84 101
85fn match_subtree( 102fn match_subtree(
@@ -87,19 +104,13 @@ fn match_subtree(
87 pattern: &tt::Subtree, 104 pattern: &tt::Subtree,
88 src: &mut TtIter, 105 src: &mut TtIter,
89) -> Result<(), ExpandError> { 106) -> Result<(), ExpandError> {
90 let mut result = Ok(());
91 for op in parse_pattern(pattern) { 107 for op in parse_pattern(pattern) {
92 if result.is_err() {
93 // We're just going through the patterns to count how many we missed
94 res.unmatched_patterns += 1;
95 continue;
96 }
97 match op? { 108 match op? {
98 Op::TokenTree(tt::TokenTree::Leaf(lhs)) => { 109 Op::TokenTree(tt::TokenTree::Leaf(lhs)) => {
99 let rhs = match src.expect_leaf() { 110 let rhs = match src.expect_leaf() {
100 Ok(l) => l, 111 Ok(l) => l,
101 Err(()) => { 112 Err(()) => {
102 result = Err(err!("expected leaf: `{}`", lhs)); 113 res.add_err(err!("expected leaf: `{}`", lhs));
103 continue; 114 continue;
104 } 115 }
105 }; 116 };
@@ -117,7 +128,7 @@ fn match_subtree(
117 tt::Leaf::Literal(tt::Literal { text: rhs, .. }), 128 tt::Leaf::Literal(tt::Literal { text: rhs, .. }),
118 ) if lhs == rhs => (), 129 ) if lhs == rhs => (),
119 _ => { 130 _ => {
120 result = Err(ExpandError::UnexpectedToken); 131 res.add_err(ExpandError::UnexpectedToken);
121 } 132 }
122 } 133 }
123 } 134 }
@@ -125,26 +136,25 @@ fn match_subtree(
125 let rhs = match src.expect_subtree() { 136 let rhs = match src.expect_subtree() {
126 Ok(s) => s, 137 Ok(s) => s,
127 Err(()) => { 138 Err(()) => {
128 result = Err(err!("expected subtree")); 139 res.add_err(err!("expected subtree"));
129 continue; 140 continue;
130 } 141 }
131 }; 142 };
132 if lhs.delimiter_kind() != rhs.delimiter_kind() { 143 if lhs.delimiter_kind() != rhs.delimiter_kind() {
133 result = Err(err!("mismatched delimiter")); 144 res.add_err(err!("mismatched delimiter"));
134 continue; 145 continue;
135 } 146 }
136 let mut src = TtIter::new(rhs); 147 let mut src = TtIter::new(rhs);
137 result = match_subtree(res, lhs, &mut src); 148 match_subtree(res, lhs, &mut src)?;
138 res.unmatched_tokens += src.len(); 149 if src.len() > 0 {
139 if src.len() > 0 && result.is_ok() { 150 res.add_err(err!("leftover tokens"));
140 result = Err(err!("leftover tokens"));
141 } 151 }
142 } 152 }
143 Op::Var { name, kind } => { 153 Op::Var { name, kind } => {
144 let kind = match kind { 154 let kind = match kind {
145 Some(k) => k, 155 Some(k) => k,
146 None => { 156 None => {
147 result = Err(ExpandError::UnexpectedToken); 157 res.add_err(ExpandError::UnexpectedToken);
148 continue; 158 continue;
149 } 159 }
150 }; 160 };
@@ -156,14 +166,16 @@ fn match_subtree(
156 None if match_err.is_none() => res.bindings.push_optional(name), 166 None if match_err.is_none() => res.bindings.push_optional(name),
157 _ => {} 167 _ => {}
158 } 168 }
159 result = match_err.map_or(Ok(()), Err); 169 if let Some(err) = match_err {
170 res.add_err(err);
171 }
160 } 172 }
161 Op::Repeat { subtree, kind, separator } => { 173 Op::Repeat { subtree, kind, separator } => {
162 result = match_repeat(res, subtree, kind, separator, src); 174 match_repeat(res, subtree, kind, separator, src)?;
163 } 175 }
164 } 176 }
165 } 177 }
166 result 178 Ok(())
167} 179}
168 180
169impl<'a> TtIter<'a> { 181impl<'a> TtIter<'a> {
@@ -345,35 +357,39 @@ pub(super) fn match_repeat(
345 } 357 }
346 358
347 let mut nested = Match::default(); 359 let mut nested = Match::default();
348 match match_subtree(&mut nested, pattern, &mut fork) { 360 match_subtree(&mut nested, pattern, &mut fork)?;
349 Ok(()) => { 361 if nested.err.is_none() {
350 limit -= 1; 362 limit -= 1;
351 if limit == 0 { 363 if limit == 0 {
352 log::warn!( 364 log::warn!(
353 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", 365 "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}",
354 pattern, 366 pattern,
355 src, 367 src,
356 kind, 368 kind,
357 separator 369 separator
358 ); 370 );
359 break; 371 break;
360 } 372 }
361 *src = fork; 373 *src = fork;
362 374
363 res.bindings.push_nested(counter, nested.bindings)?; 375 if let Err(err) = res.bindings.push_nested(counter, nested.bindings) {
364 counter += 1; 376 res.add_err(err);
365 if counter == 1 { 377 }
366 if let RepeatKind::ZeroOrOne = kind { 378 counter += 1;
367 break; 379 if counter == 1 {
368 } 380 if let RepeatKind::ZeroOrOne = kind {
381 break;
369 } 382 }
370 } 383 }
371 Err(_) => break, 384 } else {
385 break;
372 } 386 }
373 } 387 }
374 388
375 match (kind, counter) { 389 match (kind, counter) {
376 (RepeatKind::OneOrMore, 0) => return Err(ExpandError::UnexpectedToken), 390 (RepeatKind::OneOrMore, 0) => {
391 res.add_err(ExpandError::UnexpectedToken);
392 }
377 (_, 0) => { 393 (_, 0) => {
378 // Collect all empty variables in subtrees 394 // Collect all empty variables in subtrees
379 let mut vars = Vec::new(); 395 let mut vars = Vec::new();