diff options
Diffstat (limited to 'crates/ra_syntax/src/grammar/expressions.rs')
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 512823ddf..043f41b98 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -158,18 +158,18 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
158 | // Parses expression with binding power of at least bp. | 158 | // Parses expression with binding power of at least bp. |
159 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { | 159 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { |
160 | let mut lhs = match lhs(p, r) { | 160 | let mut lhs = match lhs(p, r) { |
161 | Some(lhs) => { | 161 | (Some(lhs), blocklike) => { |
162 | // test stmt_bin_expr_ambiguity | 162 | // test stmt_bin_expr_ambiguity |
163 | // fn foo() { | 163 | // fn foo() { |
164 | // let _ = {1} & 2; | 164 | // let _ = {1} & 2; |
165 | // {1} &2; | 165 | // {1} &2; |
166 | // } | 166 | // } |
167 | if r.prefer_stmt && is_block(lhs.kind()) { | 167 | if r.prefer_stmt && (is_block(lhs.kind()) || blocklike == Some(BlockLike::Block)) { |
168 | return BlockLike::Block; | 168 | return BlockLike::Block; |
169 | } | 169 | } |
170 | lhs | 170 | lhs |
171 | } | 171 | } |
172 | None => return BlockLike::NotBlock, | 172 | (None, _) => return BlockLike::NotBlock, |
173 | }; | 173 | }; |
174 | 174 | ||
175 | loop { | 175 | loop { |
@@ -213,7 +213,7 @@ const LHS_FIRST: TokenSet = token_set_union![ | |||
213 | atom::ATOM_EXPR_FIRST, | 213 | atom::ATOM_EXPR_FIRST, |
214 | ]; | 214 | ]; |
215 | 215 | ||
216 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { | 216 | fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<BlockLike>) { |
217 | let m; | 217 | let m; |
218 | let kind = match p.current() { | 218 | let kind = match p.current() { |
219 | // test ref_expr | 219 | // test ref_expr |
@@ -246,19 +246,33 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { | |||
246 | if p.at_ts(EXPR_FIRST) { | 246 | if p.at_ts(EXPR_FIRST) { |
247 | expr_bp(p, r, 2); | 247 | expr_bp(p, r, 2); |
248 | } | 248 | } |
249 | return Some(m.complete(p, RANGE_EXPR)); | 249 | return (Some(m.complete(p, RANGE_EXPR)), None); |
250 | } | 250 | } |
251 | _ => { | 251 | _ => { |
252 | let lhs = atom::atom_expr(p, r)?; | 252 | let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); |
253 | return Some(postfix_expr(p, r, lhs)); | 253 | |
254 | if let Some(lhs_marker) = lhs_marker { | ||
255 | return ( | ||
256 | Some(postfix_expr(p, r, lhs_marker, macro_block_like)), | ||
257 | macro_block_like, | ||
258 | ); | ||
259 | } else { | ||
260 | return (None, None); | ||
261 | } | ||
254 | } | 262 | } |
255 | }; | 263 | }; |
256 | expr_bp(p, r, 255); | 264 | expr_bp(p, r, 255); |
257 | Some(m.complete(p, kind)) | 265 | (Some(m.complete(p, kind)), None) |
258 | } | 266 | } |
259 | 267 | ||
260 | fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { | 268 | fn postfix_expr( |
261 | let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); | 269 | p: &mut Parser, |
270 | r: Restrictions, | ||
271 | mut lhs: CompletedMarker, | ||
272 | macro_block_like: Option<BlockLike>, | ||
273 | ) -> CompletedMarker { | ||
274 | let mut allow_calls = | ||
275 | !r.prefer_stmt || !is_block(lhs.kind()) || macro_block_like != Some(BlockLike::Block); | ||
262 | loop { | 276 | loop { |
263 | lhs = match p.current() { | 277 | lhs = match p.current() { |
264 | // test stmt_postfix_expr_ambiguity | 278 | // test stmt_postfix_expr_ambiguity |
@@ -406,21 +420,22 @@ fn arg_list(p: &mut Parser) { | |||
406 | // let _ = ::a::<b>; | 420 | // let _ = ::a::<b>; |
407 | // let _ = format!(); | 421 | // let _ = format!(); |
408 | // } | 422 | // } |
409 | fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { | 423 | fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, Option<BlockLike>) { |
410 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | 424 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); |
411 | let m = p.start(); | 425 | let m = p.start(); |
412 | paths::expr_path(p); | 426 | paths::expr_path(p); |
413 | match p.current() { | 427 | let res = match p.current() { |
414 | L_CURLY if !r.forbid_structs => { | 428 | L_CURLY if !r.forbid_structs => { |
415 | named_field_list(p); | 429 | named_field_list(p); |
416 | m.complete(p, STRUCT_LIT) | 430 | m.complete(p, STRUCT_LIT) |
417 | } | 431 | } |
418 | EXCL => { | 432 | EXCL => { |
419 | items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) | 433 | let block_like = items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) |
420 | m.complete(p, MACRO_CALL) | 434 | return (m.complete(p, MACRO_CALL), Some(block_like)); |
421 | } | 435 | } |
422 | _ => m.complete(p, PATH_EXPR), | 436 | _ => m.complete(p, PATH_EXPR), |
423 | } | 437 | }; |
438 | (res, None) | ||
424 | } | 439 | } |
425 | 440 | ||
426 | // test struct_lit | 441 | // test struct_lit |