diff options
Diffstat (limited to 'crates/ra_syntax')
4 files changed, 104 insertions, 115 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 9d75bfb90..5f5a3077d 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -64,6 +64,16 @@ pub(crate) fn block(p: &mut Parser) { | |||
64 | if p.at(R_CURLY) { | 64 | if p.at(R_CURLY) { |
65 | m.abandon(p); | 65 | m.abandon(p); |
66 | } else { | 66 | } else { |
67 | // test no_semi_after_block | ||
68 | // fn foo() { | ||
69 | // if true {} | ||
70 | // loop {} | ||
71 | // match () {} | ||
72 | // while true {} | ||
73 | // for _ in () {} | ||
74 | // {} | ||
75 | // {} | ||
76 | // } | ||
67 | if is_blocklike { | 77 | if is_blocklike { |
68 | p.eat(SEMI); | 78 | p.eat(SEMI); |
69 | } else { | 79 | } else { |
@@ -158,19 +168,18 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
158 | // Parses expression with binding power of at least bp. | 168 | // Parses expression with binding power of at least bp. |
159 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { | 169 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { |
160 | let mut lhs = match lhs(p, r) { | 170 | let mut lhs = match lhs(p, r) { |
161 | (Some(lhs), macro_blocklike) => { | 171 | Some((lhs, macro_blocklike)) => { |
162 | // test stmt_bin_expr_ambiguity | 172 | // test stmt_bin_expr_ambiguity |
163 | // fn foo() { | 173 | // fn foo() { |
164 | // let _ = {1} & 2; | 174 | // let _ = {1} & 2; |
165 | // {1} &2; | 175 | // {1} &2; |
166 | // } | 176 | // } |
167 | if r.prefer_stmt && (is_block(lhs.kind()) || macro_blocklike == Some(BlockLike::Block)) | 177 | if r.prefer_stmt && macro_blocklike.is_block() { |
168 | { | ||
169 | return BlockLike::Block; | 178 | return BlockLike::Block; |
170 | } | 179 | } |
171 | lhs | 180 | lhs |
172 | } | 181 | } |
173 | (None, _) => return BlockLike::NotBlock, | 182 | None => return BlockLike::NotBlock, |
174 | }; | 183 | }; |
175 | 184 | ||
176 | loop { | 185 | loop { |
@@ -192,29 +201,12 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { | |||
192 | BlockLike::NotBlock | 201 | BlockLike::NotBlock |
193 | } | 202 | } |
194 | 203 | ||
195 | // test no_semi_after_block | ||
196 | // fn foo() { | ||
197 | // if true {} | ||
198 | // loop {} | ||
199 | // match () {} | ||
200 | // while true {} | ||
201 | // for _ in () {} | ||
202 | // {} | ||
203 | // {} | ||
204 | // } | ||
205 | fn is_block(kind: SyntaxKind) -> bool { | ||
206 | match kind { | ||
207 | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true, | ||
208 | _ => false, | ||
209 | } | ||
210 | } | ||
211 | |||
212 | const LHS_FIRST: TokenSet = token_set_union![ | 204 | const LHS_FIRST: TokenSet = token_set_union![ |
213 | token_set![AMP, STAR, EXCL, DOTDOT, MINUS], | 205 | token_set![AMP, STAR, EXCL, DOTDOT, MINUS], |
214 | atom::ATOM_EXPR_FIRST, | 206 | atom::ATOM_EXPR_FIRST, |
215 | ]; | 207 | ]; |
216 | 208 | ||
217 | fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<BlockLike>) { | 209 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { |
218 | let m; | 210 | let m; |
219 | let kind = match p.current() { | 211 | let kind = match p.current() { |
220 | // test ref_expr | 212 | // test ref_expr |
@@ -247,30 +239,28 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc | |||
247 | if p.at_ts(EXPR_FIRST) { | 239 | if p.at_ts(EXPR_FIRST) { |
248 | expr_bp(p, r, 2); | 240 | expr_bp(p, r, 2); |
249 | } | 241 | } |
250 | return (Some(m.complete(p, RANGE_EXPR)), None); | 242 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); |
251 | } | 243 | } |
252 | _ => { | 244 | _ => { |
253 | let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); | 245 | let (lhs, blocklike) = atom::atom_expr(p, r)?; |
254 | 246 | return Some(( | |
255 | if macro_block_like == Some(BlockLike::Block) { | 247 | postfix_expr(p, lhs, !(r.prefer_stmt && blocklike.is_block())), |
256 | return (lhs_marker, macro_block_like); | 248 | blocklike, |
257 | } | 249 | )); |
258 | if let Some(lhs_marker) = lhs_marker { | ||
259 | return (Some(postfix_expr(p, r, lhs_marker)), macro_block_like); | ||
260 | } else { | ||
261 | return (None, None); | ||
262 | } | ||
263 | } | 250 | } |
264 | }; | 251 | }; |
265 | expr_bp(p, r, 255); | 252 | expr_bp(p, r, 255); |
266 | (Some(m.complete(p, kind)), None) | 253 | Some((m.complete(p, kind), BlockLike::NotBlock)) |
267 | } | 254 | } |
268 | 255 | ||
269 | fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { | 256 | fn postfix_expr( |
257 | p: &mut Parser, | ||
258 | mut lhs: CompletedMarker, | ||
270 | // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple | 259 | // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple |
271 | // E.g. `while true {break}();` is parsed as | 260 | // E.g. `while true {break}();` is parsed as |
272 | // `while true {break}; ();` | 261 | // `while true {break}; ();` |
273 | let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); | 262 | mut allow_calls: bool, |
263 | ) -> CompletedMarker { | ||
274 | loop { | 264 | loop { |
275 | lhs = match p.current() { | 265 | lhs = match p.current() { |
276 | // test stmt_postfix_expr_ambiguity | 266 | // test stmt_postfix_expr_ambiguity |
@@ -418,22 +408,21 @@ fn arg_list(p: &mut Parser) { | |||
418 | // let _ = ::a::<b>; | 408 | // let _ = ::a::<b>; |
419 | // let _ = format!(); | 409 | // let _ = format!(); |
420 | // } | 410 | // } |
421 | fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, Option<BlockLike>) { | 411 | fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { |
422 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | 412 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); |
423 | let m = p.start(); | 413 | let m = p.start(); |
424 | paths::expr_path(p); | 414 | paths::expr_path(p); |
425 | let res = match p.current() { | 415 | match p.current() { |
426 | L_CURLY if !r.forbid_structs => { | 416 | L_CURLY if !r.forbid_structs => { |
427 | named_field_list(p); | 417 | named_field_list(p); |
428 | m.complete(p, STRUCT_LIT) | 418 | (m.complete(p, STRUCT_LIT), BlockLike::Block) |
429 | } | 419 | } |
430 | EXCL => { | 420 | EXCL => { |
431 | let block_like = items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) | 421 | let block_like = items::macro_call_after_excl(p); |
432 | return (m.complete(p, MACRO_CALL), Some(block_like)); | 422 | return (m.complete(p, MACRO_CALL), block_like); |
433 | } | 423 | } |
434 | _ => m.complete(p, PATH_EXPR), | 424 | _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock), |
435 | }; | 425 | } |
436 | (res, None) | ||
437 | } | 426 | } |
438 | 427 | ||
439 | // test struct_lit | 428 | // test struct_lit |
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index 471f398f5..a976799e7 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs | |||
@@ -61,16 +61,12 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ | |||
61 | 61 | ||
62 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; | 62 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; |
63 | 63 | ||
64 | pub(super) fn atom_expr( | 64 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { |
65 | p: &mut Parser, | ||
66 | r: Restrictions, | ||
67 | ) -> (Option<CompletedMarker>, Option<BlockLike>) { | ||
68 | if let Some(m) = literal(p) { | 65 | if let Some(m) = literal(p) { |
69 | return (Some(m), None); | 66 | return Some((m, BlockLike::NotBlock)); |
70 | } | 67 | } |
71 | if paths::is_path_start(p) || p.at(L_ANGLE) { | 68 | if paths::is_path_start(p) || p.at(L_ANGLE) { |
72 | let path_expr = path_expr(p, r); | 69 | return Some(path_expr(p, r)); |
73 | return (Some(path_expr.0), path_expr.1); | ||
74 | } | 70 | } |
75 | let la = p.nth(1); | 71 | let la = p.nth(1); |
76 | let done = match p.current() { | 72 | let done = match p.current() { |
@@ -98,7 +94,7 @@ pub(super) fn atom_expr( | |||
98 | // } | 94 | // } |
99 | p.error("expected a loop"); | 95 | p.error("expected a loop"); |
100 | m.complete(p, ERROR); | 96 | m.complete(p, ERROR); |
101 | return (None, None); | 97 | return None; |
102 | } | 98 | } |
103 | } | 99 | } |
104 | } | 100 | } |
@@ -115,10 +111,14 @@ pub(super) fn atom_expr( | |||
115 | BREAK_KW => break_expr(p), | 111 | BREAK_KW => break_expr(p), |
116 | _ => { | 112 | _ => { |
117 | p.err_recover("expected expression", EXPR_RECOVERY_SET); | 113 | p.err_recover("expected expression", EXPR_RECOVERY_SET); |
118 | return (None, None); | 114 | return None; |
119 | } | 115 | } |
120 | }; | 116 | }; |
121 | (Some(done), None) | 117 | let blocklike = match done.kind() { |
118 | IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block, | ||
119 | _ => BlockLike::NotBlock, | ||
120 | }; | ||
121 | Some((done, blocklike)) | ||
122 | } | 122 | } |
123 | 123 | ||
124 | // test tuple_expr | 124 | // test tuple_expr |
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs index 3bca7bf5d..c12ab6fce 100644 --- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs +++ b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | fn main() { | 1 | fn main() { |
2 | match 92 { | 2 | match 92 { |
3 | 0 ... 100 => (), | 3 | 0 ... 100 => (), |
4 | 101 ..= 200 => (), | 4 | 101 ..= 200 => (), |
5 | 200 .. 301=> (), | 5 | 200 .. 301=> (), |
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt index 7eb0fcdf4..d47f38903 100644 --- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt +++ b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | SOURCE_FILE@[0; 113) | 1 | SOURCE_FILE@[0; 112) |
2 | FN_DEF@[0; 112) | 2 | FN_DEF@[0; 111) |
3 | FN_KW@[0; 2) | 3 | FN_KW@[0; 2) |
4 | WHITESPACE@[2; 3) | 4 | WHITESPACE@[2; 3) |
5 | NAME@[3; 7) | 5 | NAME@[3; 7) |
@@ -8,69 +8,69 @@ SOURCE_FILE@[0; 113) | |||
8 | L_PAREN@[7; 8) | 8 | L_PAREN@[7; 8) |
9 | R_PAREN@[8; 9) | 9 | R_PAREN@[8; 9) |
10 | WHITESPACE@[9; 10) | 10 | WHITESPACE@[9; 10) |
11 | BLOCK@[10; 112) | 11 | BLOCK@[10; 111) |
12 | L_CURLY@[10; 11) | 12 | L_CURLY@[10; 11) |
13 | WHITESPACE@[11; 16) | 13 | WHITESPACE@[11; 16) |
14 | MATCH_EXPR@[16; 110) | 14 | MATCH_EXPR@[16; 109) |
15 | MATCH_KW@[16; 21) | 15 | MATCH_KW@[16; 21) |
16 | WHITESPACE@[21; 22) | 16 | WHITESPACE@[21; 22) |
17 | LITERAL@[22; 24) | 17 | LITERAL@[22; 24) |
18 | INT_NUMBER@[22; 24) "92" | 18 | INT_NUMBER@[22; 24) "92" |
19 | WHITESPACE@[24; 25) | 19 | WHITESPACE@[24; 25) |
20 | MATCH_ARM_LIST@[25; 110) | 20 | MATCH_ARM_LIST@[25; 109) |
21 | L_CURLY@[25; 26) | 21 | L_CURLY@[25; 26) |
22 | WHITESPACE@[26; 36) | 22 | WHITESPACE@[26; 35) |
23 | MATCH_ARM@[36; 51) | 23 | MATCH_ARM@[35; 50) |
24 | RANGE_PAT@[36; 45) | 24 | RANGE_PAT@[35; 44) |
25 | LITERAL@[36; 37) | 25 | LITERAL@[35; 36) |
26 | INT_NUMBER@[36; 37) "0" | 26 | INT_NUMBER@[35; 36) "0" |
27 | WHITESPACE@[37; 38) | 27 | WHITESPACE@[36; 37) |
28 | DOTDOTDOT@[38; 41) | 28 | DOTDOTDOT@[37; 40) |
29 | WHITESPACE@[41; 42) | 29 | WHITESPACE@[40; 41) |
30 | LITERAL@[42; 45) | 30 | LITERAL@[41; 44) |
31 | INT_NUMBER@[42; 45) "100" | 31 | INT_NUMBER@[41; 44) "100" |
32 | WHITESPACE@[45; 46) | 32 | WHITESPACE@[44; 45) |
33 | FAT_ARROW@[46; 48) | 33 | FAT_ARROW@[45; 47) |
34 | WHITESPACE@[48; 49) | 34 | WHITESPACE@[47; 48) |
35 | TUPLE_EXPR@[49; 51) | 35 | TUPLE_EXPR@[48; 50) |
36 | L_PAREN@[49; 50) | 36 | L_PAREN@[48; 49) |
37 | R_PAREN@[50; 51) | 37 | R_PAREN@[49; 50) |
38 | COMMA@[51; 52) | 38 | COMMA@[50; 51) |
39 | WHITESPACE@[52; 61) | 39 | WHITESPACE@[51; 60) |
40 | MATCH_ARM@[61; 78) | 40 | MATCH_ARM@[60; 77) |
41 | RANGE_PAT@[61; 72) | 41 | RANGE_PAT@[60; 71) |
42 | LITERAL@[61; 64) | 42 | LITERAL@[60; 63) |
43 | INT_NUMBER@[61; 64) "101" | 43 | INT_NUMBER@[60; 63) "101" |
44 | WHITESPACE@[64; 65) | 44 | WHITESPACE@[63; 64) |
45 | DOTDOTEQ@[65; 68) | 45 | DOTDOTEQ@[64; 67) |
46 | WHITESPACE@[68; 69) | 46 | WHITESPACE@[67; 68) |
47 | LITERAL@[69; 72) | 47 | LITERAL@[68; 71) |
48 | INT_NUMBER@[69; 72) "200" | 48 | INT_NUMBER@[68; 71) "200" |
49 | WHITESPACE@[72; 73) | 49 | WHITESPACE@[71; 72) |
50 | FAT_ARROW@[73; 75) | 50 | FAT_ARROW@[72; 74) |
51 | WHITESPACE@[75; 76) | 51 | WHITESPACE@[74; 75) |
52 | TUPLE_EXPR@[76; 78) | 52 | TUPLE_EXPR@[75; 77) |
53 | L_PAREN@[76; 77) | 53 | L_PAREN@[75; 76) |
54 | R_PAREN@[77; 78) | 54 | R_PAREN@[76; 77) |
55 | COMMA@[78; 79) | 55 | COMMA@[77; 78) |
56 | WHITESPACE@[79; 88) | 56 | WHITESPACE@[78; 87) |
57 | MATCH_ARM@[88; 103) | 57 | MATCH_ARM@[87; 102) |
58 | RANGE_PAT@[88; 98) | 58 | RANGE_PAT@[87; 97) |
59 | LITERAL@[88; 91) | 59 | LITERAL@[87; 90) |
60 | INT_NUMBER@[88; 91) "200" | 60 | INT_NUMBER@[87; 90) "200" |
61 | WHITESPACE@[91; 92) | 61 | WHITESPACE@[90; 91) |
62 | DOTDOT@[92; 94) | 62 | DOTDOT@[91; 93) |
63 | WHITESPACE@[94; 95) | 63 | WHITESPACE@[93; 94) |
64 | LITERAL@[95; 98) | 64 | LITERAL@[94; 97) |
65 | INT_NUMBER@[95; 98) "301" | 65 | INT_NUMBER@[94; 97) "301" |
66 | FAT_ARROW@[98; 100) | 66 | FAT_ARROW@[97; 99) |
67 | WHITESPACE@[100; 101) | 67 | WHITESPACE@[99; 100) |
68 | TUPLE_EXPR@[101; 103) | 68 | TUPLE_EXPR@[100; 102) |
69 | L_PAREN@[101; 102) | 69 | L_PAREN@[100; 101) |
70 | R_PAREN@[102; 103) | 70 | R_PAREN@[101; 102) |
71 | COMMA@[103; 104) | 71 | COMMA@[102; 103) |
72 | WHITESPACE@[104; 109) | 72 | WHITESPACE@[103; 108) |
73 | R_CURLY@[109; 110) | 73 | R_CURLY@[108; 109) |
74 | WHITESPACE@[110; 111) | 74 | WHITESPACE@[109; 110) |
75 | R_CURLY@[111; 112) | 75 | R_CURLY@[110; 111) |
76 | WHITESPACE@[112; 113) | 76 | WHITESPACE@[111; 112) |