aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
authorDJMcNab <[email protected]>2018-12-20 11:35:02 +0000
committerDJMcNab <[email protected]>2018-12-20 11:35:02 +0000
commit5205c016e9f704796aa7893f89ef108248bda2e2 (patch)
tree8ae27dbe907f3951605c9b213721dab5ba9b5497 /crates/ra_syntax/src
parent8693b1342093e71c1c39db0daee8580687e749f2 (diff)
Fix ambiguity with if break
Brought up by #290
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs5
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs21
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};
5use super::*; 5use super::*;
6 6
7const EXPR_FIRST: TokenSet = LHS_FIRST; 7const EXPR_FIRST: TokenSet = LHS_FIRST;
8const EXPR_FIRST_NO_BLOCK: TokenSet = LHS_FIRST_NO_BLOCK;
8 9
9pub(super) fn expr(p: &mut Parser) -> BlockLike { 10pub(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];
213const 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
213fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { 218fn 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
38pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ 38// E.g. for after the break in `if break {}`, this should not match
39pub(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
62pub(super) const ATOM_EXPR_FIRST: TokenSet =
63 token_set_union![ATOM_EXPR_FIRST_NO_BLOCK, token_set![L_CURLY],];
64
62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; 65const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
63 66
64pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { 67pub(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// }
430fn break_expr(p: &mut Parser) -> CompletedMarker { 433fn 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)