aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_parser/src
diff options
context:
space:
mode:
authorGeoffry Song <[email protected]>2019-10-03 07:38:03 +0100
committerGeoffry Song <[email protected]>2019-10-03 08:39:52 +0100
commit9638adaa40d22adcf9b4002d95a13977c0f1436f (patch)
tree9a6b2a477a371499f7a9012b26bf639acd801cb6 /crates/ra_parser/src
parente1c367595139f109fb6f53811bed7d67a384793e (diff)
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).
Diffstat (limited to 'crates/ra_parser/src')
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs25
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs10
2 files changed, 25 insertions, 10 deletions
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)>
335 // } 335 // }
336 // 336 //
337 let (lhs, blocklike) = atom::atom_expr(p, r)?; 337 let (lhs, blocklike) = atom::atom_expr(p, r)?;
338 return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); 338 return Some(postfix_expr(
339 p,
340 lhs,
341 blocklike,
342 !(r.prefer_stmt && blocklike.is_block()),
343 r.forbid_structs,
344 ));
339 } 345 }
340 }; 346 };
341 expr_bp(p, r, 255); 347 expr_bp(p, r, 255);
@@ -350,6 +356,7 @@ fn postfix_expr(
350 // `while true {break}; ();` 356 // `while true {break}; ();`
351 mut block_like: BlockLike, 357 mut block_like: BlockLike,
352 mut allow_calls: bool, 358 mut allow_calls: bool,
359 forbid_structs: bool,
353) -> (CompletedMarker, BlockLike) { 360) -> (CompletedMarker, BlockLike) {
354 loop { 361 loop {
355 lhs = match p.current() { 362 lhs = match p.current() {
@@ -363,7 +370,7 @@ fn postfix_expr(
363 // } 370 // }
364 T!['('] if allow_calls => call_expr(p, lhs), 371 T!['('] if allow_calls => call_expr(p, lhs),
365 T!['['] if allow_calls => index_expr(p, lhs), 372 T!['['] if allow_calls => index_expr(p, lhs),
366 T![.] => match postfix_dot_expr(p, lhs) { 373 T![.] => match postfix_dot_expr(p, lhs, forbid_structs) {
367 Ok(it) => it, 374 Ok(it) => it,
368 Err(it) => { 375 Err(it) => {
369 lhs = it; 376 lhs = it;
@@ -382,6 +389,7 @@ fn postfix_expr(
382 fn postfix_dot_expr( 389 fn postfix_dot_expr(
383 p: &mut Parser, 390 p: &mut Parser,
384 lhs: CompletedMarker, 391 lhs: CompletedMarker,
392 forbid_structs: bool,
385 ) -> Result<CompletedMarker, CompletedMarker> { 393 ) -> Result<CompletedMarker, CompletedMarker> {
386 assert!(p.at(T![.])); 394 assert!(p.at(T![.]));
387 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) { 395 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
@@ -402,10 +410,17 @@ fn postfix_expr(
402 } 410 }
403 411
404 // test postfix_range 412 // test postfix_range
405 // fn foo() { let x = 1..; } 413 // fn foo() {
406 for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() { 414 // let x = 1..;
415 // match 1.. { _ => () };
416 // match a.b()..S { _ => () };
417 // }
418 for &(op, la) in &[(T![..=], 3), (T![..], 2)] {
407 if p.at(op) { 419 if p.at(op) {
408 return if EXPR_FIRST.contains(p.nth(la)) { 420 let next_token = p.nth(la);
421 let has_trailing_expression =
422 !(forbid_structs && next_token == T!['{']) && EXPR_FIRST.contains(next_token);
423 return if has_trailing_expression {
409 Err(lhs) 424 Err(lhs)
410 } else { 425 } else {
411 let m = lhs.precede(p); 426 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
121 // break; 121 // break;
122 // } 122 // }
123 // } 123 // }
124 if r.forbid_structs { 124 block_expr(p, None)
125 return None;
126 } else {
127 block_expr(p, None)
128 }
129 } 125 }
130 T![return] => return_expr(p), 126 T![return] => return_expr(p),
131 T![continue] => continue_expr(p), 127 T![continue] => continue_expr(p),
@@ -261,6 +257,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
261// if true {} else {}; 257// if true {} else {};
262// if true {} else if false {} else {}; 258// if true {} else if false {} else {};
263// if S {}; 259// if S {};
260// if { true } { } else { };
264// } 261// }
265fn if_expr(p: &mut Parser) -> CompletedMarker { 262fn if_expr(p: &mut Parser) -> CompletedMarker {
266 assert!(p.at(T![if])); 263 assert!(p.at(T![if]));
@@ -309,6 +306,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
309// fn foo() { 306// fn foo() {
310// while true {}; 307// while true {};
311// while let Some(x) = it.next() {}; 308// while let Some(x) = it.next() {};
309// while { true } {};
312// } 310// }
313fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 311fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
314 assert!(p.at(T![while])); 312 assert!(p.at(T![while]));
@@ -356,6 +354,8 @@ fn cond(p: &mut Parser) {
356// fn foo() { 354// fn foo() {
357// match () { }; 355// match () { };
358// match S {}; 356// match S {};
357// match { } { _ => () };
358// match { S {} } {};
359// } 359// }
360fn match_expr(p: &mut Parser) -> CompletedMarker { 360fn match_expr(p: &mut Parser) -> CompletedMarker {
361 assert!(p.at(T![match])); 361 assert!(p.at(T![match]));