Parses a comprehension. # Panics If the parser isn't positioned at an `async` or `for` token. See:
(&mut self)
| 2560 | /// |
| 2561 | /// See: <https://docs.python.org/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries> |
| 2562 | fn parse_comprehension(&mut self) -> ast::Comprehension { |
| 2563 | let start = self.node_start(); |
| 2564 | |
| 2565 | let is_async = self.eat(TokenKind::Async); |
| 2566 | |
| 2567 | if is_async { |
| 2568 | // test_err comprehension_missing_for_after_async |
| 2569 | // (async) |
| 2570 | // (x async x in iter) |
| 2571 | self.expect(TokenKind::For); |
| 2572 | } else { |
| 2573 | self.bump(TokenKind::For); |
| 2574 | } |
| 2575 | |
| 2576 | let mut target = |
| 2577 | self.parse_expression_list(ExpressionContext::starred_conditional().with_in_excluded()); |
| 2578 | |
| 2579 | helpers::set_expr_ctx(&mut target.expr, ExprContext::Store); |
| 2580 | self.validate_assignment_target(&target.expr); |
| 2581 | |
| 2582 | self.expect(TokenKind::In); |
| 2583 | let iter = self.parse_simple_expression(ExpressionContext::default()); |
| 2584 | |
| 2585 | let ifs_snapshot = self.expr_scratch.snapshot(); |
| 2586 | let mut progress = ParserProgress::default(); |
| 2587 | |
| 2588 | while self.eat(TokenKind::If) { |
| 2589 | progress.assert_progressing(self); |
| 2590 | |
| 2591 | let parsed_expr = self.parse_simple_expression(ExpressionContext::default()); |
| 2592 | |
| 2593 | self.expr_scratch.push(parsed_expr.expr); |
| 2594 | } |
| 2595 | |
| 2596 | ast::Comprehension { |
| 2597 | range: self.node_range(start), |
| 2598 | node_index: AtomicNodeIndex::NONE, |
| 2599 | target: target.expr, |
| 2600 | iter: iter.expr, |
| 2601 | ifs: self.expr_scratch.take(ifs_snapshot), |
| 2602 | is_async, |
| 2603 | } |
| 2604 | } |
| 2605 | |
| 2606 | /// Parses a generator expression. |
| 2607 | /// |
no test coverage detected