From bcd6754f1266ef3f4ce42f76974e379815234494 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Aug 2018 16:32:09 +0300 Subject: [PATCH] semis after blcoks --- src/grammar/expressions/atom.rs | 24 ++++-- src/grammar/expressions/mod.rs | 33 ++++++-- src/grammar/mod.rs | 5 ++ src/parser_api.rs | 9 +- .../parser/inline/0085_match_arms_commas.rs | 7 ++ .../parser/inline/0085_match_arms_commas.txt | 57 +++++++++++++ .../parser/inline/0086_no_semi_after_block.rs | 9 ++ .../inline/0086_no_semi_after_block.txt | 82 +++++++++++++++++++ 8 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 tests/data/parser/inline/0085_match_arms_commas.rs create mode 100644 tests/data/parser/inline/0085_match_arms_commas.txt create mode 100644 tests/data/parser/inline/0086_no_semi_after_block.rs create mode 100644 tests/data/parser/inline/0086_no_semi_after_block.txt diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index e4f681c17a1d..524a69a8c256 100644 --- a/src/grammar/expressions/atom.rs +++ b/src/grammar/expressions/atom.rs @@ -133,7 +133,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { if fn_ret_type(p) { block(p); } else { - expr(p) + expr(p); } m.complete(p, LAMBDA_EXPR) } @@ -225,8 +225,17 @@ fn match_expr(p: &mut Parser) -> CompletedMarker { expr_no_struct(p); p.eat(L_CURLY); while !p.at(EOF) && !p.at(R_CURLY) { - match_arm(p); - if !p.at(R_CURLY) { + // test match_arms_commas + // fn foo() { + // match () { + // _ => (), + // _ => {} + // _ => () + // } + // } + if match_arm(p).is_block() { + p.eat(COMMA); + } else if !p.at(R_CURLY) { p.expect(COMMA); } } @@ -241,7 +250,7 @@ fn match_expr(p: &mut Parser) -> CompletedMarker { // X | Y if Z => (), // }; // } -fn match_arm(p: &mut Parser) { +fn match_arm(p: &mut Parser) -> BlockLike { let m = p.start(); loop { patterns::pattern(p); @@ -253,8 +262,9 @@ fn match_arm(p: &mut Parser) { expr_no_struct(p); } p.expect(FAT_ARROW); - expr(p); + let ret = expr(p); m.complete(p, MATCH_ARM); + ret } // test block_expr @@ -285,8 +295,8 @@ pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker { // test pub_expr // fn foo() { pub 92; } //FIXME items::MaybeItem::None => { - expressions::expr(p); - if p.eat(SEMI) { + let is_blocklike = expressions::expr(p) == BlockLike::Block; + if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) { m.complete(p, EXPR_STMT); } else { m.abandon(p); diff --git a/src/grammar/expressions/mod.rs b/src/grammar/expressions/mod.rs index 55e965ff4207..ce709dbb2f13 100644 --- a/src/grammar/expressions/mod.rs +++ b/src/grammar/expressions/mod.rs @@ -5,14 +5,14 @@ pub(super) use self::atom::literal; const EXPR_FIRST: TokenSet = LHS_FIRST; -pub(super) fn expr(p: &mut Parser) { +pub(super) fn expr(p: &mut Parser) -> BlockLike { let r = Restrictions { forbid_structs: false }; expr_bp(p, r, 1) } fn expr_no_struct(p: &mut Parser) { let r = Restrictions { forbid_structs: true }; - expr_bp(p, r, 1) + expr_bp(p, r, 1); } // test block @@ -85,10 +85,14 @@ 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) { +fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { + let mut block: bool; let mut lhs = match lhs(p, r) { - Some(lhs) => lhs, - None => return, + Some(lhs) => { + block = is_block(lhs.kind()); + lhs + }, + None => return BlockLike::NotBlock, }; loop { @@ -97,6 +101,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { if op_bp < bp { break; } + block = false; let m = lhs.precede(p); match op { Op::Simple => p.bump(), @@ -107,6 +112,24 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) { 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 } +} + +// test no_semi_after_block +// fn foo() { +// if true {} +// loop {} +// match () {} +// while true {} +// for _ in () {} +// {} +// {} +// } +fn is_block(kind: SyntaxKind) -> bool { + match kind { + IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true, + _ => false, + } } const LHS_FIRST: TokenSet = diff --git a/src/grammar/mod.rs b/src/grammar/mod.rs index 1b997d861922..b6da0d0133a5 100644 --- a/src/grammar/mod.rs +++ b/src/grammar/mod.rs @@ -44,11 +44,16 @@ pub(crate) fn file(p: &mut Parser) { } +#[derive(Clone, Copy, PartialEq, Eq)] enum BlockLike { Block, NotBlock, } +impl BlockLike { + fn is_block(self) -> bool { self == BlockLike::Block } +} + fn visibility(p: &mut Parser) { if p.at(PUB_KW) { let vis = p.start(); diff --git a/src/parser_api.rs b/src/parser_api.rs index c739b1321057..58002a8fcfa6 100644 --- a/src/parser_api.rs +++ b/src/parser_api.rs @@ -6,6 +6,7 @@ use { #[derive(Clone, Copy)] pub(crate) struct TokenSet(pub(crate) u128); + fn mask(kind: SyntaxKind) -> u128 { 1u128 << (kind as usize) } @@ -154,7 +155,7 @@ impl Marker { pub(crate) fn complete(mut self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker { self.bomb.defuse(); p.0.complete(self.pos, kind); - CompletedMarker(self.pos) + CompletedMarker(self.pos, kind) } /// Abandons the syntax tree node. All its children @@ -165,7 +166,7 @@ impl Marker { } } -pub(crate) struct CompletedMarker(u32); +pub(crate) struct CompletedMarker(u32, SyntaxKind); impl CompletedMarker { /// This one is tricky :-) @@ -178,4 +179,8 @@ impl CompletedMarker { pub(crate) fn precede(self, p: &mut Parser) -> Marker { Marker::new(p.0.precede(self.0)) } + + pub(crate) fn kind(&self) -> SyntaxKind { + self.1 + } } diff --git a/tests/data/parser/inline/0085_match_arms_commas.rs b/tests/data/parser/inline/0085_match_arms_commas.rs new file mode 100644 index 000000000000..1f25d577a955 --- /dev/null +++ b/tests/data/parser/inline/0085_match_arms_commas.rs @@ -0,0 +1,7 @@ +fn foo() { + match () { + _ => (), + _ => {} + _ => () + } +} diff --git a/tests/data/parser/inline/0085_match_arms_commas.txt b/tests/data/parser/inline/0085_match_arms_commas.txt new file mode 100644 index 000000000000..6dfc6c9dd4dc --- /dev/null +++ b/tests/data/parser/inline/0085_match_arms_commas.txt @@ -0,0 +1,57 @@ +FILE@[0; 83) + FN_ITEM@[0; 82) + 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; 82) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + MATCH_EXPR@[15; 80) + 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) + TUPLE_EXPR@[39; 41) + L_PAREN@[39; 40) + R_PAREN@[40; 41) + COMMA@[41; 42) + WHITESPACE@[42; 51) + MATCH_ARM@[51; 58) + PLACEHOLDER_PAT@[51; 52) + UNDERSCORE@[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; 74) + PLACEHOLDER_PAT@[67; 68) + UNDERSCORE@[67; 68) + WHITESPACE@[68; 69) + FAT_ARROW@[69; 71) + WHITESPACE@[71; 72) + TUPLE_EXPR@[72; 74) + L_PAREN@[72; 73) + R_PAREN@[73; 74) + WHITESPACE@[74; 79) + R_CURLY@[79; 80) + WHITESPACE@[80; 81) + R_CURLY@[81; 82) + WHITESPACE@[82; 83) diff --git a/tests/data/parser/inline/0086_no_semi_after_block.rs b/tests/data/parser/inline/0086_no_semi_after_block.rs new file mode 100644 index 000000000000..d769da43dd4e --- /dev/null +++ b/tests/data/parser/inline/0086_no_semi_after_block.rs @@ -0,0 +1,9 @@ +fn foo() { + if true {} + loop {} + match () {} + while true {} + for _ in () {} + {} + {} +} diff --git a/tests/data/parser/inline/0086_no_semi_after_block.txt b/tests/data/parser/inline/0086_no_semi_after_block.txt new file mode 100644 index 000000000000..dd05a8a9f7e9 --- /dev/null +++ b/tests/data/parser/inline/0086_no_semi_after_block.txt @@ -0,0 +1,82 @@ +FILE@[0; 107) + FN_ITEM@[0; 106) + 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; 106) + L_CURLY@[9; 10) + WHITESPACE@[10; 15) + EXPR_STMT@[15; 25) + IF_EXPR@[15; 25) + IF_KW@[15; 17) + WHITESPACE@[17; 18) + LITERAL@[18; 22) + TRUE_KW@[18; 22) + WHITESPACE@[22; 23) + BLOCK_EXPR@[23; 25) + L_CURLY@[23; 24) + R_CURLY@[24; 25) + WHITESPACE@[25; 30) + EXPR_STMT@[30; 37) + LOOP_EXPR@[30; 37) + LOOP_KW@[30; 34) + WHITESPACE@[34; 35) + BLOCK_EXPR@[35; 37) + L_CURLY@[35; 36) + R_CURLY@[36; 37) + WHITESPACE@[37; 42) + EXPR_STMT@[42; 53) + MATCH_EXPR@[42; 53) + MATCH_KW@[42; 47) + WHITESPACE@[47; 48) + TUPLE_EXPR@[48; 50) + L_PAREN@[48; 49) + R_PAREN@[49; 50) + WHITESPACE@[50; 51) + L_CURLY@[51; 52) + R_CURLY@[52; 53) + WHITESPACE@[53; 58) + EXPR_STMT@[58; 71) + WHILE_EXPR@[58; 71) + WHILE_KW@[58; 63) + WHITESPACE@[63; 64) + LITERAL@[64; 68) + TRUE_KW@[64; 68) + WHITESPACE@[68; 69) + BLOCK_EXPR@[69; 71) + L_CURLY@[69; 70) + R_CURLY@[70; 71) + WHITESPACE@[71; 76) + EXPR_STMT@[76; 90) + FOR_EXPR@[76; 90) + FOR_KW@[76; 79) + WHITESPACE@[79; 80) + PLACEHOLDER_PAT@[80; 81) + UNDERSCORE@[80; 81) + WHITESPACE@[81; 82) + IN_KW@[82; 84) + WHITESPACE@[84; 85) + TUPLE_EXPR@[85; 87) + L_PAREN@[85; 86) + R_PAREN@[86; 87) + WHITESPACE@[87; 88) + BLOCK_EXPR@[88; 90) + L_CURLY@[88; 89) + R_CURLY@[89; 90) + WHITESPACE@[90; 95) + EXPR_STMT@[95; 97) + BLOCK_EXPR@[95; 97) + L_CURLY@[95; 96) + R_CURLY@[96; 97) + WHITESPACE@[97; 102) + BLOCK_EXPR@[102; 104) + L_CURLY@[102; 103) + R_CURLY@[103; 104) + WHITESPACE@[104; 105) + R_CURLY@[105; 106) + WHITESPACE@[106; 107)