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.rs67
1 files changed, 57 insertions, 10 deletions
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 422a4e3dc..3afbaa82b 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -11,22 +11,47 @@ 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 if !p.at(T![|]) {
45 m.abandon(p);
46 return;
47 }
24 while p.eat(T![|]) { 48 while p.eat(T![|]) {
25 pattern_r(p, recovery_set); 49 pattern_single_r(p, recovery_set);
26 } 50 }
51 m.complete(p, OR_PAT);
27} 52}
28 53
29pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { 54fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) {
30 if let Some(lhs) = atom_pat(p, recovery_set) { 55 if let Some(lhs) = atom_pat(p, recovery_set) {
31 // test range_pat 56 // test range_pat
32 // fn main() { 57 // fn main() {
@@ -258,19 +283,41 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker {
258 let m = p.start(); 283 let m = p.start();
259 p.bump(T![&]); 284 p.bump(T![&]);
260 p.eat(T![mut]); 285 p.eat(T![mut]);
261 pattern(p); 286 pattern_single(p);
262 m.complete(p, REF_PAT) 287 m.complete(p, REF_PAT)
263} 288}
264 289
265// test tuple_pat 290// test tuple_pat
266// fn main() { 291// fn main() {
267// let (a, b, ..) = (); 292// let (a, b, ..) = ();
293// let (a,) = ();
294// let (..) = ();
295// let () = ();
268// } 296// }
269fn tuple_pat(p: &mut Parser) -> CompletedMarker { 297fn tuple_pat(p: &mut Parser) -> CompletedMarker {
270 assert!(p.at(T!['('])); 298 assert!(p.at(T!['(']));
271 let m = p.start(); 299 let m = p.start();
272 tuple_pat_fields(p); 300 p.bump(T!['(']);
273 m.complete(p, TUPLE_PAT) 301 let mut has_comma = false;
302 let mut has_pat = false;
303 let mut has_rest = false;
304 while !p.at(EOF) && !p.at(T![')']) {
305 has_pat = true;
306 if !p.at_ts(PATTERN_FIRST) {
307 p.error("expected a pattern");
308 break;
309 }
310 has_rest |= p.at(T![..]);
311
312 pattern(p);
313 if !p.at(T![')']) {
314 has_comma = true;
315 p.expect(T![,]);
316 }
317 }
318 p.expect(T![')']);
319
320 m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT })
274} 321}
275 322
276// test slice_pat 323// test slice_pat
@@ -315,7 +362,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
315 p.eat(T![mut]); 362 p.eat(T![mut]);
316 name(p); 363 name(p);
317 if with_at && p.eat(T![@]) { 364 if with_at && p.eat(T![@]) {
318 pattern(p); 365 pattern_single(p);
319 } 366 }
320 m.complete(p, BIND_PAT) 367 m.complete(p, BIND_PAT)
321} 368}
@@ -330,6 +377,6 @@ fn box_pat(p: &mut Parser) -> CompletedMarker {
330 assert!(p.at(T![box])); 377 assert!(p.at(T![box]));
331 let m = p.start(); 378 let m = p.start();
332 p.bump(T![box]); 379 p.bump(T![box]);
333 pattern(p); 380 pattern_single(p);
334 m.complete(p, BOX_PAT) 381 m.complete(p, BOX_PAT)
335} 382}