1 | use crate::classify; |
2 | use crate::precedence::Precedence; |
3 | use syn::{ |
4 | Expr, ExprBreak, ExprRange, ExprRawAddr, ExprReference, ExprReturn, ExprUnary, ExprYield, |
5 | }; |
6 | |
7 | #[derive (Copy, Clone)] |
8 | pub struct FixupContext { |
9 | previous_operator: Precedence, |
10 | next_operator: Precedence, |
11 | |
12 | // Print expression such that it can be parsed back as a statement |
13 | // consisting of the original expression. |
14 | // |
15 | // The effect of this is for binary operators in statement position to set |
16 | // `leftmost_subexpression_in_stmt` when printing their left-hand operand. |
17 | // |
18 | // (match x {}) - 1; // match needs parens when LHS of binary operator |
19 | // |
20 | // match x {}; // not when its own statement |
21 | // |
22 | stmt: bool, |
23 | |
24 | // This is the difference between: |
25 | // |
26 | // (match x {}) - 1; // subexpression needs parens |
27 | // |
28 | // let _ = match x {} - 1; // no parens |
29 | // |
30 | // There are 3 distinguishable contexts in which `print_expr` might be |
31 | // called with the expression `$match` as its argument, where `$match` |
32 | // represents an expression of kind `ExprKind::Match`: |
33 | // |
34 | // - stmt=false leftmost_subexpression_in_stmt=false |
35 | // |
36 | // Example: `let _ = $match - 1;` |
37 | // |
38 | // No parentheses required. |
39 | // |
40 | // - stmt=false leftmost_subexpression_in_stmt=true |
41 | // |
42 | // Example: `$match - 1;` |
43 | // |
44 | // Must parenthesize `($match)`, otherwise parsing back the output as a |
45 | // statement would terminate the statement after the closing brace of |
46 | // the match, parsing `-1;` as a separate statement. |
47 | // |
48 | // - stmt=true leftmost_subexpression_in_stmt=false |
49 | // |
50 | // Example: `$match;` |
51 | // |
52 | // No parentheses required. |
53 | leftmost_subexpression_in_stmt: bool, |
54 | |
55 | // Print expression such that it can be parsed as a match arm. |
56 | // |
57 | // This is almost equivalent to `stmt`, but the grammar diverges a tiny bit |
58 | // between statements and match arms when it comes to braced macro calls. |
59 | // Macro calls with brace delimiter terminate a statement without a |
60 | // semicolon, but do not terminate a match-arm without comma. |
61 | // |
62 | // m! {} - 1; // two statements: a macro call followed by -1 literal |
63 | // |
64 | // match () { |
65 | // _ => m! {} - 1, // binary subtraction operator |
66 | // } |
67 | // |
68 | match_arm: bool, |
69 | |
70 | // This is almost equivalent to `leftmost_subexpression_in_stmt`, other than |
71 | // for braced macro calls. |
72 | // |
73 | // If we have `m! {} - 1` as an expression, the leftmost subexpression |
74 | // `m! {}` will need to be parenthesized in the statement case but not the |
75 | // match-arm case. |
76 | // |
77 | // (m! {}) - 1; // subexpression needs parens |
78 | // |
79 | // match () { |
80 | // _ => m! {} - 1, // no parens |
81 | // } |
82 | // |
83 | leftmost_subexpression_in_match_arm: bool, |
84 | |
85 | // This is the difference between: |
86 | // |
87 | // if let _ = (Struct {}) {} // needs parens |
88 | // |
89 | // match () { |
90 | // () if let _ = Struct {} => {} // no parens |
91 | // } |
92 | // |
93 | condition: bool, |
94 | |
95 | // This is the difference between: |
96 | // |
97 | // if break Struct {} == (break) {} // needs parens |
98 | // |
99 | // if break break == Struct {} {} // no parens |
100 | // |
101 | rightmost_subexpression_in_condition: bool, |
102 | |
103 | // This is the difference between: |
104 | // |
105 | // if break ({ x }).field + 1 {} needs parens |
106 | // |
107 | // if break 1 + { x }.field {} // no parens |
108 | // |
109 | leftmost_subexpression_in_optional_operand: bool, |
110 | |
111 | // This is the difference between: |
112 | // |
113 | // let _ = (return) - 1; // without paren, this would return -1 |
114 | // |
115 | // let _ = return + 1; // no paren because '+' cannot begin expr |
116 | // |
117 | next_operator_can_begin_expr: bool, |
118 | |
119 | // This is the difference between: |
120 | // |
121 | // let _ = 1 + return 1; // no parens if rightmost subexpression |
122 | // |
123 | // let _ = 1 + (return 1) + 1; // needs parens |
124 | // |
125 | next_operator_can_continue_expr: bool, |
126 | |
127 | // This is the difference between: |
128 | // |
129 | // let _ = x as u8 + T; |
130 | // |
131 | // let _ = (x as u8) < T; |
132 | // |
133 | // Without parens, the latter would want to parse `u8<T...` as a type. |
134 | next_operator_can_begin_generics: bool, |
135 | } |
136 | |
137 | impl FixupContext { |
138 | /// The default amount of fixing is minimal fixing. Fixups should be turned |
139 | /// on in a targeted fashion where needed. |
140 | pub const NONE: Self = FixupContext { |
141 | previous_operator: Precedence::MIN, |
142 | next_operator: Precedence::MIN, |
143 | stmt: false, |
144 | leftmost_subexpression_in_stmt: false, |
145 | match_arm: false, |
146 | leftmost_subexpression_in_match_arm: false, |
147 | condition: false, |
148 | rightmost_subexpression_in_condition: false, |
149 | leftmost_subexpression_in_optional_operand: false, |
150 | next_operator_can_begin_expr: false, |
151 | next_operator_can_continue_expr: false, |
152 | next_operator_can_begin_generics: false, |
153 | }; |
154 | |
155 | /// Create the initial fixup for printing an expression in statement |
156 | /// position. |
157 | pub fn new_stmt() -> Self { |
158 | FixupContext { |
159 | stmt: true, |
160 | ..FixupContext::NONE |
161 | } |
162 | } |
163 | |
164 | /// Create the initial fixup for printing an expression as the right-hand |
165 | /// side of a match arm. |
166 | pub fn new_match_arm() -> Self { |
167 | FixupContext { |
168 | match_arm: true, |
169 | ..FixupContext::NONE |
170 | } |
171 | } |
172 | |
173 | /// Create the initial fixup for printing an expression as the "condition" |
174 | /// of an `if` or `while`. There are a few other positions which are |
175 | /// grammatically equivalent and also use this, such as the iterator |
176 | /// expression in `for` and the scrutinee in `match`. |
177 | pub fn new_condition() -> Self { |
178 | FixupContext { |
179 | condition: true, |
180 | rightmost_subexpression_in_condition: true, |
181 | ..FixupContext::NONE |
182 | } |
183 | } |
184 | |
185 | /// Transform this fixup into the one that should apply when printing the |
186 | /// leftmost subexpression of the current expression. |
187 | /// |
188 | /// The leftmost subexpression is any subexpression that has the same first |
189 | /// token as the current expression, but has a different last token. |
190 | /// |
191 | /// For example in `$a + $b` and `$a.method()`, the subexpression `$a` is a |
192 | /// leftmost subexpression. |
193 | /// |
194 | /// Not every expression has a leftmost subexpression. For example neither |
195 | /// `-$a` nor `[$a]` have one. |
196 | pub fn leftmost_subexpression_with_operator( |
197 | self, |
198 | expr: &Expr, |
199 | next_operator_can_begin_expr: bool, |
200 | next_operator_can_begin_generics: bool, |
201 | precedence: Precedence, |
202 | ) -> (Precedence, Self) { |
203 | let fixup = FixupContext { |
204 | next_operator: precedence, |
205 | stmt: false, |
206 | leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt, |
207 | match_arm: false, |
208 | leftmost_subexpression_in_match_arm: self.match_arm |
209 | || self.leftmost_subexpression_in_match_arm, |
210 | rightmost_subexpression_in_condition: false, |
211 | next_operator_can_begin_expr, |
212 | next_operator_can_continue_expr: true, |
213 | next_operator_can_begin_generics, |
214 | ..self |
215 | }; |
216 | |
217 | (fixup.leftmost_subexpression_precedence(expr), fixup) |
218 | } |
219 | |
220 | /// Transform this fixup into the one that should apply when printing a |
221 | /// leftmost subexpression followed by a `.` or `?` token, which confer |
222 | /// different statement boundary rules compared to other leftmost |
223 | /// subexpressions. |
224 | pub fn leftmost_subexpression_with_dot(self, expr: &Expr) -> (Precedence, Self) { |
225 | let fixup = FixupContext { |
226 | next_operator: Precedence::Unambiguous, |
227 | stmt: self.stmt || self.leftmost_subexpression_in_stmt, |
228 | leftmost_subexpression_in_stmt: false, |
229 | match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm, |
230 | leftmost_subexpression_in_match_arm: false, |
231 | rightmost_subexpression_in_condition: false, |
232 | next_operator_can_begin_expr: false, |
233 | next_operator_can_continue_expr: true, |
234 | next_operator_can_begin_generics: false, |
235 | ..self |
236 | }; |
237 | |
238 | (fixup.leftmost_subexpression_precedence(expr), fixup) |
239 | } |
240 | |
241 | fn leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence { |
242 | if !self.next_operator_can_begin_expr || self.next_operator == Precedence::Range { |
243 | if let Scan::Bailout = scan_right(expr, self, Precedence::MIN, 0, 0) { |
244 | if scan_left(expr, self) { |
245 | return Precedence::Unambiguous; |
246 | } |
247 | } |
248 | } |
249 | |
250 | self.precedence(expr) |
251 | } |
252 | |
253 | /// Transform this fixup into the one that should apply when printing the |
254 | /// rightmost subexpression of the current expression. |
255 | /// |
256 | /// The rightmost subexpression is any subexpression that has a different |
257 | /// first token than the current expression, but has the same last token. |
258 | /// |
259 | /// For example in `$a + $b` and `-$b`, the subexpression `$b` is a |
260 | /// rightmost subexpression. |
261 | /// |
262 | /// Not every expression has a rightmost subexpression. For example neither |
263 | /// `[$b]` nor `$a.f($b)` have one. |
264 | pub fn rightmost_subexpression( |
265 | self, |
266 | expr: &Expr, |
267 | precedence: Precedence, |
268 | ) -> (Precedence, Self) { |
269 | let fixup = self.rightmost_subexpression_fixup(false, false, precedence); |
270 | (fixup.rightmost_subexpression_precedence(expr), fixup) |
271 | } |
272 | |
273 | pub fn rightmost_subexpression_fixup( |
274 | self, |
275 | reset_allow_struct: bool, |
276 | optional_operand: bool, |
277 | precedence: Precedence, |
278 | ) -> Self { |
279 | FixupContext { |
280 | previous_operator: precedence, |
281 | stmt: false, |
282 | leftmost_subexpression_in_stmt: false, |
283 | match_arm: false, |
284 | leftmost_subexpression_in_match_arm: false, |
285 | condition: self.condition && !reset_allow_struct, |
286 | leftmost_subexpression_in_optional_operand: self.condition && optional_operand, |
287 | ..self |
288 | } |
289 | } |
290 | |
291 | pub fn rightmost_subexpression_precedence(self, expr: &Expr) -> Precedence { |
292 | let default_prec = self.precedence(expr); |
293 | |
294 | if match self.previous_operator { |
295 | Precedence::Assign | Precedence::Let | Precedence::Prefix => { |
296 | default_prec < self.previous_operator |
297 | } |
298 | _ => default_prec <= self.previous_operator, |
299 | } && match self.next_operator { |
300 | Precedence::Range | Precedence::Or | Precedence::And => true, |
301 | _ => !self.next_operator_can_begin_expr, |
302 | } { |
303 | if let Scan::Bailout | Scan::Fail = scan_right(expr, self, self.previous_operator, 1, 0) |
304 | { |
305 | if scan_left(expr, self) { |
306 | return Precedence::Prefix; |
307 | } |
308 | } |
309 | } |
310 | |
311 | default_prec |
312 | } |
313 | |
314 | /// Determine whether parentheses are needed around the given expression to |
315 | /// head off the early termination of a statement or condition. |
316 | pub fn parenthesize(self, expr: &Expr) -> bool { |
317 | (self.leftmost_subexpression_in_stmt && !classify::requires_semi_to_be_stmt(expr)) |
318 | || ((self.stmt || self.leftmost_subexpression_in_stmt) && matches!(expr, Expr::Let(_))) |
319 | || (self.leftmost_subexpression_in_match_arm |
320 | && !classify::requires_comma_to_be_match_arm(expr)) |
321 | || (self.condition && matches!(expr, Expr::Struct(_))) |
322 | || (self.rightmost_subexpression_in_condition |
323 | && matches!( |
324 | expr, |
325 | Expr::Return(ExprReturn { expr: None, .. }) |
326 | | Expr::Yield(ExprYield { expr: None, .. }) |
327 | )) |
328 | || (self.rightmost_subexpression_in_condition |
329 | && !self.condition |
330 | && matches!( |
331 | expr, |
332 | Expr::Break(ExprBreak { expr: None, .. }) |
333 | | Expr::Path(_) |
334 | | Expr::Range(ExprRange { end: None, .. }) |
335 | )) |
336 | || (self.leftmost_subexpression_in_optional_operand |
337 | && matches!(expr, Expr::Block(expr) if expr.attrs.is_empty() && expr.label.is_none())) |
338 | } |
339 | |
340 | /// Determines the effective precedence of a subexpression. Some expressions |
341 | /// have higher or lower precedence when adjacent to particular operators. |
342 | fn precedence(self, expr: &Expr) -> Precedence { |
343 | if self.next_operator_can_begin_expr { |
344 | // Decrease precedence of value-less jumps when followed by an |
345 | // operator that would otherwise get interpreted as beginning a |
346 | // value for the jump. |
347 | if let Expr::Break(ExprBreak { expr: None, .. }) |
348 | | Expr::Return(ExprReturn { expr: None, .. }) |
349 | | Expr::Yield(ExprYield { expr: None, .. }) = expr |
350 | { |
351 | return Precedence::Jump; |
352 | } |
353 | } |
354 | |
355 | if !self.next_operator_can_continue_expr { |
356 | match expr { |
357 | // Increase precedence of expressions that extend to the end of |
358 | // current statement or group. |
359 | Expr::Break(_) |
360 | | Expr::Closure(_) |
361 | | Expr::Let(_) |
362 | | Expr::Return(_) |
363 | | Expr::Yield(_) => { |
364 | return Precedence::Prefix; |
365 | } |
366 | Expr::Range(e) if e.start.is_none() => return Precedence::Prefix, |
367 | _ => {} |
368 | } |
369 | } |
370 | |
371 | if self.next_operator_can_begin_generics { |
372 | if let Expr::Cast(cast) = expr { |
373 | if classify::trailing_unparameterized_path(&cast.ty) { |
374 | return Precedence::MIN; |
375 | } |
376 | } |
377 | } |
378 | |
379 | Precedence::of(expr) |
380 | } |
381 | } |
382 | |
383 | #[derive (Copy, Clone, PartialEq)] |
384 | enum Scan { |
385 | Fail, |
386 | Bailout, |
387 | Consume, |
388 | } |
389 | |
390 | fn scan_left(expr: &Expr, fixup: FixupContext) -> bool { |
391 | match expr { |
392 | Expr::Assign(_) => fixup.previous_operator <= Precedence::Assign, |
393 | Expr::Binary(e: &ExprBinary) => match Precedence::of_binop(&e.op) { |
394 | Precedence::Assign => fixup.previous_operator <= Precedence::Assign, |
395 | binop_prec: Precedence => fixup.previous_operator < binop_prec, |
396 | }, |
397 | Expr::Cast(_) => fixup.previous_operator < Precedence::Cast, |
398 | Expr::Range(e: &ExprRange) => e.start.is_none() || fixup.previous_operator < Precedence::Assign, |
399 | _ => true, |
400 | } |
401 | } |
402 | |
403 | fn scan_right( |
404 | expr: &Expr, |
405 | fixup: FixupContext, |
406 | precedence: Precedence, |
407 | fail_offset: u8, |
408 | bailout_offset: u8, |
409 | ) -> Scan { |
410 | let consume_by_precedence = if match precedence { |
411 | Precedence::Assign | Precedence::Compare => precedence <= fixup.next_operator, |
412 | _ => precedence < fixup.next_operator, |
413 | } || fixup.next_operator == Precedence::MIN |
414 | { |
415 | Scan::Consume |
416 | } else { |
417 | Scan::Bailout |
418 | }; |
419 | if fixup.parenthesize(expr) { |
420 | return consume_by_precedence; |
421 | } |
422 | match expr { |
423 | #![cfg_attr (all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] |
424 | Expr::Assign(e) => { |
425 | if match fixup.next_operator { |
426 | Precedence::Unambiguous => fail_offset >= 2, |
427 | _ => bailout_offset >= 1, |
428 | } { |
429 | return Scan::Consume; |
430 | } |
431 | let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign); |
432 | let scan = scan_right( |
433 | &e.right, |
434 | right_fixup, |
435 | Precedence::Assign, |
436 | match fixup.next_operator { |
437 | Precedence::Unambiguous => fail_offset, |
438 | _ => 1, |
439 | }, |
440 | 1, |
441 | ); |
442 | if let Scan::Bailout | Scan::Consume = scan { |
443 | Scan::Consume |
444 | } else if let Precedence::Unambiguous = fixup.next_operator { |
445 | Scan::Fail |
446 | } else { |
447 | Scan::Bailout |
448 | } |
449 | } |
450 | Expr::Binary(e) => { |
451 | if match fixup.next_operator { |
452 | Precedence::Unambiguous => { |
453 | fail_offset >= 2 |
454 | && (consume_by_precedence == Scan::Consume || bailout_offset >= 1) |
455 | } |
456 | _ => bailout_offset >= 1, |
457 | } { |
458 | return Scan::Consume; |
459 | } |
460 | let binop_prec = Precedence::of_binop(&e.op); |
461 | if binop_prec == Precedence::Compare && fixup.next_operator == Precedence::Compare { |
462 | return Scan::Consume; |
463 | } |
464 | let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec); |
465 | let scan = scan_right( |
466 | &e.right, |
467 | right_fixup, |
468 | binop_prec, |
469 | match fixup.next_operator { |
470 | Precedence::Unambiguous => fail_offset, |
471 | _ => 1, |
472 | }, |
473 | consume_by_precedence as u8 - Scan::Bailout as u8, |
474 | ); |
475 | match scan { |
476 | Scan::Fail => {} |
477 | Scan::Bailout => return consume_by_precedence, |
478 | Scan::Consume => return Scan::Consume, |
479 | } |
480 | let right_needs_group = binop_prec != Precedence::Assign |
481 | && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec; |
482 | if right_needs_group { |
483 | consume_by_precedence |
484 | } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) { |
485 | Scan::Fail |
486 | } else { |
487 | Scan::Bailout |
488 | } |
489 | } |
490 | Expr::RawAddr(ExprRawAddr { expr, .. }) |
491 | | Expr::Reference(ExprReference { expr, .. }) |
492 | | Expr::Unary(ExprUnary { expr, .. }) => { |
493 | if match fixup.next_operator { |
494 | Precedence::Unambiguous => { |
495 | fail_offset >= 2 |
496 | && (consume_by_precedence == Scan::Consume || bailout_offset >= 1) |
497 | } |
498 | _ => bailout_offset >= 1, |
499 | } { |
500 | return Scan::Consume; |
501 | } |
502 | let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Prefix); |
503 | let scan = scan_right( |
504 | expr, |
505 | right_fixup, |
506 | precedence, |
507 | match fixup.next_operator { |
508 | Precedence::Unambiguous => fail_offset, |
509 | _ => 1, |
510 | }, |
511 | consume_by_precedence as u8 - Scan::Bailout as u8, |
512 | ); |
513 | match scan { |
514 | Scan::Fail => {} |
515 | Scan::Bailout => return consume_by_precedence, |
516 | Scan::Consume => return Scan::Consume, |
517 | } |
518 | if right_fixup.rightmost_subexpression_precedence(expr) < Precedence::Prefix { |
519 | consume_by_precedence |
520 | } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) { |
521 | Scan::Fail |
522 | } else { |
523 | Scan::Bailout |
524 | } |
525 | } |
526 | Expr::Range(e) => match &e.end { |
527 | Some(end) => { |
528 | if fail_offset >= 2 { |
529 | return Scan::Consume; |
530 | } |
531 | let right_fixup = |
532 | fixup.rightmost_subexpression_fixup(false, true, Precedence::Range); |
533 | let scan = scan_right( |
534 | end, |
535 | right_fixup, |
536 | Precedence::Range, |
537 | fail_offset, |
538 | match fixup.next_operator { |
539 | Precedence::Assign | Precedence::Range => 0, |
540 | _ => 1, |
541 | }, |
542 | ); |
543 | if match (scan, fixup.next_operator) { |
544 | (Scan::Fail, _) => false, |
545 | (Scan::Bailout, Precedence::Assign | Precedence::Range) => false, |
546 | (Scan::Bailout | Scan::Consume, _) => true, |
547 | } { |
548 | return Scan::Consume; |
549 | } |
550 | if right_fixup.rightmost_subexpression_precedence(end) <= Precedence::Range { |
551 | Scan::Consume |
552 | } else { |
553 | Scan::Fail |
554 | } |
555 | } |
556 | None => { |
557 | if fixup.next_operator_can_begin_expr { |
558 | Scan::Consume |
559 | } else { |
560 | Scan::Fail |
561 | } |
562 | } |
563 | }, |
564 | Expr::Break(e) => match &e.expr { |
565 | Some(value) => { |
566 | if bailout_offset >= 1 || e.label.is_none() && classify::expr_leading_label(value) { |
567 | return Scan::Consume; |
568 | } |
569 | let right_fixup = fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump); |
570 | match scan_right(value, right_fixup, Precedence::Jump, 1, 1) { |
571 | Scan::Fail => Scan::Bailout, |
572 | Scan::Bailout | Scan::Consume => Scan::Consume, |
573 | } |
574 | } |
575 | None => match fixup.next_operator { |
576 | Precedence::Assign if precedence > Precedence::Assign => Scan::Fail, |
577 | _ => Scan::Consume, |
578 | }, |
579 | }, |
580 | Expr::Return(ExprReturn { expr, .. }) | Expr::Yield(ExprYield { expr, .. }) => match expr { |
581 | Some(e) => { |
582 | if bailout_offset >= 1 { |
583 | return Scan::Consume; |
584 | } |
585 | let right_fixup = |
586 | fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump); |
587 | match scan_right(e, right_fixup, Precedence::Jump, 1, 1) { |
588 | Scan::Fail => Scan::Bailout, |
589 | Scan::Bailout | Scan::Consume => Scan::Consume, |
590 | } |
591 | } |
592 | None => match fixup.next_operator { |
593 | Precedence::Assign if precedence > Precedence::Assign => Scan::Fail, |
594 | _ => Scan::Consume, |
595 | }, |
596 | }, |
597 | Expr::Closure(_) => Scan::Consume, |
598 | Expr::Let(e) => { |
599 | if bailout_offset >= 1 { |
600 | return Scan::Consume; |
601 | } |
602 | let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Let); |
603 | let scan = scan_right( |
604 | &e.expr, |
605 | right_fixup, |
606 | Precedence::Let, |
607 | 1, |
608 | if fixup.next_operator < Precedence::Let { |
609 | 0 |
610 | } else { |
611 | 1 |
612 | }, |
613 | ); |
614 | match scan { |
615 | Scan::Fail | Scan::Bailout if fixup.next_operator < Precedence::Let => { |
616 | return Scan::Bailout; |
617 | } |
618 | Scan::Consume => return Scan::Consume, |
619 | _ => {} |
620 | } |
621 | if right_fixup.rightmost_subexpression_precedence(&e.expr) < Precedence::Let { |
622 | Scan::Consume |
623 | } else if let Scan::Fail = scan { |
624 | Scan::Bailout |
625 | } else { |
626 | Scan::Consume |
627 | } |
628 | } |
629 | Expr::Group(e) => scan_right(&e.expr, fixup, precedence, fail_offset, bailout_offset), |
630 | Expr::Array(_) |
631 | | Expr::Async(_) |
632 | | Expr::Await(_) |
633 | | Expr::Block(_) |
634 | | Expr::Call(_) |
635 | | Expr::Cast(_) |
636 | | Expr::Const(_) |
637 | | Expr::Continue(_) |
638 | | Expr::Field(_) |
639 | | Expr::ForLoop(_) |
640 | | Expr::If(_) |
641 | | Expr::Index(_) |
642 | | Expr::Infer(_) |
643 | | Expr::Lit(_) |
644 | | Expr::Loop(_) |
645 | | Expr::Macro(_) |
646 | | Expr::Match(_) |
647 | | Expr::MethodCall(_) |
648 | | Expr::Paren(_) |
649 | | Expr::Path(_) |
650 | | Expr::Repeat(_) |
651 | | Expr::Struct(_) |
652 | | Expr::Try(_) |
653 | | Expr::TryBlock(_) |
654 | | Expr::Tuple(_) |
655 | | Expr::Unsafe(_) |
656 | | Expr::Verbatim(_) |
657 | | Expr::While(_) => match fixup.next_operator { |
658 | Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail, |
659 | _ if precedence == Precedence::Let && fixup.next_operator < Precedence::Let => { |
660 | Scan::Fail |
661 | } |
662 | _ => consume_by_precedence, |
663 | }, |
664 | |
665 | _ => match fixup.next_operator { |
666 | Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail, |
667 | _ if precedence == Precedence::Let && fixup.next_operator < Precedence::Let => { |
668 | Scan::Fail |
669 | } |
670 | _ => consume_by_precedence, |
671 | }, |
672 | } |
673 | } |
674 | |