aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander/matcher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander/matcher.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs212
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
11use super::ExpandResult;
11use ra_parser::{FragmentKind::*, TreeSink}; 12use ra_parser::{FragmentKind::*, TreeSink};
12use ra_syntax::{SmolStr, SyntaxKind}; 13use ra_syntax::{SmolStr, SyntaxKind};
13use tt::buffer::{Cursor, TokenBuffer}; 14use tt::buffer::{Cursor, TokenBuffer};
@@ -58,36 +59,61 @@ macro_rules! err {
58 }; 59 };
59} 60}
60 61
61macro_rules! bail { 62#[derive(Debug, Default)]
62 ($($tt:tt)*) => { 63pub(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
67pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result<Bindings, ExpandError> { 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> {
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
82fn match_subtree( 102fn 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
286pub(super) fn match_repeat( 338pub(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
344fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, ExpandError> { 406fn 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
385fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { 445fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> {