Fix parsing of block expressions in "forbid_structs" contexts.

Forbidding block expressions entirely is too strict; instead, we should only
forbid them in contexts where we are parsing an optional RHS (i.e. the RHS of a
range expression).
This commit is contained in:
Geoffry Song 2019-10-02 23:38:03 -07:00
parent e1c3675951
commit 9638adaa40
11 changed files with 242 additions and 54 deletions

View file

@ -335,7 +335,13 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
// }
//
let (lhs, blocklike) = atom::atom_expr(p, r)?;
return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block())));
return Some(postfix_expr(
p,
lhs,
blocklike,
!(r.prefer_stmt && blocklike.is_block()),
r.forbid_structs,
));
}
};
expr_bp(p, r, 255);
@ -350,6 +356,7 @@ fn postfix_expr(
// `while true {break}; ();`
mut block_like: BlockLike,
mut allow_calls: bool,
forbid_structs: bool,
) -> (CompletedMarker, BlockLike) {
loop {
lhs = match p.current() {
@ -363,7 +370,7 @@ fn postfix_expr(
// }
T!['('] if allow_calls => call_expr(p, lhs),
T!['['] if allow_calls => index_expr(p, lhs),
T![.] => match postfix_dot_expr(p, lhs) {
T![.] => match postfix_dot_expr(p, lhs, forbid_structs) {
Ok(it) => it,
Err(it) => {
lhs = it;
@ -382,6 +389,7 @@ fn postfix_expr(
fn postfix_dot_expr(
p: &mut Parser,
lhs: CompletedMarker,
forbid_structs: bool,
) -> Result<CompletedMarker, CompletedMarker> {
assert!(p.at(T![.]));
if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
@ -402,10 +410,17 @@ fn postfix_expr(
}
// test postfix_range
// fn foo() { let x = 1..; }
for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() {
// fn foo() {
// let x = 1..;
// match 1.. { _ => () };
// match a.b()..S { _ => () };
// }
for &(op, la) in &[(T![..=], 3), (T![..], 2)] {
if p.at(op) {
return if EXPR_FIRST.contains(p.nth(la)) {
let next_token = p.nth(la);
let has_trailing_expression =
!(forbid_structs && next_token == T!['{']) && EXPR_FIRST.contains(next_token);
return if has_trailing_expression {
Err(lhs)
} else {
let m = lhs.precede(p);

View file

@ -121,11 +121,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
// break;
// }
// }
if r.forbid_structs {
return None;
} else {
block_expr(p, None)
}
block_expr(p, None)
}
T![return] => return_expr(p),
T![continue] => continue_expr(p),
@ -261,6 +257,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
// if true {} else {};
// if true {} else if false {} else {};
// if S {};
// if { true } { } else { };
// }
fn if_expr(p: &mut Parser) -> CompletedMarker {
assert!(p.at(T![if]));
@ -309,6 +306,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
// fn foo() {
// while true {};
// while let Some(x) = it.next() {};
// while { true } {};
// }
fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(T![while]));
@ -356,6 +354,8 @@ fn cond(p: &mut Parser) {
// fn foo() {
// match () { };
// match S {};
// match { } { _ => () };
// match { S {} } {};
// }
fn match_expr(p: &mut Parser) -> CompletedMarker {
assert!(p.at(T![match]));

View file

@ -1,5 +1,5 @@
// Stores definitions which must be used in multiple places
// See `cargo gen-syntax` (defined in crates/tools/src/main.rs)
// See `cargo gen-syntax` (defined in crates/ra_tools/src/main.rs)
Grammar(
punct: [
(";", "SEMI"),

View file

@ -1,4 +1,5 @@
fn foo() {
while true {};
while let Some(x) = it.next() {};
while { true } {};
}

View file

@ -1,5 +1,5 @@
SOURCE_FILE@[0; 70)
FN_DEF@[0; 69)
SOURCE_FILE@[0; 93)
FN_DEF@[0; 92)
FN_KW@[0; 2) "fn"
WHITESPACE@[2; 3) " "
NAME@[3; 6)
@ -8,8 +8,8 @@ SOURCE_FILE@[0; 70)
L_PAREN@[6; 7) "("
R_PAREN@[7; 8) ")"
WHITESPACE@[8; 9) " "
BLOCK_EXPR@[9; 69)
BLOCK@[9; 69)
BLOCK_EXPR@[9; 92)
BLOCK@[9; 92)
L_CURLY@[9; 10) "{"
WHITESPACE@[10; 15) "\n "
EXPR_STMT@[15; 29)
@ -64,6 +64,26 @@ SOURCE_FILE@[0; 70)
L_CURLY@[64; 65) "{"
R_CURLY@[65; 66) "}"
SEMI@[66; 67) ";"
WHITESPACE@[67; 68) "\n"
R_CURLY@[68; 69) "}"
WHITESPACE@[69; 70) "\n"
WHITESPACE@[67; 72) "\n "
EXPR_STMT@[72; 90)
WHILE_EXPR@[72; 89)
WHILE_KW@[72; 77) "while"
WHITESPACE@[77; 78) " "
CONDITION@[78; 86)
BLOCK_EXPR@[78; 86)
BLOCK@[78; 86)
L_CURLY@[78; 79) "{"
WHITESPACE@[79; 80) " "
LITERAL@[80; 84)
TRUE_KW@[80; 84) "true"
WHITESPACE@[84; 85) " "
R_CURLY@[85; 86) "}"
WHITESPACE@[86; 87) " "
BLOCK_EXPR@[87; 89)
BLOCK@[87; 89)
L_CURLY@[87; 88) "{"
R_CURLY@[88; 89) "}"
SEMI@[89; 90) ";"
WHITESPACE@[90; 91) "\n"
R_CURLY@[91; 92) "}"
WHITESPACE@[92; 93) "\n"

View file

@ -3,4 +3,5 @@ fn foo() {
if true {} else {};
if true {} else if false {} else {};
if S {};
if { true } { } else { };
}

View file

@ -1,5 +1,5 @@
SOURCE_FILE@[0; 107)
FN_DEF@[0; 106)
SOURCE_FILE@[0; 137)
FN_DEF@[0; 136)
FN_KW@[0; 2) "fn"
WHITESPACE@[2; 3) " "
NAME@[3; 6)
@ -8,8 +8,8 @@ SOURCE_FILE@[0; 107)
L_PAREN@[6; 7) "("
R_PAREN@[7; 8) ")"
WHITESPACE@[8; 9) " "
BLOCK_EXPR@[9; 106)
BLOCK@[9; 106)
BLOCK_EXPR@[9; 136)
BLOCK@[9; 136)
L_CURLY@[9; 10) "{"
WHITESPACE@[10; 15) "\n "
EXPR_STMT@[15; 26)
@ -98,6 +98,35 @@ SOURCE_FILE@[0; 107)
L_CURLY@[101; 102) "{"
R_CURLY@[102; 103) "}"
SEMI@[103; 104) ";"
WHITESPACE@[104; 105) "\n"
R_CURLY@[105; 106) "}"
WHITESPACE@[106; 107) "\n"
WHITESPACE@[104; 109) "\n "
EXPR_STMT@[109; 134)
IF_EXPR@[109; 133)
IF_KW@[109; 111) "if"
WHITESPACE@[111; 112) " "
CONDITION@[112; 120)
BLOCK_EXPR@[112; 120)
BLOCK@[112; 120)
L_CURLY@[112; 113) "{"
WHITESPACE@[113; 114) " "
LITERAL@[114; 118)
TRUE_KW@[114; 118) "true"
WHITESPACE@[118; 119) " "
R_CURLY@[119; 120) "}"
WHITESPACE@[120; 121) " "
BLOCK_EXPR@[121; 124)
BLOCK@[121; 124)
L_CURLY@[121; 122) "{"
WHITESPACE@[122; 123) " "
R_CURLY@[123; 124) "}"
WHITESPACE@[124; 125) " "
ELSE_KW@[125; 129) "else"
WHITESPACE@[129; 130) " "
BLOCK_EXPR@[130; 133)
BLOCK@[130; 133)
L_CURLY@[130; 131) "{"
WHITESPACE@[131; 132) " "
R_CURLY@[132; 133) "}"
SEMI@[133; 134) ";"
WHITESPACE@[134; 135) "\n"
R_CURLY@[135; 136) "}"
WHITESPACE@[136; 137) "\n"

View file

@ -1,4 +1,6 @@
fn foo() {
match () { };
match S {};
match { } { _ => () };
match { S {} } {};
}

View file

@ -1,5 +1,5 @@
SOURCE_FILE@[0; 47)
FN_DEF@[0; 46)
SOURCE_FILE@[0; 97)
FN_DEF@[0; 96)
FN_KW@[0; 2) "fn"
WHITESPACE@[2; 3) " "
NAME@[3; 6)
@ -8,8 +8,8 @@ SOURCE_FILE@[0; 47)
L_PAREN@[6; 7) "("
R_PAREN@[7; 8) ")"
WHITESPACE@[8; 9) " "
BLOCK_EXPR@[9; 46)
BLOCK@[9; 46)
BLOCK_EXPR@[9; 96)
BLOCK@[9; 96)
L_CURLY@[9; 10) "{"
WHITESPACE@[10; 15) "\n "
EXPR_STMT@[15; 28)
@ -40,6 +40,57 @@ SOURCE_FILE@[0; 47)
L_CURLY@[41; 42) "{"
R_CURLY@[42; 43) "}"
SEMI@[43; 44) ";"
WHITESPACE@[44; 45) "\n"
R_CURLY@[45; 46) "}"
WHITESPACE@[46; 47) "\n"
WHITESPACE@[44; 49) "\n "
EXPR_STMT@[49; 71)
MATCH_EXPR@[49; 70)
MATCH_KW@[49; 54) "match"
WHITESPACE@[54; 55) " "
BLOCK_EXPR@[55; 58)
BLOCK@[55; 58)
L_CURLY@[55; 56) "{"
WHITESPACE@[56; 57) " "
R_CURLY@[57; 58) "}"
WHITESPACE@[58; 59) " "
MATCH_ARM_LIST@[59; 70)
L_CURLY@[59; 60) "{"
WHITESPACE@[60; 61) " "
MATCH_ARM@[61; 68)
PLACEHOLDER_PAT@[61; 62)
UNDERSCORE@[61; 62) "_"
WHITESPACE@[62; 63) " "
FAT_ARROW@[63; 65) "=>"
WHITESPACE@[65; 66) " "
TUPLE_EXPR@[66; 68)
L_PAREN@[66; 67) "("
R_PAREN@[67; 68) ")"
WHITESPACE@[68; 69) " "
R_CURLY@[69; 70) "}"
SEMI@[70; 71) ";"
WHITESPACE@[71; 76) "\n "
EXPR_STMT@[76; 94)
MATCH_EXPR@[76; 93)
MATCH_KW@[76; 81) "match"
WHITESPACE@[81; 82) " "
BLOCK_EXPR@[82; 90)
BLOCK@[82; 90)
L_CURLY@[82; 83) "{"
WHITESPACE@[83; 84) " "
RECORD_LIT@[84; 88)
PATH@[84; 85)
PATH_SEGMENT@[84; 85)
NAME_REF@[84; 85)
IDENT@[84; 85) "S"
WHITESPACE@[85; 86) " "
RECORD_FIELD_LIST@[86; 88)
L_CURLY@[86; 87) "{"
R_CURLY@[87; 88) "}"
WHITESPACE@[88; 89) " "
R_CURLY@[89; 90) "}"
WHITESPACE@[90; 91) " "
MATCH_ARM_LIST@[91; 93)
L_CURLY@[91; 92) "{"
R_CURLY@[92; 93) "}"
SEMI@[93; 94) ";"
WHITESPACE@[94; 95) "\n"
R_CURLY@[95; 96) "}"
WHITESPACE@[96; 97) "\n"

View file

@ -1 +1,5 @@
fn foo() { let x = 1..; }
fn foo() {
let x = 1..;
match 1.. { _ => () };
match a.b()..S { _ => () };
}

View file

@ -1,5 +1,5 @@
SOURCE_FILE@[0; 26)
FN_DEF@[0; 25)
SOURCE_FILE@[0; 89)
FN_DEF@[0; 88)
FN_KW@[0; 2) "fn"
WHITESPACE@[2; 3) " "
NAME@[3; 6)
@ -8,24 +8,89 @@ SOURCE_FILE@[0; 26)
L_PAREN@[6; 7) "("
R_PAREN@[7; 8) ")"
WHITESPACE@[8; 9) " "
BLOCK_EXPR@[9; 25)
BLOCK@[9; 25)
BLOCK_EXPR@[9; 88)
BLOCK@[9; 88)
L_CURLY@[9; 10) "{"
WHITESPACE@[10; 11) " "
LET_STMT@[11; 23)
LET_KW@[11; 14) "let"
WHITESPACE@[14; 15) " "
BIND_PAT@[15; 16)
NAME@[15; 16)
IDENT@[15; 16) "x"
WHITESPACE@[16; 17) " "
EQ@[17; 18) "="
WHITESPACE@[10; 15) "\n "
LET_STMT@[15; 27)
LET_KW@[15; 18) "let"
WHITESPACE@[18; 19) " "
RANGE_EXPR@[19; 22)
LITERAL@[19; 20)
INT_NUMBER@[19; 20) "1"
DOTDOT@[20; 22) ".."
SEMI@[22; 23) ";"
WHITESPACE@[23; 24) " "
R_CURLY@[24; 25) "}"
WHITESPACE@[25; 26) "\n"
BIND_PAT@[19; 20)
NAME@[19; 20)
IDENT@[19; 20) "x"
WHITESPACE@[20; 21) " "
EQ@[21; 22) "="
WHITESPACE@[22; 23) " "
RANGE_EXPR@[23; 26)
LITERAL@[23; 24)
INT_NUMBER@[23; 24) "1"
DOTDOT@[24; 26) ".."
SEMI@[26; 27) ";"
WHITESPACE@[27; 32) "\n "
EXPR_STMT@[32; 54)
MATCH_EXPR@[32; 53)
MATCH_KW@[32; 37) "match"
WHITESPACE@[37; 38) " "
RANGE_EXPR@[38; 41)
LITERAL@[38; 39)
INT_NUMBER@[38; 39) "1"
DOTDOT@[39; 41) ".."
WHITESPACE@[41; 42) " "
MATCH_ARM_LIST@[42; 53)
L_CURLY@[42; 43) "{"
WHITESPACE@[43; 44) " "
MATCH_ARM@[44; 51)
PLACEHOLDER_PAT@[44; 45)
UNDERSCORE@[44; 45) "_"
WHITESPACE@[45; 46) " "
FAT_ARROW@[46; 48) "=>"
WHITESPACE@[48; 49) " "
TUPLE_EXPR@[49; 51)
L_PAREN@[49; 50) "("
R_PAREN@[50; 51) ")"
WHITESPACE@[51; 52) " "
R_CURLY@[52; 53) "}"
SEMI@[53; 54) ";"
WHITESPACE@[54; 59) "\n "
EXPR_STMT@[59; 86)
MATCH_EXPR@[59; 85)
MATCH_KW@[59; 64) "match"
WHITESPACE@[64; 65) " "
RANGE_EXPR@[65; 73)
METHOD_CALL_EXPR@[65; 70)
PATH_EXPR@[65; 66)
PATH@[65; 66)
PATH_SEGMENT@[65; 66)
NAME_REF@[65; 66)
IDENT@[65; 66) "a"
DOT@[66; 67) "."
NAME_REF@[67; 68)
IDENT@[67; 68) "b"
ARG_LIST@[68; 70)
L_PAREN@[68; 69) "("
R_PAREN@[69; 70) ")"
DOTDOT@[70; 72) ".."
PATH_EXPR@[72; 73)
PATH@[72; 73)
PATH_SEGMENT@[72; 73)
NAME_REF@[72; 73)
IDENT@[72; 73) "S"
WHITESPACE@[73; 74) " "
MATCH_ARM_LIST@[74; 85)
L_CURLY@[74; 75) "{"
WHITESPACE@[75; 76) " "
MATCH_ARM@[76; 83)
PLACEHOLDER_PAT@[76; 77)
UNDERSCORE@[76; 77) "_"
WHITESPACE@[77; 78) " "
FAT_ARROW@[78; 80) "=>"
WHITESPACE@[80; 81) " "
TUPLE_EXPR@[81; 83)
L_PAREN@[81; 82) "("
R_PAREN@[82; 83) ")"
WHITESPACE@[83; 84) " "
R_CURLY@[84; 85) "}"
SEMI@[85; 86) ";"
WHITESPACE@[86; 87) "\n"
R_CURLY@[87; 88) "}"
WHITESPACE@[88; 89) "\n"