Skip to content

Commit a078be5

Browse files
committed
Attempt 2
To recap: the objective is to make starred expressions valid in `subscription`, which is used for generics: `Generic[...]`, `list[...]`, etc. What _is_ gramatically valid in such contexts? Seemingly any of the following. (At least, none of the following throw `SyntaxError` in a 3.12.3 REPL.) Generic[x] Generic[*x] Generic[*x, y] Generic[y, *x] Generic[x := 1] Generic[x := 1, y := 2] So introducting flexible_expression: expression | assignment_expression | starred_item end then switching `subscription` to use `flexible_expression` sorts that. But then we need to field `yield` - for which any of the following are apparently valid: yield x yield x, yield x, y yield *x, yield *x, *y Introducing a separate `yield_list` is the simplest way I've been figure out to do this - separating out the special case of `starred_item ,`.
1 parent b215211 commit a078be5

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

Doc/reference/expressions.rst

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ Yield expressions
423423
.. productionlist:: python-grammar
424424
yield_atom: "(" `yield_expression` ")"
425425
yield_from: "yield" "from" `expression`
426-
yield_expression: "yield" `expression_list` | `yield_from`
426+
yield_expression: "yield" `yield_list` | `yield_from`
427427

428428
The yield expression is used when defining a :term:`generator` function
429429
or an :term:`asynchronous generator` function and
@@ -454,9 +454,9 @@ When a generator function is called, it returns an iterator known as a
454454
generator. That generator then controls the execution of the generator
455455
function. The execution starts when one of the generator's methods is called.
456456
At that time, the execution proceeds to the first yield expression, where it is
457-
suspended again, returning the value of :token:`~python-grammar:expression_list`
458-
to the generator's caller,
459-
or ``None`` if :token:`~python-grammar:expression_list` is omitted.
457+
suspended again, returning the value of
458+
:token:`~python-grammar:flexible_expression_list` to the generator's caller,
459+
or ``None`` if :token:`~python-grammar:flexible_expression_list` is omitted.
460460
By suspended, we mean that all local state is
461461
retained, including the current bindings of local variables, the instruction
462462
pointer, the internal evaluation stack, and the state of any exception handling.
@@ -545,9 +545,9 @@ is already executing raises a :exc:`ValueError` exception.
545545
:meth:`~generator.__next__` method, the current yield expression always
546546
evaluates to :const:`None`. The execution then continues to the next yield
547547
expression, where the generator is suspended again, and the value of the
548-
:token:`~python-grammar:expression_list` is returned to :meth:`__next__`'s
549-
caller. If the generator exits without yielding another value, a
550-
:exc:`StopIteration` exception is raised.
548+
:token:`~python-grammar:flexible_expression_list` is returned to
549+
:meth:`__next__`'s caller. If the generator exits without yielding another
550+
value, a :exc:`StopIteration` exception is raised.
551551

552552
This method is normally called implicitly, e.g. by a :keyword:`for` loop, or
553553
by the built-in :func:`next` function.
@@ -664,17 +664,17 @@ how a generator object would be used in a :keyword:`for` statement.
664664
Calling one of the asynchronous generator's methods returns an :term:`awaitable`
665665
object, and the execution starts when this object is awaited on. At that time,
666666
the execution proceeds to the first yield expression, where it is suspended
667-
again, returning the value of :token:`~python-grammar:expression_list` to the
668-
awaiting coroutine. As with a generator, suspension means that all local state
669-
is retained, including the current bindings of local variables, the instruction
670-
pointer, the internal evaluation stack, and the state of any exception handling.
671-
When the execution is resumed by awaiting on the next object returned by the
672-
asynchronous generator's methods, the function can proceed exactly as if the
673-
yield expression were just another external call. The value of the yield
674-
expression after resuming depends on the method which resumed the execution. If
675-
:meth:`~agen.__anext__` is used then the result is :const:`None`. Otherwise, if
676-
:meth:`~agen.asend` is used, then the result will be the value passed in to that
677-
method.
667+
again, returning the value of :token:`~python-grammar:flexible_expression_list`
668+
to the awaiting coroutine. As with a generator, suspension means that all local
669+
state is retained, including the current bindings of local variables, the
670+
instruction pointer, the internal evaluation stack, and the state of any
671+
exception handling. When the execution is resumed by awaiting on the next object
672+
returned by the asynchronous generator's methods, the function can proceed
673+
exactly as if the yield expression were just another external call. The value of
674+
the yield expression after resuming depends on the method which resumed the
675+
execution. If :meth:`~agen.__anext__` is used then the result is :const:`None`.
676+
Otherwise, if :meth:`~agen.asend` is used, then the result will be the value
677+
passed in to that method.
678678

679679
If an asynchronous generator happens to exit early by :keyword:`break`, the caller
680680
task being cancelled, or other exceptions, the generator's async cleanup code
@@ -728,10 +728,10 @@ which are used to control the execution of a generator function.
728728
asynchronous generator function is resumed with an :meth:`~agen.__anext__`
729729
method, the current yield expression always evaluates to :const:`None` in the
730730
returned awaitable, which when run will continue to the next yield
731-
expression. The value of the :token:`~python-grammar:expression_list` of the
732-
yield expression is the value of the :exc:`StopIteration` exception raised by
733-
the completing coroutine. If the asynchronous generator exits without
734-
yielding another value, the awaitable instead raises a
731+
expression. The value of the :token:`~python-grammar:flexible_expression_list`
732+
of the yield expression is the value of the :exc:`StopIteration` exception
733+
raised by the completing coroutine. If the asynchronous generator exits
734+
without yielding another value, the awaitable instead raises a
735735
:exc:`StopAsyncIteration` exception, signalling that the asynchronous
736736
iteration has completed.
737737

@@ -861,7 +861,7 @@ will generally select an element from the container. The subscription of a
861861
:ref:`GenericAlias <types-genericalias>` object.
862862

863863
.. productionlist:: python-grammar
864-
subscription: `primary` "[" `expression_list` "]"
864+
subscription: `primary` "[" `flexible_expression_list` "]"
865865

866866
When an object is subscripted, the interpreter will evaluate the primary and
867867
the expression list.
@@ -1878,10 +1878,12 @@ Expression lists
18781878
single: , (comma); expression list
18791879

18801880
.. productionlist:: python-grammar
1881-
expression_list: `starred_expression` ("," `starred_expression`)* [","]
1882-
starred_list: `starred_item` ("," `starred_item`)* [","]
1883-
starred_expression: `expression` | (`starred_item` ",")* [`starred_item`]
1884-
starred_item: `assignment_expression` | "*" `or_expr`
1881+
1882+
starred_item: "*" `or_expr`
1883+
flexible_expression: `expression` | `assignment_expression` | `starred_item`
1884+
flexible_expression_list: `flexible_expression` ("," `flexible_expression`)* [","]
1885+
yield_list: `expression` ["," `flexible_expression_list`]
1886+
| `starred_item` "," [`flexible_expression_list`]
18851887
18861888
.. index:: pair: object; tuple
18871889

0 commit comments

Comments
 (0)