summaryrefslogtreecommitdiffstats
path: root/Doc/reference
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-09-18 07:10:15 (GMT)
committerGitHub <noreply@github.com>2020-09-18 07:10:15 (GMT)
commit8af239eacfcf52e4e0e2b0223e7cea4672309483 (patch)
treeb8bbfbf4ef54aefcb69b9690555b4bb47bf96b19 /Doc/reference
parent27201cddf3b25be7df25bbe36966531539757d60 (diff)
downloadcpython-8af239eacfcf52e4e0e2b0223e7cea4672309483.zip
cpython-8af239eacfcf52e4e0e2b0223e7cea4672309483.tar.gz
cpython-8af239eacfcf52e4e0e2b0223e7cea4672309483.tar.bz2
bpo-41762: Fix usage of productionlist markup in the doc (GH-22281)
Use an unique identifier for the different grammars documented using the Sphinx productionlist markup. productionlist markups of the same grammar, like "expressions" or "compound statements", use the same identifier "python-grammar".
Diffstat (limited to 'Doc/reference')
-rw-r--r--Doc/reference/compound_stmts.rst23
-rw-r--r--Doc/reference/expressions.rst54
-rw-r--r--Doc/reference/introduction.rst2
-rw-r--r--Doc/reference/lexical_analysis.rst14
-rw-r--r--Doc/reference/simple_stmts.rst34
-rw-r--r--Doc/reference/toplevel_components.rst6
6 files changed, 67 insertions, 66 deletions
diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst
index df720f6..158d6a8 100644
--- a/Doc/reference/compound_stmts.rst
+++ b/Doc/reference/compound_stmts.rst
@@ -44,7 +44,8 @@ executed::
Summarizing:
-.. productionlist::
+
+.. productionlist:: python-grammar
compound_stmt: `if_stmt`
: | `while_stmt`
: | `for_stmt`
@@ -89,7 +90,7 @@ The :keyword:`!if` statement
The :keyword:`if` statement is used for conditional execution:
-.. productionlist::
+.. productionlist:: python-grammar
if_stmt: "if" `assignment_expression` ":" `suite`
: ("elif" `assignment_expression` ":" `suite`)*
: ["else" ":" `suite`]
@@ -115,7 +116,7 @@ The :keyword:`!while` statement
The :keyword:`while` statement is used for repeated execution as long as an
expression is true:
-.. productionlist::
+.. productionlist:: python-grammar
while_stmt: "while" `assignment_expression` ":" `suite`
: ["else" ":" `suite`]
@@ -151,7 +152,7 @@ The :keyword:`!for` statement
The :keyword:`for` statement is used to iterate over the elements of a sequence
(such as a string, tuple or list) or other iterable object:
-.. productionlist::
+.. productionlist:: python-grammar
for_stmt: "for" `target_list` "in" `expression_list` ":" `suite`
: ["else" ":" `suite`]
@@ -234,7 +235,7 @@ The :keyword:`!try` statement
The :keyword:`try` statement specifies exception handlers and/or cleanup code
for a group of statements:
-.. productionlist::
+.. productionlist:: python-grammar
try_stmt: `try1_stmt` | `try2_stmt`
try1_stmt: "try" ":" `suite`
: ("except" [`expression` ["as" `identifier`]] ":" `suite`)+
@@ -390,7 +391,7 @@ methods defined by a context manager (see section :ref:`context-managers`).
This allows common :keyword:`try`...\ :keyword:`except`...\ :keyword:`finally`
usage patterns to be encapsulated for convenient reuse.
-.. productionlist::
+.. productionlist:: python-grammar
with_stmt: "with" `with_item` ("," `with_item`)* ":" `suite`
with_item: `expression` ["as" `target`]
@@ -503,7 +504,7 @@ Function definitions
A function definition defines a user-defined function object (see section
:ref:`types`):
-.. productionlist::
+.. productionlist:: python-grammar
funcdef: [`decorators`] "def" `funcname` "(" [`parameter_list`] ")"
: ["->" `expression`] ":" `suite`
decorators: `decorator`+
@@ -670,7 +671,7 @@ Class definitions
A class definition defines a class object (see section :ref:`types`):
-.. productionlist::
+.. productionlist:: python-grammar
classdef: [`decorators`] "class" `classname` [`inheritance`] ":" `suite`
inheritance: "(" [`argument_list`] ")"
classname: `identifier`
@@ -762,7 +763,7 @@ Coroutines
Coroutine function definition
-----------------------------
-.. productionlist::
+.. productionlist:: python-grammar
async_funcdef: [`decorators`] "async" "def" `funcname` "(" [`parameter_list`] ")"
: ["->" `expression`] ":" `suite`
@@ -795,7 +796,7 @@ An example of a coroutine function::
The :keyword:`!async for` statement
-----------------------------------
-.. productionlist::
+.. productionlist:: python-grammar
async_for_stmt: "async" `for_stmt`
An :term:`asynchronous iterable` is able to call asynchronous code in its
@@ -840,7 +841,7 @@ body of a coroutine function.
The :keyword:`!async with` statement
------------------------------------
-.. productionlist::
+.. productionlist:: python-grammar
async_with_stmt: "async" `with_stmt`
An :term:`asynchronous context manager` is a :term:`context manager` that is
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index 18abce3..b68c298 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -13,7 +13,7 @@ This chapter explains the meaning of the elements of expressions in Python.
be used to describe syntax, not lexical analysis. When (one alternative of) a
syntax rule has the form
-.. productionlist:: *
+.. productionlist:: python-grammar
name: `othername`
and no semantics are given, the semantics of this form of ``name`` are the same
@@ -54,7 +54,7 @@ Atoms are the most basic elements of expressions. The simplest atoms are
identifiers or literals. Forms enclosed in parentheses, brackets or braces are
also categorized syntactically as atoms. The syntax for atoms is:
-.. productionlist::
+.. productionlist:: python-grammar
atom: `identifier` | `literal` | `enclosure`
enclosure: `parenth_form` | `list_display` | `dict_display` | `set_display`
: | `generator_expression` | `yield_atom`
@@ -103,7 +103,7 @@ Literals
Python supports string and bytes literals and various numeric literals:
-.. productionlist::
+.. productionlist:: python-grammar
literal: `stringliteral` | `bytesliteral`
: | `integer` | `floatnumber` | `imagnumber`
@@ -134,7 +134,7 @@ Parenthesized forms
A parenthesized form is an optional expression list enclosed in parentheses:
-.. productionlist::
+.. productionlist:: python-grammar
parenth_form: "(" [`starred_expression`] ")"
A parenthesized expression list yields whatever that expression list yields: if
@@ -177,7 +177,7 @@ called "displays", each of them in two flavors:
Common syntax elements for comprehensions are:
-.. productionlist::
+.. productionlist:: python-grammar
comprehension: `assignment_expression` `comp_for`
comp_for: ["async"] "for" `target_list` "in" `or_test` [`comp_iter`]
comp_iter: `comp_for` | `comp_if`
@@ -243,7 +243,7 @@ List displays
A list display is a possibly empty series of expressions enclosed in square
brackets:
-.. productionlist::
+.. productionlist:: python-grammar
list_display: "[" [`starred_list` | `comprehension`] "]"
A list display yields a new list object, the contents being specified by either
@@ -267,7 +267,7 @@ Set displays
A set display is denoted by curly braces and distinguishable from dictionary
displays by the lack of colons separating keys and values:
-.. productionlist::
+.. productionlist:: python-grammar
set_display: "{" (`starred_list` | `comprehension`) "}"
A set display yields a new mutable set object, the contents being specified by
@@ -296,7 +296,7 @@ Dictionary displays
A dictionary display is a possibly empty series of key/datum pairs enclosed in
curly braces:
-.. productionlist::
+.. productionlist:: python-grammar
dict_display: "{" [`key_datum_list` | `dict_comprehension`] "}"
key_datum_list: `key_datum` ("," `key_datum`)* [","]
key_datum: `expression` ":" `expression` | "**" `or_expr`
@@ -355,7 +355,7 @@ Generator expressions
A generator expression is a compact generator notation in parentheses:
-.. productionlist::
+.. productionlist:: python-grammar
generator_expression: "(" `expression` `comp_for` ")"
A generator expression yields a new generator object. Its syntax is the same as
@@ -409,7 +409,7 @@ Yield expressions
pair: yield; expression
pair: generator; function
-.. productionlist::
+.. productionlist:: python-grammar
yield_atom: "(" `yield_expression` ")"
yield_expression: "yield" [`expression_list` | "from" `expression`]
@@ -746,7 +746,7 @@ Primaries
Primaries represent the most tightly bound operations of the language. Their
syntax is:
-.. productionlist::
+.. productionlist:: python-grammar
primary: `atom` | `attributeref` | `subscription` | `slicing` | `call`
@@ -761,7 +761,7 @@ Attribute references
An attribute reference is a primary followed by a period and a name:
-.. productionlist::
+.. productionlist:: python-grammar
attributeref: `primary` "." `identifier`
.. index::
@@ -799,7 +799,7 @@ Subscriptions
A subscription selects an item of a sequence (string, tuple or list) or mapping
(dictionary) object:
-.. productionlist::
+.. productionlist:: python-grammar
subscription: `primary` "[" `expression_list` "]"
The primary must evaluate to an object that supports subscription (lists or
@@ -855,7 +855,7 @@ A slicing selects a range of items in a sequence object (e.g., a string, tuple
or list). Slicings may be used as expressions or as targets in assignment or
:keyword:`del` statements. The syntax for a slicing:
-.. productionlist::
+.. productionlist:: python-grammar
slicing: `primary` "[" `slice_list` "]"
slice_list: `slice_item` ("," `slice_item`)* [","]
slice_item: `expression` | `proper_slice`
@@ -905,7 +905,7 @@ Calls
A call calls a callable object (e.g., a :term:`function`) with a possibly empty
series of :term:`arguments <argument>`:
-.. productionlist::
+.. productionlist:: python-grammar
call: `primary` "(" [`argument_list` [","] | `comprehension`] ")"
argument_list: `positional_arguments` ["," `starred_and_keywords`]
: ["," `keywords_arguments`]
@@ -1088,7 +1088,7 @@ Await expression
Suspend the execution of :term:`coroutine` on an :term:`awaitable` object.
Can only be used inside a :term:`coroutine function`.
-.. productionlist::
+.. productionlist:: python-grammar
await_expr: "await" `primary`
.. versionadded:: 3.5
@@ -1106,7 +1106,7 @@ The power operator
The power operator binds more tightly than unary operators on its left; it binds
less tightly than unary operators on its right. The syntax is:
-.. productionlist::
+.. productionlist:: python-grammar
power: (`await_expr` | `primary`) ["**" `u_expr`]
Thus, in an unparenthesized sequence of power and unary operators, the operators
@@ -1139,7 +1139,7 @@ Unary arithmetic and bitwise operations
All unary arithmetic and bitwise operations have the same priority:
-.. productionlist::
+.. productionlist:: python-grammar
u_expr: `power` | "-" `u_expr` | "+" `u_expr` | "~" `u_expr`
.. index::
@@ -1183,7 +1183,7 @@ that some of these operations also apply to certain non-numeric types. Apart
from the power operator, there are only two levels, one for multiplicative
operators and one for additive operators:
-.. productionlist::
+.. productionlist:: python-grammar
m_expr: `u_expr` | `m_expr` "*" `u_expr` | `m_expr` "@" `m_expr` |
: `m_expr` "//" `u_expr` | `m_expr` "/" `u_expr` |
: `m_expr` "%" `u_expr`
@@ -1279,7 +1279,7 @@ Shifting operations
The shifting operations have lower priority than the arithmetic operations:
-.. productionlist::
+.. productionlist:: python-grammar
shift_expr: `a_expr` | `shift_expr` ("<<" | ">>") `a_expr`
These operators accept integers as arguments. They shift the first argument to
@@ -1300,7 +1300,7 @@ Binary bitwise operations
Each of the three bitwise operations has a different priority level:
-.. productionlist::
+.. productionlist:: python-grammar
and_expr: `shift_expr` | `and_expr` "&" `shift_expr`
xor_expr: `and_expr` | `xor_expr` "^" `and_expr`
or_expr: `xor_expr` | `or_expr` "|" `xor_expr`
@@ -1349,7 +1349,7 @@ lower than that of any arithmetic, shifting or bitwise operation. Also unlike
C, expressions like ``a < b < c`` have the interpretation that is conventional
in mathematics:
-.. productionlist::
+.. productionlist:: python-grammar
comparison: `or_expr` (`comp_operator` `or_expr`)*
comp_operator: "<" | ">" | "==" | ">=" | "<=" | "!="
: | "is" ["not"] | ["not"] "in"
@@ -1608,7 +1608,7 @@ Boolean operations
pair: Conditional; expression
pair: Boolean; operation
-.. productionlist::
+.. productionlist:: python-grammar
or_test: `and_test` | `or_test` "or" `and_test`
and_test: `not_test` | `and_test` "and" `not_test`
not_test: `comparison` | "not" `not_test`
@@ -1647,7 +1647,7 @@ returns a boolean value regardless of the type of its argument
Assignment expressions
======================
-.. productionlist::
+.. productionlist:: python-grammar
assignment_expression: [`identifier` ":="] `expression`
An assignment expression (sometimes also called a "named expression" or
@@ -1683,7 +1683,7 @@ Conditional expressions
single: if; conditional expression
single: else; conditional expression
-.. productionlist::
+.. productionlist:: python-grammar
conditional_expression: `or_test` ["if" `or_test` "else" `expression`]
expression: `conditional_expression` | `lambda_expr`
expression_nocond: `or_test` | `lambda_expr_nocond`
@@ -1710,7 +1710,7 @@ Lambdas
pair: anonymous; function
single: : (colon); lambda expression
-.. productionlist::
+.. productionlist:: python-grammar
lambda_expr: "lambda" [`parameter_list`] ":" `expression`
lambda_expr_nocond: "lambda" [`parameter_list`] ":" `expression_nocond`
@@ -1737,7 +1737,7 @@ Expression lists
pair: expression; list
single: , (comma); expression list
-.. productionlist::
+.. productionlist:: python-grammar
expression_list: `expression` ("," `expression`)* [","]
starred_list: `starred_item` ("," `starred_item`)* [","]
starred_expression: `expression` | (`starred_item` ",")* [`starred_item`]
diff --git a/Doc/reference/introduction.rst b/Doc/reference/introduction.rst
index 62480bd..72e874e 100644
--- a/Doc/reference/introduction.rst
+++ b/Doc/reference/introduction.rst
@@ -93,7 +93,7 @@ Notation
The descriptions of lexical analysis and syntax use a modified BNF grammar
notation. This uses the following style of definition:
-.. productionlist::
+.. productionlist:: notation
name: `lc_letter` (`lc_letter` | "_")*
lc_letter: "a"..."z"
diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst
index 19ba83a..77e0578 100644
--- a/Doc/reference/lexical_analysis.rst
+++ b/Doc/reference/lexical_analysis.rst
@@ -296,7 +296,7 @@ Unicode Character Database as included in the :mod:`unicodedata` module.
Identifiers are unlimited in length. Case is significant.
-.. productionlist::
+.. productionlist:: python-grammar
identifier: `xid_start` `xid_continue`*
id_start: <all characters in general categories Lu, Ll, Lt, Lm, Lo, Nl, the underscore, and characters with the Other_ID_Start property>
id_continue: <all characters in `id_start`, plus characters in the categories Mn, Mc, Nd, Pc and others with the Other_ID_Continue property>
@@ -412,7 +412,7 @@ String and Bytes literals
String literals are described by the following lexical definitions:
-.. productionlist::
+.. productionlist:: python-grammar
stringliteral: [`stringprefix`](`shortstring` | `longstring`)
stringprefix: "r" | "u" | "R" | "U" | "f" | "F"
: | "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF"
@@ -424,7 +424,7 @@ String literals are described by the following lexical definitions:
longstringchar: <any source character except "\">
stringescapeseq: "\" <any source character>
-.. productionlist::
+.. productionlist:: python-grammar
bytesliteral: `bytesprefix`(`shortbytes` | `longbytes`)
bytesprefix: "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"
shortbytes: "'" `shortbytesitem`* "'" | '"' `shortbytesitem`* '"'
@@ -659,7 +659,7 @@ Escape sequences are decoded like in ordinary string literals (except when
a literal is also marked as a raw string). After decoding, the grammar
for the contents of the string is:
-.. productionlist::
+.. productionlist:: python-grammar
f_string: (`literal_char` | "{{" | "}}" | `replacement_field`)*
replacement_field: "{" `f_expression` ["="] ["!" `conversion`] [":" `format_spec`] "}"
f_expression: (`conditional_expression` | "*" `or_expr`)
@@ -820,7 +820,7 @@ Integer literals
Integer literals are described by the following lexical definitions:
-.. productionlist::
+.. productionlist:: python-grammar
integer: `decinteger` | `bininteger` | `octinteger` | `hexinteger`
decinteger: `nonzerodigit` (["_"] `digit`)* | "0"+ (["_"] "0")*
bininteger: "0" ("b" | "B") (["_"] `bindigit`)+
@@ -864,7 +864,7 @@ Floating point literals
Floating point literals are described by the following lexical definitions:
-.. productionlist::
+.. productionlist:: python-grammar
floatnumber: `pointfloat` | `exponentfloat`
pointfloat: [`digitpart`] `fraction` | `digitpart` "."
exponentfloat: (`digitpart` | `pointfloat`) `exponent`
@@ -894,7 +894,7 @@ Imaginary literals
Imaginary literals are described by the following lexical definitions:
-.. productionlist::
+.. productionlist:: python-grammar
imagnumber: (`floatnumber` | `digitpart`) ("j" | "J")
An imaginary literal yields a complex number with a real part of 0.0. Complex
diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst
index a8ec0fb..93be327 100644
--- a/Doc/reference/simple_stmts.rst
+++ b/Doc/reference/simple_stmts.rst
@@ -11,7 +11,7 @@ A simple statement is comprised within a single logical line. Several simple
statements may occur on a single line separated by semicolons. The syntax for
simple statements is:
-.. productionlist::
+.. productionlist:: python-grammar
simple_stmt: `expression_stmt`
: | `assert_stmt`
: | `assignment_stmt`
@@ -46,7 +46,7 @@ result; in Python, procedures return the value ``None``). Other uses of
expression statements are allowed and occasionally useful. The syntax for an
expression statement is:
-.. productionlist::
+.. productionlist:: python-grammar
expression_stmt: `starred_expression`
An expression statement evaluates the expression list (which may be a single
@@ -82,7 +82,7 @@ Assignment statements
Assignment statements are used to (re)bind names to values and to modify
attributes or items of mutable objects:
-.. productionlist::
+.. productionlist:: python-grammar
assignment_stmt: (`target_list` "=")+ (`starred_expression` | `yield_expression`)
target_list: `target` ("," `target`)* [","]
target: `identifier`
@@ -280,7 +280,7 @@ Augmented assignment statements
Augmented assignment is the combination, in a single statement, of a binary
operation and an assignment statement:
-.. productionlist::
+.. productionlist:: python-grammar
augmented_assignment_stmt: `augtarget` `augop` (`expression_list` | `yield_expression`)
augtarget: `identifier` | `attributeref` | `subscription` | `slicing`
augop: "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="
@@ -328,7 +328,7 @@ Annotated assignment statements
:term:`Annotation <variable annotation>` assignment is the combination, in a single
statement, of a variable or attribute annotation and an optional assignment statement:
-.. productionlist::
+.. productionlist:: python-grammar
annotated_assignment_stmt: `augtarget` ":" `expression`
: ["=" (`starred_expression` | `yield_expression`)]
@@ -385,7 +385,7 @@ The :keyword:`!assert` statement
Assert statements are a convenient way to insert debugging assertions into a
program:
-.. productionlist::
+.. productionlist:: python-grammar
assert_stmt: "assert" `expression` ["," `expression`]
The simple form, ``assert expression``, is equivalent to ::
@@ -425,7 +425,7 @@ The :keyword:`!pass` statement
pair: null; operation
pair: null; operation
-.. productionlist::
+.. productionlist:: python-grammar
pass_stmt: "pass"
:keyword:`pass` is a null operation --- when it is executed, nothing happens.
@@ -447,7 +447,7 @@ The :keyword:`!del` statement
pair: deletion; target
triple: deletion; target; list
-.. productionlist::
+.. productionlist:: python-grammar
del_stmt: "del" `target_list`
Deletion is recursively defined very similar to the way assignment is defined.
@@ -486,7 +486,7 @@ The :keyword:`!return` statement
pair: function; definition
pair: class; definition
-.. productionlist::
+.. productionlist:: python-grammar
return_stmt: "return" [`expression_list`]
:keyword:`return` may only occur syntactically nested in a function definition,
@@ -525,7 +525,7 @@ The :keyword:`!yield` statement
single: function; generator
exception: StopIteration
-.. productionlist::
+.. productionlist:: python-grammar
yield_stmt: `yield_expression`
A :keyword:`yield` statement is semantically equivalent to a :ref:`yield
@@ -560,7 +560,7 @@ The :keyword:`!raise` statement
pair: raising; exception
single: __traceback__ (exception attribute)
-.. productionlist::
+.. productionlist:: python-grammar
raise_stmt: "raise" [`expression` ["from" `expression`]]
If no expressions are present, :keyword:`raise` re-raises the last exception
@@ -663,7 +663,7 @@ The :keyword:`!break` statement
statement: while
pair: loop; statement
-.. productionlist::
+.. productionlist:: python-grammar
break_stmt: "break"
:keyword:`break` may only occur syntactically nested in a :keyword:`for` or
@@ -698,7 +698,7 @@ The :keyword:`!continue` statement
pair: loop; statement
keyword: finally
-.. productionlist::
+.. productionlist:: python-grammar
continue_stmt: "continue"
:keyword:`continue` may only occur syntactically nested in a :keyword:`for` or
@@ -725,7 +725,7 @@ The :keyword:`!import` statement
exception: ImportError
single: , (comma); import statement
-.. productionlist::
+.. productionlist:: python-grammar
import_stmt: "import" `module` ["as" `identifier`] ("," `module` ["as" `identifier`])*
: | "from" `relative_module` "import" `identifier` ["as" `identifier`]
: ("," `identifier` ["as" `identifier`])*
@@ -859,7 +859,7 @@ that introduce incompatible changes to the language. It allows use of the new
features on a per-module basis before the release in which the feature becomes
standard.
-.. productionlist:: *
+.. productionlist:: python-grammar
future_stmt: "from" "__future__" "import" `feature` ["as" `identifier`]
: ("," `feature` ["as" `identifier`])*
: | "from" "__future__" "import" "(" `feature` ["as" `identifier`]
@@ -937,7 +937,7 @@ The :keyword:`!global` statement
triple: global; name; binding
single: , (comma); identifier list
-.. productionlist::
+.. productionlist:: python-grammar
global_stmt: "global" `identifier` ("," `identifier`)*
The :keyword:`global` statement is a declaration which holds for the entire
@@ -982,7 +982,7 @@ The :keyword:`!nonlocal` statement
.. index:: statement: nonlocal
single: , (comma); identifier list
-.. productionlist::
+.. productionlist:: python-grammar
nonlocal_stmt: "nonlocal" `identifier` ("," `identifier`)*
.. XXX add when implemented
diff --git a/Doc/reference/toplevel_components.rst b/Doc/reference/toplevel_components.rst
index d5ffb37..319c9de 100644
--- a/Doc/reference/toplevel_components.rst
+++ b/Doc/reference/toplevel_components.rst
@@ -66,7 +66,7 @@ File input
All input read from non-interactive files has the same form:
-.. productionlist::
+.. productionlist:: python-grammar
file_input: (NEWLINE | `statement`)*
This syntax is used in the following situations:
@@ -85,7 +85,7 @@ Interactive input
Input in interactive mode is parsed using the following grammar:
-.. productionlist::
+.. productionlist:: python-grammar
interactive_input: [`stmt_list`] NEWLINE | `compound_stmt` NEWLINE
Note that a (top-level) compound statement must be followed by a blank line in
@@ -103,5 +103,5 @@ Expression input
:func:`eval` is used for expression input. It ignores leading whitespace. The
string argument to :func:`eval` must have the following form:
-.. productionlist::
+.. productionlist:: python-grammar
eval_input: `expression_list` NEWLINE*