summaryrefslogtreecommitdiff
path: root/devdocs/python~3.12/reference%2Fgrammar.html
diff options
context:
space:
mode:
Diffstat (limited to 'devdocs/python~3.12/reference%2Fgrammar.html')
-rw-r--r--devdocs/python~3.12/reference%2Fgrammar.html907
1 files changed, 907 insertions, 0 deletions
diff --git a/devdocs/python~3.12/reference%2Fgrammar.html b/devdocs/python~3.12/reference%2Fgrammar.html
new file mode 100644
index 00000000..bdf7bd76
--- /dev/null
+++ b/devdocs/python~3.12/reference%2Fgrammar.html
@@ -0,0 +1,907 @@
+ <span id="id1"></span><h1> Full Grammar specification</h1> <p>This is the full Python grammar, derived directly from the grammar used to generate the CPython parser (see <a class="reference external" href="https://github.com/python/cpython/tree/3.12/Grammar/python.gram">Grammar/python.gram</a>). The version here omits details related to code generation and error recovery.</p> <p>The notation is a mixture of <a class="reference external" href="https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form">EBNF</a> and <a class="reference external" href="https://en.wikipedia.org/wiki/Parsing_expression_grammar">PEG</a>. In particular, <code>&amp;</code> followed by a symbol, token or parenthesized group indicates a positive lookahead (i.e., is required to match but not consumed), while <code>!</code> indicates a negative lookahead (i.e., is required <em>not</em> to match). We use the <code>|</code> separator to mean PEG’s “ordered choice” (written as <code>/</code> in traditional PEG grammars). See <span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0617/"><strong>PEP 617</strong></a> for more details on the grammar’s syntax.</p> <pre data-language="peg"># PEG grammar for Python
+
+
+
+# ========================= START OF THE GRAMMAR =========================
+
+# General grammatical elements and rules:
+#
+# * Strings with double quotes (") denote SOFT KEYWORDS
+# * Strings with single quotes (') denote KEYWORDS
+# * Upper case names (NAME) denote tokens in the Grammar/Tokens file
+# * Rule names starting with "invalid_" are used for specialized syntax errors
+# - These rules are NOT used in the first pass of the parser.
+# - Only if the first pass fails to parse, a second pass including the invalid
+# rules will be executed.
+# - If the parser fails in the second phase with a generic syntax error, the
+# location of the generic failure of the first pass will be used (this avoids
+# reporting incorrect locations due to the invalid rules).
+# - The order of the alternatives involving invalid rules matter
+# (like any rule in PEG).
+#
+# Grammar Syntax (see PEP 617 for more information):
+#
+# rule_name: expression
+# Optionally, a type can be included right after the rule name, which
+# specifies the return type of the C or Python function corresponding to the
+# rule:
+# rule_name[return_type]: expression
+# If the return type is omitted, then a void * is returned in C and an Any in
+# Python.
+# e1 e2
+# Match e1, then match e2.
+# e1 | e2
+# Match e1 or e2.
+# The first alternative can also appear on the line after the rule name for
+# formatting purposes. In that case, a | must be used before the first
+# alternative, like so:
+# rule_name[return_type]:
+# | first_alt
+# | second_alt
+# ( e )
+# Match e (allows also to use other operators in the group like '(e)*')
+# [ e ] or e?
+# Optionally match e.
+# e*
+# Match zero or more occurrences of e.
+# e+
+# Match one or more occurrences of e.
+# s.e+
+# Match one or more occurrences of e, separated by s. The generated parse tree
+# does not include the separator. This is otherwise identical to (e (s e)*).
+# &amp;e
+# Succeed if e can be parsed, without consuming any input.
+# !e
+# Fail if e can be parsed, without consuming any input.
+# ~
+# Commit to the current alternative, even if it fails to parse.
+#
+
+# STARTING RULES
+# ==============
+
+file: [statements] ENDMARKER
+interactive: statement_newline
+eval: expressions NEWLINE* ENDMARKER
+func_type: '(' [type_expressions] ')' '-&gt;' expression NEWLINE* ENDMARKER
+
+# GENERAL STATEMENTS
+# ==================
+
+statements: statement+
+
+statement: compound_stmt | simple_stmts
+
+statement_newline:
+ | compound_stmt NEWLINE
+ | simple_stmts
+ | NEWLINE
+ | ENDMARKER
+
+simple_stmts:
+ | simple_stmt !';' NEWLINE # Not needed, there for speedup
+ | ';'.simple_stmt+ [';'] NEWLINE
+
+# NOTE: assignment MUST precede expression, else parsing a simple assignment
+# will throw a SyntaxError.
+simple_stmt:
+ | assignment
+ | type_alias
+ | star_expressions
+ | return_stmt
+ | import_stmt
+ | raise_stmt
+ | 'pass'
+ | del_stmt
+ | yield_stmt
+ | assert_stmt
+ | 'break'
+ | 'continue'
+ | global_stmt
+ | nonlocal_stmt
+
+compound_stmt:
+ | function_def
+ | if_stmt
+ | class_def
+ | with_stmt
+ | for_stmt
+ | try_stmt
+ | while_stmt
+ | match_stmt
+
+# SIMPLE STATEMENTS
+# =================
+
+# NOTE: annotated_rhs may start with 'yield'; yield_expr must start with 'yield'
+assignment:
+ | NAME ':' expression ['=' annotated_rhs ]
+ | ('(' single_target ')'
+ | single_subscript_attribute_target) ':' expression ['=' annotated_rhs ]
+ | (star_targets '=' )+ (yield_expr | star_expressions) !'=' [TYPE_COMMENT]
+ | single_target augassign ~ (yield_expr | star_expressions)
+
+annotated_rhs: yield_expr | star_expressions
+
+augassign:
+ | '+='
+ | '-='
+ | '*='
+ | '@='
+ | '/='
+ | '%='
+ | '&amp;='
+ | '|='
+ | '^='
+ | '&lt;&lt;='
+ | '&gt;&gt;='
+ | '**='
+ | '//='
+
+return_stmt:
+ | 'return' [star_expressions]
+
+raise_stmt:
+ | 'raise' expression ['from' expression ]
+ | 'raise'
+
+global_stmt: 'global' ','.NAME+
+
+nonlocal_stmt: 'nonlocal' ','.NAME+
+
+del_stmt:
+ | 'del' del_targets &amp;(';' | NEWLINE)
+
+yield_stmt: yield_expr
+
+assert_stmt: 'assert' expression [',' expression ]
+
+import_stmt:
+ | import_name
+ | import_from
+
+# Import statements
+# -----------------
+
+import_name: 'import' dotted_as_names
+# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
+import_from:
+ | 'from' ('.' | '...')* dotted_name 'import' import_from_targets
+ | 'from' ('.' | '...')+ 'import' import_from_targets
+import_from_targets:
+ | '(' import_from_as_names [','] ')'
+ | import_from_as_names !','
+ | '*'
+import_from_as_names:
+ | ','.import_from_as_name+
+import_from_as_name:
+ | NAME ['as' NAME ]
+dotted_as_names:
+ | ','.dotted_as_name+
+dotted_as_name:
+ | dotted_name ['as' NAME ]
+dotted_name:
+ | dotted_name '.' NAME
+ | NAME
+
+# COMPOUND STATEMENTS
+# ===================
+
+# Common elements
+# ---------------
+
+block:
+ | NEWLINE INDENT statements DEDENT
+ | simple_stmts
+
+decorators: ('@' named_expression NEWLINE )+
+
+# Class definitions
+# -----------------
+
+class_def:
+ | decorators class_def_raw
+ | class_def_raw
+
+class_def_raw:
+ | 'class' NAME [type_params] ['(' [arguments] ')' ] ':' block
+
+# Function definitions
+# --------------------
+
+function_def:
+ | decorators function_def_raw
+ | function_def_raw
+
+function_def_raw:
+ | 'def' NAME [type_params] '(' [params] ')' ['-&gt;' expression ] ':' [func_type_comment] block
+ | ASYNC 'def' NAME [type_params] '(' [params] ')' ['-&gt;' expression ] ':' [func_type_comment] block
+
+# Function parameters
+# -------------------
+
+params:
+ | parameters
+
+parameters:
+ | slash_no_default param_no_default* param_with_default* [star_etc]
+ | slash_with_default param_with_default* [star_etc]
+ | param_no_default+ param_with_default* [star_etc]
+ | param_with_default+ [star_etc]
+ | star_etc
+
+# Some duplication here because we can't write (',' | &amp;')'),
+# which is because we don't support empty alternatives (yet).
+
+slash_no_default:
+ | param_no_default+ '/' ','
+ | param_no_default+ '/' &amp;')'
+slash_with_default:
+ | param_no_default* param_with_default+ '/' ','
+ | param_no_default* param_with_default+ '/' &amp;')'
+
+star_etc:
+ | '*' param_no_default param_maybe_default* [kwds]
+ | '*' param_no_default_star_annotation param_maybe_default* [kwds]
+ | '*' ',' param_maybe_default+ [kwds]
+ | kwds
+
+kwds:
+ | '**' param_no_default
+
+# One parameter. This *includes* a following comma and type comment.
+#
+# There are three styles:
+# - No default
+# - With default
+# - Maybe with default
+#
+# There are two alternative forms of each, to deal with type comments:
+# - Ends in a comma followed by an optional type comment
+# - No comma, optional type comment, must be followed by close paren
+# The latter form is for a final parameter without trailing comma.
+#
+
+param_no_default:
+ | param ',' TYPE_COMMENT?
+ | param TYPE_COMMENT? &amp;')'
+param_no_default_star_annotation:
+ | param_star_annotation ',' TYPE_COMMENT?
+ | param_star_annotation TYPE_COMMENT? &amp;')'
+param_with_default:
+ | param default ',' TYPE_COMMENT?
+ | param default TYPE_COMMENT? &amp;')'
+param_maybe_default:
+ | param default? ',' TYPE_COMMENT?
+ | param default? TYPE_COMMENT? &amp;')'
+param: NAME annotation?
+param_star_annotation: NAME star_annotation
+annotation: ':' expression
+star_annotation: ':' star_expression
+default: '=' expression | invalid_default
+
+# If statement
+# ------------
+
+if_stmt:
+ | 'if' named_expression ':' block elif_stmt
+ | 'if' named_expression ':' block [else_block]
+elif_stmt:
+ | 'elif' named_expression ':' block elif_stmt
+ | 'elif' named_expression ':' block [else_block]
+else_block:
+ | 'else' ':' block
+
+# While statement
+# ---------------
+
+while_stmt:
+ | 'while' named_expression ':' block [else_block]
+
+# For statement
+# -------------
+
+for_stmt:
+ | 'for' star_targets 'in' ~ star_expressions ':' [TYPE_COMMENT] block [else_block]
+ | ASYNC 'for' star_targets 'in' ~ star_expressions ':' [TYPE_COMMENT] block [else_block]
+
+# With statement
+# --------------
+
+with_stmt:
+ | 'with' '(' ','.with_item+ ','? ')' ':' block
+ | 'with' ','.with_item+ ':' [TYPE_COMMENT] block
+ | ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block
+ | ASYNC 'with' ','.with_item+ ':' [TYPE_COMMENT] block
+
+with_item:
+ | expression 'as' star_target &amp;(',' | ')' | ':')
+ | expression
+
+# Try statement
+# -------------
+
+try_stmt:
+ | 'try' ':' block finally_block
+ | 'try' ':' block except_block+ [else_block] [finally_block]
+ | 'try' ':' block except_star_block+ [else_block] [finally_block]
+
+
+# Except statement
+# ----------------
+
+except_block:
+ | 'except' expression ['as' NAME ] ':' block
+ | 'except' ':' block
+except_star_block:
+ | 'except' '*' expression ['as' NAME ] ':' block
+finally_block:
+ | 'finally' ':' block
+
+# Match statement
+# ---------------
+
+match_stmt:
+ | "match" subject_expr ':' NEWLINE INDENT case_block+ DEDENT
+
+subject_expr:
+ | star_named_expression ',' star_named_expressions?
+ | named_expression
+
+case_block:
+ | "case" patterns guard? ':' block
+
+guard: 'if' named_expression
+
+patterns:
+ | open_sequence_pattern
+ | pattern
+
+pattern:
+ | as_pattern
+ | or_pattern
+
+as_pattern:
+ | or_pattern 'as' pattern_capture_target
+
+or_pattern:
+ | '|'.closed_pattern+
+
+closed_pattern:
+ | literal_pattern
+ | capture_pattern
+ | wildcard_pattern
+ | value_pattern
+ | group_pattern
+ | sequence_pattern
+ | mapping_pattern
+ | class_pattern
+
+# Literal patterns are used for equality and identity constraints
+literal_pattern:
+ | signed_number !('+' | '-')
+ | complex_number
+ | strings
+ | 'None'
+ | 'True'
+ | 'False'
+
+# Literal expressions are used to restrict permitted mapping pattern keys
+literal_expr:
+ | signed_number !('+' | '-')
+ | complex_number
+ | strings
+ | 'None'
+ | 'True'
+ | 'False'
+
+complex_number:
+ | signed_real_number '+' imaginary_number
+ | signed_real_number '-' imaginary_number
+
+signed_number:
+ | NUMBER
+ | '-' NUMBER
+
+signed_real_number:
+ | real_number
+ | '-' real_number
+
+real_number:
+ | NUMBER
+
+imaginary_number:
+ | NUMBER
+
+capture_pattern:
+ | pattern_capture_target
+
+pattern_capture_target:
+ | !"_" NAME !('.' | '(' | '=')
+
+wildcard_pattern:
+ | "_"
+
+value_pattern:
+ | attr !('.' | '(' | '=')
+
+attr:
+ | name_or_attr '.' NAME
+
+name_or_attr:
+ | attr
+ | NAME
+
+group_pattern:
+ | '(' pattern ')'
+
+sequence_pattern:
+ | '[' maybe_sequence_pattern? ']'
+ | '(' open_sequence_pattern? ')'
+
+open_sequence_pattern:
+ | maybe_star_pattern ',' maybe_sequence_pattern?
+
+maybe_sequence_pattern:
+ | ','.maybe_star_pattern+ ','?
+
+maybe_star_pattern:
+ | star_pattern
+ | pattern
+
+star_pattern:
+ | '*' pattern_capture_target
+ | '*' wildcard_pattern
+
+mapping_pattern:
+ | '{' '}'
+ | '{' double_star_pattern ','? '}'
+ | '{' items_pattern ',' double_star_pattern ','? '}'
+ | '{' items_pattern ','? '}'
+
+items_pattern:
+ | ','.key_value_pattern+
+
+key_value_pattern:
+ | (literal_expr | attr) ':' pattern
+
+double_star_pattern:
+ | '**' pattern_capture_target
+
+class_pattern:
+ | name_or_attr '(' ')'
+ | name_or_attr '(' positional_patterns ','? ')'
+ | name_or_attr '(' keyword_patterns ','? ')'
+ | name_or_attr '(' positional_patterns ',' keyword_patterns ','? ')'
+
+positional_patterns:
+ | ','.pattern+
+
+keyword_patterns:
+ | ','.keyword_pattern+
+
+keyword_pattern:
+ | NAME '=' pattern
+
+# Type statement
+# ---------------
+
+type_alias:
+ | "type" NAME [type_params] '=' expression
+
+# Type parameter declaration
+# --------------------------
+
+type_params: '[' type_param_seq ']'
+
+type_param_seq: ','.type_param+ [',']
+
+type_param:
+ | NAME [type_param_bound]
+ | '*' NAME ':' expression
+ | '*' NAME
+ | '**' NAME ':' expression
+ | '**' NAME
+
+type_param_bound: ':' expression
+
+# EXPRESSIONS
+# -----------
+
+expressions:
+ | expression (',' expression )+ [',']
+ | expression ','
+ | expression
+
+expression:
+ | disjunction 'if' disjunction 'else' expression
+ | disjunction
+ | lambdef
+
+yield_expr:
+ | 'yield' 'from' expression
+ | 'yield' [star_expressions]
+
+star_expressions:
+ | star_expression (',' star_expression )+ [',']
+ | star_expression ','
+ | star_expression
+
+star_expression:
+ | '*' bitwise_or
+ | expression
+
+star_named_expressions: ','.star_named_expression+ [',']
+
+star_named_expression:
+ | '*' bitwise_or
+ | named_expression
+
+assignment_expression:
+ | NAME ':=' ~ expression
+
+named_expression:
+ | assignment_expression
+ | expression !':='
+
+disjunction:
+ | conjunction ('or' conjunction )+
+ | conjunction
+
+conjunction:
+ | inversion ('and' inversion )+
+ | inversion
+
+inversion:
+ | 'not' inversion
+ | comparison
+
+# Comparison operators
+# --------------------
+
+comparison:
+ | bitwise_or compare_op_bitwise_or_pair+
+ | bitwise_or
+
+compare_op_bitwise_or_pair:
+ | eq_bitwise_or
+ | noteq_bitwise_or
+ | lte_bitwise_or
+ | lt_bitwise_or
+ | gte_bitwise_or
+ | gt_bitwise_or
+ | notin_bitwise_or
+ | in_bitwise_or
+ | isnot_bitwise_or
+ | is_bitwise_or
+
+eq_bitwise_or: '==' bitwise_or
+noteq_bitwise_or:
+ | ('!=' ) bitwise_or
+lte_bitwise_or: '&lt;=' bitwise_or
+lt_bitwise_or: '&lt;' bitwise_or
+gte_bitwise_or: '&gt;=' bitwise_or
+gt_bitwise_or: '&gt;' bitwise_or
+notin_bitwise_or: 'not' 'in' bitwise_or
+in_bitwise_or: 'in' bitwise_or
+isnot_bitwise_or: 'is' 'not' bitwise_or
+is_bitwise_or: 'is' bitwise_or
+
+# Bitwise operators
+# -----------------
+
+bitwise_or:
+ | bitwise_or '|' bitwise_xor
+ | bitwise_xor
+
+bitwise_xor:
+ | bitwise_xor '^' bitwise_and
+ | bitwise_and
+
+bitwise_and:
+ | bitwise_and '&amp;' shift_expr
+ | shift_expr
+
+shift_expr:
+ | shift_expr '&lt;&lt;' sum
+ | shift_expr '&gt;&gt;' sum
+ | sum
+
+# Arithmetic operators
+# --------------------
+
+sum:
+ | sum '+' term
+ | sum '-' term
+ | term
+
+term:
+ | term '*' factor
+ | term '/' factor
+ | term '//' factor
+ | term '%' factor
+ | term '@' factor
+ | factor
+
+factor:
+ | '+' factor
+ | '-' factor
+ | '~' factor
+ | power
+
+power:
+ | await_primary '**' factor
+ | await_primary
+
+# Primary elements
+# ----------------
+
+# Primary elements are things like "obj.something.something", "obj[something]", "obj(something)", "obj" ...
+
+await_primary:
+ | AWAIT primary
+ | primary
+
+primary:
+ | primary '.' NAME
+ | primary genexp
+ | primary '(' [arguments] ')'
+ | primary '[' slices ']'
+ | atom
+
+slices:
+ | slice !','
+ | ','.(slice | starred_expression)+ [',']
+
+slice:
+ | [expression] ':' [expression] [':' [expression] ]
+ | named_expression
+
+atom:
+ | NAME
+ | 'True'
+ | 'False'
+ | 'None'
+ | strings
+ | NUMBER
+ | (tuple | group | genexp)
+ | (list | listcomp)
+ | (dict | set | dictcomp | setcomp)
+ | '...'
+
+group:
+ | '(' (yield_expr | named_expression) ')'
+
+# Lambda functions
+# ----------------
+
+lambdef:
+ | 'lambda' [lambda_params] ':' expression
+
+lambda_params:
+ | lambda_parameters
+
+# lambda_parameters etc. duplicates parameters but without annotations
+# or type comments, and if there's no comma after a parameter, we expect
+# a colon, not a close parenthesis. (For more, see parameters above.)
+#
+lambda_parameters:
+ | lambda_slash_no_default lambda_param_no_default* lambda_param_with_default* [lambda_star_etc]
+ | lambda_slash_with_default lambda_param_with_default* [lambda_star_etc]
+ | lambda_param_no_default+ lambda_param_with_default* [lambda_star_etc]
+ | lambda_param_with_default+ [lambda_star_etc]
+ | lambda_star_etc
+
+lambda_slash_no_default:
+ | lambda_param_no_default+ '/' ','
+ | lambda_param_no_default+ '/' &amp;':'
+
+lambda_slash_with_default:
+ | lambda_param_no_default* lambda_param_with_default+ '/' ','
+ | lambda_param_no_default* lambda_param_with_default+ '/' &amp;':'
+
+lambda_star_etc:
+ | '*' lambda_param_no_default lambda_param_maybe_default* [lambda_kwds]
+ | '*' ',' lambda_param_maybe_default+ [lambda_kwds]
+ | lambda_kwds
+
+lambda_kwds:
+ | '**' lambda_param_no_default
+
+lambda_param_no_default:
+ | lambda_param ','
+ | lambda_param &amp;':'
+lambda_param_with_default:
+ | lambda_param default ','
+ | lambda_param default &amp;':'
+lambda_param_maybe_default:
+ | lambda_param default? ','
+ | lambda_param default? &amp;':'
+lambda_param: NAME
+
+# LITERALS
+# ========
+
+fstring_middle:
+ | fstring_replacement_field
+ | FSTRING_MIDDLE
+fstring_replacement_field:
+ | '{' (yield_expr | star_expressions) '='? [fstring_conversion] [fstring_full_format_spec] '}'
+fstring_conversion:
+ | "!" NAME
+fstring_full_format_spec:
+ | ':' fstring_format_spec*
+fstring_format_spec:
+ | FSTRING_MIDDLE
+ | fstring_replacement_field
+fstring:
+ | FSTRING_START fstring_middle* FSTRING_END
+
+string: STRING
+strings: (fstring|string)+
+
+list:
+ | '[' [star_named_expressions] ']'
+
+tuple:
+ | '(' [star_named_expression ',' [star_named_expressions] ] ')'
+
+set: '{' star_named_expressions '}'
+
+# Dicts
+# -----
+
+dict:
+ | '{' [double_starred_kvpairs] '}'
+
+double_starred_kvpairs: ','.double_starred_kvpair+ [',']
+
+double_starred_kvpair:
+ | '**' bitwise_or
+ | kvpair
+
+kvpair: expression ':' expression
+
+# Comprehensions &amp; Generators
+# ---------------------------
+
+for_if_clauses:
+ | for_if_clause+
+
+for_if_clause:
+ | ASYNC 'for' star_targets 'in' ~ disjunction ('if' disjunction )*
+ | 'for' star_targets 'in' ~ disjunction ('if' disjunction )*
+
+listcomp:
+ | '[' named_expression for_if_clauses ']'
+
+setcomp:
+ | '{' named_expression for_if_clauses '}'
+
+genexp:
+ | '(' ( assignment_expression | expression !':=') for_if_clauses ')'
+
+dictcomp:
+ | '{' kvpair for_if_clauses '}'
+
+# FUNCTION CALL ARGUMENTS
+# =======================
+
+arguments:
+ | args [','] &amp;')'
+
+args:
+ | ','.(starred_expression | ( assignment_expression | expression !':=') !'=')+ [',' kwargs ]
+ | kwargs
+
+kwargs:
+ | ','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+
+ | ','.kwarg_or_starred+
+ | ','.kwarg_or_double_starred+
+
+starred_expression:
+ | '*' expression
+
+kwarg_or_starred:
+ | NAME '=' expression
+ | starred_expression
+
+kwarg_or_double_starred:
+ | NAME '=' expression
+ | '**' expression
+
+# ASSIGNMENT TARGETS
+# ==================
+
+# Generic targets
+# ---------------
+
+# NOTE: star_targets may contain *bitwise_or, targets may not.
+star_targets:
+ | star_target !','
+ | star_target (',' star_target )* [',']
+
+star_targets_list_seq: ','.star_target+ [',']
+
+star_targets_tuple_seq:
+ | star_target (',' star_target )+ [',']
+ | star_target ','
+
+star_target:
+ | '*' (!'*' star_target)
+ | target_with_star_atom
+
+target_with_star_atom:
+ | t_primary '.' NAME !t_lookahead
+ | t_primary '[' slices ']' !t_lookahead
+ | star_atom
+
+star_atom:
+ | NAME
+ | '(' target_with_star_atom ')'
+ | '(' [star_targets_tuple_seq] ')'
+ | '[' [star_targets_list_seq] ']'
+
+single_target:
+ | single_subscript_attribute_target
+ | NAME
+ | '(' single_target ')'
+
+single_subscript_attribute_target:
+ | t_primary '.' NAME !t_lookahead
+ | t_primary '[' slices ']' !t_lookahead
+
+t_primary:
+ | t_primary '.' NAME &amp;t_lookahead
+ | t_primary '[' slices ']' &amp;t_lookahead
+ | t_primary genexp &amp;t_lookahead
+ | t_primary '(' [arguments] ')' &amp;t_lookahead
+ | atom &amp;t_lookahead
+
+t_lookahead: '(' | '[' | '.'
+
+# Targets for del statements
+# --------------------------
+
+del_targets: ','.del_target+ [',']
+
+del_target:
+ | t_primary '.' NAME !t_lookahead
+ | t_primary '[' slices ']' !t_lookahead
+ | del_t_atom
+
+del_t_atom:
+ | NAME
+ | '(' del_target ')'
+ | '(' [del_targets] ')'
+ | '[' [del_targets] ']'
+
+# TYPING ELEMENTS
+# ---------------
+
+# type_expressions allow */** but ignore them
+type_expressions:
+ | ','.expression+ ',' '*' expression ',' '**' expression
+ | ','.expression+ ',' '*' expression
+ | ','.expression+ ',' '**' expression
+ | '*' expression ',' '**' expression
+ | '*' expression
+ | '**' expression
+ | ','.expression+
+
+func_type_comment:
+ | NEWLINE TYPE_COMMENT &amp;(NEWLINE INDENT) # Must be followed by indented block
+ | TYPE_COMMENT
+
+# ========================= END OF THE GRAMMAR ===========================
+
+
+
+# ========================= START OF INVALID RULES =======================
+
+</pre> <div class="_attribution">
+ <p class="_attribution-p">
+ &copy; 2001&ndash;2023 Python Software Foundation<br>Licensed under the PSF License.<br>
+ <a href="https://docs.python.org/3.12/reference/grammar.html" class="_attribution-link">https://docs.python.org/3.12/reference/grammar.html</a>
+ </p>
+</div>