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 + .../inline/0087_stmt_postfix_expr_ambiguity.rs | 7 +++ .../inline/0087_stmt_postfix_expr_ambiguity.txt | 58 ++++++++++++++++++++++ .../parser/inline/0088_stmt_bin_expr_ambiguity.rs | 4 ++ .../parser/inline/0088_stmt_bin_expr_ambiguity.txt | 50 +++++++++++++++++++ tests/data/parser/inline/0089_slice_pat.rs | 3 ++ tests/data/parser/inline/0089_slice_pat.txt | 40 +++++++++++++++ 11 files changed, 224 insertions(+), 15 deletions(-) create mode 100644 tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs create mode 100644 tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt create mode 100644 tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs create mode 100644 tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt create mode 100644 tests/data/parser/inline/0089_slice_pat.rs create mode 100644 tests/data/parser/inline/0089_slice_pat.txt 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" }, diff --git a/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs new file mode 100644 index 000000000..2edd578f9 --- /dev/null +++ b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs @@ -0,0 +1,7 @@ +fn foo() { + match () { + _ => {} + () => {} + [] => {} + } +} diff --git a/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt new file mode 100644 index 000000000..47b4d4481 --- /dev/null +++ b/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt @@ -0,0 +1,58 @@ +FILE@[0; 84) + FN_ITEM@[0; 83) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 83) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + MATCH_EXPR@[15; 81) + MATCH_KW@[15; 20) + WHITESPACE@[20; 21) + TUPLE_EXPR@[21; 23) + L_PAREN@[21; 22) + R_PAREN@[22; 23) + WHITESPACE@[23; 24) + L_CURLY@[24; 25) + WHITESPACE@[25; 34) + MATCH_ARM@[34; 41) + PLACEHOLDER_PAT@[34; 35) + UNDERSCORE@[34; 35) + WHITESPACE@[35; 36) + FAT_ARROW@[36; 38) + WHITESPACE@[38; 39) + BLOCK_EXPR@[39; 41) + L_CURLY@[39; 40) + R_CURLY@[40; 41) + WHITESPACE@[41; 50) + MATCH_ARM@[50; 58) + TUPLE_PAT@[50; 52) + L_PAREN@[50; 51) + R_PAREN@[51; 52) + WHITESPACE@[52; 53) + FAT_ARROW@[53; 55) + WHITESPACE@[55; 56) + BLOCK_EXPR@[56; 58) + L_CURLY@[56; 57) + R_CURLY@[57; 58) + WHITESPACE@[58; 67) + MATCH_ARM@[67; 75) + SLICE_PAT@[67; 69) + L_BRACK@[67; 68) + R_BRACK@[68; 69) + WHITESPACE@[69; 70) + FAT_ARROW@[70; 72) + WHITESPACE@[72; 73) + BLOCK_EXPR@[73; 75) + L_CURLY@[73; 74) + R_CURLY@[74; 75) + WHITESPACE@[75; 80) + R_CURLY@[80; 81) + WHITESPACE@[81; 82) + R_CURLY@[82; 83) + WHITESPACE@[83; 84) diff --git a/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs new file mode 100644 index 000000000..37b843742 --- /dev/null +++ b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs @@ -0,0 +1,4 @@ +fn foo() { + let _ = {1} & 2; + {1} &2; +} diff --git a/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt new file mode 100644 index 000000000..df0aa44b3 --- /dev/null +++ b/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt @@ -0,0 +1,50 @@ +FILE@[0; 46) + FN_ITEM@[0; 45) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) + R_PAREN@[7; 8) + WHITESPACE@[8; 9) + BLOCK_EXPR@[9; 45) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + LET_STMT@[15; 31) + LET_KW@[15; 18) + WHITESPACE@[18; 19) + PLACEHOLDER_PAT@[19; 20) + UNDERSCORE@[19; 20) + WHITESPACE@[20; 21) + EQ@[21; 22) + WHITESPACE@[22; 23) + BIN_EXPR@[23; 30) + BLOCK_EXPR@[23; 26) + L_CURLY@[23; 24) + LITERAL@[24; 25) + INT_NUMBER@[24; 25) "1" + R_CURLY@[25; 26) + WHITESPACE@[26; 27) + AMP@[27; 28) + WHITESPACE@[28; 29) + LITERAL@[29; 30) + INT_NUMBER@[29; 30) "2" + SEMI@[30; 31) + WHITESPACE@[31; 36) + EXPR_STMT@[36; 39) + BLOCK_EXPR@[36; 39) + L_CURLY@[36; 37) + LITERAL@[37; 38) + INT_NUMBER@[37; 38) "1" + R_CURLY@[38; 39) + WHITESPACE@[39; 40) + EXPR_STMT@[40; 43) + REF_EXPR@[40; 42) + AMP@[40; 41) + LITERAL@[41; 42) + INT_NUMBER@[41; 42) "2" + SEMI@[42; 43) + WHITESPACE@[43; 44) + R_CURLY@[44; 45) + WHITESPACE@[45; 46) diff --git a/tests/data/parser/inline/0089_slice_pat.rs b/tests/data/parser/inline/0089_slice_pat.rs new file mode 100644 index 000000000..7955973b9 --- /dev/null +++ b/tests/data/parser/inline/0089_slice_pat.rs @@ -0,0 +1,3 @@ +fn main() { + let [a, b, ..] = []; +} diff --git a/tests/data/parser/inline/0089_slice_pat.txt b/tests/data/parser/inline/0089_slice_pat.txt new file mode 100644 index 000000000..1e7f20119 --- /dev/null +++ b/tests/data/parser/inline/0089_slice_pat.txt @@ -0,0 +1,40 @@ +FILE@[0; 39) + FN_ITEM@[0; 38) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 7) + IDENT@[3; 7) "main" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) + R_PAREN@[8; 9) + WHITESPACE@[9; 10) + BLOCK_EXPR@[10; 38) + L_CURLY@[10; 11) + WHITESPACE@[11; 16) + LET_STMT@[16; 36) + LET_KW@[16; 19) + WHITESPACE@[19; 20) + SLICE_PAT@[20; 30) + L_BRACK@[20; 21) + BIND_PAT@[21; 22) + NAME@[21; 22) + IDENT@[21; 22) "a" + COMMA@[22; 23) + WHITESPACE@[23; 24) + BIND_PAT@[24; 25) + NAME@[24; 25) + IDENT@[24; 25) "b" + COMMA@[25; 26) + WHITESPACE@[26; 27) + DOTDOT@[27; 29) + R_BRACK@[29; 30) + WHITESPACE@[30; 31) + EQ@[31; 32) + WHITESPACE@[32; 33) + ARRAY_EXPR@[33; 35) + L_BRACK@[33; 34) + R_BRACK@[34; 35) + SEMI@[35; 36) + WHITESPACE@[36; 37) + R_CURLY@[37; 38) + WHITESPACE@[38; 39) -- cgit v1.2.3