Semi statements

This commit is contained in:
Aleksey Kladov 2018-08-07 17:00:45 +03:00
parent bcd6754f12
commit a04473e2bb
11 changed files with 224 additions and 15 deletions

View File

@ -142,6 +142,7 @@ Grammar(
"STRUCT_PAT", "STRUCT_PAT",
"TUPLE_STRUCT_PAT", "TUPLE_STRUCT_PAT",
"TUPLE_PAT", "TUPLE_PAT",
"SLICE_PAT",
// atoms // atoms
"TUPLE_EXPR", "TUPLE_EXPR",

View File

@ -262,7 +262,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
expr_no_struct(p); expr_no_struct(p);
} }
p.expect(FAT_ARROW); p.expect(FAT_ARROW);
let ret = expr(p); let ret = expr_stmt(p);
m.complete(p, MATCH_ARM); m.complete(p, MATCH_ARM);
ret ret
} }
@ -295,7 +295,7 @@ pub(super) fn block_expr(p: &mut Parser) -> CompletedMarker {
// test pub_expr // test pub_expr
// fn foo() { pub 92; } //FIXME // fn foo() { pub 92; } //FIXME
items::MaybeItem::None => { 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)) { if p.eat(SEMI) || (is_blocklike && !p.at(R_CURLY)) {
m.complete(p, EXPR_STMT); m.complete(p, EXPR_STMT);
} else { } else {

View File

@ -6,12 +6,17 @@ pub(super) use self::atom::literal;
const EXPR_FIRST: TokenSet = LHS_FIRST; const EXPR_FIRST: TokenSet = LHS_FIRST;
pub(super) fn expr(p: &mut Parser) -> BlockLike { 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) expr_bp(p, r, 1)
} }
fn expr_no_struct(p: &mut Parser) { 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); expr_bp(p, r, 1);
} }
@ -30,7 +35,8 @@ pub(super) fn block(p: &mut Parser) {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct Restrictions { struct Restrictions {
forbid_structs: bool forbid_structs: bool,
prefer_stmt: bool,
} }
enum Op { enum Op {
@ -86,12 +92,18 @@ fn current_op(p: &Parser) -> (u8, Op) {
// Parses expression with binding power of at least bp. // Parses expression with binding power of at least bp.
fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
let mut block: bool;
let mut lhs = match lhs(p, r) { let mut lhs = match lhs(p, r) {
Some(lhs) => { 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 lhs
}, }
None => return BlockLike::NotBlock, None => return BlockLike::NotBlock,
}; };
@ -101,7 +113,6 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
if op_bp < bp { if op_bp < bp {
break; break;
} }
block = false;
let m = lhs.precede(p); let m = lhs.precede(p);
match op { match op {
Op::Simple => p.bump(), 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); expr_bp(p, r, op_bp + 1);
lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); 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 // test no_semi_after_block
@ -171,18 +182,27 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> {
} }
_ => { _ => {
let lhs = atom::atom_expr(p, r)?; 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); expr_bp(p, r, 255);
Some(m.complete(p, kind)) 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 { loop {
lhs = match p.current() { lhs = match p.current() {
L_PAREN => call_expr(p, lhs), // test stmt_postfix_expr_ambiguity
L_BRACK => index_expr(p, lhs), // 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 { DOT if p.nth(1) == IDENT => if p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON {
method_call_expr(p, lhs) method_call_expr(p, lhs)
} else { } else {
@ -199,7 +219,8 @@ fn postfix_expr(p: &mut Parser, mut lhs: CompletedMarker) -> CompletedMarker {
QUESTION => try_expr(p, lhs), QUESTION => try_expr(p, lhs),
AS_KW => cast_expr(p, lhs), AS_KW => cast_expr(p, lhs),
_ => break, _ => break,
} };
allow_calls = true
} }
lhs lhs
} }

View File

@ -17,6 +17,7 @@ pub(super) fn pattern(p: &mut Parser) {
UNDERSCORE => placeholder_pat(p), UNDERSCORE => placeholder_pat(p),
AMP => ref_pat(p), AMP => ref_pat(p),
L_PAREN => tuple_pat(p), L_PAREN => tuple_pat(p),
L_BRACK => slice_pat(p),
_ => p.err_and_bump("expected pattern"), _ => p.err_and_bump("expected pattern"),
} }
} }
@ -128,6 +129,28 @@ fn tuple_pat(p: &mut Parser) {
m.complete(p, TUPLE_PAT); 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 // test bind_pat
// fn main() { // fn main() {
// let a = (); // let a = ();

View File

@ -134,6 +134,7 @@ pub enum SyntaxKind {
STRUCT_PAT, STRUCT_PAT,
TUPLE_STRUCT_PAT, TUPLE_STRUCT_PAT,
TUPLE_PAT, TUPLE_PAT,
SLICE_PAT,
TUPLE_EXPR, TUPLE_EXPR,
ARRAY_EXPR, ARRAY_EXPR,
PAREN_EXPR, PAREN_EXPR,
@ -372,6 +373,7 @@ impl SyntaxKind {
STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" }, STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" },
TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" }, TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" },
TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" }, ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" },
PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" }, PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" },

View File

@ -0,0 +1,7 @@
fn foo() {
match () {
_ => {}
() => {}
[] => {}
}
}

View File

@ -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)

View File

@ -0,0 +1,4 @@
fn foo() {
let _ = {1} & 2;
{1} &2;
}

View File

@ -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)

View File

@ -0,0 +1,3 @@
fn main() {
let [a, b, ..] = [];
}

View File

@ -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)