Try parsing a `match` statement. This uses speculative parsing to remove the ambiguity of whether the `match` token is used as a keyword or an identifier. This ambiguity arises only in if the `match` token is followed by certain tokens. For example, if `match` is followed by `[`, we can't know if it's used in the context of a subscript expression or as a list expression: ```python # Subscript ex
(&mut self)
| 2542 | /// |
| 2543 | /// See: <https://docs.python.org/3/reference/compound_stmts.html#the-match-statement> |
| 2544 | fn try_parse_match_statement(&mut self) -> Option<ast::StmtMatch> { |
| 2545 | let checkpoint = self.checkpoint(); |
| 2546 | |
| 2547 | let start = self.node_start(); |
| 2548 | self.bump(TokenKind::Match); |
| 2549 | |
| 2550 | let subject = self.parse_match_subject_expression(); |
| 2551 | |
| 2552 | match self.current_token_kind() { |
| 2553 | // test_ok match_annotated_assignment |
| 2554 | // match[0]: int |
| 2555 | // match [x, y, z]: dict |
| 2556 | TokenKind::Colon if self.peek() == TokenKind::Newline => { |
| 2557 | // `match` is a keyword — colon followed by newline confirms |
| 2558 | // this is a match statement, not an annotated assignment like |
| 2559 | // `match [x, y, z]: {dict}` or `match[0]: int`. |
| 2560 | self.bump(TokenKind::Colon); |
| 2561 | |
| 2562 | let cases = self.parse_match_body(); |
| 2563 | |
| 2564 | Some(ast::StmtMatch { |
| 2565 | subject: Box::new(subject), |
| 2566 | cases, |
| 2567 | range: self.node_range(start), |
| 2568 | node_index: AtomicNodeIndex::NONE, |
| 2569 | }) |
| 2570 | } |
| 2571 | TokenKind::Newline if matches!(self.peek2(), (TokenKind::Indent, TokenKind::Case)) => { |
| 2572 | // `match` is a keyword |
| 2573 | |
| 2574 | // test_err match_expected_colon |
| 2575 | // match [1, 2] |
| 2576 | // case _: ... |
| 2577 | self.add_error( |
| 2578 | ParseErrorType::ExpectedToken { |
| 2579 | found: self.current_token_kind(), |
| 2580 | expected: TokenKind::Colon, |
| 2581 | }, |
| 2582 | self.current_token_range(), |
| 2583 | ); |
| 2584 | |
| 2585 | let cases = self.parse_match_body(); |
| 2586 | |
| 2587 | Some(ast::StmtMatch { |
| 2588 | subject: Box::new(subject), |
| 2589 | cases, |
| 2590 | range: self.node_range(start), |
| 2591 | node_index: AtomicNodeIndex::NONE, |
| 2592 | }) |
| 2593 | } |
| 2594 | _ => { |
| 2595 | // `match` is an identifier |
| 2596 | self.rewind(checkpoint); |
| 2597 | |
| 2598 | None |
| 2599 | } |
| 2600 | } |
| 2601 | } |
no test coverage detected