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",
"TUPLE_STRUCT_PAT",
"TUPLE_PAT",
"SLICE_PAT",
// atoms
"TUPLE_EXPR",

View File

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

View File

@ -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<CompletedMarker> {
}
_ => {
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
}

View File

@ -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 = ();

View File

@ -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" },

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)