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