From 8c8d0bb34f5495e0f260b5aaf3685ecb98406f32 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 9 Feb 2020 18:57:01 +0000 Subject: Add or- and parenthesized-patterns --- crates/ra_parser/src/grammar/expressions/atom.rs | 4 +- crates/ra_parser/src/grammar/params.rs | 4 +- crates/ra_parser/src/grammar/patterns.rs | 66 ++++++++++++++++++++---- crates/ra_parser/src/syntax_kind/generated.rs | 2 + 4 files changed, 62 insertions(+), 14 deletions(-) (limited to 'crates/ra_parser') 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) -> CompletedMarker { fn cond(p: &mut Parser) { let m = p.start(); if p.eat(T![let]) { - patterns::pattern_list(p); + patterns::pattern_top(p); p.expect(T![=]); } expr_no_struct(p); @@ -430,7 +430,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { // } attributes::outer_attributes(p); - patterns::pattern_list_r(p, TokenSet::EMPTY); + patterns::pattern_top_r(p, TokenSet::EMPTY); if p.at(T![if]) { match_guard(p); } 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) { // type Qux = fn(baz: Bar::Baz); Flavor::FnPointer => { if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { - patterns::pattern(p); + patterns::pattern_single(p); types::ascription(p); } else { types::type_(p); @@ -127,7 +127,7 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) { // let foo = |bar, baz: Baz, qux: Qux::Quux| (); // } Flavor::Closure => { - patterns::pattern(p); + patterns::pattern_single(p); if p.at(T![:]) && !p.at(T![::]) { types::ascription(p); } 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) { } /// Parses a pattern list separated by pipes `|` -pub(super) fn pattern_list(p: &mut Parser) { - pattern_list_r(p, PAT_RECOVERY_SET) +pub(super) fn pattern_top(p: &mut Parser) { + pattern_top_r(p, PAT_RECOVERY_SET) +} + +pub(crate) fn pattern_single(p: &mut Parser) { + pattern_single_r(p, PAT_RECOVERY_SET); } /// Parses a pattern list separated by pipes `|` /// using the given `recovery_set` -pub(super) fn pattern_list_r(p: &mut Parser, recovery_set: TokenSet) { +pub(super) fn pattern_top_r(p: &mut Parser, recovery_set: TokenSet) { p.eat(T![|]); pattern_r(p, recovery_set); +} +/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the +/// given `recovery_set` +// test or_pattern +// fn main() { +// match () { +// (_ | _) => (), +// &(_ | _) => (), +// (_ | _,) => (), +// [_ | _,] => (), +// } +// } +fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { + let m = p.start(); + pattern_single_r(p, recovery_set); + + let mut is_or_pat = false; while p.eat(T![|]) { - pattern_r(p, recovery_set); + is_or_pat = true; + pattern_single_r(p, recovery_set); + } + if is_or_pat { + m.complete(p, OR_PAT); + } else { + m.abandon(p); } } -pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { +fn pattern_single_r(p: &mut Parser, recovery_set: TokenSet) { if let Some(lhs) = atom_pat(p, recovery_set) { // test range_pat // fn main() { @@ -258,7 +285,7 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker { let m = p.start(); p.bump(T![&]); p.eat(T![mut]); - pattern(p); + pattern_single(p); m.complete(p, REF_PAT) } @@ -269,8 +296,27 @@ fn ref_pat(p: &mut Parser) -> CompletedMarker { fn tuple_pat(p: &mut Parser) -> CompletedMarker { assert!(p.at(T!['('])); let m = p.start(); - tuple_pat_fields(p); - m.complete(p, TUPLE_PAT) + p.bump(T!['(']); + let mut has_comma = false; + let mut has_pat = false; + let mut has_rest = false; + while !p.at(EOF) && !p.at(T![')']) { + has_pat = true; + if !p.at_ts(PATTERN_FIRST) { + p.error("expected a pattern"); + break; + } + has_rest |= p.at(T![..]); + + pattern(p); + if !p.at(T![')']) { + has_comma = true; + p.expect(T![,]); + } + } + p.expect(T![')']); + + m.complete(p, if !has_comma && !has_rest && has_pat { PAREN_PAT } else { TUPLE_PAT }) } // test slice_pat @@ -315,7 +361,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { p.eat(T![mut]); name(p); if with_at && p.eat(T![@]) { - pattern(p); + pattern_single(p); } m.complete(p, BIND_PAT) } @@ -330,6 +376,6 @@ fn box_pat(p: &mut Parser) -> CompletedMarker { assert!(p.at(T![box])); let m = p.start(); p.bump(T![box]); - pattern(p); + pattern_single(p); m.complete(p, BOX_PAT) } diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index e27b27ffa..1068da0a0 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -151,6 +151,8 @@ pub enum SyntaxKind { FOR_TYPE, IMPL_TRAIT_TYPE, DYN_TRAIT_TYPE, + OR_PAT, + PAREN_PAT, REF_PAT, BOX_PAT, BIND_PAT, -- cgit v1.2.3