diff options
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions.rs | 39 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions/atom.rs | 16 | ||||
-rw-r--r-- | crates/ra_syntax/tests/test.rs | 3 |
3 files changed, 22 insertions, 36 deletions
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs index 9d75bfb90..512823ddf 100644 --- a/crates/ra_syntax/src/grammar/expressions.rs +++ b/crates/ra_syntax/src/grammar/expressions.rs | |||
@@ -158,19 +158,18 @@ 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), macro_blocklike) => { | 161 | Some(lhs) => { |
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()) || macro_blocklike == Some(BlockLike::Block)) | 167 | if r.prefer_stmt && is_block(lhs.kind()) { |
168 | { | ||
169 | return BlockLike::Block; | 168 | return BlockLike::Block; |
170 | } | 169 | } |
171 | lhs | 170 | lhs |
172 | } | 171 | } |
173 | (None, _) => return BlockLike::NotBlock, | 172 | None => return BlockLike::NotBlock, |
174 | }; | 173 | }; |
175 | 174 | ||
176 | loop { | 175 | loop { |
@@ -214,7 +213,7 @@ const LHS_FIRST: TokenSet = token_set_union![ | |||
214 | atom::ATOM_EXPR_FIRST, | 213 | atom::ATOM_EXPR_FIRST, |
215 | ]; | 214 | ]; |
216 | 215 | ||
217 | fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<BlockLike>) { | 216 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
218 | let m; | 217 | let m; |
219 | let kind = match p.current() { | 218 | let kind = match p.current() { |
220 | // test ref_expr | 219 | // test ref_expr |
@@ -247,29 +246,18 @@ fn lhs(p: &mut Parser, r: Restrictions) -> (Option<CompletedMarker>, Option<Bloc | |||
247 | if p.at_ts(EXPR_FIRST) { | 246 | if p.at_ts(EXPR_FIRST) { |
248 | expr_bp(p, r, 2); | 247 | expr_bp(p, r, 2); |
249 | } | 248 | } |
250 | return (Some(m.complete(p, RANGE_EXPR)), None); | 249 | return Some(m.complete(p, RANGE_EXPR)); |
251 | } | 250 | } |
252 | _ => { | 251 | _ => { |
253 | let (lhs_marker, macro_block_like) = atom::atom_expr(p, r); | 252 | let lhs = atom::atom_expr(p, r)?; |
254 | 253 | return Some(postfix_expr(p, r, lhs)); | |
255 | if macro_block_like == Some(BlockLike::Block) { | ||
256 | return (lhs_marker, macro_block_like); | ||
257 | } | ||
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 | } | 254 | } |
264 | }; | 255 | }; |
265 | expr_bp(p, r, 255); | 256 | expr_bp(p, r, 255); |
266 | (Some(m.complete(p, kind)), None) | 257 | Some(m.complete(p, kind)) |
267 | } | 258 | } |
268 | 259 | ||
269 | fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { | 260 | fn postfix_expr(p: &mut Parser, r: Restrictions, mut lhs: CompletedMarker) -> CompletedMarker { |
270 | // 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 | ||
272 | // `while true {break}; ();` | ||
273 | let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); | 261 | let mut allow_calls = !r.prefer_stmt || !is_block(lhs.kind()); |
274 | loop { | 262 | loop { |
275 | lhs = match p.current() { | 263 | lhs = match p.current() { |
@@ -418,22 +406,21 @@ fn arg_list(p: &mut Parser) { | |||
418 | // let _ = ::a::<b>; | 406 | // let _ = ::a::<b>; |
419 | // let _ = format!(); | 407 | // let _ = format!(); |
420 | // } | 408 | // } |
421 | fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, Option<BlockLike>) { | 409 | fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { |
422 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | 410 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); |
423 | let m = p.start(); | 411 | let m = p.start(); |
424 | paths::expr_path(p); | 412 | paths::expr_path(p); |
425 | let res = match p.current() { | 413 | match p.current() { |
426 | L_CURLY if !r.forbid_structs => { | 414 | L_CURLY if !r.forbid_structs => { |
427 | named_field_list(p); | 415 | named_field_list(p); |
428 | m.complete(p, STRUCT_LIT) | 416 | m.complete(p, STRUCT_LIT) |
429 | } | 417 | } |
430 | EXCL => { | 418 | EXCL => { |
431 | let block_like = items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) | 419 | items::macro_call_after_excl(p); // TODO: Use return type (BlockLike) |
432 | return (m.complete(p, MACRO_CALL), Some(block_like)); | 420 | m.complete(p, MACRO_CALL) |
433 | } | 421 | } |
434 | _ => m.complete(p, PATH_EXPR), | 422 | _ => m.complete(p, PATH_EXPR), |
435 | }; | 423 | } |
436 | (res, None) | ||
437 | } | 424 | } |
438 | 425 | ||
439 | // test struct_lit | 426 | // test struct_lit |
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index e86a33090..04087fd60 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 | ||
62 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; | 62 | const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW]; |
63 | 63 | ||
64 | pub(super) fn atom_expr( | 64 | pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMarker> { |
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); |
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,10 @@ 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 | Some(done) |
122 | } | 118 | } |
123 | 119 | ||
124 | // test tuple_expr | 120 | // test tuple_expr |
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs index a07855768..7f385f86f 100644 --- a/crates/ra_syntax/tests/test.rs +++ b/crates/ra_syntax/tests/test.rs | |||
@@ -43,6 +43,7 @@ fn parser_fuzz_tests() { | |||
43 | fn self_hosting_parsing() { | 43 | fn self_hosting_parsing() { |
44 | let empty_vec = vec![]; | 44 | let empty_vec = vec![]; |
45 | let dir = project_dir(); | 45 | let dir = project_dir(); |
46 | let mut count = 0u32; | ||
46 | for entry in walkdir::WalkDir::new(dir) | 47 | for entry in walkdir::WalkDir::new(dir) |
47 | .into_iter() | 48 | .into_iter() |
48 | .filter_entry(|entry| { | 49 | .filter_entry(|entry| { |
@@ -63,6 +64,7 @@ fn self_hosting_parsing() { | |||
63 | !entry.path().is_dir() && (entry.path().extension() == Some(std::ffi::OsStr::new("rs"))) | 64 | !entry.path().is_dir() && (entry.path().extension() == Some(std::ffi::OsStr::new("rs"))) |
64 | }) | 65 | }) |
65 | { | 66 | { |
67 | count += 1; | ||
66 | let text = read_text(entry.path()); | 68 | let text = read_text(entry.path()); |
67 | let node = SourceFileNode::parse(&text); | 69 | let node = SourceFileNode::parse(&text); |
68 | let errors = node.errors(); | 70 | let errors = node.errors(); |
@@ -72,6 +74,7 @@ fn self_hosting_parsing() { | |||
72 | entry | 74 | entry |
73 | ); | 75 | ); |
74 | } | 76 | } |
77 | panic!("{}", count) | ||
75 | } | 78 | } |
76 | /// Read file and normalize newlines. | 79 | /// Read file and normalize newlines. |
77 | /// | 80 | /// |