From c4cbadf3a5ec12060e2071cbad7bb266eb0feedf Mon Sep 17 00:00:00 2001 From: Tom Jakubowski Date: Mon, 8 Jul 2019 00:41:14 -0700 Subject: [PATCH] Parse subslice patterns in slice patterns cc #1479 --- crates/ra_parser/src/grammar/patterns.rs | 71 ++++++++++++++----- crates/ra_parser/src/syntax_kind/generated.rs | 2 + crates/ra_syntax/src/grammar.ron | 3 +- .../parser/inline/ok/0137_subslice_pat.rs | 4 ++ .../parser/inline/ok/0137_subslice_pat.txt | 69 ++++++++++++++++++ 5 files changed, 130 insertions(+), 19 deletions(-) create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.rs create mode 100644 crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.txt diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 46034942a93e..6611654b1491 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs @@ -37,8 +37,12 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { if p.at(T![...]) || p.at(T![..=]) || p.at(T![..]) { let m = lhs.precede(p); p.bump(); - atom_pat(p, recovery_set); - m.complete(p, RANGE_PAT); + if let Some(_) = atom_pat(p, recovery_set) { + m.complete(p, RANGE_PAT); + } else { + m.abandon(p); + p.err_recover("expected pattern", recovery_set); + } } // test marco_pat // fn main() { @@ -145,7 +149,21 @@ fn path_pat(p: &mut Parser) -> CompletedMarker { fn tuple_pat_fields(p: &mut Parser) { assert!(p.at(T!['('])); p.bump(); - pat_list(p, T![')']); + while !p.at(EOF) && !p.at(T![')']) { + match p.current() { + T![..] => p.bump(), + _ => { + if !p.at_ts(PATTERN_FIRST) { + p.error("expected a pattern"); + break; + } + pattern(p); + } + } + if !p.at(T![')']) { + p.expect(T![,]); + } + } p.expect(T![')']); } @@ -229,28 +247,45 @@ fn tuple_pat(p: &mut Parser) -> CompletedMarker { fn slice_pat(p: &mut Parser) -> CompletedMarker { assert!(p.at(T!['['])); let m = p.start(); + // test subslice_pat + // fn main() { + // let [a, b..] = []; + // let &[ref a.., ref b] = []; + // } p.bump(); - pat_list(p, T![']']); - p.expect(T![']']); - m.complete(p, SLICE_PAT) -} -fn pat_list(p: &mut Parser, ket: SyntaxKind) { - while !p.at(EOF) && !p.at(ket) { - match p.current() { - T![..] => p.bump(), - _ => { - if !p.at_ts(PATTERN_FIRST) { - p.error("expected a pattern"); - break; - } - pattern(p) + while !p.at(EOF) && !p.at(T![']']) { + let la0 = p.nth(0); + let la1 = p.nth(1); + if la0 == T![ref] + || la0 == T![mut] + || la0 == T![box] + || (la0 == IDENT + && !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!])) + { + let m = p.start(); + bind_pat(p, true); + if p.current() == T![..] { + p.bump(); + m.complete(p, SUBSLICE_PAT); + } else { + m.abandon(p); + } + } else if la0 == T![..] { + p.bump(); + } else { + if !p.at_ts(PATTERN_FIRST) { + p.error("expected a pattern"); + break; } + pattern(p); } - if !p.at(ket) { + if !p.at(T![']']) { p.expect(T![,]); } } + p.expect(T![']']); + m.complete(p, SLICE_PAT) } // test bind_pat diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index 374fd5aec584..53a2142ecd35 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -165,6 +165,7 @@ pub enum SyntaxKind { SLICE_PAT, RANGE_PAT, LITERAL_PAT, + SUBSLICE_PAT, TUPLE_EXPR, ARRAY_EXPR, PAREN_EXPR, @@ -632,6 +633,7 @@ impl SyntaxKind { SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" }, RANGE_PAT => &SyntaxInfo { name: "RANGE_PAT" }, LITERAL_PAT => &SyntaxInfo { name: "LITERAL_PAT" }, + SUBSLICE_PAT => &SyntaxInfo { name: "SUBSLICE_PAT" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" }, PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" }, diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 6c075a700f78..71aec1fe33f3 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -168,6 +168,7 @@ Grammar( "SLICE_PAT", "RANGE_PAT", "LITERAL_PAT", + "SUBSLICE_PAT", // atoms "TUPLE_EXPR", @@ -686,7 +687,7 @@ Grammar( "LifetimeArg": (), "MacroItems": ( - traits: [ "ModuleItemOwner", "FnDefOwner" ], + traits: [ "ModuleItemOwner", "FnDefOwner" ], ), "MacroStmts" : ( diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.rs new file mode 100644 index 000000000000..73912564e422 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.rs @@ -0,0 +1,4 @@ +fn main() { + let [a, b..] = []; + let &[ref a.., ref b] = []; +} diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.txt new file mode 100644 index 000000000000..8e19fbf12407 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0137_subslice_pat.txt @@ -0,0 +1,69 @@ +SOURCE_FILE@[0; 69) + FN_DEF@[0; 68) + FN_KW@[0; 2) "fn" + WHITESPACE@[2; 3) " " + NAME@[3; 7) + IDENT@[3; 7) "main" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) "(" + R_PAREN@[8; 9) ")" + WHITESPACE@[9; 10) " " + BLOCK@[10; 68) + L_CURLY@[10; 11) "{" + WHITESPACE@[11; 16) "\n " + LET_STMT@[16; 34) + LET_KW@[16; 19) "let" + WHITESPACE@[19; 20) " " + SLICE_PAT@[20; 28) + L_BRACK@[20; 21) "[" + BIND_PAT@[21; 22) + NAME@[21; 22) + IDENT@[21; 22) "a" + COMMA@[22; 23) "," + WHITESPACE@[23; 24) " " + SUBSLICE_PAT@[24; 27) + BIND_PAT@[24; 25) + NAME@[24; 25) + IDENT@[24; 25) "b" + DOTDOT@[25; 27) ".." + R_BRACK@[27; 28) "]" + WHITESPACE@[28; 29) " " + EQ@[29; 30) "=" + WHITESPACE@[30; 31) " " + ARRAY_EXPR@[31; 33) + L_BRACK@[31; 32) "[" + R_BRACK@[32; 33) "]" + SEMI@[33; 34) ";" + WHITESPACE@[34; 39) "\n " + LET_STMT@[39; 66) + LET_KW@[39; 42) "let" + WHITESPACE@[42; 43) " " + REF_PAT@[43; 60) + AMP@[43; 44) "&" + SLICE_PAT@[44; 60) + L_BRACK@[44; 45) "[" + SUBSLICE_PAT@[45; 52) + BIND_PAT@[45; 50) + REF_KW@[45; 48) "ref" + WHITESPACE@[48; 49) " " + NAME@[49; 50) + IDENT@[49; 50) "a" + DOTDOT@[50; 52) ".." + COMMA@[52; 53) "," + WHITESPACE@[53; 54) " " + BIND_PAT@[54; 59) + REF_KW@[54; 57) "ref" + WHITESPACE@[57; 58) " " + NAME@[58; 59) + IDENT@[58; 59) "b" + R_BRACK@[59; 60) "]" + WHITESPACE@[60; 61) " " + EQ@[61; 62) "=" + WHITESPACE@[62; 63) " " + ARRAY_EXPR@[63; 65) + L_BRACK@[63; 64) "[" + R_BRACK@[64; 65) "]" + SEMI@[65; 66) ";" + WHITESPACE@[66; 67) "\n" + R_CURLY@[67; 68) "}" + WHITESPACE@[68; 69) "\n"