diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/patterns.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 67 |
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 `|` |
14 | pub(super) fn pattern_list(p: &mut Parser) { | 14 | pub(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 | |||
18 | pub(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` |
20 | pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) { | 24 | pub(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 | // } | ||
40 | fn 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 | ||
29 | pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { | 54 | fn 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 | // } |
269 | fn tuple_pat(p: &mut Parser) -> CompletedMarker { | 297 | fn 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 | } |