1 //! FIXME: write short doc here
18 pub(crate) const LITERAL_FIRST: TokenSet =
19 TokenSet::new(&[TRUE_KW, FALSE_KW, INT_NUMBER, FLOAT_NUMBER, BYTE, CHAR, STRING, BYTE_STRING]);
21 pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
22 if !p.at_ts(LITERAL_FIRST) {
27 Some(m.complete(p, LITERAL))
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(&[
55 const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[LET_KW, R_DOLLAR]);
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));
61 if paths::is_path_start(p) {
62 return Some(path_expr(p, r));
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),
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![:] => {
83 T![loop] => loop_expr(p, Some(m)),
84 T![for] => for_expr(p, Some(m)),
85 T![while] => while_expr(p, Some(m)),
87 // fn f() { 'label: {}; }
90 m.complete(p, EFFECT_EXPR)
93 // test_err misplaced_label_err
97 p.error("expected a loop");
103 T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => {
108 m.complete(p, EFFECT_EXPR)
110 T![match] => match_expr(p),
112 // fn f() { unsafe { } }
113 T![unsafe] if la == T!['{'] => {
117 m.complete(p, EFFECT_EXPR)
120 // fn f() { const { } }
121 T![const] if la == T!['{'] => {
125 m.complete(p, EFFECT_EXPR)
128 // test for_range_from
134 block_expr_unchecked(p)
136 T![return] => return_expr(p),
137 T![continue] => continue_expr(p),
138 T![break] => break_expr(p, r),
140 p.err_recover("expected expression", EXPR_RECOVERY_SET);
144 let blocklike = match done.kind() {
145 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | EFFECT_EXPR => {
148 _ => BlockLike::NotBlock,
150 Some((done, blocklike))
159 fn tuple_expr(p: &mut Parser) -> CompletedMarker {
160 assert!(p.at(T!['(']));
164 let mut saw_comma = false;
165 let mut saw_expr = false;
166 while !p.at(EOF) && !p.at(T![')']) {
170 // const A: (i64, i64) = (1, #[cfg(test)] 2);
171 if !expr_with_attrs(p) {
181 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
191 fn array_expr(p: &mut Parser) -> CompletedMarker {
192 assert!(p.at(T!['[']));
195 let mut n_exprs = 0u32;
196 let mut has_semi = false;
199 while !p.at(EOF) && !p.at(T![']']) {
203 // const A: &[i64] = &[1, #[cfg(test)] 2];
204 if !expr_with_attrs(p) {
208 if n_exprs == 1 && p.eat(T![;]) {
213 if has_semi || !p.at(T![']']) && !p.expect(T![,]) {
219 m.complete(p, ARRAY_EXPR)
232 fn closure_expr(p: &mut Parser) -> CompletedMarker {
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![|])
242 params::param_list_closure(p);
244 // test lambda_ret_block
245 // fn main() { || -> i32 { 92 }(); }
248 if p.at_ts(EXPR_FIRST) {
251 p.error("expected expression");
254 m.complete(p, CLOSURE_EXPR)
260 // if true {} else {};
261 // if true {} else if false {} else {};
263 // if { true } { } else { };
265 fn if_expr(p: &mut Parser) -> CompletedMarker {
266 assert!(p.at(T![if]));
279 m.complete(p, IF_EXPR)
286 // 'c: for x in () {}
288 fn label(p: &mut Parser) {
289 assert!(p.at(LIFETIME_IDENT) && p.nth(1) == T![:]);
293 m.complete(p, LABEL);
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());
305 m.complete(p, LOOP_EXPR)
311 // while let Some(x) = it.next() {};
312 // while { true } {};
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());
320 m.complete(p, WHILE_EXPR)
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());
331 patterns::pattern(p);
335 m.complete(p, FOR_EXPR)
339 // fn foo() { if let Some(_) = None {} }
341 // if let Some(_) | Some(_) = None {}
342 // if let | Some(_) = None {}
343 // while let Some(_) | Some(_) = None {}
344 // while let | Some(_) = None {}
346 fn condition(p: &mut Parser) {
349 patterns::pattern_top(p);
353 m.complete(p, CONDITION);
360 // match { } { _ => () };
361 // match { S {} } {};
363 fn match_expr(p: &mut Parser) -> CompletedMarker {
364 assert!(p.at(T![match]));
371 p.error("expected `{`")
373 m.complete(p, MATCH_EXPR)
376 pub(crate) fn match_arm_list(p: &mut Parser) {
377 assert!(p.at(T!['{']));
381 // test match_arms_inner_attribute
384 // #![doc("Inner attribute")]
386 // #![doc("Stacked")]
390 attributes::inner_attrs(p);
392 while !p.at(EOF) && !p.at(T!['}']) {
394 error_block(p, "expected match arm");
398 // test match_arms_commas
406 if match_arm(p).is_block() {
408 } else if !p.at(T!['}']) {
413 m.complete(p, MATCH_ARM_LIST);
420 // _ if Test > Test{field: 0} => (),
422 // | X | Y if Z => (),
426 fn match_arm(p: &mut Parser) -> BlockLike {
428 // test match_arms_outer_attributes
431 // #[cfg(feature = "some")]
433 // #[cfg(feature = "other")]
435 // #[cfg(feature = "many")]
436 // #[cfg(feature = "attributes")]
437 // #[cfg(feature = "before")]
441 attributes::outer_attrs(p);
443 patterns::pattern_top_r(p, TokenSet::EMPTY);
448 let blocklike = expr_stmt(p).1;
449 m.complete(p, MATCH_ARM);
459 fn match_guard(p: &mut Parser) -> CompletedMarker {
460 assert!(p.at(T![if]));
464 m.complete(p, MATCH_GUARD)
469 // fn b() { let _ = 1; }
472 pub(crate) fn block_expr(p: &mut Parser) {
474 p.error("expected a block");
477 block_expr_unchecked(p);
480 fn block_expr_unchecked(p: &mut Parser) -> CompletedMarker {
481 assert!(p.at(T!['{']));
484 expr_block_contents(p);
486 m.complete(p, BLOCK_EXPR)
494 fn return_expr(p: &mut Parser) -> CompletedMarker {
495 assert!(p.at(T![return]));
498 if p.at_ts(EXPR_FIRST) {
501 m.complete(p, RETURN_EXPR)
504 // test continue_expr
511 fn continue_expr(p: &mut Parser) -> CompletedMarker {
512 assert!(p.at(T![continue]));
514 p.bump(T![continue]);
515 if p.at(LIFETIME_IDENT) {
518 m.complete(p, CONTINUE_EXPR)
530 fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
531 assert!(p.at(T![break]));
534 if p.at(LIFETIME_IDENT) {
537 // test break_ambiguity
544 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
547 m.complete(p, BREAK_EXPR)
550 // test try_block_expr
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();
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);
575 m.complete(p, EFFECT_EXPR)
581 // let y = (box 1i32, box 2i32);
582 // let z = Foo(box 1i32, box 2i32);
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());
588 if p.at_ts(EXPR_FIRST) {
591 m.complete(p, BOX_EXPR)
594 /// Expression from `$var` macro expansion, wrapped in dollars
595 fn meta_var_expr(p: &mut Parser) -> CompletedMarker {
596 assert!(p.at(L_DOLLAR));
599 let (completed, _is_block) =
600 expr_bp(p, Restrictions { forbid_structs: false, prefer_stmt: false }, 1);
602 match (completed, p.current()) {
603 (Some(it), R_DOLLAR) => {
609 while !p.at(R_DOLLAR) {