aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/patterns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/patterns.rs')
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs66
1 files changed, 56 insertions, 10 deletions
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 422a4e3dc..c6a2e4d39 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -11,22 +11,49 @@ pub(crate) fn pattern(p: &mut Parser) {
11} 11}
12 12
13/// Parses a pattern list separated by pipes `|` 13/// Parses a pattern list separated by pipes `|`
14pub(super) fn pattern_list(p: &mut Parser) { 14pub(super) fn pattern_top(p: &mut Parser) {
15 pattern_list_r(p, PAT_RECOVERY_SET) 15 pattern_top_r(p, PAT_RECOVERY_SET)
16}
17
18pub(crate) fn pattern_single(p: &mut Parser) {
19 pattern_single_r(p, PAT_RECOVERY_SET);
16} 20}
17 21
18/// Parses a pattern list separated by pipes `|` 22/// Parses a pattern list separated by pipes `|`
19/// using the given `recovery_set` 23/// using the given `recovery_set`
20pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) { 24pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) {
21 p.eat(T![|]); 25 p.eat(T![|]);
22 pattern_r(p, recovery_set); 26 pattern_r(p, recovery_set);
27}
23 28
29/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
30/// given `recovery_set`
31// test or_pattern
32// fn main() {
33// match () {
34// (_ | _) => (),
35// &(_ | _) => (),
36// (_ | _,) => (),
37// [_ | _,] => (),
38// }
39// }
40fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
41 let m = p.start();
42 pattern_single_r(p, recovery_set);
43
44 let mut is_or_pat = false;
24 while p.eat(T![|]) { 45 while p.eat(T![|]) {
25 pattern_r(p, recovery_set); 46 is_or_pat = true;
47 pattern_single_r(p, recovery_set);
48 }
49 if is_or_pat {
50 m.complete(p, OR_PAT);
51 } else {
52 m.abandon(p);
26 } 53 }
27} 54}
28 55
29pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { 56fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
30 if let Some(lhs) = atom_pat(p, recovery_set) { 57 if let Some(lhs) = atom_pat(p, recovery_set) {
31 // test range_pat 58 // test range_pat
32 // fn main() { 59 // fn main() {
@@ -258,7 +285,7 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker {
258 let m = p.start(); 285 let m = p.start();
259 p.bump(T![&]); 286 p.bump(T![&]);
260 p.eat(T![mut]); 287 p.eat(T![mut]);
261 pattern(p); 288 pattern_single(p);
262 m.complete(p, REF_PAT) 289 m.complete(p, REF_PAT)
263} 290}
264 291
@@ -269,8 +296,27 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker {
269fn tuple_pat(p: &mut Parser) -> CompletedMarker { 296fn tuple_pat(p: &mut Parser) -> CompletedMarker {
270 assert!(p.at(T!['('])); 297 assert!(p.at(T!['(']));
271 let m = p.start(); 298 let m = p.start();
272 tuple_pat_fields(p); 299 p.bump(T!['(']);
273 m.complete(p, TUPLE_PAT) 300 let mut has_comma = false;
301 let mut has_pat = false;
302 let mut has_rest = false;
303 while !p.at(EOF) && !p.at(T![')']) {
304 has_pat = true;
305 if !p.at_ts(PATTERN_FIRST) {
306 p.error("expected a pattern");
307 break;
308 }
309 has_rest |= p.at(T![..]);
310
311 pattern(p);
312 if !p.at(T![')']) {
313 has_comma = true;
314 p.expect(T![,]);
315 }
316 }
317 p.expect(T![')']);
318
319 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
274} 320}
275 321
276// test slice_pat 322// test slice_pat
@@ -315,7 +361,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
315 p.eat(T![mut]); 361 p.eat(T![mut]);
316 name(p); 362 name(p);
317 if with_at && p.eat(T![@]) { 363 if with_at && p.eat(T![@]) {
318 pattern(p); 364 pattern_single(p);
319 } 365 }
320 m.complete(p, BIND_PAT) 366 m.complete(p, BIND_PAT)
321} 367}
@@ -330,6 +376,6 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
330 assert!(p.at(T![box])); 376 assert!(p.at(T![box]));
331 let m = p.start(); 377 let m = p.start();
332 p.bump(T![box]); 378 p.bump(T![box]);
333 pattern(p); 379 pattern_single(p);
334 m.complete(p, BOX_PAT) 380 m.complete(p, BOX_PAT)
335} 381}