diff options
author | DJMcNab <[email protected]> | 2018-12-19 18:12:19 +0000 |
---|---|---|
committer | DJMcNab <[email protected]> | 2018-12-19 20:12:18 +0000 |
commit | 7a8560ba382af4b3955b14757518f748e0d67709 (patch) | |
tree | 59924b78fc7ab10700624e5c5b143309526c8eed /crates/ra_syntax/src | |
parent | 97e70bf50f15007f5782f7f96d19da342b7c9505 (diff) |
Fix expression parsing by bailing out upon a macro block being found
TODO: Fix this when the block like macro is in expression position
E.g. `test(test!{})` currently parses
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 043f41b98..9d75bfb90 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -158,13 +158,14 @@ 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), blocklike) => { | 161 | (Some(lhs), macro_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()) || blocklike == Some(BlockLike::Block)) { | 167 | if r.prefer_stmt && (is_block(lhs.kind()) || macro_blocklike == Some(BlockLike::Block)) |
168 | { | ||
168 | return BlockLike::Block; | 169 | return BlockLike::Block; |
169 | } | 170 | } |
170 | lhs | 171 | lhs |
@@ -251,11 +252,11 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc | |||
251 | _ => { | 252 | _ => { |
252 | let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); | 253 | let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); |
253 | 254 | ||
255 | if macro_block_like == Some(BlockLike::Block) { | ||
256 | return (lhs_marker, macro_block_like); | ||
257 | } | ||
254 | if let Some(lhs_marker) = lhs_marker { | 258 | if let Some(lhs_marker) = lhs_marker { |
255 | return ( | 259 | return (Some(postfix_expr(p, r, lhs_marker)), macro_block_like); |
256 | Some(postfix_expr(p, r, lhs_marker, macro_block_like)), | ||
257 | macro_block_like, | ||
258 | ); | ||
259 | } else { | 260 | } else { |
260 | return (None, None); | 261 | return (None, None); |
261 | } | 262 | } |
@@ -265,14 +266,11 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc | |||
265 | (Some(m.complete(p, kind)), None) | 266 | (Some(m.complete(p, kind)), None) |
266 | } | 267 | } |
267 | 268 | ||
268 | fn postfix_expr( | 269 | fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { |
269 | p: &mut Parser, | 270 | // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple |
270 | r: Restrictions, | 271 | // E.g. `while true {break}();` is parsed as |
271 | mut lhs: CompletedMarker, | 272 | // `while true {break}; ();` |
272 | macro_block_like: Option<BlockLike>, | 273 | let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); |
273 | ) -> CompletedMarker { | ||
274 | let mut allow_calls = | ||
275 | !r.prefer_stmt || !is_block(lhs.kind()) || macro_block_like != Some(BlockLike::Block); | ||
276 | loop { | 274 | loop { |
277 | lhs = match p.current() { | 275 | lhs = match p.current() { |
278 | // test stmt_postfix_expr_ambiguity | 276 | // test stmt_postfix_expr_ambiguity |