aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/grammar/expressions.rs
diff options
context:
space:
mode:
authorDJMcNab <[email protected]>2018-12-19 18:12:19 +0000
committerDJMcNab <[email protected]>2018-12-19 20:12:18 +0000
commit7a8560ba382af4b3955b14757518f748e0d67709 (patch)
tree59924b78fc7ab10700624e5c5b143309526c8eed /crates/ra_syntax/src/grammar/expressions.rs
parent97e70bf50f15007f5782f7f96d19da342b7c9505 (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/grammar/expressions.rs')
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs26
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.
159fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { 159fn 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
268fn postfix_expr( 269fn 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