From 9638adaa40d22adcf9b4002d95a13977c0f1436f Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Wed, 2 Oct 2019 23:38:03 -0700 Subject: 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). --- crates/ra_parser/src/grammar/expressions.rs | 25 ++++- crates/ra_parser/src/grammar/expressions/atom.rs | 10 +- crates/ra_syntax/src/grammar.ron | 2 +- .../test_data/parser/inline/ok/0031_while_expr.rs | 1 + .../test_data/parser/inline/ok/0031_while_expr.txt | 34 +++++-- .../test_data/parser/inline/ok/0064_if_expr.rs | 1 + .../test_data/parser/inline/ok/0064_if_expr.txt | 43 +++++++-- .../test_data/parser/inline/ok/0071_match_expr.rs | 2 + .../test_data/parser/inline/ok/0071_match_expr.txt | 65 +++++++++++-- .../parser/inline/ok/0080_postfix_range.rs | 6 +- .../parser/inline/ok/0080_postfix_range.txt | 107 +++++++++++++++++---- 11 files changed, 242 insertions(+), 54 deletions(-) (limited to 'crates') diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 413ecb278..74b23e2f7 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs @@ -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 { 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); diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index a52bdb3ea..7454005c4 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -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) -> CompletedMarker { // fn foo() { // while true {}; // while let Some(x) = it.next() {}; +// while { true } {}; // } fn while_expr(p: &mut Parser, m: Option) -> 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])); diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 30328f59f..17477a696 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -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"), diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs index 293046a04..2f8188160 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs @@ -1,4 +1,5 @@ fn foo() { while true {}; while let Some(x) = it.next() {}; + while { true } {}; } diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt index 9b43d624c..a6e14a114 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt @@ -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" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs index 4b0d9af89..40f227ba3 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs @@ -3,4 +3,5 @@ fn foo() { if true {} else {}; if true {} else if false {} else {}; if S {}; + if { true } { } else { }; } diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt index 14ea91fd2..2ace3c8ee 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt @@ -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" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs index c9205dfa3..c4021dc10 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs @@ -1,4 +1,6 @@ fn foo() { match () { }; match S {}; + match { } { _ => () }; + match { S {} } {}; } diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt index f62b6c6d5..0af668056 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt @@ -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" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs index c39fe8e68..e7b7cfc6b 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs @@ -1 +1,5 @@ -fn foo() { let x = 1..; } +fn foo() { + let x = 1..; + match 1.. { _ => () }; + match a.b()..S { _ => () }; +} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt index f3c292f5e..9f8a6b0f6 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt @@ -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" -- cgit v1.2.3