aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs77
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs20
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt120
4 files changed, 104 insertions, 115 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 9d75bfb90..5f5a3077d 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -64,6 +64,16 @@ pub(crate) fn block(p: &mut Parser) {
64 if p.at(R_CURLY) { 64 if p.at(R_CURLY) {
65 m.abandon(p); 65 m.abandon(p);
66 } else { 66 } else {
67 // test no_semi_after_block
68 // fn foo() {
69 // if true {}
70 // loop {}
71 // match () {}
72 // while true {}
73 // for _ in () {}
74 // {}
75 // {}
76 // }
67 if is_blocklike { 77 if is_blocklike {
68 p.eat(SEMI); 78 p.eat(SEMI);
69 } else { 79 } else {
@@ -158,19 +168,18 @@ fn current_op(p: &Parser) -> (u8, Op) {
158// Parses expression with binding power of at least bp. 168// Parses expression with binding power of at least bp.
159fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike { 169fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
160 let mut lhs = match lhs(p, r) { 170 let mut lhs = match lhs(p, r) {
161 (Some(lhs), macro_blocklike) => { 171 Some((lhs, macro_blocklike)) => {
162 // test stmt_bin_expr_ambiguity 172 // test stmt_bin_expr_ambiguity
163 // fn foo() { 173 // fn foo() {
164 // let _ = {1} & 2; 174 // let _ = {1} & 2;
165 // {1} &2; 175 // {1} &2;
166 // } 176 // }
167 if r.prefer_stmt && (is_block(lhs.kind()) || macro_blocklike == Some(BlockLike::Block)) 177 if r.prefer_stmt && macro_blocklike.is_block() {
168 {
169 return BlockLike::Block; 178 return BlockLike::Block;
170 } 179 }
171 lhs 180 lhs
172 } 181 }
173 (None, _) => return BlockLike::NotBlock, 182 None => return BlockLike::NotBlock,
174 }; 183 };
175 184
176 loop { 185 loop {
@@ -192,29 +201,12 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
192 BlockLike::NotBlock 201 BlockLike::NotBlock
193} 202}
194 203
195// test no_semi_after_block
196// fn foo() {
197// if true {}
198// loop {}
199// match () {}
200// while true {}
201// for _ in () {}
202// {}
203// {}
204// }
205fn is_block(kind: SyntaxKind) -> bool {
206 match kind {
207 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true,
208 _ => false,
209 }
210}
211
212const LHS_FIRST: TokenSet = token_set_union![ 204const LHS_FIRST: TokenSet = token_set_union![
213 token_set![AMP, STAR, EXCL, DOTDOT, MINUS], 205 token_set![AMP, STAR, EXCL, DOTDOT, MINUS],
214 atom::ATOM_EXPR_FIRST, 206 atom::ATOM_EXPR_FIRST,
215]; 207];
216 208
217fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<BlockLike>) { 209fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
218 let m; 210 let m;
219 let kind = match p.current() { 211 let kind = match p.current() {
220 // test ref_expr 212 // test ref_expr
@@ -247,30 +239,28 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc
247 if p.at_ts(EXPR_FIRST) { 239 if p.at_ts(EXPR_FIRST) {
248 expr_bp(p, r, 2); 240 expr_bp(p, r, 2);
249 } 241 }
250 return (Some(m.complete(p, RANGE_EXPR)), None); 242 return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock));
251 } 243 }
252 _ => { 244 _ => {
253 let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); 245 let (lhs, blocklike) = atom::atom_expr(p, r)?;
254 246 return Some((
255 if macro_block_like == Some(BlockLike::Block) { 247 postfix_expr(p, lhs, !(r.prefer_stmt && blocklike.is_block())),
256 return (lhs_marker, macro_block_like); 248 blocklike,
257 } 249 ));
258 if let Some(lhs_marker) = lhs_marker {
259 return (Some(postfix_expr(p, r, lhs_marker)), macro_block_like);
260 } else {
261 return (None, None);
262 }
263 } 250 }
264 }; 251 };
265 expr_bp(p, r, 255); 252 expr_bp(p, r, 255);
266 (Some(m.complete(p, kind)), None) 253 Some((m.complete(p, kind), BlockLike::NotBlock))
267} 254}
268 255
269fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { 256fn postfix_expr(
257 p: &mut Parser,
258 mut lhs: CompletedMarker,
270 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple 259 // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
271 // E.g. `while true {break}();` is parsed as 260 // E.g. `while true {break}();` is parsed as
272 // `while true {break}; ();` 261 // `while true {break}; ();`
273 let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); 262 mut allow_calls: bool,
263) -> CompletedMarker {
274 loop { 264 loop {
275 lhs = match p.current() { 265 lhs = match p.current() {
276 // test stmt_postfix_expr_ambiguity 266 // test stmt_postfix_expr_ambiguity
@@ -418,22 +408,21 @@ fn arg_list(p: &mut Parser) {
418// let _ = ::a::<b>; 408// let _ = ::a::<b>;
419// let _ = format!(); 409// let _ = format!();
420// } 410// }
421fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, Option<BlockLike>) { 411fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
422 assert!(paths::is_path_start(p) || p.at(L_ANGLE)); 412 assert!(paths::is_path_start(p) || p.at(L_ANGLE));
423 let m = p.start(); 413 let m = p.start();
424 paths::expr_path(p); 414 paths::expr_path(p);
425 let res = match p.current() { 415 match p.current() {
426 L_CURLY if !r.forbid_structs => { 416 L_CURLY if !r.forbid_structs => {
427 named_field_list(p); 417 named_field_list(p);
428 m.complete(p, STRUCT_LIT) 418 (m.complete(p, STRUCT_LIT), BlockLike::Block)
429 } 419 }
430 EXCL => { 420 EXCL => {
431 let block_like = items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) 421 let block_like = items::macro_call_after_excl(p);
432 return (m.complete(p, MACRO_CALL), Some(block_like)); 422 return (m.complete(p, MACRO_CALL), block_like);
433 } 423 }
434 _ => m.complete(p, PATH_EXPR), 424 _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
435 }; 425 }
436 (res, None)
437} 426}
438 427
439// test struct_lit 428// test struct_lit
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 471f398f5..a976799e7 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -61,16 +61,12 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![
61 61
62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; 62const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
63 63
64pub(super) fn atom_expr( 64pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
65 p: &mut Parser,
66 r: Restrictions,
67) -> (Option<CompletedMarker>, Option<BlockLike>) {
68 if let Some(m) = literal(p) { 65 if let Some(m) = literal(p) {
69 return (Some(m), None); 66 return Some((m, BlockLike::NotBlock));
70 } 67 }
71 if paths::is_path_start(p) || p.at(L_ANGLE) { 68 if paths::is_path_start(p) || p.at(L_ANGLE) {
72 let path_expr = path_expr(p, r); 69 return Some(path_expr(p, r));
73 return (Some(path_expr.0), path_expr.1);
74 } 70 }
75 let la = p.nth(1); 71 let la = p.nth(1);
76 let done = match p.current() { 72 let done = match p.current() {
@@ -98,7 +94,7 @@ pub(super) fn atom_expr(
98 // } 94 // }
99 p.error("expected a loop"); 95 p.error("expected a loop");
100 m.complete(p, ERROR); 96 m.complete(p, ERROR);
101 return (None, None); 97 return None;
102 } 98 }
103 } 99 }
104 } 100 }
@@ -115,10 +111,14 @@ pub(super) fn atom_expr(
115 BREAK_KW => break_expr(p), 111 BREAK_KW => break_expr(p),
116 _ => { 112 _ => {
117 p.err_recover("expected expression", EXPR_RECOVERY_SET); 113 p.err_recover("expected expression", EXPR_RECOVERY_SET);
118 return (None, None); 114 return None;
119 } 115 }
120 }; 116 };
121 (Some(done), None) 117 let blocklike = match done.kind() {
118 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => BlockLike::Block,
119 _ => BlockLike::NotBlock,
120 };
121 Some((done, blocklike))
122} 122}
123 123
124// test tuple_expr 124// test tuple_expr
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
index 3bca7bf5d..c12ab6fce 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
@@ -1,5 +1,5 @@
1fn main() { 1fn main() {
2 match 92 { 2 match 92 {
3 0 ... 100 => (), 3 0 ... 100 => (),
4 101 ..= 200 => (), 4 101 ..= 200 => (),
5 200 .. 301=> (), 5 200 .. 301=> (),
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
index 7eb0fcdf4..d47f38903 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 113) 1SOURCE_FILE@[0; 112)
2 FN_DEF@[0; 112) 2 FN_DEF@[0; 111)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 7) 5 NAME@[3; 7)
@@ -8,69 +8,69 @@ SOURCE_FILE@[0; 113)
8 L_PAREN@[7; 8) 8 L_PAREN@[7; 8)
9 R_PAREN@[8; 9) 9 R_PAREN@[8; 9)
10 WHITESPACE@[9; 10) 10 WHITESPACE@[9; 10)
11 BLOCK@[10; 112) 11 BLOCK@[10; 111)
12 L_CURLY@[10; 11) 12 L_CURLY@[10; 11)
13 WHITESPACE@[11; 16) 13 WHITESPACE@[11; 16)
14 MATCH_EXPR@[16; 110) 14 MATCH_EXPR@[16; 109)
15 MATCH_KW@[16; 21) 15 MATCH_KW@[16; 21)
16 WHITESPACE@[21; 22) 16 WHITESPACE@[21; 22)
17 LITERAL@[22; 24) 17 LITERAL@[22; 24)
18 INT_NUMBER@[22; 24) "92" 18 INT_NUMBER@[22; 24) "92"
19 WHITESPACE@[24; 25) 19 WHITESPACE@[24; 25)
20 MATCH_ARM_LIST@[25; 110) 20 MATCH_ARM_LIST@[25; 109)
21 L_CURLY@[25; 26) 21 L_CURLY@[25; 26)
22 WHITESPACE@[26; 36) 22 WHITESPACE@[26; 35)
23 MATCH_ARM@[36; 51) 23 MATCH_ARM@[35; 50)
24 RANGE_PAT@[36; 45) 24 RANGE_PAT@[35; 44)
25 LITERAL@[36; 37) 25 LITERAL@[35; 36)
26 INT_NUMBER@[36; 37) "0" 26 INT_NUMBER@[35; 36) "0"
27 WHITESPACE@[37; 38) 27 WHITESPACE@[36; 37)
28 DOTDOTDOT@[38; 41) 28 DOTDOTDOT@[37; 40)
29 WHITESPACE@[41; 42) 29 WHITESPACE@[40; 41)
30 LITERAL@[42; 45) 30 LITERAL@[41; 44)
31 INT_NUMBER@[42; 45) "100" 31 INT_NUMBER@[41; 44) "100"
32 WHITESPACE@[45; 46) 32 WHITESPACE@[44; 45)
33 FAT_ARROW@[46; 48) 33 FAT_ARROW@[45; 47)
34 WHITESPACE@[48; 49) 34 WHITESPACE@[47; 48)
35 TUPLE_EXPR@[49; 51) 35 TUPLE_EXPR@[48; 50)
36 L_PAREN@[49; 50) 36 L_PAREN@[48; 49)
37 R_PAREN@[50; 51) 37 R_PAREN@[49; 50)
38 COMMA@[51; 52) 38 COMMA@[50; 51)
39 WHITESPACE@[52; 61) 39 WHITESPACE@[51; 60)
40 MATCH_ARM@[61; 78) 40 MATCH_ARM@[60; 77)
41 RANGE_PAT@[61; 72) 41 RANGE_PAT@[60; 71)
42 LITERAL@[61; 64) 42 LITERAL@[60; 63)
43 INT_NUMBER@[61; 64) "101" 43 INT_NUMBER@[60; 63) "101"
44 WHITESPACE@[64; 65) 44 WHITESPACE@[63; 64)
45 DOTDOTEQ@[65; 68) 45 DOTDOTEQ@[64; 67)
46 WHITESPACE@[68; 69) 46 WHITESPACE@[67; 68)
47 LITERAL@[69; 72) 47 LITERAL@[68; 71)
48 INT_NUMBER@[69; 72) "200" 48 INT_NUMBER@[68; 71) "200"
49 WHITESPACE@[72; 73) 49 WHITESPACE@[71; 72)
50 FAT_ARROW@[73; 75) 50 FAT_ARROW@[72; 74)
51 WHITESPACE@[75; 76) 51 WHITESPACE@[74; 75)
52 TUPLE_EXPR@[76; 78) 52 TUPLE_EXPR@[75; 77)
53 L_PAREN@[76; 77) 53 L_PAREN@[75; 76)
54 R_PAREN@[77; 78) 54 R_PAREN@[76; 77)
55 COMMA@[78; 79) 55 COMMA@[77; 78)
56 WHITESPACE@[79; 88) 56 WHITESPACE@[78; 87)
57 MATCH_ARM@[88; 103) 57 MATCH_ARM@[87; 102)
58 RANGE_PAT@[88; 98) 58 RANGE_PAT@[87; 97)
59 LITERAL@[88; 91) 59 LITERAL@[87; 90)
60 INT_NUMBER@[88; 91) "200" 60 INT_NUMBER@[87; 90) "200"
61 WHITESPACE@[91; 92) 61 WHITESPACE@[90; 91)
62 DOTDOT@[92; 94) 62 DOTDOT@[91; 93)
63 WHITESPACE@[94; 95) 63 WHITESPACE@[93; 94)
64 LITERAL@[95; 98) 64 LITERAL@[94; 97)
65 INT_NUMBER@[95; 98) "301" 65 INT_NUMBER@[94; 97) "301"
66 FAT_ARROW@[98; 100) 66 FAT_ARROW@[97; 99)
67 WHITESPACE@[100; 101) 67 WHITESPACE@[99; 100)
68 TUPLE_EXPR@[101; 103) 68 TUPLE_EXPR@[100; 102)
69 L_PAREN@[101; 102) 69 L_PAREN@[100; 101)
70 R_PAREN@[102; 103) 70 R_PAREN@[101; 102)
71 COMMA@[103; 104) 71 COMMA@[102; 103)
72 WHITESPACE@[104; 109) 72 WHITESPACE@[103; 108)
73 R_CURLY@[109; 110) 73 R_CURLY@[108; 109)
74 WHITESPACE@[110; 111) 74 WHITESPACE@[109; 110)
75 R_CURLY@[111; 112) 75 R_CURLY@[110; 111)
76 WHITESPACE@[112; 113) 76 WHITESPACE@[111; 112)