aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src/grammar/patterns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_parser/src/grammar/patterns.rs')
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs65
1 files changed, 38 insertions, 27 deletions
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index 1f6a6fd48..eae70ab85 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -56,37 +56,33 @@ const PAT_RECOVERY_SET: TokenSet =
56 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; 56 token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA];
57 57
58fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { 58fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
59 let la0 = p.nth(0); 59 // Checks the token after an IDENT to see if a pattern is a path (Struct { .. }) or macro
60 let la1 = p.nth(1); 60 // (T![x]).
61 if la0 == T![ref] 61 let is_path_or_macro_pat =
62 || la0 == T![mut] 62 |la1| la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!];
63 || la0 == T![box]
64 || (la0 == IDENT && !(la1 == T![::] || la1 == T!['('] || la1 == T!['{'] || la1 == T![!]))
65 {
66 return Some(bind_pat(p, true));
67 }
68 if paths::is_use_path_start(p) {
69 return Some(path_pat(p));
70 }
71 63
72 if is_literal_pat_start(p) { 64 let m = match p.nth(0) {
73 return Some(literal_pat(p)); 65 T![box] => box_pat(p),
74 } 66 T![ref] | T![mut] | IDENT if !is_path_or_macro_pat(p.nth(1)) => bind_pat(p, true),
67
68 _ if paths::is_use_path_start(p) => path_pat(p),
69 _ if is_literal_pat_start(p) => literal_pat(p),
75 70
76 let m = match la0 {
77 T![_] => placeholder_pat(p), 71 T![_] => placeholder_pat(p),
78 T![&] => ref_pat(p), 72 T![&] => ref_pat(p),
79 T!['('] => tuple_pat(p), 73 T!['('] => tuple_pat(p),
80 T!['['] => slice_pat(p), 74 T!['['] => slice_pat(p),
75
81 _ => { 76 _ => {
82 p.err_recover("expected pattern", recovery_set); 77 p.err_recover("expected pattern", recovery_set);
83 return None; 78 return None;
84 } 79 }
85 }; 80 };
81
86 Some(m) 82 Some(m)
87} 83}
88 84
89fn is_literal_pat_start(p: &mut Parser) -> bool { 85fn is_literal_pat_start(p: &Parser) -> bool {
90 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER) 86 p.at(T![-]) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
91 || p.at_ts(expressions::LITERAL_FIRST) 87 || p.at_ts(expressions::LITERAL_FIRST)
92} 88}
@@ -127,8 +123,8 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
127 TUPLE_STRUCT_PAT 123 TUPLE_STRUCT_PAT
128 } 124 }
129 T!['{'] => { 125 T!['{'] => {
130 field_pat_list(p); 126 record_field_pat_list(p);
131 STRUCT_PAT 127 RECORD_PAT
132 } 128 }
133 _ => PATH_PAT, 129 _ => PATH_PAT,
134 }; 130 };
@@ -149,22 +145,25 @@ fn tuple_pat_fields(p: &mut Parser) {
149 p.expect(T![')']); 145 p.expect(T![')']);
150} 146}
151 147
152// test field_pat_list 148// test record_field_pat_list
153// fn foo() { 149// fn foo() {
154// let S {} = (); 150// let S {} = ();
155// let S { f, ref mut g } = (); 151// let S { f, ref mut g } = ();
156// let S { h: _, ..} = (); 152// let S { h: _, ..} = ();
157// let S { h: _, } = (); 153// let S { h: _, } = ();
158// } 154// }
159fn field_pat_list(p: &mut Parser) { 155fn record_field_pat_list(p: &mut Parser) {
160 assert!(p.at(T!['{'])); 156 assert!(p.at(T!['{']));
161 let m = p.start(); 157 let m = p.start();
162 p.bump(); 158 p.bump();
163 while !p.at(EOF) && !p.at(T!['}']) { 159 while !p.at(EOF) && !p.at(T!['}']) {
164 match p.current() { 160 match p.current() {
165 T![..] => p.bump(), 161 T![..] => p.bump(),
166 IDENT if p.nth(1) == T![:] => field_pat(p), 162 IDENT if p.nth(1) == T![:] => record_field_pat(p),
167 T!['{'] => error_block(p, "expected ident"), 163 T!['{'] => error_block(p, "expected ident"),
164 T![box] => {
165 box_pat(p);
166 }
168 _ => { 167 _ => {
169 bind_pat(p, false); 168 bind_pat(p, false);
170 } 169 }
@@ -174,10 +173,10 @@ fn field_pat_list(p: &mut Parser) {
174 } 173 }
175 } 174 }
176 p.expect(T!['}']); 175 p.expect(T!['}']);
177 m.complete(p, FIELD_PAT_LIST); 176 m.complete(p, RECORD_FIELD_PAT_LIST);
178} 177}
179 178
180fn field_pat(p: &mut Parser) { 179fn record_field_pat(p: &mut Parser) {
181 assert!(p.at(IDENT)); 180 assert!(p.at(IDENT));
182 assert!(p.nth(1) == T![:]); 181 assert!(p.nth(1) == T![:]);
183 182
@@ -185,7 +184,7 @@ fn field_pat(p: &mut Parser) {
185 name(p); 184 name(p);
186 p.bump(); 185 p.bump();
187 pattern(p); 186 pattern(p);
188 m.complete(p, FIELD_PAT); 187 m.complete(p, RECORD_FIELD_PAT);
189} 188}
190 189
191// test placeholder_pat 190// test placeholder_pat
@@ -261,11 +260,9 @@ fn pat_list(p: &mut Parser, ket: SyntaxKind) {
261// let ref mut d = (); 260// let ref mut d = ();
262// let e @ _ = (); 261// let e @ _ = ();
263// let ref mut f @ g @ _ = (); 262// let ref mut f @ g @ _ = ();
264// let box i = Box::new(1i32);
265// } 263// }
266fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { 264fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
267 let m = p.start(); 265 let m = p.start();
268 p.eat(T![box]);
269 p.eat(T![ref]); 266 p.eat(T![ref]);
270 p.eat(T![mut]); 267 p.eat(T![mut]);
271 name(p); 268 name(p);
@@ -274,3 +271,17 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
274 } 271 }
275 m.complete(p, BIND_PAT) 272 m.complete(p, BIND_PAT)
276} 273}
274
275// test box_pat
276// fn main() {
277// let box i = ();
278// let box Outer { box i, j: box Inner(box &x) } = ();
279// let box ref mut i = ();
280// }
281fn box_pat(p: &mut Parser) -> CompletedMarker {
282 assert!(p.at(T![box]));
283 let m = p.start();
284 p.bump();
285 pattern(p);
286 m.complete(p, BOX_PAT)
287}