Skip to content

Commit f700e1d

Browse files
committed
Disallow lone starred expressions at the grammar level
Statements like the following (where `()` can be any iterable -- or at the syntax level, any value): *() x = *() yield *() return *() for _ in *(): ... are not valid without a comma after the iterable. These were allowed by `python.gram` and only rejected in the codegen step. This means that the documented "Full Grammar specification" was incomplete. Change the grammar itself to disallow "lone" starred expressions. This interfered with the `invalid_legacy_expression` rule, where in ``return i*i for _ in _`` the ``i *i`` was parsed similarly to ``print *i``, generating "can't use starred expression here" from `*i` (before getting to the "Missing parentheses in call" message instead of a generic "invalid syntax". Exclude the star in `invalid_legacy_expression` to prevent this. Co-authored-by: Blaise Pabon <blaise@gmail.com> .
1 parent 20e6c2f commit f700e1d

3 files changed

Lines changed: 552 additions & 444 deletions

File tree

Grammar/python.gram

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,8 @@ star_expressions[expr_ty]:
732732
| a=star_expression b=(',' c=star_expression { c })+ [','] {
733733
_PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Load, EXTRA) }
734734
| a=star_expression ',' { _PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_singleton_seq(p, a)), Load, EXTRA) }
735-
| star_expression
735+
| expression
736+
| invalid_lone_star_expression
736737

737738
star_expression[expr_ty] (memo):
738739
| '*' a=bitwise_or { _PyAST_Starred(a, Load, EXTRA) }
@@ -1245,7 +1246,7 @@ expression_without_invalid[expr_ty]:
12451246
| disjunction
12461247
| lambdef
12471248
invalid_legacy_expression:
1248-
| a=NAME !'(' b=star_expressions {
1249+
| a=NAME !'(' !'*' b=star_expressions {
12491250
_PyPegen_check_legacy_stmt(p, a) ? RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b,
12501251
"Missing parentheses in call to '%U'. Did you mean %U(...)?", a->v.Name.id, a->v.Name.id) : NULL}
12511252

@@ -1295,6 +1296,9 @@ invalid_named_expression(memo):
12951296
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot assign to %s here. Maybe you meant '==' instead of '='?",
12961297
_PyPegen_get_expr_name(a)) }
12971298

1299+
invalid_lone_star_expression:
1300+
| a='*' b=bitwise_or { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "can't use starred expression here") }
1301+
12981302
invalid_assignment:
12991303
| a=invalid_ann_assign_target ':' expression {
13001304
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
@@ -1325,6 +1329,8 @@ invalid_raise_stmt:
13251329
| 'raise' expression a='from' {
13261330
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "did you forget an expression after 'from'?") }
13271331
invalid_del_stmt:
1332+
| 'del' &'*' a=star_expression {
1333+
RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) }
13281334
| 'del' a=star_expressions {
13291335
RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) }
13301336
invalid_assert_stmt:

0 commit comments

Comments
 (0)