Skip to content

Commit 1b58f00

Browse files
authored
Merge pull request RustPython#4109 from charliermarsh/charlie/named-expr-generator
Allow named expressions in generator comprehensions
2 parents ff20f31 + 32030a0 commit 1b58f00

6 files changed

Lines changed: 255 additions & 1 deletion

extra_tests/snippets/syntax_generator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ def make_numbers():
1717
r = list(x for x in [1, 2, 3])
1818
assert r == [1, 2, 3]
1919

20+
r = list(y := x + 1 for x in [1, 2, 3])
21+
assert r == [2, 3, 4]
22+
2023
def g2(x):
2124
x = yield x
2225
yield x + 5

parser/python.lalrpop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ Atom: ast::Expr = {
10121012
}
10131013
},
10141014
"(" <e:YieldExpr> ")" => e,
1015-
<location:@L> "(" <elt:Test> <generators:CompFor> ")" => {
1015+
<location:@L> "(" <elt:NamedExpressionTest> <generators:CompFor> ")" => {
10161016
ast::Expr {
10171017
location,
10181018
custom: (),

parser/src/parser.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,25 @@ class Foo(A, B):
178178
let parse_ast = parse_expression(&source).unwrap();
179179
insta::assert_debug_snapshot!(parse_ast);
180180
}
181+
182+
#[test]
183+
fn test_parse_generator_comprehension() {
184+
let source = String::from("(x for y in z)");
185+
let parse_ast = parse_expression(&source).unwrap();
186+
insta::assert_debug_snapshot!(parse_ast);
187+
}
188+
189+
#[test]
190+
fn test_parse_named_expression_generator_comprehension() {
191+
let source = String::from("(x := y + 1 for y in z)");
192+
let parse_ast = parse_expression(&source).unwrap();
193+
insta::assert_debug_snapshot!(parse_ast);
194+
}
195+
196+
#[test]
197+
fn test_parse_if_else_generator_comprehension() {
198+
let source = String::from("(x if y else y for y in z)");
199+
let parse_ast = parse_expression(&source).unwrap();
200+
insta::assert_debug_snapshot!(parse_ast);
201+
}
181202
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
source: parser/src/parser.rs
3+
expression: parse_ast
4+
---
5+
Located {
6+
location: Location {
7+
row: 1,
8+
column: 1,
9+
},
10+
custom: (),
11+
node: GeneratorExp {
12+
elt: Located {
13+
location: Location {
14+
row: 1,
15+
column: 2,
16+
},
17+
custom: (),
18+
node: Name {
19+
id: "x",
20+
ctx: Load,
21+
},
22+
},
23+
generators: [
24+
Comprehension {
25+
target: Located {
26+
location: Location {
27+
row: 1,
28+
column: 8,
29+
},
30+
custom: (),
31+
node: Name {
32+
id: "y",
33+
ctx: Load,
34+
},
35+
},
36+
iter: Located {
37+
location: Location {
38+
row: 1,
39+
column: 13,
40+
},
41+
custom: (),
42+
node: Name {
43+
id: "z",
44+
ctx: Load,
45+
},
46+
},
47+
ifs: [],
48+
is_async: 0,
49+
},
50+
],
51+
},
52+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
source: parser/src/parser.rs
3+
expression: parse_ast
4+
---
5+
Located {
6+
location: Location {
7+
row: 1,
8+
column: 1,
9+
},
10+
custom: (),
11+
node: GeneratorExp {
12+
elt: Located {
13+
location: Location {
14+
row: 1,
15+
column: 4,
16+
},
17+
custom: (),
18+
node: IfExp {
19+
test: Located {
20+
location: Location {
21+
row: 1,
22+
column: 7,
23+
},
24+
custom: (),
25+
node: Name {
26+
id: "y",
27+
ctx: Load,
28+
},
29+
},
30+
body: Located {
31+
location: Location {
32+
row: 1,
33+
column: 2,
34+
},
35+
custom: (),
36+
node: Name {
37+
id: "x",
38+
ctx: Load,
39+
},
40+
},
41+
orelse: Located {
42+
location: Location {
43+
row: 1,
44+
column: 14,
45+
},
46+
custom: (),
47+
node: Name {
48+
id: "y",
49+
ctx: Load,
50+
},
51+
},
52+
},
53+
},
54+
generators: [
55+
Comprehension {
56+
target: Located {
57+
location: Location {
58+
row: 1,
59+
column: 20,
60+
},
61+
custom: (),
62+
node: Name {
63+
id: "y",
64+
ctx: Load,
65+
},
66+
},
67+
iter: Located {
68+
location: Location {
69+
row: 1,
70+
column: 25,
71+
},
72+
custom: (),
73+
node: Name {
74+
id: "z",
75+
ctx: Load,
76+
},
77+
},
78+
ifs: [],
79+
is_async: 0,
80+
},
81+
],
82+
},
83+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
source: parser/src/parser.rs
3+
expression: parse_ast
4+
---
5+
Located {
6+
location: Location {
7+
row: 1,
8+
column: 1,
9+
},
10+
custom: (),
11+
node: GeneratorExp {
12+
elt: Located {
13+
location: Location {
14+
row: 1,
15+
column: 2,
16+
},
17+
custom: (),
18+
node: NamedExpr {
19+
target: Located {
20+
location: Location {
21+
row: 1,
22+
column: 2,
23+
},
24+
custom: (),
25+
node: Name {
26+
id: "x",
27+
ctx: Store,
28+
},
29+
},
30+
value: Located {
31+
location: Location {
32+
row: 1,
33+
column: 9,
34+
},
35+
custom: (),
36+
node: BinOp {
37+
left: Located {
38+
location: Location {
39+
row: 1,
40+
column: 7,
41+
},
42+
custom: (),
43+
node: Name {
44+
id: "y",
45+
ctx: Load,
46+
},
47+
},
48+
op: Add,
49+
right: Located {
50+
location: Location {
51+
row: 1,
52+
column: 11,
53+
},
54+
custom: (),
55+
node: Constant {
56+
value: Int(
57+
1,
58+
),
59+
kind: None,
60+
},
61+
},
62+
},
63+
},
64+
},
65+
},
66+
generators: [
67+
Comprehension {
68+
target: Located {
69+
location: Location {
70+
row: 1,
71+
column: 17,
72+
},
73+
custom: (),
74+
node: Name {
75+
id: "y",
76+
ctx: Load,
77+
},
78+
},
79+
iter: Located {
80+
location: Location {
81+
row: 1,
82+
column: 22,
83+
},
84+
custom: (),
85+
node: Name {
86+
id: "z",
87+
ctx: Load,
88+
},
89+
},
90+
ifs: [],
91+
is_async: 0,
92+
},
93+
],
94+
},
95+
}

0 commit comments

Comments
 (0)