diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/patterns.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/patterns.rs | 65 |
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 | ||
58 | fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> { | 58 | fn 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 | ||
89 | fn is_literal_pat_start(p: &mut Parser) -> bool { | 85 | fn 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 | // } |
159 | fn field_pat_list(p: &mut Parser) { | 155 | fn 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 | ||
180 | fn field_pat(p: &mut Parser) { | 179 | fn 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 | // } |
266 | fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker { | 264 | fn 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 | // } | ||
281 | fn 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 | } | ||