diff options
Diffstat (limited to 'crates/ra_parser/src/grammar')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/params.rs | 4 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 66 |
3 files changed, 60 insertions, 14 deletions
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index f154077a8..b72d2e9e6 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -336,7 +336,7 @@ fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | |||
336 | fn cond(p: &mut Parser) { | 336 | fn cond(p: &mut Parser) { |
337 | let m = p.start(); | 337 | let m = p.start(); |
338 | if p.eat(T![let]) { | 338 | if p.eat(T![let]) { |
339 | patterns::pattern_list(p); | 339 | patterns::pattern_top(p); |
340 | p.expect(T![=]); | 340 | p.expect(T![=]); |
341 | } | 341 | } |
342 | expr_no_struct(p); | 342 | expr_no_struct(p); |
@@ -430,7 +430,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { | |||
430 | // } | 430 | // } |
431 | attributes::outer_attributes(p); | 431 | attributes::outer_attributes(p); |
432 | 432 | ||
433 | patterns::pattern_list_r(p, TokenSet::EMPTY); | 433 | patterns::pattern_top_r(p, TokenSet::EMPTY); |
434 | if p.at(T![if]) { | 434 | if p.at(T![if]) { |
435 | match_guard(p); | 435 | match_guard(p); |
436 | } | 436 | } |
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs index 94edc7f35..ed4f93347 100644 --- a/crates/ra_parser/src/grammar/params.rs +++ b/crates/ra_parser/src/grammar/params.rs | |||
@@ -116,7 +116,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { | |||
116 | // type Qux = fn(baz: Bar::Baz); | 116 | // type Qux = fn(baz: Bar::Baz); |
117 | Flavor::FnPointer => { | 117 | Flavor::FnPointer => { |
118 | if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { | 118 | if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { |
119 | patterns::pattern(p); | 119 | patterns::pattern_single(p); |
120 | types::ascription(p); | 120 | types::ascription(p); |
121 | } else { | 121 | } else { |
122 | types::type_(p); | 122 | types::type_(p); |
@@ -127,7 +127,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { | |||
127 | // let foo = |bar, baz: Baz, qux: Qux::Quux| (); | 127 | // let foo = |bar, baz: Baz, qux: Qux::Quux| (); |
128 | // } | 128 | // } |
129 | Flavor::Closure => { | 129 | Flavor::Closure => { |
130 | patterns::pattern(p); | 130 | patterns::pattern_single(p); |
131 | if p.at(T![:]) && !p.at(T![::]) { | 131 | if p.at(T![:]) && !p.at(T![::]) { |
132 | types::ascription(p); | 132 | types::ascription(p); |
133 | } | 133 | } |
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 `|` |
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 | 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 | ||
29 | pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { | 56 | fn 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 { | |||
269 | fn tuple_pat(p: &mut Parser) -> CompletedMarker { | 296 | fn 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 | } |