diff options
Diffstat (limited to 'crates/ra_syntax/src/grammar')
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions/atom.rs | 21 |
2 files changed, 21 insertions, 5 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 4f8c46ab3..79de0add0 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -5,6 +5,7 @@ pub(super) use self::atom::{literal, LITERAL_FIRST}; | |||
5 | use super::*; | 5 | use super::*; |
6 | 6 | ||
7 | const EXPR_FIRST: TokenSet = LHS_FIRST; | 7 | const EXPR_FIRST: TokenSet = LHS_FIRST; |
8 | const EXPR_FIRST_NO_BLOCK: TokenSet = LHS_FIRST_NO_BLOCK; | ||
8 | 9 | ||
9 | pub(super) fn expr(p: &mut Parser) -> BlockLike { | 10 | pub(super) fn expr(p: &mut Parser) -> BlockLike { |
10 | let r = Restrictions { | 11 | let r = Restrictions { |
@@ -209,6 +210,10 @@ const LHS_FIRST: TokenSet = token_set_union![ | |||
209 | token_set![AMP, STAR, EXCL, DOTDOT, MINUS], | 210 | token_set![AMP, STAR, EXCL, DOTDOT, MINUS], |
210 | atom::ATOM_EXPR_FIRST, | 211 | atom::ATOM_EXPR_FIRST, |
211 | ]; | 212 | ]; |
213 | const LHS_FIRST_NO_BLOCK: TokenSet = token_set_union![ | ||
214 | token_set![AMP, STAR, EXCL, DOTDOT, MINUS], | ||
215 | atom::ATOM_EXPR_FIRST_NO_BLOCK, | ||
216 | ]; | ||
212 | 217 | ||
213 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { | 218 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { |
214 | let m; | 219 | let m; |
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index cd7d62aff..fcc0a4490 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs | |||
@@ -35,10 +35,10 @@ pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> { | |||
35 | Some(m.complete(p, LITERAL)) | 35 | Some(m.complete(p, LITERAL)) |
36 | } | 36 | } |
37 | 37 | ||
38 | pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ | 38 | // E.g. for after the break in `if break {}`, this should not match |
39 | pub(super) const ATOM_EXPR_FIRST_NO_BLOCK: TokenSet = token_set_union![ | ||
39 | LITERAL_FIRST, | 40 | LITERAL_FIRST, |
40 | token_set![ | 41 | token_set![ |
41 | L_CURLY, | ||
42 | L_PAREN, | 42 | L_PAREN, |
43 | L_BRACK, | 43 | L_BRACK, |
44 | PIPE, | 44 | PIPE, |
@@ -59,6 +59,9 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ | |||
59 | ], | 59 | ], |
60 | ]; | 60 | ]; |
61 | 61 | ||
62 | pub(super) const ATOM_EXPR_FIRST: TokenSet = | ||
63 | token_set_union![ATOM_EXPR_FIRST_NO_BLOCK, token_set![L_CURLY],]; | ||
64 | |||
62 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; | 65 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; |
63 | 66 | ||
64 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { | 67 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { |
@@ -108,7 +111,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar | |||
108 | L_CURLY => block_expr(p, None), | 111 | L_CURLY => block_expr(p, None), |
109 | RETURN_KW => return_expr(p), | 112 | RETURN_KW => return_expr(p), |
110 | CONTINUE_KW => continue_expr(p), | 113 | CONTINUE_KW => continue_expr(p), |
111 | BREAK_KW => break_expr(p), | 114 | BREAK_KW => break_expr(p, r), |
112 | _ => { | 115 | _ => { |
113 | p.err_recover("expected expression", EXPR_RECOVERY_SET); | 116 | p.err_recover("expected expression", EXPR_RECOVERY_SET); |
114 | return None; | 117 | return None; |
@@ -427,12 +430,20 @@ fn continue_expr(p: &mut Parser) -> CompletedMarker { | |||
427 | // break 'l 92; | 430 | // break 'l 92; |
428 | // } | 431 | // } |
429 | // } | 432 | // } |
430 | fn break_expr(p: &mut Parser) -> CompletedMarker { | 433 | fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { |
431 | assert!(p.at(BREAK_KW)); | 434 | assert!(p.at(BREAK_KW)); |
432 | let m = p.start(); | 435 | let m = p.start(); |
433 | p.bump(); | 436 | p.bump(); |
434 | p.eat(LIFETIME); | 437 | p.eat(LIFETIME); |
435 | if p.at_ts(EXPR_FIRST) { | 438 | // test break_ambiguity |
439 | // fn foo(){ | ||
440 | // if break {} | ||
441 | // while break {} | ||
442 | // for i in break {} | ||
443 | // match break {} | ||
444 | // } | ||
445 | if r.forbid_structs && p.at_ts(EXPR_FIRST_NO_BLOCK) || !r.forbid_structs && p.at_ts(EXPR_FIRST) | ||
446 | { | ||
436 | expr(p); | 447 | expr(p); |
437 | } | 448 | } |
438 | m.complete(p, BREAK_EXPR) | 449 | m.complete(p, BREAK_EXPR) |