Skip to content

Commit c4cbadf

Browse files
committed
Parse subslice patterns in slice patterns
cc #1479
1 parent c4e2e36 commit c4cbadf

File tree

5 files changed

+130
-19
lines changed

5 files changed

+130
-19
lines changed

crates/ra_parser/src/grammar/patterns.rs

+53-18
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) {
3737
if p.at(T![...]) || p.at(T![..=]) || p.at(T![..]) {
3838
let m = lhs.precede(p);
3939
p.bump();
40-
atom_pat(p, recovery_set);
41-
m.complete(p, RANGE_PAT);
40+
if let Some(_) = atom_pat(p, recovery_set) {
41+
m.complete(p, RANGE_PAT);
42+
} else {
43+
m.abandon(p);
44+
p.err_recover("expected pattern", recovery_set);
45+
}
4246
}
4347
// test marco_pat
4448
// fn main() {
@@ -145,7 +149,21 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
145149
fn tuple_pat_fields(p: &mut Parser) {
146150
assert!(p.at(T!['(']));
147151
p.bump();
148-
pat_list(p, T![')']);
152+
while !p.at(EOF) && !p.at(T![')']) {
153+
match p.current() {
154+
T![..] => p.bump(),
155+
_ => {
156+
if !p.at_ts(PATTERN_FIRST) {
157+
p.error("expected a pattern");
158+
break;
159+
}
160+
pattern(p);
161+
}
162+
}
163+
if !p.at(T![')']) {
164+
p.expect(T![,]);
165+
}
166+
}
149167
p.expect(T![')']);
150168
}
151169

@@ -229,28 +247,45 @@ fn tuple_pat(p: &mut Parser) -> CompletedMarker {
229247
fn slice_pat(p: &mut Parser) -> CompletedMarker {
230248
assert!(p.at(T!['[']));
231249
let m = p.start();
250+
// test subslice_pat
251+
// fn main() {
252+
// let [a, b..] = [];
253+
// let &[ref a.., ref b] = [];
254+
// }
232255
p.bump();
233-
pat_list(p, T![']']);
234-
p.expect(T![']']);
235-
m.complete(p, SLICE_PAT)
236-
}
237256

238-
fn pat_list(p: &mut Parser, ket: SyntaxKind) {
239-
while !p.at(EOF) && !p.at(ket) {
240-
match p.current() {
241-
T![..] => p.bump(),
242-
_ => {
243-
if !p.at_ts(PATTERN_FIRST) {
244-
p.error("expected a pattern");
245-
break;
246-
}
247-
pattern(p)
257+
while !p.at(EOF) && !p.at(T![']']) {
258+
let la0 = p.nth(0);
259+
let la1 = p.nth(1);
260+
if la0 == T![ref]
261+
|| la0 == T![mut]
262+
|| la0 == T![box]
263+
|| (la0 == IDENT
264+
&& !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!]))
265+
{
266+
let m = p.start();
267+
bind_pat(p, true);
268+
if p.current() == T![..] {
269+
p.bump();
270+
m.complete(p, SUBSLICE_PAT);
271+
} else {
272+
m.abandon(p);
273+
}
274+
} else if la0 == T![..] {
275+
p.bump();
276+
} else {
277+
if !p.at_ts(PATTERN_FIRST) {
278+
p.error("expected a pattern");
279+
break;
248280
}
281+
pattern(p);
249282
}
250-
if !p.at(ket) {
283+
if !p.at(T![']']) {
251284
p.expect(T![,]);
252285
}
253286
}
287+
p.expect(T![']']);
288+
m.complete(p, SLICE_PAT)
254289
}
255290

256291
// test bind_pat

crates/ra_parser/src/syntax_kind/generated.rs

+2
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub enum SyntaxKind {
165165
SLICE_PAT,
166166
RANGE_PAT,
167167
LITERAL_PAT,
168+
SUBSLICE_PAT,
168169
TUPLE_EXPR,
169170
ARRAY_EXPR,
170171
PAREN_EXPR,
@@ -632,6 +633,7 @@ impl SyntaxKind {
632633
SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
633634
RANGE_PAT => &SyntaxInfo { name: "RANGE_PAT" },
634635
LITERAL_PAT => &SyntaxInfo { name: "LITERAL_PAT" },
636+
SUBSLICE_PAT => &SyntaxInfo { name: "SUBSLICE_PAT" },
635637
TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
636638
ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" },
637639
PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" },

crates/ra_syntax/src/grammar.ron

+2-1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ Grammar(
168168
"SLICE_PAT",
169169
"RANGE_PAT",
170170
"LITERAL_PAT",
171+
"SUBSLICE_PAT",
171172

172173
// atoms
173174
"TUPLE_EXPR",
@@ -686,7 +687,7 @@ Grammar(
686687
"LifetimeArg": (),
687688

688689
"MacroItems": (
689-
traits: [ "ModuleItemOwner", "FnDefOwner" ],
690+
traits: [ "ModuleItemOwner", "FnDefOwner" ],
690691
),
691692

692693
"MacroStmts" : (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
let [a, b..] = [];
3+
let &[ref a.., ref b] = [];
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
SOURCE_FILE@[0; 69)
2+
FN_DEF@[0; 68)
3+
FN_KW@[0; 2) "fn"
4+
WHITESPACE@[2; 3) " "
5+
NAME@[3; 7)
6+
IDENT@[3; 7) "main"
7+
PARAM_LIST@[7; 9)
8+
L_PAREN@[7; 8) "("
9+
R_PAREN@[8; 9) ")"
10+
WHITESPACE@[9; 10) " "
11+
BLOCK@[10; 68)
12+
L_CURLY@[10; 11) "{"
13+
WHITESPACE@[11; 16) "\n "
14+
LET_STMT@[16; 34)
15+
LET_KW@[16; 19) "let"
16+
WHITESPACE@[19; 20) " "
17+
SLICE_PAT@[20; 28)
18+
L_BRACK@[20; 21) "["
19+
BIND_PAT@[21; 22)
20+
NAME@[21; 22)
21+
IDENT@[21; 22) "a"
22+
COMMA@[22; 23) ","
23+
WHITESPACE@[23; 24) " "
24+
SUBSLICE_PAT@[24; 27)
25+
BIND_PAT@[24; 25)
26+
NAME@[24; 25)
27+
IDENT@[24; 25) "b"
28+
DOTDOT@[25; 27) ".."
29+
R_BRACK@[27; 28) "]"
30+
WHITESPACE@[28; 29) " "
31+
EQ@[29; 30) "="
32+
WHITESPACE@[30; 31) " "
33+
ARRAY_EXPR@[31; 33)
34+
L_BRACK@[31; 32) "["
35+
R_BRACK@[32; 33) "]"
36+
SEMI@[33; 34) ";"
37+
WHITESPACE@[34; 39) "\n "
38+
LET_STMT@[39; 66)
39+
LET_KW@[39; 42) "let"
40+
WHITESPACE@[42; 43) " "
41+
REF_PAT@[43; 60)
42+
AMP@[43; 44) "&"
43+
SLICE_PAT@[44; 60)
44+
L_BRACK@[44; 45) "["
45+
SUBSLICE_PAT@[45; 52)
46+
BIND_PAT@[45; 50)
47+
REF_KW@[45; 48) "ref"
48+
WHITESPACE@[48; 49) " "
49+
NAME@[49; 50)
50+
IDENT@[49; 50) "a"
51+
DOTDOT@[50; 52) ".."
52+
COMMA@[52; 53) ","
53+
WHITESPACE@[53; 54) " "
54+
BIND_PAT@[54; 59)
55+
REF_KW@[54; 57) "ref"
56+
WHITESPACE@[57; 58) " "
57+
NAME@[58; 59)
58+
IDENT@[58; 59) "b"
59+
R_BRACK@[59; 60) "]"
60+
WHITESPACE@[60; 61) " "
61+
EQ@[61; 62) "="
62+
WHITESPACE@[62; 63) " "
63+
ARRAY_EXPR@[63; 65)
64+
L_BRACK@[63; 64) "["
65+
R_BRACK@[64; 65) "]"
66+
SEMI@[65; 66) ";"
67+
WHITESPACE@[66; 67) "\n"
68+
R_CURLY@[67; 68) "}"
69+
WHITESPACE@[68; 69) "\n"

0 commit comments

Comments
 (0)