Parses a comprehension. # Panics If the parser isn't positioned at an `async` or `for` token. See:
(&mut self)
| 2626 | /// |
| 2627 | /// See: <https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries> |
| 2628 | fn parse_comprehension(&mut self) -> ast::Comprehension { |
| 2629 | let start = self.node_start(); |
| 2630 | |
| 2631 | let is_async = self.eat(TokenKind::Async); |
| 2632 | |
| 2633 | if is_async { |
| 2634 | // test_err comprehension_missing_for_after_async |
| 2635 | // (async) |
| 2636 | // (x async x in iter) |
| 2637 | self.expect(TokenKind::For); |
| 2638 | } else { |
| 2639 | self.bump(TokenKind::For); |
| 2640 | } |
| 2641 | |
| 2642 | let mut target = |
| 2643 | self.parse_expression_list(ExpressionContext::starred_conditional().with_in_excluded()); |
| 2644 | |
| 2645 | helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); |
| 2646 | self.validate_assignment_target(&target.expr); |
| 2647 | |
| 2648 | self.expect(TokenKind::In); |
| 2649 | let iter = self.parse_simple_expression(ExpressionContext::default()); |
| 2650 | |
| 2651 | let ifs_snapshot = self.expr_scratch.snapshot(); |
| 2652 | let mut progress = ParserProgress::default(); |
| 2653 | |
| 2654 | while self.eat(TokenKind::If) { |
| 2655 | progress.assert_progressing(self); |
| 2656 | |
| 2657 | let parsed_expr = self.parse_simple_expression(ExpressionContext::default()); |
| 2658 | |
| 2659 | self.expr_scratch.push(parsed_expr.expr); |
| 2660 | } |
| 2661 | |
| 2662 | ast::Comprehension { |
| 2663 | range: self.node_range(start), |
| 2664 | node_index: AtomicNodeIndex::NONE, |
| 2665 | target: target.expr, |
| 2666 | iter: iter.expr, |
| 2667 | ifs: self.expr_scratch.take(ifs_snapshot), |
| 2668 | is_async, |
| 2669 | } |
| 2670 | } |
| 2671 | |
| 2672 | /// Parses a generator expression. |
| 2673 | /// |
no test coverage detected