Skip to content

Commit 4a3a15f

Browse files
Parse .. as a proper pattern
1 parent 426112c commit 4a3a15f

File tree

1 file changed

+42
-10
lines changed

1 file changed

+42
-10
lines changed

crates/ra_parser/src/grammar/patterns.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::*;
22

33
pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
44
.union(paths::PATH_FIRST)
5-
.union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]);
5+
.union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS, DOT]);
66

77
pub(crate) fn pattern(p: &mut Parser) {
88
pattern_r(p, PAT_RECOVERY_SET);
@@ -73,6 +73,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
7373
_ if paths::is_use_path_start(p) => path_pat(p),
7474
_ if is_literal_pat_start(p) => literal_pat(p),
7575

76+
T![.] if p.at(T![..]) => dot_dot_pat(p),
7677
T![_] => placeholder_pat(p),
7778
T![&] => ref_pat(p),
7879
T!['('] => tuple_pat(p),
@@ -163,7 +164,9 @@ fn record_field_pat_list(p: &mut Parser) {
163164
p.bump_any();
164165
while !p.at(EOF) && !p.at(T!['}']) {
165166
match p.current() {
167+
// A trailing `..` is *not* treated as a DOT_DOT_PAT.
166168
T![.] if p.at(T![..]) => p.bump(T![..]),
169+
167170
IDENT if p.nth(1) == T![:] => record_field_pat(p),
168171
T!['{'] => error_block(p, "expected ident"),
169172
T![box] => {
@@ -201,6 +204,39 @@ fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
201204
m.complete(p, PLACEHOLDER_PAT)
202205
}
203206

207+
// test dot_dot_pat
208+
// fn main() {
209+
// let .. = ();
210+
// //
211+
// // Tuples
212+
// //
213+
// let (a, ..) = ();
214+
// let (a, ..,) = ();
215+
// let Tuple(a, ..) = ();
216+
// let Tuple(a, ..,) = ();
217+
// let (.., ..) = ();
218+
// let Tuple(.., ..) = ();
219+
// let (.., a, ..) = ();
220+
// let Tuple(.., a, ..) = ();
221+
// //
222+
// // Slices
223+
// //
224+
// let [..] = ();
225+
// let [head, ..] = ();
226+
// let [head, tail @ ..] = ();
227+
// let [head, .., cons] = ();
228+
// let [head, mid @ .., cons] = ();
229+
// let [head, .., .., cons] = ();
230+
// let [head, .., mid, tail @ ..] = ();
231+
// let [head, .., mid, .., cons] = ();
232+
// }
233+
fn dot_dot_pat(p: &mut Parser) -> CompletedMarker {
234+
assert!(p.at(T![..]));
235+
let m = p.start();
236+
p.bump(T![..]);
237+
m.complete(p, DOT_DOT_PAT)
238+
}
239+
204240
// test ref_pat
205241
// fn main() {
206242
// let &a = ();
@@ -241,16 +277,12 @@ fn slice_pat(p: &mut Parser) -> CompletedMarker {
241277

242278
fn pat_list(p: &mut Parser, ket: SyntaxKind) {
243279
while !p.at(EOF) && !p.at(ket) {
244-
match p.current() {
245-
T![.] if p.at(T![..]) => p.bump(T![..]),
246-
_ => {
247-
if !p.at_ts(PATTERN_FIRST) {
248-
p.error("expected a pattern");
249-
break;
250-
}
251-
pattern(p)
252-
}
280+
if !p.at_ts(PATTERN_FIRST) {
281+
p.error("expected a pattern");
282+
break;
253283
}
284+
285+
pattern(p);
254286
if !p.at(ket) {
255287
p.expect(T![,]);
256288
}

0 commit comments

Comments
 (0)