diff options
Diffstat (limited to 'crates/ra_parser/src/grammar/expressions.rs')
-rw-r--r-- | crates/ra_parser/src/grammar/expressions.rs | 49 |
1 files changed, 9 insertions, 40 deletions
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index ea04b9458..1dd9a586c 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -14,20 +14,17 @@ const EXPR_FIRST: TokenSet = LHS_FIRST; | |||
14 | 14 | ||
15 | pub(super) fn expr(p: &mut Parser) -> BlockLike { | 15 | pub(super) fn expr(p: &mut Parser) -> BlockLike { |
16 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; | 16 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; |
17 | let mut dollar_lvl = 0; | 17 | expr_bp(p, r, 1).1 |
18 | expr_bp(p, r, 1, &mut dollar_lvl).1 | ||
19 | } | 18 | } |
20 | 19 | ||
21 | pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { | 20 | pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { |
22 | let r = Restrictions { forbid_structs: false, prefer_stmt: true }; | 21 | let r = Restrictions { forbid_structs: false, prefer_stmt: true }; |
23 | let mut dollar_lvl = 0; | 22 | expr_bp(p, r, 1) |
24 | expr_bp(p, r, 1, &mut dollar_lvl) | ||
25 | } | 23 | } |
26 | 24 | ||
27 | fn expr_no_struct(p: &mut Parser) { | 25 | fn expr_no_struct(p: &mut Parser) { |
28 | let r = Restrictions { forbid_structs: true, prefer_stmt: false }; | 26 | let r = Restrictions { forbid_structs: true, prefer_stmt: false }; |
29 | let mut dollar_lvl = 0; | 27 | expr_bp(p, r, 1); |
30 | expr_bp(p, r, 1, &mut dollar_lvl); | ||
31 | } | 28 | } |
32 | 29 | ||
33 | // test block | 30 | // test block |
@@ -257,23 +254,8 @@ fn current_op(p: &Parser) -> (u8, SyntaxKind) { | |||
257 | } | 254 | } |
258 | 255 | ||
259 | // Parses expression with binding power of at least bp. | 256 | // Parses expression with binding power of at least bp. |
260 | fn expr_bp( | 257 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) { |
261 | p: &mut Parser, | 258 | let mut lhs = match lhs(p, r) { |
262 | r: Restrictions, | ||
263 | mut bp: u8, | ||
264 | dollar_lvl: &mut usize, | ||
265 | ) -> (Option<CompletedMarker>, BlockLike) { | ||
266 | // `newly_dollar_open` is a flag indicated that dollar is just closed after lhs, e.g. | ||
267 | // `$1$ + a` | ||
268 | // We use this flag to skip handling it. | ||
269 | let mut newly_dollar_open = if p.at_l_dollar() { | ||
270 | *dollar_lvl += p.eat_l_dollars(); | ||
271 | true | ||
272 | } else { | ||
273 | false | ||
274 | }; | ||
275 | |||
276 | let mut lhs = match lhs(p, r, dollar_lvl) { | ||
277 | Some((lhs, blocklike)) => { | 259 | Some((lhs, blocklike)) => { |
278 | // test stmt_bin_expr_ambiguity | 260 | // test stmt_bin_expr_ambiguity |
279 | // fn foo() { | 261 | // fn foo() { |
@@ -289,15 +271,6 @@ fn expr_bp( | |||
289 | }; | 271 | }; |
290 | 272 | ||
291 | loop { | 273 | loop { |
292 | if *dollar_lvl > 0 && p.at_r_dollar() { | ||
293 | *dollar_lvl -= p.eat_r_dollars(*dollar_lvl); | ||
294 | if !newly_dollar_open { | ||
295 | // We "pump" bp for make it highest priority | ||
296 | bp = 255; | ||
297 | } | ||
298 | newly_dollar_open = false; | ||
299 | } | ||
300 | |||
301 | let is_range = p.at(T![..]) || p.at(T![..=]); | 274 | let is_range = p.at(T![..]) || p.at(T![..=]); |
302 | let (op_bp, op) = current_op(p); | 275 | let (op_bp, op) = current_op(p); |
303 | if op_bp < bp { | 276 | if op_bp < bp { |
@@ -306,7 +279,7 @@ fn expr_bp( | |||
306 | let m = lhs.precede(p); | 279 | let m = lhs.precede(p); |
307 | p.bump(op); | 280 | p.bump(op); |
308 | 281 | ||
309 | expr_bp(p, r, op_bp + 1, dollar_lvl); | 282 | expr_bp(p, r, op_bp + 1); |
310 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); | 283 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); |
311 | } | 284 | } |
312 | (Some(lhs), BlockLike::NotBlock) | 285 | (Some(lhs), BlockLike::NotBlock) |
@@ -314,11 +287,7 @@ fn expr_bp( | |||
314 | 287 | ||
315 | const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]); | 288 | const LHS_FIRST: TokenSet = atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOT, MINUS]); |
316 | 289 | ||
317 | fn lhs( | 290 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { |
318 | p: &mut Parser, | ||
319 | r: Restrictions, | ||
320 | dollar_lvl: &mut usize, | ||
321 | ) -> Option<(CompletedMarker, BlockLike)> { | ||
322 | let m; | 291 | let m; |
323 | let kind = match p.current() { | 292 | let kind = match p.current() { |
324 | // test ref_expr | 293 | // test ref_expr |
@@ -351,7 +320,7 @@ fn lhs( | |||
351 | m = p.start(); | 320 | m = p.start(); |
352 | p.bump(op); | 321 | p.bump(op); |
353 | if p.at_ts(EXPR_FIRST) { | 322 | if p.at_ts(EXPR_FIRST) { |
354 | expr_bp(p, r, 2, dollar_lvl); | 323 | expr_bp(p, r, 2); |
355 | } | 324 | } |
356 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); | 325 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); |
357 | } | 326 | } |
@@ -367,7 +336,7 @@ fn lhs( | |||
367 | return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); | 336 | return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); |
368 | } | 337 | } |
369 | }; | 338 | }; |
370 | expr_bp(p, r, 255, dollar_lvl); | 339 | expr_bp(p, r, 255); |
371 | Some((m.complete(p, kind), BlockLike::NotBlock)) | 340 | Some((m.complete(p, kind), BlockLike::NotBlock)) |
372 | } | 341 | } |
373 | 342 | ||