X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fparser%2Fsrc%2Fgrammar%2Fexpressions%2Fatom.rs;h=e2c1b1fec579ce7358aef88a16b30f1d9d0f43d5;hb=0b53744f2d7e0694cd7207cca632fd6de1dc5bff;hp=d61950b96a049a9a37779e15b91f9a5ccfec48d1;hpb=42e00032c6ba07eaf2f7d5886c60133c65d84cf5;p=rust.git diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index d61950b96a0..e2c1b1fec57 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -1,5 +1,3 @@ -//! FIXME: write short doc here - use super::*; // test expr_literals @@ -41,7 +39,6 @@ pub(crate) fn literal(p: &mut Parser) -> Option { T!['('], T!['{'], T!['['], - L_DOLLAR, T![|], T![move], T![box], @@ -50,6 +47,7 @@ pub(crate) fn literal(p: &mut Parser) -> Option { T![match], T![unsafe], T![return], + T![yield], T![break], T![continue], T![async], @@ -60,7 +58,7 @@ pub(crate) fn literal(p: &mut Parser) -> Option { LIFETIME_IDENT, ])); -const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[LET_KW, R_DOLLAR]); +const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![let]]); pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { if let Some(m) = literal(p) { @@ -73,11 +71,15 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar let done = match p.current() { T!['('] => tuple_expr(p), T!['['] => array_expr(p), - L_DOLLAR => meta_var_expr(p), T![|] => closure_expr(p), - T![move] if la == T![|] => closure_expr(p), - T![async] if la == T![|] || (la == T![move] && p.nth(2) == T![|]) => closure_expr(p), + T![static] | T![async] | T![move] if la == T![|] => closure_expr(p), + T![static] | T![async] if la == T![move] && p.nth(2) == T![|] => closure_expr(p), + T![static] if la == T![async] && p.nth(2) == T![|] => closure_expr(p), + T![static] if la == T![async] && p.nth(2) == T![move] && p.nth(3) == T![|] => { + closure_expr(p) + } T![if] => if_expr(p), + T![let] => let_expr(p), T![loop] => loop_expr(p, None), T![box] => box_expr(p, None), @@ -94,8 +96,8 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar // test labeled_block // fn f() { 'label: {}; } T!['{'] => { - block_expr(p); - m.complete(p, EFFECT_EXPR) + stmt_list(p); + m.complete(p, BLOCK_EXPR) } _ => { // test_err misplaced_label_err @@ -112,8 +114,8 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar let m = p.start(); p.bump(T![async]); p.eat(T![move]); - block_expr(p); - m.complete(p, EFFECT_EXPR) + stmt_list(p); + m.complete(p, BLOCK_EXPR) } T![match] => match_expr(p), // test unsafe_block @@ -121,16 +123,16 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar T![unsafe] if la == T!['{'] => { let m = p.start(); p.bump(T![unsafe]); - block_expr(p); - m.complete(p, EFFECT_EXPR) + stmt_list(p); + m.complete(p, BLOCK_EXPR) } // test const_block // fn f() { const { } } T![const] if la == T!['{'] => { let m = p.start(); p.bump(T![const]); - block_expr(p); - m.complete(p, EFFECT_EXPR) + stmt_list(p); + m.complete(p, BLOCK_EXPR) } T!['{'] => { // test for_range_from @@ -139,9 +141,12 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar // break; // } // } - block_expr_unchecked(p) + let m = p.start(); + stmt_list(p); + m.complete(p, BLOCK_EXPR) } T![return] => return_expr(p), + T![yield] => yield_expr(p), T![continue] => continue_expr(p), T![break] => break_expr(p, r), _ => { @@ -150,9 +155,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar } }; let blocklike = match done.kind() { - IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | EFFECT_EXPR => { - BlockLike::Block - } + IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block, _ => BlockLike::NotBlock, }; Some((done, blocklike)) @@ -176,7 +179,7 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker { // test tuple_attrs // const A: (i64, i64) = (1, #[cfg(test)] 2); - if !expr_with_attrs(p) { + if !expr(p) { break; } @@ -209,7 +212,7 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { // test array_attrs // const A: &[i64] = &[1, #[cfg(test)] 2]; - if !expr_with_attrs(p) { + if !expr(p) { break; } @@ -236,6 +239,10 @@ fn array_expr(p: &mut Parser) -> CompletedMarker { // async || {}; // move || {}; // async move || {}; +// static || {}; +// static move || {}; +// static async || {}; +// static async move || {}; // } fn closure_expr(p: &mut Parser) -> CompletedMarker { assert!( @@ -243,8 +250,16 @@ fn closure_expr(p: &mut Parser) -> CompletedMarker { || (p.at(T![move]) && p.nth(1) == T![|]) || (p.at(T![async]) && p.nth(1) == T![|]) || (p.at(T![async]) && p.nth(1) == T![move] && p.nth(2) == T![|]) + || (p.at(T![static]) && p.nth(1) == T![|]) + || (p.at(T![static]) && p.nth(1) == T![move] && p.nth(2) == T![|]) + || (p.at(T![static]) && p.nth(1) == T![async] && p.nth(2) == T![|]) + || (p.at(T![static]) + && p.nth(1) == T![async] + && p.nth(2) == T![move] + && p.nth(3) == T![|]) ); let m = p.start(); + p.eat(T![static]); p.eat(T![async]); p.eat(T![move]); params::param_list_closure(p); @@ -252,12 +267,10 @@ fn closure_expr(p: &mut Parser) -> CompletedMarker { // test lambda_ret_block // fn main() { || -> i32 { 92 }(); } block_expr(p); + } else if p.at_ts(EXPR_FIRST) { + expr(p); } else { - if p.at_ts(EXPR_FIRST) { - expr(p); - } else { - p.error("expected expression"); - } + p.error("expected expression"); } m.complete(p, CLOSURE_EXPR) } @@ -274,7 +287,7 @@ fn if_expr(p: &mut Parser) -> CompletedMarker { assert!(p.at(T![if])); let m = p.start(); p.bump(T![if]); - condition(p); + expr_no_struct(p); block_expr(p); if p.at(T![else]) { p.bump(T![else]); @@ -323,7 +336,7 @@ fn while_expr(p: &mut Parser, m: Option) -> CompletedMarker { assert!(p.at(T![while])); let m = m.unwrap_or_else(|| p.start()); p.bump(T![while]); - condition(p); + expr_no_struct(p); block_expr(p); m.complete(p, WHILE_EXPR) } @@ -343,22 +356,18 @@ fn for_expr(p: &mut Parser, m: Option) -> CompletedMarker { m.complete(p, FOR_EXPR) } -// test cond -// fn foo() { if let Some(_) = None {} } -// fn bar() { -// if let Some(_) | Some(_) = None {} -// if let | Some(_) = None {} -// while let Some(_) | Some(_) = None {} -// while let | Some(_) = None {} +// test let_expr +// fn foo() { +// if let Some(_) = None && true {} +// while 1 == 5 && (let None = None) {} // } -fn condition(p: &mut Parser) { +fn let_expr(p: &mut Parser) -> CompletedMarker { let m = p.start(); - if p.eat(T![let]) { - patterns::pattern_top(p); - p.expect(T![=]); - } - expr_no_struct(p); - m.complete(p, CONDITION); + p.bump(T![let]); + patterns::pattern_top(p); + p.expect(T![=]); + expr_let(p); + m.complete(p, LET_EXPR) } // test match_expr @@ -376,7 +385,7 @@ fn match_expr(p: &mut Parser) -> CompletedMarker { if p.at(T!['{']) { match_arm_list(p); } else { - p.error("expected `{`") + p.error("expected `{`"); } m.complete(p, MATCH_EXPR) } @@ -402,20 +411,7 @@ pub(crate) fn match_arm_list(p: &mut Parser) { error_block(p, "expected match arm"); continue; } - - // test match_arms_commas - // fn foo() { - // match () { - // _ => (), - // _ => {} - // _ => () - // } - // } - if match_arm(p).is_block() { - p.eat(T![,]); - } else if !p.at(T!['}']) { - p.expect(T![,]); - } + match_arm(p); } p.expect(T!['}']); m.complete(p, MATCH_ARM_LIST); @@ -431,7 +427,7 @@ pub(crate) fn match_arm_list(p: &mut Parser) { // | X => (), // }; // } -fn match_arm(p: &mut Parser) -> BlockLike { +fn match_arm(p: &mut Parser) { let m = p.start(); // test match_arms_outer_attributes // fn foo() { @@ -453,15 +449,30 @@ fn match_arm(p: &mut Parser) -> BlockLike { match_guard(p); } p.expect(T![=>]); - let blocklike = expr_stmt(p).1; + let blocklike = match expr_stmt(p, None) { + Some((_, blocklike)) => blocklike, + None => BlockLike::NotBlock, + }; + + // test match_arms_commas + // fn foo() { + // match () { + // _ => (), + // _ => {} + // _ => () + // } + // } + if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) { + p.error("expected `,`"); + } m.complete(p, MATCH_ARM); - blocklike } // test match_guard // fn foo() { // match () { // _ if foo => (), +// _ if let foo = bar => (), // } // } fn match_guard(p: &mut Parser) -> CompletedMarker { @@ -482,16 +493,18 @@ pub(crate) fn block_expr(p: &mut Parser) { p.error("expected a block"); return; } - block_expr_unchecked(p); + let m = p.start(); + stmt_list(p); + m.complete(p, BLOCK_EXPR); } -fn block_expr_unchecked(p: &mut Parser) -> CompletedMarker { +fn stmt_list(p: &mut Parser) -> CompletedMarker { assert!(p.at(T!['{'])); let m = p.start(); p.bump(T!['{']); expr_block_contents(p); p.expect(T!['}']); - m.complete(p, BLOCK_EXPR) + m.complete(p, STMT_LIST) } // test return_expr @@ -508,6 +521,20 @@ fn return_expr(p: &mut Parser) -> CompletedMarker { } m.complete(p, RETURN_EXPR) } +// test yield_expr +// fn foo() { +// yield; +// yield 1; +// } +fn yield_expr(p: &mut Parser) -> CompletedMarker { + assert!(p.at(T![yield])); + let m = p.start(); + p.bump(T![yield]); + if p.at_ts(EXPR_FIRST) { + expr(p); + } + m.complete(p, YIELD_EXPR) +} // test continue_expr // fn foo() { @@ -579,8 +606,12 @@ fn try_block_expr(p: &mut Parser, m: Option) -> CompletedMarker { } p.bump(T![try]); - block_expr(p); - m.complete(p, EFFECT_EXPR) + if p.at(T!['{']) { + stmt_list(p); + } else { + p.error("expected a block"); + } + m.complete(p, BLOCK_EXPR) } // test box_expr @@ -598,27 +629,3 @@ fn box_expr(p: &mut Parser, m: Option) -> CompletedMarker { } m.complete(p, BOX_EXPR) } - -/// Expression from `$var` macro expansion, wrapped in dollars -fn meta_var_expr(p: &mut Parser) -> CompletedMarker { - assert!(p.at(L_DOLLAR)); - let m = p.start(); - p.bump(L_DOLLAR); - let (completed, _is_block) = - expr_bp(p, Restrictions { forbid_structs: false, prefer_stmt: false }, 1); - - match (completed, p.current()) { - (Some(it), R_DOLLAR) => { - p.bump(R_DOLLAR); - m.abandon(p); - it - } - _ => { - while !p.at(R_DOLLAR) { - p.bump_any() - } - p.bump(R_DOLLAR); - m.complete(p, ERROR) - } - } -}