16 pub(crate) const LITERAL_FIRST: TokenSet = TokenSet::new(&[
27 pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
28 if !p.at_ts(LITERAL_FIRST) {
33 Some(m.complete(p, LITERAL))
36 // E.g. for after the break in `if break {}`, this should not match
37 pub(super) const ATOM_EXPR_FIRST: TokenSet =
38 LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[
62 const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![let], R_DOLLAR]);
64 pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
65 if let Some(m) = literal(p) {
66 return Some((m, BlockLike::NotBlock));
68 if paths::is_path_start(p) {
69 return Some(path_expr(p, r));
72 let done = match p.current() {
73 T!['('] => tuple_expr(p),
74 T!['['] => array_expr(p),
75 L_DOLLAR => meta_var_expr(p),
76 T![|] => closure_expr(p),
77 T![move] if la == T![|] => closure_expr(p),
78 T![async] if la == T![|] || (la == T![move] && p.nth(2) == T![|]) => closure_expr(p),
81 T![loop] => loop_expr(p, None),
82 T![box] => box_expr(p, None),
83 T![for] => for_expr(p, None),
84 T![while] => while_expr(p, None),
85 T![try] => try_block_expr(p, None),
86 LIFETIME_IDENT if la == T![:] => {
90 T![loop] => loop_expr(p, Some(m)),
91 T![for] => for_expr(p, Some(m)),
92 T![while] => while_expr(p, Some(m)),
94 // fn f() { 'label: {}; }
97 m.complete(p, BLOCK_EXPR)
100 // test_err misplaced_label_err
104 p.error("expected a loop");
105 m.complete(p, ERROR);
110 T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => {
115 m.complete(p, BLOCK_EXPR)
117 T![match] => match_expr(p),
119 // fn f() { unsafe { } }
120 T![unsafe] if la == T!['{'] => {
124 m.complete(p, BLOCK_EXPR)
127 // fn f() { const { } }
128 T![const] if la == T!['{'] => {
132 m.complete(p, BLOCK_EXPR)
135 // test for_range_from
143 m.complete(p, BLOCK_EXPR)
145 T![return] => return_expr(p),
146 T![yield] => yield_expr(p),
147 T![continue] => continue_expr(p),
148 T![break] => break_expr(p, r),
150 p.err_recover("expected expression", EXPR_RECOVERY_SET);
154 let blocklike = match done.kind() {
155 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block,
156 _ => BlockLike::NotBlock,
158 Some((done, blocklike))
167 fn tuple_expr(p: &mut Parser) -> CompletedMarker {
168 assert!(p.at(T!['(']));
172 let mut saw_comma = false;
173 let mut saw_expr = false;
174 while !p.at(EOF) && !p.at(T![')']) {
178 // const A: (i64, i64) = (1, #[cfg(test)] 2);
189 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
199 fn array_expr(p: &mut Parser) -> CompletedMarker {
200 assert!(p.at(T!['[']));
203 let mut n_exprs = 0u32;
204 let mut has_semi = false;
207 while !p.at(EOF) && !p.at(T![']']) {
211 // const A: &[i64] = &[1, #[cfg(test)] 2];
216 if n_exprs == 1 && p.eat(T![;]) {
221 if has_semi || !p.at(T![']']) && !p.expect(T![,]) {
227 m.complete(p, ARRAY_EXPR)
240 fn closure_expr(p: &mut Parser) -> CompletedMarker {
243 || (p.at(T![move]) && p.nth(1) == T![|])
244 || (p.at(T![async]) && p.nth(1) == T![|])
245 || (p.at(T![async]) && p.nth(1) == T![move] && p.nth(2) == T![|])
250 params::param_list_closure(p);
252 // test lambda_ret_block
253 // fn main() { || -> i32 { 92 }(); }
255 } else if p.at_ts(EXPR_FIRST) {
258 p.error("expected expression");
260 m.complete(p, CLOSURE_EXPR)
266 // if true {} else {};
267 // if true {} else if false {} else {};
269 // if { true } { } else { };
271 fn if_expr(p: &mut Parser) -> CompletedMarker {
272 assert!(p.at(T![if]));
285 m.complete(p, IF_EXPR)
292 // 'c: for x in () {}
294 fn label(p: &mut Parser) {
295 assert!(p.at(LIFETIME_IDENT) && p.nth(1) == T![:]);
299 m.complete(p, LABEL);
306 fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
307 assert!(p.at(T![loop]));
308 let m = m.unwrap_or_else(|| p.start());
311 m.complete(p, LOOP_EXPR)
317 // while let Some(x) = it.next() {};
318 // while { true } {};
320 fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
321 assert!(p.at(T![while]));
322 let m = m.unwrap_or_else(|| p.start());
326 m.complete(p, WHILE_EXPR)
333 fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
334 assert!(p.at(T![for]));
335 let m = m.unwrap_or_else(|| p.start());
337 patterns::pattern(p);
341 m.complete(p, FOR_EXPR)
345 // fn foo() { if let Some(_) = None {} }
347 // if let Some(_) | Some(_) = None {}
348 // if let | Some(_) = None {}
349 // while let Some(_) | Some(_) = None {}
350 // while let | Some(_) = None {}
352 fn condition(p: &mut Parser) {
355 patterns::pattern_top(p);
359 m.complete(p, CONDITION);
366 // match { } { _ => () };
367 // match { S {} } {};
369 fn match_expr(p: &mut Parser) -> CompletedMarker {
370 assert!(p.at(T![match]));
377 p.error("expected `{`");
379 m.complete(p, MATCH_EXPR)
382 pub(crate) fn match_arm_list(p: &mut Parser) {
383 assert!(p.at(T!['{']));
387 // test match_arms_inner_attribute
390 // #![doc("Inner attribute")]
392 // #![doc("Stacked")]
396 attributes::inner_attrs(p);
398 while !p.at(EOF) && !p.at(T!['}']) {
400 error_block(p, "expected match arm");
406 m.complete(p, MATCH_ARM_LIST);
413 // _ if Test > Test{field: 0} => (),
415 // | X | Y if Z => (),
419 fn match_arm(p: &mut Parser) {
421 // test match_arms_outer_attributes
424 // #[cfg(feature = "some")]
426 // #[cfg(feature = "other")]
428 // #[cfg(feature = "many")]
429 // #[cfg(feature = "attributes")]
430 // #[cfg(feature = "before")]
434 attributes::outer_attrs(p);
436 patterns::pattern_top_r(p, TokenSet::EMPTY);
441 let blocklike = match expr_stmt(p, None) {
442 Some((_, blocklike)) => blocklike,
443 None => BlockLike::NotBlock,
446 // test match_arms_commas
454 if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
455 p.error("expected `,`");
457 m.complete(p, MATCH_ARM);
464 // _ if let foo = bar => (),
467 fn match_guard(p: &mut Parser) -> CompletedMarker {
468 assert!(p.at(T![if]));
472 patterns::pattern_top(p);
476 m.complete(p, MATCH_GUARD)
481 // fn b() { let _ = 1; }
484 pub(crate) fn block_expr(p: &mut Parser) {
486 p.error("expected a block");
491 m.complete(p, BLOCK_EXPR);
494 fn stmt_list(p: &mut Parser) -> CompletedMarker {
495 assert!(p.at(T!['{']));
498 expr_block_contents(p);
500 m.complete(p, STMT_LIST)
508 fn return_expr(p: &mut Parser) -> CompletedMarker {
509 assert!(p.at(T![return]));
512 if p.at_ts(EXPR_FIRST) {
515 m.complete(p, RETURN_EXPR)
522 fn yield_expr(p: &mut Parser) -> CompletedMarker {
523 assert!(p.at(T![yield]));
526 if p.at_ts(EXPR_FIRST) {
529 m.complete(p, YIELD_EXPR)
532 // test continue_expr
539 fn continue_expr(p: &mut Parser) -> CompletedMarker {
540 assert!(p.at(T![continue]));
542 p.bump(T![continue]);
543 if p.at(LIFETIME_IDENT) {
546 m.complete(p, CONTINUE_EXPR)
558 fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
559 assert!(p.at(T![break]));
562 if p.at(LIFETIME_IDENT) {
565 // test break_ambiguity
572 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
575 m.complete(p, BREAK_EXPR)
578 // test try_block_expr
582 fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
583 assert!(p.at(T![try]));
584 let m = m.unwrap_or_else(|| p.start());
585 // Special-case `try!` as macro.
586 // This is a hack until we do proper edition support
587 if p.nth_at(1, T![!]) {
588 // test try_macro_fallback
589 // fn foo() { try!(Ok(())); }
590 let path = p.start();
591 let path_segment = p.start();
592 let name_ref = p.start();
594 name_ref.complete(p, NAME_REF);
595 path_segment.complete(p, PATH_SEGMENT);
596 path.complete(p, PATH);
597 let _block_like = items::macro_call_after_excl(p);
598 return m.complete(p, MACRO_CALL);
605 p.error("expected a block");
607 m.complete(p, BLOCK_EXPR)
613 // let y = (box 1i32, box 2i32);
614 // let z = Foo(box 1i32, box 2i32);
616 fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
617 assert!(p.at(T![box]));
618 let m = m.unwrap_or_else(|| p.start());
620 if p.at_ts(EXPR_FIRST) {
623 m.complete(p, BOX_EXPR)
626 /// Expression from `$var` macro expansion, wrapped in dollars
627 fn meta_var_expr(p: &mut Parser) -> CompletedMarker {
628 assert!(p.at(L_DOLLAR));
631 let expr = expr_bp(p, None, Restrictions { forbid_structs: false, prefer_stmt: false }, 1);
633 match (expr, p.current()) {
634 (Some((cm, _)), R_DOLLAR) => {
636 // FIXME: this leaves the dollar hanging in the air...
641 while !p.at(R_DOLLAR) {