Skip to content

Commit 8caafe3

Browse files
encukoublaisep
andcommitted
Start on enclosures
Co-authored-by: Blaise Pabon <blaise@gmail.com>
1 parent 5db331a commit 8caafe3

File tree

3 files changed

+92
-24
lines changed

3 files changed

+92
-24
lines changed

Doc/reference/expressions.rst

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,16 @@ also categorized syntactically as atoms. The syntax for atoms is:
5555

5656
.. productionlist:: python-grammar
5757
atom: `identifier` | `literal` | `enclosure`
58-
enclosure: `parenth_form` | `list_display` | `dict_display` | `set_display`
59-
: | `generator_expression` | `yield_atom`
6058

59+
.. grammar-snippet::
60+
:group: python-grammar
61+
62+
enclosure:
63+
| (`group` | `tuple` | `yield_atom` | `generator_expression`) # in (parentheses)
64+
| `list_display`
65+
| `dict_display`
66+
| `set_display`
67+
| `yield_atom`
6168
6269
.. _atom-identifiers:
6370

@@ -211,36 +218,75 @@ string literals::
211218

212219
.. _parenthesized:
213220

214-
Parenthesized forms
215-
-------------------
221+
Parenthesized groups
222+
--------------------
216223

217-
.. index::
218-
single: parenthesized form
219-
single: () (parentheses); tuple display
224+
A :dfn:`group` is an expression enclosed in parentheses.
225+
The parenthesized group evaluates to the same value as the expression inside.
220226

221-
A parenthesized form is an optional expression list enclosed in parentheses:
227+
Groups are used to override or clarify
228+
:ref:`operator precedence <operator-precedence>`,
229+
in the same way as in math notation.
230+
For example::
222231

223-
.. productionlist:: python-grammar
224-
parenth_form: "(" [`starred_expression`] ")"
232+
>>> 3 + 2 * 4
233+
11
234+
>>> (3 + 2) * 4 # Override precedence of the addition
235+
20
236+
>>> 3 + (2 * 4) # Same effect as without parentheses
237+
11
238+
239+
>>> 3 << 2 | 4
240+
12
241+
>>> 3 << (2 | 4) # Override precedence of the bitwise OR
242+
192
243+
>>> (3 << 2) | 4 # Same as without parentheses, but much clearer
244+
12
225245

226-
A parenthesized expression list yields whatever that expression list yields: if
227-
the list contains at least one comma, it yields a tuple; otherwise, it yields
228-
the single expression that makes up the expression list.
246+
Formally, the syntax for groups is:
229247

230-
.. index:: pair: empty; tuple
248+
.. grammar-snippet::
249+
:group: python-grammar
231250

232-
An empty pair of parentheses yields an empty tuple object. Since tuples are
233-
immutable, the same rules as for literals apply (i.e., two occurrences of the empty
234-
tuple may or may not yield the same object).
251+
group: '(' `assignment_expression` ')'
235252

236-
.. index::
237-
single: comma
238-
single: , (comma)
239253

240-
Note that tuples are not formed by the parentheses, but rather by use of the
241-
comma. The exception is the empty tuple, for which parentheses *are*
242-
required --- allowing unparenthesized "nothing" in expressions would cause
243-
ambiguities and allow common typos to pass uncaught.
254+
255+
Tuple displays
256+
--------------
257+
258+
..
259+
260+
Parenthesized forms
261+
-------------------
262+
263+
.. index::
264+
single: parenthesized form
265+
single: () (parentheses); tuple display
266+
267+
A parenthesized form is an optional expression list enclosed in parentheses:
268+
269+
.. productionlist:: python-grammar
270+
parenth_form: "(" [`starred_expression`] ")"
271+
272+
A parenthesized expression list yields whatever that expression list yields: if
273+
the list contains at least one comma, it yields a tuple; otherwise, it yields
274+
the single expression that makes up the expression list.
275+
276+
.. index:: pair: empty; tuple
277+
278+
An empty pair of parentheses yields an empty tuple object. Since tuples are
279+
immutable, the same rules as for literals apply (i.e., two occurrences of the empty
280+
tuple may or may not yield the same object).
281+
282+
.. index::
283+
single: comma
284+
single: , (comma)
285+
286+
Note that tuples are not formed by the parentheses, but rather by use of the
287+
comma. The exception is the empty tuple, for which parentheses *are*
288+
required --- allowing unparenthesized "nothing" in expressions would cause
289+
ambiguities and allow common typos to pass uncaught.
244290

245291

246292
.. _comprehensions:
@@ -2049,6 +2095,7 @@ their suffixes::
20492095

20502096

20512097
.. _operator-summary:
2098+
.. _operator-precedence:
20522099

20532100
Operator precedence
20542101
===================

Doc/reference/introduction.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ The definition to the right of the colon uses the following syntax elements:
145145
* ``e?``: A question mark has exactly the same meaning as square brackets:
146146
the preceding item is optional.
147147
* ``(e)``: Parentheses are used for grouping.
148+
* ``# ...``: As in Python, ``#`` introduces a comment that continues until the
149+
end of the line.
148150

149151
The following notation is only used in
150152
:ref:`lexical definitions <notation-lexical-vs-syntactic>`.

Doc/tools/extensions/grammar_snippet.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ def __init__(
3636
self['classes'].append('sx')
3737

3838

39+
class snippet_comment_node(nodes.inline): # noqa: N801 (snake_case is fine)
40+
"""Node for a comment in a grammar snippet."""
41+
42+
def __init__(
43+
self,
44+
rawsource: str = '',
45+
text: str = '',
46+
*children: Node,
47+
**attributes: Any,
48+
) -> None:
49+
super().__init__(rawsource, text, *children, **attributes)
50+
# Use the Pygments highlight class for `Comment.Single`
51+
self['classes'].append('c1')
52+
53+
3954
class GrammarSnippetBase(SphinxDirective):
4055
"""Common functionality for GrammarSnippetDirective & CompatProductionList."""
4156

@@ -51,6 +66,8 @@ class GrammarSnippetBase(SphinxDirective):
5166
(?P<single_quoted>'[^']*') # string in 'quotes'
5267
|
5368
(?P<double_quoted>"[^"]*") # string in "quotes"
69+
|
70+
(?P<comment>[#].*) # comment
5471
""",
5572
re.VERBOSE,
5673
)
@@ -147,6 +164,8 @@ def make_production(
147164
production_node += token_xrefs(content, group_name)
148165
case 'single_quoted' | 'double_quoted':
149166
production_node += snippet_string_node('', content)
167+
case 'comment':
168+
production_node += snippet_comment_node('', content)
150169
case 'text':
151170
production_node += nodes.Text(content)
152171
case _:

0 commit comments

Comments
 (0)