@@ -360,7 +360,7 @@ impl<'src> Parser<'src> {
360
360
}
361
361
362
362
// Don't parse a `CompareExpr` if we are parsing a `Comprehension` or `ForStmt`
363
- if token . is_compare_operator ( ) && self . has_ctx ( ParserCtxFlags :: FOR_TARGET ) {
363
+ if matches ! ( token , TokenKind :: In ) && self . has_ctx ( ParserCtxFlags :: FOR_TARGET ) {
364
364
break ;
365
365
}
366
366
@@ -659,11 +659,38 @@ impl<'src> Parser<'src> {
659
659
Expr :: IpyEscapeCommand ( self . parse_ipython_escape_command_expression ( ) )
660
660
}
661
661
TokenKind :: String | TokenKind :: FStringStart => self . parse_strings ( ) ,
662
- TokenKind :: Lpar => {
663
- return self . parse_parenthesized_expression ( ) ;
662
+ tok @ ( TokenKind :: Lpar | TokenKind :: Lsqb | TokenKind :: Lbrace ) => {
663
+ // We need to unset the `FOR_TARGET` in the context when parsing an expression
664
+ // inside a parentheses, curly brace or brackets otherwise the `in` operator of a
665
+ // comparison expression will not be parsed in a `for` target.
666
+
667
+ // test_ok parenthesized_compare_expr_in_for
668
+ // for (x in y)[0] in iter: ...
669
+ // for (x in y).attr in iter: ...
670
+
671
+ // test_err parenthesized_compare_expr_in_for
672
+ // for (x in y)() in iter: ...
673
+ // for (x in y) in iter: ...
674
+ // for (x in y, z) in iter: ...
675
+ // for [x in y, z] in iter: ...
676
+ // for {x in y, z} in iter: ...
677
+ let current_context = self . ctx - ParserCtxFlags :: FOR_TARGET ;
678
+ let saved_context = self . set_ctx ( current_context) ;
679
+
680
+ let expr = match tok {
681
+ TokenKind :: Lpar => {
682
+ let parsed_expr = self . parse_parenthesized_expression ( ) ;
683
+ self . restore_ctx ( current_context, saved_context) ;
684
+ return parsed_expr;
685
+ }
686
+ TokenKind :: Lsqb => self . parse_list_like_expression ( ) ,
687
+ TokenKind :: Lbrace => self . parse_set_or_dict_like_expression ( ) ,
688
+ _ => unreachable ! ( ) ,
689
+ } ;
690
+
691
+ self . restore_ctx ( current_context, saved_context) ;
692
+ expr
664
693
}
665
- TokenKind :: Lsqb => self . parse_list_like_expression ( ) ,
666
- TokenKind :: Lbrace => self . parse_set_or_dict_like_expression ( ) ,
667
694
668
695
kind => {
669
696
if kind. is_keyword ( ) {
@@ -692,14 +719,25 @@ impl<'src> Parser<'src> {
692
719
///
693
720
/// This method does nothing if the current token is not a candidate for a postfix expression.
694
721
pub ( super ) fn parse_postfix_expression ( & mut self , mut lhs : Expr , start : TextSize ) -> Expr {
695
- loop {
722
+ // test_ok for_in_target_postfix_expr
723
+ // for d[x in y] in target: ...
724
+
725
+ // test_err for_in_target_postfix_expr
726
+ // for d(x in y) in target: ...
727
+ let current_context = self . ctx - ParserCtxFlags :: FOR_TARGET ;
728
+ let saved_context = self . set_ctx ( current_context) ;
729
+
730
+ lhs = loop {
696
731
lhs = match self . current_token_kind ( ) {
697
732
TokenKind :: Lpar => Expr :: Call ( self . parse_call_expression ( lhs, start) ) ,
698
733
TokenKind :: Lsqb => Expr :: Subscript ( self . parse_subscript_expression ( lhs, start) ) ,
699
734
TokenKind :: Dot => Expr :: Attribute ( self . parse_attribute_expression ( lhs, start) ) ,
700
735
_ => break lhs,
701
736
} ;
702
- }
737
+ } ;
738
+
739
+ self . restore_ctx ( current_context, saved_context) ;
740
+ lhs
703
741
}
704
742
705
743
/// Parse a call expression.
@@ -1748,26 +1786,13 @@ impl<'src> Parser<'src> {
1748
1786
. into ( ) ;
1749
1787
}
1750
1788
1751
- // We need to unset the `FOR_TARGET` in the context when parsing a parenthesized expression
1752
- // otherwise a parenthesized comparison expression will not be parsed in a `for` target.
1753
-
1754
- // test_ok parenthesized_compare_expr_in_for
1755
- // for (x in y)[0] in iter: ...
1756
- // for (x in y).attr in iter: ...
1757
-
1758
- // test_err parenthesized_compare_expr_in_for
1759
- // for (x in y)() in iter: ...
1760
- // for (x in y) in iter: ...
1761
- let current_context = self . ctx - ParserCtxFlags :: FOR_TARGET ;
1762
- let saved_context = self . set_ctx ( current_context) ;
1763
-
1764
1789
// Use the more general rule of the three to parse the first element
1765
1790
// and limit it later.
1766
1791
let mut parsed_expr = self . parse_yield_expression_or_else ( |p| {
1767
1792
p. parse_star_expression_or_higher ( AllowNamedExpression :: Yes )
1768
1793
} ) ;
1769
1794
1770
- let parsed_expr = match self . current_token_kind ( ) {
1795
+ match self . current_token_kind ( ) {
1771
1796
TokenKind :: Comma => {
1772
1797
// grammar: `tuple`
1773
1798
let tuple = self . parse_tuple_expression (
@@ -1812,11 +1837,7 @@ impl<'src> Parser<'src> {
1812
1837
parsed_expr. is_parenthesized = true ;
1813
1838
parsed_expr
1814
1839
}
1815
- } ;
1816
-
1817
- self . restore_ctx ( current_context, saved_context) ;
1818
-
1819
- parsed_expr
1840
+ }
1820
1841
}
1821
1842
1822
1843
/// Parses multiple items separated by a comma into a tuple expression.
0 commit comments