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 +++++----- 2 files changed, 25 insertions(+), 10 deletions(-) (limited to 'crates/ra_parser/src/grammar') 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])); -- cgit v1.2.3