diff options
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander/matcher.rs')
-rw-r--r-- | crates/ra_mbe/src/mbe_expander/matcher.rs | 212 |
1 files changed, 136 insertions, 76 deletions
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index 49c53183a..2579382da 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs | |||
@@ -8,6 +8,7 @@ use crate::{ | |||
8 | ExpandError, | 8 | ExpandError, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use super::ExpandResult; | ||
11 | use ra_parser::{FragmentKind::*, TreeSink}; | 12 | use ra_parser::{FragmentKind::*, TreeSink}; |
12 | use ra_syntax::{SmolStr, SyntaxKind}; | 13 | use ra_syntax::{SmolStr, SyntaxKind}; |
13 | use tt::buffer::{Cursor, TokenBuffer}; | 14 | use tt::buffer::{Cursor, TokenBuffer}; |
@@ -58,36 +59,61 @@ macro_rules! err { | |||
58 | }; | 59 | }; |
59 | } | 60 | } |
60 | 61 | ||
61 | macro_rules! bail { | 62 | #[derive(Debug, Default)] |
62 | ($($tt:tt)*) => { | 63 | pub(super) struct Match { |
63 | return Err(err!($($tt)*)) | 64 | pub bindings: Bindings, |
64 | }; | 65 | /// We currently just keep the first error and count the rest to compare matches. |
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, | ||
65 | } | 70 | } |
66 | 71 | ||
67 | pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Bindings, ExpandError> { | 72 | impl 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 | |||
86 | pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Match, ExpandError> { | ||
68 | assert!(pattern.delimiter == None); | 87 | assert!(pattern.delimiter == None); |
69 | 88 | ||
70 | let mut res = Bindings::default(); | 89 | let mut res = Match::default(); |
71 | let mut src = TtIter::new(src); | 90 | let mut src = TtIter::new(src); |
72 | 91 | ||
73 | match_subtree(&mut res, pattern, &mut src)?; | 92 | match_subtree(&mut res, pattern, &mut src)?; |
74 | 93 | ||
75 | if src.len() > 0 { | 94 | if src.len() > 0 { |
76 | bail!("leftover tokens"); | 95 | res.unmatched_tts += src.len(); |
96 | res.add_err(err!("leftover tokens")); | ||
77 | } | 97 | } |
78 | 98 | ||
79 | Ok(res) | 99 | Ok(res) |
80 | } | 100 | } |
81 | 101 | ||
82 | fn match_subtree( | 102 | fn match_subtree( |
83 | bindings: &mut Bindings, | 103 | res: &mut Match, |
84 | pattern: &tt::Subtree, | 104 | pattern: &tt::Subtree, |
85 | src: &mut TtIter, | 105 | src: &mut TtIter, |
86 | ) -> Result<(), ExpandError> { | 106 | ) -> Result<(), ExpandError> { |
87 | for op in parse_pattern(pattern) { | 107 | for op in parse_pattern(pattern) { |
88 | match op? { | 108 | match op? { |
89 | Op::TokenTree(tt::TokenTree::Leaf(lhs)) => { | 109 | Op::TokenTree(tt::TokenTree::Leaf(lhs)) => { |
90 | let rhs = src.expect_leaf().map_err(|()| err!("expected leaf: `{}`", lhs))?; | 110 | let rhs = match src.expect_leaf() { |
111 | Ok(l) => l, | ||
112 | Err(()) => { | ||
113 | res.add_err(err!("expected leaf: `{}`", lhs)); | ||
114 | continue; | ||
115 | } | ||
116 | }; | ||
91 | match (lhs, rhs) { | 117 | match (lhs, rhs) { |
92 | ( | 118 | ( |
93 | tt::Leaf::Punct(tt::Punct { char: lhs, .. }), | 119 | tt::Leaf::Punct(tt::Punct { char: lhs, .. }), |
@@ -101,31 +127,51 @@ fn match_subtree( | |||
101 | tt::Leaf::Literal(tt::Literal { text: lhs, .. }), | 127 | tt::Leaf::Literal(tt::Literal { text: lhs, .. }), |
102 | tt::Leaf::Literal(tt::Literal { text: rhs, .. }), | 128 | tt::Leaf::Literal(tt::Literal { text: rhs, .. }), |
103 | ) if lhs == rhs => (), | 129 | ) if lhs == rhs => (), |
104 | _ => return Err(ExpandError::UnexpectedToken), | 130 | _ => { |
131 | res.add_err(ExpandError::UnexpectedToken); | ||
132 | } | ||
105 | } | 133 | } |
106 | } | 134 | } |
107 | Op::TokenTree(tt::TokenTree::Subtree(lhs)) => { | 135 | Op::TokenTree(tt::TokenTree::Subtree(lhs)) => { |
108 | let rhs = src.expect_subtree().map_err(|()| err!("expected subtree"))?; | 136 | let rhs = match src.expect_subtree() { |
137 | Ok(s) => s, | ||
138 | Err(()) => { | ||
139 | res.add_err(err!("expected subtree")); | ||
140 | continue; | ||
141 | } | ||
142 | }; | ||
109 | if lhs.delimiter_kind() != rhs.delimiter_kind() { | 143 | if lhs.delimiter_kind() != rhs.delimiter_kind() { |
110 | bail!("mismatched delimiter") | 144 | res.add_err(err!("mismatched delimiter")); |
145 | continue; | ||
111 | } | 146 | } |
112 | let mut src = TtIter::new(rhs); | 147 | let mut src = TtIter::new(rhs); |
113 | match_subtree(bindings, lhs, &mut src)?; | 148 | match_subtree(res, lhs, &mut src)?; |
114 | if src.len() > 0 { | 149 | if src.len() > 0 { |
115 | bail!("leftover tokens"); | 150 | res.add_err(err!("leftover tokens")); |
116 | } | 151 | } |
117 | } | 152 | } |
118 | Op::Var { name, kind } => { | 153 | Op::Var { name, kind } => { |
119 | let kind = kind.as_ref().ok_or(ExpandError::UnexpectedToken)?; | 154 | let kind = match kind { |
120 | match match_meta_var(kind.as_str(), src)? { | 155 | Some(k) => k, |
156 | None => { | ||
157 | res.add_err(ExpandError::UnexpectedToken); | ||
158 | continue; | ||
159 | } | ||
160 | }; | ||
161 | let ExpandResult(matched, match_err) = match_meta_var(kind.as_str(), src); | ||
162 | match matched { | ||
121 | Some(fragment) => { | 163 | Some(fragment) => { |
122 | bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); | 164 | res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); |
123 | } | 165 | } |
124 | None => bindings.push_optional(name), | 166 | None if match_err.is_none() => res.bindings.push_optional(name), |
167 | _ => {} | ||
168 | } | ||
169 | if let Some(err) = match_err { | ||
170 | res.add_err(err); | ||
125 | } | 171 | } |
126 | } | 172 | } |
127 | Op::Repeat { subtree, kind, separator } => { | 173 | Op::Repeat { subtree, kind, separator } => { |
128 | match_repeat(bindings, subtree, kind, separator, src)? | 174 | match_repeat(res, subtree, kind, separator, src)?; |
129 | } | 175 | } |
130 | } | 176 | } |
131 | } | 177 | } |
@@ -221,7 +267,7 @@ impl<'a> TtIter<'a> { | |||
221 | pub(crate) fn expect_fragment( | 267 | pub(crate) fn expect_fragment( |
222 | &mut self, | 268 | &mut self, |
223 | fragment_kind: ra_parser::FragmentKind, | 269 | fragment_kind: ra_parser::FragmentKind, |
224 | ) -> Result<tt::TokenTree, ()> { | 270 | ) -> ExpandResult<Option<tt::TokenTree>> { |
225 | pub(crate) struct OffsetTokenSink<'a> { | 271 | pub(crate) struct OffsetTokenSink<'a> { |
226 | pub(crate) cursor: Cursor<'a>, | 272 | pub(crate) cursor: Cursor<'a>, |
227 | pub(crate) error: bool, | 273 | pub(crate) error: bool, |
@@ -246,45 +292,51 @@ impl<'a> TtIter<'a> { | |||
246 | 292 | ||
247 | ra_parser::parse_fragment(&mut src, &mut sink, fragment_kind); | 293 | ra_parser::parse_fragment(&mut src, &mut sink, fragment_kind); |
248 | 294 | ||
295 | let mut err = None; | ||
249 | if !sink.cursor.is_root() || sink.error { | 296 | if !sink.cursor.is_root() || sink.error { |
250 | // FIXME better recovery in this case would help completion inside macros immensely | 297 | err = Some(err!("expected {:?}", fragment_kind)); |
251 | return Err(()); | ||
252 | } | 298 | } |
253 | 299 | ||
254 | let mut curr = buffer.begin(); | 300 | let mut curr = buffer.begin(); |
255 | let mut res = vec![]; | 301 | let mut res = vec![]; |
256 | 302 | ||
257 | while curr != sink.cursor { | 303 | if sink.cursor.is_root() { |
258 | if let Some(token) = curr.token_tree() { | 304 | while curr != sink.cursor { |
259 | res.push(token); | 305 | if let Some(token) = curr.token_tree() { |
306 | res.push(token); | ||
307 | } | ||
308 | curr = curr.bump(); | ||
260 | } | 309 | } |
261 | curr = curr.bump(); | ||
262 | } | 310 | } |
263 | self.inner = self.inner.as_slice()[res.len()..].iter(); | 311 | self.inner = self.inner.as_slice()[res.len()..].iter(); |
264 | match res.len() { | 312 | if res.len() == 0 && err.is_none() { |
265 | 0 => Err(()), | 313 | err = Some(err!("no tokens consumed")); |
266 | 1 => Ok(res[0].clone()), | 314 | } |
267 | _ => Ok(tt::TokenTree::Subtree(tt::Subtree { | 315 | let res = match res.len() { |
316 | 1 => Some(res[0].clone()), | ||
317 | 0 => None, | ||
318 | _ => Some(tt::TokenTree::Subtree(tt::Subtree { | ||
268 | delimiter: None, | 319 | delimiter: None, |
269 | token_trees: res.into_iter().cloned().collect(), | 320 | token_trees: res.into_iter().cloned().collect(), |
270 | })), | 321 | })), |
271 | } | 322 | }; |
323 | ExpandResult(res, err) | ||
272 | } | 324 | } |
273 | 325 | ||
274 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { | 326 | pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { |
275 | let mut fork = self.clone(); | 327 | let mut fork = self.clone(); |
276 | match fork.expect_fragment(Visibility) { | 328 | match fork.expect_fragment(Visibility) { |
277 | Ok(tt) => { | 329 | ExpandResult(tt, None) => { |
278 | *self = fork; | 330 | *self = fork; |
279 | Some(tt) | 331 | tt |
280 | } | 332 | } |
281 | Err(()) => None, | 333 | ExpandResult(_, Some(_)) => None, |
282 | } | 334 | } |
283 | } | 335 | } |
284 | } | 336 | } |
285 | 337 | ||
286 | pub(super) fn match_repeat( | 338 | pub(super) fn match_repeat( |
287 | bindings: &mut Bindings, | 339 | res: &mut Match, |
288 | pattern: &tt::Subtree, | 340 | pattern: &tt::Subtree, |
289 | kind: RepeatKind, | 341 | kind: RepeatKind, |
290 | separator: Option<Separator>, | 342 | separator: Option<Separator>, |
@@ -304,36 +356,46 @@ pub(super) fn match_repeat( | |||
304 | } | 356 | } |
305 | } | 357 | } |
306 | 358 | ||
307 | let mut nested = Bindings::default(); | 359 | let mut nested = Match::default(); |
308 | match match_subtree(&mut nested, pattern, &mut fork) { | 360 | match_subtree(&mut nested, pattern, &mut fork)?; |
309 | Ok(()) => { | 361 | if nested.err.is_none() { |
310 | limit -= 1; | 362 | limit -= 1; |
311 | if limit == 0 { | 363 | if limit == 0 { |
312 | log::warn!("match_lhs excced in repeat pattern exceed limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", pattern, src, kind, separator); | 364 | log::warn!( |
313 | break; | 365 | "match_lhs exceeded repeat pattern limit => {:#?}\n{:#?}\n{:#?}\n{:#?}", |
314 | } | 366 | pattern, |
315 | *src = fork; | 367 | src, |
368 | kind, | ||
369 | separator | ||
370 | ); | ||
371 | break; | ||
372 | } | ||
373 | *src = fork; | ||
316 | 374 | ||
317 | bindings.push_nested(counter, nested)?; | 375 | if let Err(err) = res.bindings.push_nested(counter, nested.bindings) { |
318 | counter += 1; | 376 | res.add_err(err); |
319 | if counter == 1 { | 377 | } |
320 | if let RepeatKind::ZeroOrOne = kind { | 378 | counter += 1; |
321 | break; | 379 | if counter == 1 { |
322 | } | 380 | if let RepeatKind::ZeroOrOne = kind { |
381 | break; | ||
323 | } | 382 | } |
324 | } | 383 | } |
325 | Err(_) => break, | 384 | } else { |
385 | break; | ||
326 | } | 386 | } |
327 | } | 387 | } |
328 | 388 | ||
329 | match (kind, counter) { | 389 | match (kind, counter) { |
330 | (RepeatKind::OneOrMore, 0) => return Err(ExpandError::UnexpectedToken), | 390 | (RepeatKind::OneOrMore, 0) => { |
391 | res.add_err(ExpandError::UnexpectedToken); | ||
392 | } | ||
331 | (_, 0) => { | 393 | (_, 0) => { |
332 | // Collect all empty variables in subtrees | 394 | // Collect all empty variables in subtrees |
333 | let mut vars = Vec::new(); | 395 | let mut vars = Vec::new(); |
334 | collect_vars(&mut vars, pattern)?; | 396 | collect_vars(&mut vars, pattern)?; |
335 | for var in vars { | 397 | for var in vars { |
336 | bindings.push_empty(&var) | 398 | res.bindings.push_empty(&var) |
337 | } | 399 | } |
338 | } | 400 | } |
339 | _ => (), | 401 | _ => (), |
@@ -341,7 +403,7 @@ pub(super) fn match_repeat( | |||
341 | Ok(()) | 403 | Ok(()) |
342 | } | 404 | } |
343 | 405 | ||
344 | fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, ExpandError> { | 406 | fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragment>> { |
345 | let fragment = match kind { | 407 | let fragment = match kind { |
346 | "path" => Path, | 408 | "path" => Path, |
347 | "expr" => Expr, | 409 | "expr" => Expr, |
@@ -352,34 +414,32 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, Ex | |||
352 | "meta" => MetaItem, | 414 | "meta" => MetaItem, |
353 | "item" => Item, | 415 | "item" => Item, |
354 | _ => { | 416 | _ => { |
355 | let tt = match kind { | 417 | let tt_result = match kind { |
356 | "ident" => { | 418 | "ident" => input |
357 | let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); | 419 | .expect_ident() |
358 | tt::Leaf::from(ident).into() | 420 | .map(|ident| Some(tt::Leaf::from(ident.clone()).into())) |
359 | } | 421 | .map_err(|()| err!("expected ident")), |
360 | "tt" => input.expect_tt().map_err(|()| err!())?.clone(), | 422 | "tt" => input.expect_tt().map(Some).map_err(|()| err!()), |
361 | "lifetime" => { | 423 | "lifetime" => input |
362 | let ident = input.expect_lifetime().map_err(|()| err!())?; | 424 | .expect_lifetime() |
363 | tt::Leaf::Ident(ident.clone()).into() | 425 | .map(|ident| Some(tt::Leaf::Ident(ident.clone()).into())) |
364 | } | 426 | .map_err(|()| err!("expected lifetime")), |
365 | "literal" => { | 427 | "literal" => input |
366 | let literal = input.expect_literal().map_err(|()| err!())?.clone(); | 428 | .expect_literal() |
367 | tt::Leaf::from(literal).into() | 429 | .map(|literal| Some(tt::Leaf::from(literal.clone()).into())) |
368 | } | 430 | .map_err(|()| err!()), |
369 | // `vis` is optional | 431 | // `vis` is optional |
370 | "vis" => match input.eat_vis() { | 432 | "vis" => match input.eat_vis() { |
371 | Some(vis) => vis, | 433 | Some(vis) => Ok(Some(vis)), |
372 | None => return Ok(None), | 434 | None => Ok(None), |
373 | }, | 435 | }, |
374 | _ => return Err(ExpandError::UnexpectedToken), | 436 | _ => Err(ExpandError::UnexpectedToken), |
375 | }; | 437 | }; |
376 | return Ok(Some(Fragment::Tokens(tt))); | 438 | return tt_result.map(|it| it.map(Fragment::Tokens)).into(); |
377 | } | 439 | } |
378 | }; | 440 | }; |
379 | let tt = | 441 | let result = input.expect_fragment(fragment); |
380 | input.expect_fragment(fragment).map_err(|()| err!("fragment did not parse as {}", kind))?; | 442 | result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) }) |
381 | let fragment = if kind == "expr" { Fragment::Ast(tt) } else { Fragment::Tokens(tt) }; | ||
382 | Ok(Some(fragment)) | ||
383 | } | 443 | } |
384 | 444 | ||
385 | fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { | 445 | fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { |