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