]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/grammar/expressions/atom.rs
c7a3556a775092960a18e3b1aa8b45f4482102ad
[rust.git] / crates / parser / src / grammar / expressions / atom.rs
1 //! FIXME: write short doc here
2
3 use super::*;
4
5 // test expr_literals
6 // fn foo() {
7 //     let _ = true;
8 //     let _ = false;
9 //     let _ = 1;
10 //     let _ = 2.0;
11 //     let _ = b'a';
12 //     let _ = 'b';
13 //     let _ = "c";
14 //     let _ = r"d";
15 //     let _ = b"e";
16 //     let _ = br"f";
17 // }
18 pub(crate) const LITERAL_FIRST: TokenSet =
19     TokenSet::new(&[TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR, STRING, BYTE_STRING]);
20
21 pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
22     if !p.at_ts(LITERAL_FIRST) {
23         return None;
24     }
25     let m = p.start();
26     p.bump_any();
27     Some(m.complete(p, LITERAL))
28 }
29
30 // E.g. for after the break in `if break {}`, this should not match
31 pub(super) const ATOM_EXPR_FIRST: TokenSet =
32     LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[
33         T!['('],
34         T!['{'],
35         T!['['],
36         L_DOLLAR,
37         T![|],
38         T![move],
39         T![box],
40         T![if],
41         T![while],
42         T![match],
43         T![unsafe],
44         T![return],
45         T![break],
46         T![continue],
47         T![async],
48         T![try],
49         T![const],
50         T![loop],
51         T![for],
52         LIFETIME_IDENT,
53     ]));
54
55 const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[LET_KW, R_DOLLAR]);
56
57 pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
58     if let Some(m) = literal(p) {
59         return Some((m, BlockLike::NotBlock));
60     }
61     if paths::is_path_start(p) {
62         return Some(path_expr(p, r));
63     }
64     let la = p.nth(1);
65     let done = match p.current() {
66         T!['('] => tuple_expr(p),
67         T!['['] => array_expr(p),
68         L_DOLLAR => meta_var_expr(p),
69         T![|] => closure_expr(p),
70         T![move] if la == T![|] => closure_expr(p),
71         T![async] if la == T![|] || (la == T![move] && p.nth(2) == T![|]) => closure_expr(p),
72         T![if] => if_expr(p),
73
74         T![loop] => loop_expr(p, None),
75         T![box] => box_expr(p, None),
76         T![for] => for_expr(p, None),
77         T![while] => while_expr(p, None),
78         T![try] => try_block_expr(p, None),
79         LIFETIME_IDENT if la == T![:] => {
80             let m = p.start();
81             label(p);
82             match p.current() {
83                 T![loop] => loop_expr(p, Some(m)),
84                 T![for] => for_expr(p, Some(m)),
85                 T![while] => while_expr(p, Some(m)),
86                 // test labeled_block
87                 // fn f() { 'label: {}; }
88                 T!['{'] => {
89                     block_expr(p);
90                     m.complete(p, EFFECT_EXPR)
91                 }
92                 _ => {
93                     // test_err misplaced_label_err
94                     // fn main() {
95                     //     'loop: impl
96                     // }
97                     p.error("expected a loop");
98                     m.complete(p, ERROR);
99                     return None;
100                 }
101             }
102         }
103         T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => {
104             let m = p.start();
105             p.bump(T![async]);
106             p.eat(T![move]);
107             block_expr(p);
108             m.complete(p, EFFECT_EXPR)
109         }
110         T![match] => match_expr(p),
111         // test unsafe_block
112         // fn f() { unsafe { } }
113         T![unsafe] if la == T!['{'] => {
114             let m = p.start();
115             p.bump(T![unsafe]);
116             block_expr(p);
117             m.complete(p, EFFECT_EXPR)
118         }
119         // test const_block
120         // fn f() { const { } }
121         T![const] if la == T!['{'] => {
122             let m = p.start();
123             p.bump(T![const]);
124             block_expr(p);
125             m.complete(p, EFFECT_EXPR)
126         }
127         T!['{'] => {
128             // test for_range_from
129             // fn foo() {
130             //    for x in 0 .. {
131             //        break;
132             //    }
133             // }
134             block_expr_unchecked(p)
135         }
136         T![return] => return_expr(p),
137         T![continue] => continue_expr(p),
138         T![break] => break_expr(p, r),
139         _ => {
140             p.err_recover("expected expression", EXPR_RECOVERY_SET);
141             return None;
142         }
143     };
144     let blocklike = match done.kind() {
145         IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | EFFECT_EXPR => {
146             BlockLike::Block
147         }
148         _ => BlockLike::NotBlock,
149     };
150     Some((done, blocklike))
151 }
152
153 // test tuple_expr
154 // fn foo() {
155 //     ();
156 //     (1);
157 //     (1,);
158 // }
159 fn tuple_expr(p: &mut Parser) -> CompletedMarker {
160     assert!(p.at(T!['(']));
161     let m = p.start();
162     p.expect(T!['(']);
163
164     let mut saw_comma = false;
165     let mut saw_expr = false;
166     while !p.at(EOF) && !p.at(T![')']) {
167         saw_expr = true;
168
169         // test tuple_attrs
170         // const A: (i64, i64) = (1, #[cfg(test)] 2);
171         if !expr_with_attrs(p) {
172             break;
173         }
174
175         if !p.at(T![')']) {
176             saw_comma = true;
177             p.expect(T![,]);
178         }
179     }
180     p.expect(T![')']);
181     m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
182 }
183
184 // test array_expr
185 // fn foo() {
186 //     [];
187 //     [1];
188 //     [1, 2,];
189 //     [1; 2];
190 // }
191 fn array_expr(p: &mut Parser) -> CompletedMarker {
192     assert!(p.at(T!['[']));
193     let m = p.start();
194
195     let mut n_exprs = 0u32;
196     let mut has_semi = false;
197
198     p.bump(T!['[']);
199     while !p.at(EOF) && !p.at(T![']']) {
200         n_exprs += 1;
201
202         // test array_attrs
203         // const A: &[i64] = &[1, #[cfg(test)] 2];
204         if !expr_with_attrs(p) {
205             break;
206         }
207
208         if n_exprs == 1 && p.eat(T![;]) {
209             has_semi = true;
210             continue;
211         }
212
213         if has_semi || !p.at(T![']']) && !p.expect(T![,]) {
214             break;
215         }
216     }
217     p.expect(T![']']);
218
219     m.complete(p, ARRAY_EXPR)
220 }
221
222 // test lambda_expr
223 // fn foo() {
224 //     || ();
225 //     || -> i32 { 92 };
226 //     |x| x;
227 //     move |x: i32,| x;
228 //     async || {};
229 //     move || {};
230 //     async move || {};
231 // }
232 fn closure_expr(p: &mut Parser) -> CompletedMarker {
233     assert!(
234         p.at(T![|])
235             || (p.at(T![move]) && p.nth(1) == T![|])
236             || (p.at(T![async]) && p.nth(1) == T![|])
237             || (p.at(T![async]) && p.nth(1) == T![move] && p.nth(2) == T![|])
238     );
239     let m = p.start();
240     p.eat(T![async]);
241     p.eat(T![move]);
242     params::param_list_closure(p);
243     if opt_ret_type(p) {
244         // test lambda_ret_block
245         // fn main() { || -> i32 { 92 }(); }
246         block_expr(p);
247     } else {
248         if p.at_ts(EXPR_FIRST) {
249             expr(p);
250         } else {
251             p.error("expected expression");
252         }
253     }
254     m.complete(p, CLOSURE_EXPR)
255 }
256
257 // test if_expr
258 // fn foo() {
259 //     if true {};
260 //     if true {} else {};
261 //     if true {} else if false {} else {};
262 //     if S {};
263 //     if { true } { } else { };
264 // }
265 fn if_expr(p: &mut Parser) -> CompletedMarker {
266     assert!(p.at(T![if]));
267     let m = p.start();
268     p.bump(T![if]);
269     condition(p);
270     block_expr(p);
271     if p.at(T![else]) {
272         p.bump(T![else]);
273         if p.at(T![if]) {
274             if_expr(p);
275         } else {
276             block_expr(p);
277         }
278     }
279     m.complete(p, IF_EXPR)
280 }
281
282 // test label
283 // fn foo() {
284 //     'a: loop {}
285 //     'b: while true {}
286 //     'c: for x in () {}
287 // }
288 fn label(p: &mut Parser) {
289     assert!(p.at(LIFETIME_IDENT) && p.nth(1) == T![:]);
290     let m = p.start();
291     lifetime(p);
292     p.bump_any();
293     m.complete(p, LABEL);
294 }
295
296 // test loop_expr
297 // fn foo() {
298 //     loop {};
299 // }
300 fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
301     assert!(p.at(T![loop]));
302     let m = m.unwrap_or_else(|| p.start());
303     p.bump(T![loop]);
304     block_expr(p);
305     m.complete(p, LOOP_EXPR)
306 }
307
308 // test while_expr
309 // fn foo() {
310 //     while true {};
311 //     while let Some(x) = it.next() {};
312 //     while { true } {};
313 // }
314 fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
315     assert!(p.at(T![while]));
316     let m = m.unwrap_or_else(|| p.start());
317     p.bump(T![while]);
318     condition(p);
319     block_expr(p);
320     m.complete(p, WHILE_EXPR)
321 }
322
323 // test for_expr
324 // fn foo() {
325 //     for x in [] {};
326 // }
327 fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
328     assert!(p.at(T![for]));
329     let m = m.unwrap_or_else(|| p.start());
330     p.bump(T![for]);
331     patterns::pattern(p);
332     p.expect(T![in]);
333     expr_no_struct(p);
334     block_expr(p);
335     m.complete(p, FOR_EXPR)
336 }
337
338 // test cond
339 // fn foo() { if let Some(_) = None {} }
340 // fn bar() {
341 //     if let Some(_) | Some(_) = None {}
342 //     if let | Some(_) = None {}
343 //     while let Some(_) | Some(_) = None {}
344 //     while let | Some(_) = None {}
345 // }
346 fn condition(p: &mut Parser) {
347     let m = p.start();
348     if p.eat(T![let]) {
349         patterns::pattern_top(p);
350         p.expect(T![=]);
351     }
352     expr_no_struct(p);
353     m.complete(p, CONDITION);
354 }
355
356 // test match_expr
357 // fn foo() {
358 //     match () { };
359 //     match S {};
360 //     match { } { _ => () };
361 //     match { S {} } {};
362 // }
363 fn match_expr(p: &mut Parser) -> CompletedMarker {
364     assert!(p.at(T![match]));
365     let m = p.start();
366     p.bump(T![match]);
367     expr_no_struct(p);
368     if p.at(T!['{']) {
369         match_arm_list(p);
370     } else {
371         p.error("expected `{`")
372     }
373     m.complete(p, MATCH_EXPR)
374 }
375
376 pub(crate) fn match_arm_list(p: &mut Parser) {
377     assert!(p.at(T!['{']));
378     let m = p.start();
379     p.eat(T!['{']);
380
381     // test match_arms_inner_attribute
382     // fn foo() {
383     //     match () {
384     //         #![doc("Inner attribute")]
385     //         #![doc("Can be")]
386     //         #![doc("Stacked")]
387     //         _ => (),
388     //     }
389     // }
390     attributes::inner_attrs(p);
391
392     while !p.at(EOF) && !p.at(T!['}']) {
393         if p.at(T!['{']) {
394             error_block(p, "expected match arm");
395             continue;
396         }
397
398         // test match_arms_commas
399         // fn foo() {
400         //     match () {
401         //         _ => (),
402         //         _ => {}
403         //         _ => ()
404         //     }
405         // }
406         if match_arm(p).is_block() {
407             p.eat(T![,]);
408         } else if !p.at(T!['}']) {
409             p.expect(T![,]);
410         }
411     }
412     p.expect(T!['}']);
413     m.complete(p, MATCH_ARM_LIST);
414 }
415
416 // test match_arm
417 // fn foo() {
418 //     match () {
419 //         _ => (),
420 //         _ if Test > Test{field: 0} => (),
421 //         X | Y if Z => (),
422 //         | X | Y if Z => (),
423 //         | X => (),
424 //     };
425 // }
426 fn match_arm(p: &mut Parser) -> BlockLike {
427     let m = p.start();
428     // test match_arms_outer_attributes
429     // fn foo() {
430     //     match () {
431     //         #[cfg(feature = "some")]
432     //         _ => (),
433     //         #[cfg(feature = "other")]
434     //         _ => (),
435     //         #[cfg(feature = "many")]
436     //         #[cfg(feature = "attributes")]
437     //         #[cfg(feature = "before")]
438     //         _ => (),
439     //     }
440     // }
441     attributes::outer_attrs(p);
442
443     patterns::pattern_top_r(p, TokenSet::EMPTY);
444     if p.at(T![if]) {
445         match_guard(p);
446     }
447     p.expect(T![=>]);
448     let blocklike = expr_stmt(p).1;
449     m.complete(p, MATCH_ARM);
450     blocklike
451 }
452
453 // test match_guard
454 // fn foo() {
455 //     match () {
456 //         _ if foo => (),
457 //     }
458 // }
459 fn match_guard(p: &mut Parser) -> CompletedMarker {
460     assert!(p.at(T![if]));
461     let m = p.start();
462     p.bump(T![if]);
463     expr(p);
464     m.complete(p, MATCH_GUARD)
465 }
466
467 // test block
468 // fn a() {}
469 // fn b() { let _ = 1; }
470 // fn c() { 1; 2; }
471 // fn d() { 1; 2 }
472 pub(crate) fn block_expr(p: &mut Parser) {
473     if !p.at(T!['{']) {
474         p.error("expected a block");
475         return;
476     }
477     block_expr_unchecked(p);
478 }
479
480 fn block_expr_unchecked(p: &mut Parser) -> CompletedMarker {
481     assert!(p.at(T!['{']));
482     let m = p.start();
483     p.bump(T!['{']);
484     expr_block_contents(p);
485     p.expect(T!['}']);
486     m.complete(p, BLOCK_EXPR)
487 }
488
489 // test return_expr
490 // fn foo() {
491 //     return;
492 //     return 92;
493 // }
494 fn return_expr(p: &mut Parser) -> CompletedMarker {
495     assert!(p.at(T![return]));
496     let m = p.start();
497     p.bump(T![return]);
498     if p.at_ts(EXPR_FIRST) {
499         expr(p);
500     }
501     m.complete(p, RETURN_EXPR)
502 }
503
504 // test continue_expr
505 // fn foo() {
506 //     loop {
507 //         continue;
508 //         continue 'l;
509 //     }
510 // }
511 fn continue_expr(p: &mut Parser) -> CompletedMarker {
512     assert!(p.at(T![continue]));
513     let m = p.start();
514     p.bump(T![continue]);
515     if p.at(LIFETIME_IDENT) {
516         lifetime(p);
517     }
518     m.complete(p, CONTINUE_EXPR)
519 }
520
521 // test break_expr
522 // fn foo() {
523 //     loop {
524 //         break;
525 //         break 'l;
526 //         break 92;
527 //         break 'l 92;
528 //     }
529 // }
530 fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
531     assert!(p.at(T![break]));
532     let m = p.start();
533     p.bump(T![break]);
534     if p.at(LIFETIME_IDENT) {
535         lifetime(p);
536     }
537     // test break_ambiguity
538     // fn foo(){
539     //     if break {}
540     //     while break {}
541     //     for i in break {}
542     //     match break {}
543     // }
544     if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
545         expr(p);
546     }
547     m.complete(p, BREAK_EXPR)
548 }
549
550 // test try_block_expr
551 // fn foo() {
552 //     let _ = try {};
553 // }
554 fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
555     assert!(p.at(T![try]));
556     let m = m.unwrap_or_else(|| p.start());
557     // Special-case `try!` as macro.
558     // This is a hack until we do proper edition support
559     if p.nth_at(1, T![!]) {
560         // test try_macro_fallback
561         // fn foo() { try!(Ok(())); }
562         let path = p.start();
563         let path_segment = p.start();
564         let name_ref = p.start();
565         p.bump_remap(IDENT);
566         name_ref.complete(p, NAME_REF);
567         path_segment.complete(p, PATH_SEGMENT);
568         path.complete(p, PATH);
569         let _block_like = items::macro_call_after_excl(p);
570         return m.complete(p, MACRO_CALL);
571     }
572
573     p.bump(T![try]);
574     block_expr(p);
575     m.complete(p, EFFECT_EXPR)
576 }
577
578 // test box_expr
579 // fn foo() {
580 //     let x = box 1i32;
581 //     let y = (box 1i32, box 2i32);
582 //     let z = Foo(box 1i32, box 2i32);
583 // }
584 fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
585     assert!(p.at(T![box]));
586     let m = m.unwrap_or_else(|| p.start());
587     p.bump(T![box]);
588     if p.at_ts(EXPR_FIRST) {
589         expr(p);
590     }
591     m.complete(p, BOX_EXPR)
592 }
593
594 /// Expression from `$var` macro expansion, wrapped in dollars
595 fn meta_var_expr(p: &mut Parser) -> CompletedMarker {
596     assert!(p.at(L_DOLLAR));
597     let m = p.start();
598     p.bump(L_DOLLAR);
599     let (completed, _is_block) =
600         expr_bp(p, Restrictions { forbid_structs: false, prefer_stmt: false }, 1);
601
602     match (completed, p.current()) {
603         (Some(it), R_DOLLAR) => {
604             p.bump(R_DOLLAR);
605             m.abandon(p);
606             it
607         }
608         _ => {
609             while !p.at(R_DOLLAR) {
610                 p.bump_any()
611             }
612             p.bump(R_DOLLAR);
613             m.complete(p, ERROR)
614         }
615     }
616 }