diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/expressions')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions/atom.rs | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs new file mode 100644 index 000000000..e74305b6a --- /dev/null +++ b/crates/ra_parser/src/grammar/expressions/atom.rs | |||
@@ -0,0 +1,475 @@ | |||
1 | use super::*; | ||
2 | |||
3 | // test expr_literals | ||
4 | // fn foo() { | ||
5 | // let _ = true; | ||
6 | // let _ = false; | ||
7 | // let _ = 1; | ||
8 | // let _ = 2.0; | ||
9 | // let _ = b'a'; | ||
10 | // let _ = 'b'; | ||
11 | // let _ = "c"; | ||
12 | // let _ = r"d"; | ||
13 | // let _ = b"e"; | ||
14 | // let _ = br"f"; | ||
15 | // } | ||
16 | pub(crate) const LITERAL_FIRST: TokenSet = token_set![ | ||
17 | TRUE_KW, | ||
18 | FALSE_KW, | ||
19 | INT_NUMBER, | ||
20 | FLOAT_NUMBER, | ||
21 | BYTE, | ||
22 | CHAR, | ||
23 | STRING, | ||
24 | RAW_STRING, | ||
25 | BYTE_STRING, | ||
26 | RAW_BYTE_STRING | ||
27 | ]; | ||
28 | |||
29 | pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> { | ||
30 | if !p.at_ts(LITERAL_FIRST) { | ||
31 | return None; | ||
32 | } | ||
33 | let m = p.start(); | ||
34 | p.bump(); | ||
35 | Some(m.complete(p, LITERAL)) | ||
36 | } | ||
37 | |||
38 | // E.g. for after the break in `if break {}`, this should not match | ||
39 | pub(super) const ATOM_EXPR_FIRST: TokenSet = | ||
40 | LITERAL_FIRST.union(paths::PATH_FIRST).union(token_set![ | ||
41 | L_PAREN, | ||
42 | L_CURLY, | ||
43 | L_BRACK, | ||
44 | PIPE, | ||
45 | MOVE_KW, | ||
46 | IF_KW, | ||
47 | WHILE_KW, | ||
48 | MATCH_KW, | ||
49 | UNSAFE_KW, | ||
50 | RETURN_KW, | ||
51 | BREAK_KW, | ||
52 | CONTINUE_KW, | ||
53 | LIFETIME, | ||
54 | ]); | ||
55 | |||
56 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; | ||
57 | |||
58 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { | ||
59 | if let Some(m) = literal(p) { | ||
60 | return Some((m, BlockLike::NotBlock)); | ||
61 | } | ||
62 | if paths::is_path_start(p) || p.at(L_ANGLE) { | ||
63 | return Some(path_expr(p, r)); | ||
64 | } | ||
65 | let la = p.nth(1); | ||
66 | let done = match p.current() { | ||
67 | L_PAREN => tuple_expr(p), | ||
68 | L_BRACK => array_expr(p), | ||
69 | PIPE => lambda_expr(p), | ||
70 | MOVE_KW if la == PIPE => lambda_expr(p), | ||
71 | IF_KW => if_expr(p), | ||
72 | |||
73 | LOOP_KW => loop_expr(p, None), | ||
74 | FOR_KW => for_expr(p, None), | ||
75 | WHILE_KW => while_expr(p, None), | ||
76 | LIFETIME if la == COLON => { | ||
77 | let m = p.start(); | ||
78 | label(p); | ||
79 | match p.current() { | ||
80 | LOOP_KW => loop_expr(p, Some(m)), | ||
81 | FOR_KW => for_expr(p, Some(m)), | ||
82 | WHILE_KW => while_expr(p, Some(m)), | ||
83 | L_CURLY => block_expr(p, Some(m)), | ||
84 | _ => { | ||
85 | // test_err misplaced_label_err | ||
86 | // fn main() { | ||
87 | // 'loop: impl | ||
88 | // } | ||
89 | p.error("expected a loop"); | ||
90 | m.complete(p, ERROR); | ||
91 | return None; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | MATCH_KW => match_expr(p), | ||
97 | UNSAFE_KW if la == L_CURLY => { | ||
98 | let m = p.start(); | ||
99 | p.bump(); | ||
100 | block_expr(p, Some(m)) | ||
101 | } | ||
102 | L_CURLY => block_expr(p, None), | ||
103 | RETURN_KW => return_expr(p), | ||
104 | CONTINUE_KW => continue_expr(p), | ||
105 | BREAK_KW => break_expr(p, r), | ||
106 | _ => { | ||
107 | p.err_recover("expected expression", EXPR_RECOVERY_SET); | ||
108 | return None; | ||
109 | } | ||
110 | }; | ||
111 | let blocklike = match done.kind() { | ||
112 | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block, | ||
113 | _ => BlockLike::NotBlock, | ||
114 | }; | ||
115 | Some((done, blocklike)) | ||
116 | } | ||
117 | |||
118 | // test tuple_expr | ||
119 | // fn foo() { | ||
120 | // (); | ||
121 | // (1); | ||
122 | // (1,); | ||
123 | // } | ||
124 | fn tuple_expr(p: &mut Parser) -> CompletedMarker { | ||
125 | assert!(p.at(L_PAREN)); | ||
126 | let m = p.start(); | ||
127 | p.expect(L_PAREN); | ||
128 | |||
129 | let mut saw_comma = false; | ||
130 | let mut saw_expr = false; | ||
131 | while !p.at(EOF) && !p.at(R_PAREN) { | ||
132 | saw_expr = true; | ||
133 | if !p.at_ts(EXPR_FIRST) { | ||
134 | p.error("expected expression"); | ||
135 | break; | ||
136 | } | ||
137 | expr(p); | ||
138 | if !p.at(R_PAREN) { | ||
139 | saw_comma = true; | ||
140 | p.expect(COMMA); | ||
141 | } | ||
142 | } | ||
143 | p.expect(R_PAREN); | ||
144 | m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR }) | ||
145 | } | ||
146 | |||
147 | // test array_expr | ||
148 | // fn foo() { | ||
149 | // []; | ||
150 | // [1]; | ||
151 | // [1, 2,]; | ||
152 | // [1; 2]; | ||
153 | // } | ||
154 | fn array_expr(p: &mut Parser) -> CompletedMarker { | ||
155 | assert!(p.at(L_BRACK)); | ||
156 | let m = p.start(); | ||
157 | p.bump(); | ||
158 | if p.eat(R_BRACK) { | ||
159 | return m.complete(p, ARRAY_EXPR); | ||
160 | } | ||
161 | expr(p); | ||
162 | if p.eat(SEMI) { | ||
163 | expr(p); | ||
164 | p.expect(R_BRACK); | ||
165 | return m.complete(p, ARRAY_EXPR); | ||
166 | } | ||
167 | while !p.at(EOF) && !p.at(R_BRACK) { | ||
168 | p.expect(COMMA); | ||
169 | if p.at(R_BRACK) { | ||
170 | break; | ||
171 | } | ||
172 | if !p.at_ts(EXPR_FIRST) { | ||
173 | p.error("expected expression"); | ||
174 | break; | ||
175 | } | ||
176 | expr(p); | ||
177 | } | ||
178 | p.expect(R_BRACK); | ||
179 | m.complete(p, ARRAY_EXPR) | ||
180 | } | ||
181 | |||
182 | // test lambda_expr | ||
183 | // fn foo() { | ||
184 | // || (); | ||
185 | // || -> i32 { 92 }; | ||
186 | // |x| x; | ||
187 | // move |x: i32,| x; | ||
188 | // } | ||
189 | fn lambda_expr(p: &mut Parser) -> CompletedMarker { | ||
190 | assert!(p.at(PIPE) || (p.at(MOVE_KW) && p.nth(1) == PIPE)); | ||
191 | let m = p.start(); | ||
192 | p.eat(MOVE_KW); | ||
193 | params::param_list_opt_types(p); | ||
194 | if opt_fn_ret_type(p) { | ||
195 | if !p.at(L_CURLY) { | ||
196 | p.error("expected `{`"); | ||
197 | } | ||
198 | } | ||
199 | expr(p); | ||
200 | m.complete(p, LAMBDA_EXPR) | ||
201 | } | ||
202 | |||
203 | // test if_expr | ||
204 | // fn foo() { | ||
205 | // if true {}; | ||
206 | // if true {} else {}; | ||
207 | // if true {} else if false {} else {}; | ||
208 | // if S {}; | ||
209 | // } | ||
210 | fn if_expr(p: &mut Parser) -> CompletedMarker { | ||
211 | assert!(p.at(IF_KW)); | ||
212 | let m = p.start(); | ||
213 | p.bump(); | ||
214 | cond(p); | ||
215 | block(p); | ||
216 | if p.at(ELSE_KW) { | ||
217 | p.bump(); | ||
218 | if p.at(IF_KW) { | ||
219 | if_expr(p); | ||
220 | } else { | ||
221 | block(p); | ||
222 | } | ||
223 | } | ||
224 | m.complete(p, IF_EXPR) | ||
225 | } | ||
226 | |||
227 | // test label | ||
228 | // fn foo() { | ||
229 | // 'a: loop {} | ||
230 | // 'b: while true {} | ||
231 | // 'c: for x in () {} | ||
232 | // } | ||
233 | fn label(p: &mut Parser) { | ||
234 | assert!(p.at(LIFETIME) && p.nth(1) == COLON); | ||
235 | let m = p.start(); | ||
236 | p.bump(); | ||
237 | p.bump(); | ||
238 | m.complete(p, LABEL); | ||
239 | } | ||
240 | |||
241 | // test loop_expr | ||
242 | // fn foo() { | ||
243 | // loop {}; | ||
244 | // } | ||
245 | fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | ||
246 | assert!(p.at(LOOP_KW)); | ||
247 | let m = m.unwrap_or_else(|| p.start()); | ||
248 | p.bump(); | ||
249 | block(p); | ||
250 | m.complete(p, LOOP_EXPR) | ||
251 | } | ||
252 | |||
253 | // test while_expr | ||
254 | // fn foo() { | ||
255 | // while true {}; | ||
256 | // while let Some(x) = it.next() {}; | ||
257 | // } | ||
258 | fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | ||
259 | assert!(p.at(WHILE_KW)); | ||
260 | let m = m.unwrap_or_else(|| p.start()); | ||
261 | p.bump(); | ||
262 | cond(p); | ||
263 | block(p); | ||
264 | m.complete(p, WHILE_EXPR) | ||
265 | } | ||
266 | |||
267 | // test for_expr | ||
268 | // fn foo() { | ||
269 | // for x in [] {}; | ||
270 | // } | ||
271 | fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | ||
272 | assert!(p.at(FOR_KW)); | ||
273 | let m = m.unwrap_or_else(|| p.start()); | ||
274 | p.bump(); | ||
275 | patterns::pattern(p); | ||
276 | p.expect(IN_KW); | ||
277 | expr_no_struct(p); | ||
278 | block(p); | ||
279 | m.complete(p, FOR_EXPR) | ||
280 | } | ||
281 | |||
282 | // test cond | ||
283 | // fn foo() { if let Some(_) = None {} } | ||
284 | fn cond(p: &mut Parser) { | ||
285 | let m = p.start(); | ||
286 | if p.eat(LET_KW) { | ||
287 | patterns::pattern(p); | ||
288 | p.expect(EQ); | ||
289 | } | ||
290 | expr_no_struct(p); | ||
291 | m.complete(p, CONDITION); | ||
292 | } | ||
293 | |||
294 | // test match_expr | ||
295 | // fn foo() { | ||
296 | // match () { }; | ||
297 | // match S {}; | ||
298 | // } | ||
299 | fn match_expr(p: &mut Parser) -> CompletedMarker { | ||
300 | assert!(p.at(MATCH_KW)); | ||
301 | let m = p.start(); | ||
302 | p.bump(); | ||
303 | expr_no_struct(p); | ||
304 | if p.at(L_CURLY) { | ||
305 | match_arm_list(p); | ||
306 | } else { | ||
307 | p.error("expected `{`") | ||
308 | } | ||
309 | m.complete(p, MATCH_EXPR) | ||
310 | } | ||
311 | |||
312 | pub(crate) fn match_arm_list(p: &mut Parser) { | ||
313 | assert!(p.at(L_CURLY)); | ||
314 | let m = p.start(); | ||
315 | p.eat(L_CURLY); | ||
316 | |||
317 | // test match_arms_inner_attribute | ||
318 | // fn foo() { | ||
319 | // match () { | ||
320 | // #![doc("Inner attribute")] | ||
321 | // #![doc("Can be")] | ||
322 | // #![doc("Stacked")] | ||
323 | // _ => (), | ||
324 | // } | ||
325 | // } | ||
326 | attributes::inner_attributes(p); | ||
327 | |||
328 | while !p.at(EOF) && !p.at(R_CURLY) { | ||
329 | if p.at(L_CURLY) { | ||
330 | error_block(p, "expected match arm"); | ||
331 | continue; | ||
332 | } | ||
333 | |||
334 | // test match_arms_outer_attributes | ||
335 | // fn foo() { | ||
336 | // match () { | ||
337 | // #[cfg(feature = "some")] | ||
338 | // _ => (), | ||
339 | // #[cfg(feature = "other")] | ||
340 | // _ => (), | ||
341 | // #[cfg(feature = "many")] | ||
342 | // #[cfg(feature = "attributes")] | ||
343 | // #[cfg(feature = "before")] | ||
344 | // _ => (), | ||
345 | // } | ||
346 | // } | ||
347 | attributes::outer_attributes(p); | ||
348 | |||
349 | // test match_arms_commas | ||
350 | // fn foo() { | ||
351 | // match () { | ||
352 | // _ => (), | ||
353 | // _ => {} | ||
354 | // _ => () | ||
355 | // } | ||
356 | // } | ||
357 | if match_arm(p).is_block() { | ||
358 | p.eat(COMMA); | ||
359 | } else if !p.at(R_CURLY) { | ||
360 | p.expect(COMMA); | ||
361 | } | ||
362 | } | ||
363 | p.expect(R_CURLY); | ||
364 | m.complete(p, MATCH_ARM_LIST); | ||
365 | } | ||
366 | |||
367 | // test match_arm | ||
368 | // fn foo() { | ||
369 | // match () { | ||
370 | // _ => (), | ||
371 | // _ if Test > Test{field: 0} => (), | ||
372 | // X | Y if Z => (), | ||
373 | // | X | Y if Z => (), | ||
374 | // | X => (), | ||
375 | // }; | ||
376 | // } | ||
377 | fn match_arm(p: &mut Parser) -> BlockLike { | ||
378 | let m = p.start(); | ||
379 | p.eat(PIPE); | ||
380 | patterns::pattern_r(p, TokenSet::empty()); | ||
381 | while p.eat(PIPE) { | ||
382 | patterns::pattern(p); | ||
383 | } | ||
384 | if p.at(IF_KW) { | ||
385 | match_guard(p); | ||
386 | } | ||
387 | p.expect(FAT_ARROW); | ||
388 | let ret = expr_stmt(p); | ||
389 | m.complete(p, MATCH_ARM); | ||
390 | ret | ||
391 | } | ||
392 | |||
393 | // test match_guard | ||
394 | // fn foo() { | ||
395 | // match () { | ||
396 | // _ if foo => (), | ||
397 | // } | ||
398 | // } | ||
399 | fn match_guard(p: &mut Parser) -> CompletedMarker { | ||
400 | assert!(p.at(IF_KW)); | ||
401 | let m = p.start(); | ||
402 | p.bump(); | ||
403 | expr(p); | ||
404 | m.complete(p, MATCH_GUARD) | ||
405 | } | ||
406 | |||
407 | // test block_expr | ||
408 | // fn foo() { | ||
409 | // {}; | ||
410 | // unsafe {}; | ||
411 | // 'label: {}; | ||
412 | // } | ||
413 | fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { | ||
414 | assert!(p.at(L_CURLY)); | ||
415 | let m = m.unwrap_or_else(|| p.start()); | ||
416 | block(p); | ||
417 | m.complete(p, BLOCK_EXPR) | ||
418 | } | ||
419 | |||
420 | // test return_expr | ||
421 | // fn foo() { | ||
422 | // return; | ||
423 | // return 92; | ||
424 | // } | ||
425 | fn return_expr(p: &mut Parser) -> CompletedMarker { | ||
426 | assert!(p.at(RETURN_KW)); | ||
427 | let m = p.start(); | ||
428 | p.bump(); | ||
429 | if p.at_ts(EXPR_FIRST) { | ||
430 | expr(p); | ||
431 | } | ||
432 | m.complete(p, RETURN_EXPR) | ||
433 | } | ||
434 | |||
435 | // test continue_expr | ||
436 | // fn foo() { | ||
437 | // loop { | ||
438 | // continue; | ||
439 | // continue 'l; | ||
440 | // } | ||
441 | // } | ||
442 | fn continue_expr(p: &mut Parser) -> CompletedMarker { | ||
443 | assert!(p.at(CONTINUE_KW)); | ||
444 | let m = p.start(); | ||
445 | p.bump(); | ||
446 | p.eat(LIFETIME); | ||
447 | m.complete(p, CONTINUE_EXPR) | ||
448 | } | ||
449 | |||
450 | // test break_expr | ||
451 | // fn foo() { | ||
452 | // loop { | ||
453 | // break; | ||
454 | // break 'l; | ||
455 | // break 92; | ||
456 | // break 'l 92; | ||
457 | // } | ||
458 | // } | ||
459 | fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { | ||
460 | assert!(p.at(BREAK_KW)); | ||
461 | let m = p.start(); | ||
462 | p.bump(); | ||
463 | p.eat(LIFETIME); | ||
464 | // test break_ambiguity | ||
465 | // fn foo(){ | ||
466 | // if break {} | ||
467 | // while break {} | ||
468 | // for i in break {} | ||
469 | // match break {} | ||
470 | // } | ||
471 | if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(L_CURLY)) { | ||
472 | expr(p); | ||
473 | } | ||
474 | m.complete(p, BREAK_EXPR) | ||
475 | } | ||