From bcd6754f1266ef3f4ce42f76974e379815234494 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 7 Aug 2018 16:32:09 +0300 Subject: semis after blcoks --- src/grammar/expressions/atom.rs | 24 +++++++++++++++++------- src/grammar/expressions/mod.rs | 33 ++++++++++++++++++++++++++++----- src/grammar/mod.rs | 5 +++++ 3 files changed, 50 insertions(+), 12 deletions(-) (limited to 'src/grammar') diff --git a/src/grammar/expressions/atom.rs b/src/grammar/expressions/atom.rs index e4f681c17..524a69a8c 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 55e965ff4..ce709dbb2 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 1b997d861..b6da0d013 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(); -- cgit v1.2.3