From a04473e2bb95483e84404c57426ee9ed21fa5d6b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Aug 2018 17:00:45 +0300 Subject: Semi statements --- src/grammar.ron | 1 + src/grammar/expressions/atom.rs | 4 ++-- src/grammar/expressions/mod.rs | 47 +++++++++++++++++++++++++++++------------ src/grammar/patterns.rs | 23 ++++++++++++++++++++ src/syntax_kinds/generated.rs | 2 ++ 5 files changed, 62 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/grammar.ron b/src/grammar.ron index 960838c97..f1c3502bc 100644 --- a/src/grammar.ron +++ b/src/grammar.ron @@ -142,6 +142,7 @@ Grammar( "STRUCT_PAT", "TUPLE_STRUCT_PAT", "TUPLE_PAT", + "SLICE_PAT", // atoms "TUPLE_EXPR", diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index 524a69a8c..af9f47c5e 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs @@ -262,7 +262,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { expr_no_struct(p); } p.expect(FAT_ARROW); - let ret = expr(p); + let ret = expr_stmt(p); m.complete(p, MATCH_ARM); ret } @@ -295,7 +295,7 @@ pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker { // test pub_expr // fn foo() { pub 92; } //FIXME items::MaybeItem::None => { - let is_blocklike = expressions::expr(p) == BlockLike::Block; + let is_blocklike = expressions::expr_stmt(p) == BlockLike::Block; if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) { m.complete(p, EXPR_STMT); } else { diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index ce709dbb2..dcbb1e2a8 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs @@ -6,12 +6,17 @@ pub(super) use self::atom::literal; const EXPR_FIRST: TokenSet = LHS_FIRST; pub(super) fn expr(p: &mut Parser) -> BlockLike { - let r = Restrictions { forbid_structs: false }; + let r = Restrictions { forbid_structs: false, prefer_stmt: false }; + expr_bp(p, r, 1) +} + +pub(super) fn expr_stmt(p: &mut Parser) -> BlockLike { + let r = Restrictions { forbid_structs: false, prefer_stmt: true }; expr_bp(p, r, 1) } fn expr_no_struct(p: &mut Parser) { - let r = Restrictions { forbid_structs: true }; + let r = Restrictions { forbid_structs: true, prefer_stmt: false }; expr_bp(p, r, 1); } @@ -30,7 +35,8 @@ pub(super) fn block(p: &mut Parser) { #[derive(Clone, Copy)] struct Restrictions { - forbid_structs: bool + forbid_structs: bool, + prefer_stmt: bool, } enum Op { @@ -86,12 +92,18 @@ fn current_op(p: &Parser) -> (u8, Op) { // Parses expression with binding power of at least bp. fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { - let mut block: bool; let mut lhs = match lhs(p, r) { Some(lhs) => { - block = is_block(lhs.kind()); + // test stmt_bin_expr_ambiguity + // fn foo() { + // let _ = {1} & 2; + // {1} &2; + // } + if r.prefer_stmt && is_block(lhs.kind()) { + return BlockLike::Block; + } lhs - }, + } None => return BlockLike::NotBlock, }; @@ -101,7 +113,6 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { if op_bp < bp { break; } - block = false; let m = lhs.precede(p); match op { Op::Simple => p.bump(), @@ -112,7 +123,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { expr_bp(p, r, op_bp + 1); lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); } - if block { BlockLike::Block } else { BlockLike::NotBlock } + BlockLike::NotBlock } // test no_semi_after_block @@ -171,18 +182,27 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option { } _ => { let lhs = atom::atom_expr(p, r)?; - return Some(postfix_expr(p, lhs)); + return Some(postfix_expr(p, r, lhs)); } }; expr_bp(p, r, 255); Some(m.complete(p, kind)) } -fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { +fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { + let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); loop { lhs = match p.current() { - L_PAREN => call_expr(p, lhs), - L_BRACK => index_expr(p, lhs), + // test stmt_postfix_expr_ambiguity + // fn foo() { + // match () { + // _ => {} + // () => {} + // [] => {} + // } + // } + L_PAREN if allow_calls => call_expr(p, lhs), + L_BRACK if allow_calls => index_expr(p, lhs), DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON { method_call_expr(p, lhs) } else { @@ -199,7 +219,8 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker { QUESTION => try_expr(p, lhs), AS_KW => cast_expr(p, lhs), _ => break, - } + }; + allow_calls = true } lhs } diff --git a/src/grammar/patterns.rs b/src/grammar/patterns.rs index f1d48b5fa..36ead7561 100644 --- a/src/grammar/patterns.rs +++ b/src/grammar/patterns.rs @@ -17,6 +17,7 @@ pub(super) fn pattern(p: &mut Parser) { UNDERSCORE => placeholder_pat(p), AMP => ref_pat(p), L_PAREN => tuple_pat(p), + L_BRACK => slice_pat(p), _ => p.err_and_bump("expected pattern"), } } @@ -128,6 +129,28 @@ fn tuple_pat(p: &mut Parser) { m.complete(p, TUPLE_PAT); } +// test slice_pat +// fn main() { +// let [a, b, ..] = []; +// } +fn slice_pat(p: &mut Parser) { + assert!(p.at(L_BRACK)); + let m = p.start(); + p.bump(); + while !p.at(EOF) && !p.at(R_BRACK) { + match p.current() { + DOTDOT => p.bump(), + _ => pattern(p), + } + if !p.at(R_BRACK) { + p.expect(COMMA); + } + } + p.expect(R_BRACK); + + m.complete(p, SLICE_PAT); +} + // test bind_pat // fn main() { // let a = (); diff --git a/src/syntax_kinds/generated.rs b/src/syntax_kinds/generated.rs index cf286a0f1..0c6a1f8e7 100644 --- a/src/syntax_kinds/generated.rs +++ b/src/syntax_kinds/generated.rs @@ -134,6 +134,7 @@ pub enum SyntaxKind { STRUCT_PAT, TUPLE_STRUCT_PAT, TUPLE_PAT, + SLICE_PAT, TUPLE_EXPR, ARRAY_EXPR, PAREN_EXPR, @@ -372,6 +373,7 @@ impl SyntaxKind { STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" }, TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" }, TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, + SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" }, PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" }, -- cgit v1.2.3