10. 完整的文法規格書¶
這是完整的 Python 文法,是直接從用來產生 CPython 剖析器的文法衍生出來的(請參閱 Grammar/python.gram)。這裡的版本省略了與程式碼產生和錯誤復原相關的細節。
這裡使用的標示法與前面文件相同,並在標示法部分中進行了說明。除有一個額外的複雜性:
~(「切斷」):提交至目前的替代方案,即使這無法剖析也會使規則失敗。
# Python 的 PEG 文法
# ========================= 文法的開始 =========================
# 通用文法結構與規則
#
# * 雙引號(")字串表示軟關鍵字 (SOFT KEYWORDS)
# * 單引號(')字串表示關鍵字 (KEYWORDS)
# * 大寫名稱 (NAME) 表示 Grammar/Tokens 檔案中的語彙符號 (token)
# * 以 "invalid_" 開頭的規則名稱用於專門的語法錯誤
# - 這些規則不會在剖析器的第一遍剖析中使用。
# - 只有當第一遍剖析失敗時,才會執行包含無效規則的第二遍。
# - 如果剖析器在第二階段因泛用語法錯誤而失敗,
# 則會使用第一遍泛用失敗的位置(這可避免因無效規則
# 而報告錯誤的位置)。
# - 涉及無效規則的替代方案的順序很重要
# (就像 PEG 中的任何規則一樣)。
#
# 文法語法(更多資訊請參閱 PEP 617):
#
# rule_name: expression
# 在規則名稱後面可以選擇性地包含型別,用來指定對應此規則的
# C 或 Python 函式的回傳型別:
# rule_name[return_type]: expression
# 如果省略回傳型別,則在 C 中回傳 void *,並在 Python 中回傳 Any。
# e1 e2
# 匹配 e1,然後匹配 e2。
# e1 | e2
# 匹配 e1 或 e2。
# 為了格式化目的,第一個替代選項也可以出現在規則名稱後的下一行。
# 在這種情況下,必須在第一個替代選項之前使用 |,如下所示:
# rule_name[return_type]:
# | first_alt
# | second_alt
# ( e )
# 匹配 e(也允許在群組中使用其他運算子,如 '(e)*')
# [ e ] or e?
# 可選地匹配 e。
# e*
# 匹配零個或多個 e。
# e+
# 匹配一個或多個 e。
# s.e+
# 匹配一個或多個 e,以 s 分隔。產生的剖析樹不包含分隔符號。
# 這在其他方面與 (e (s e)*) 相同。
# &e
# 如果可以剖析 e 則成功,但不消耗任何輸入。
# !e
# 如果可以剖析 e 則失敗,但不消耗任何輸入。
# ~
# 提交到目前的替代選項,即使剖析失敗。
# &&e
# 急切剖析 e。如果無法剖析 e,剖析器將不會回溯 (backtrack),並會立即
# 引發 SyntaxError 失敗。
#
# 起始規則
# =======
file: [statements] ENDMARKER
interactive: statement_newline
eval: expressions NEWLINE* ENDMARKER
func_type: '(' [type_expressions] ')' '->' expression NEWLINE* ENDMARKER
# 一般陳述式
# =========
statements: statement+
statement:
| compound_stmt
| simple_stmts
single_compound_stmt:
| compound_stmt
statement_newline:
| single_compound_stmt NEWLINE
| simple_stmts
| NEWLINE
| ENDMARKER
simple_stmts:
| simple_stmt !';' NEWLINE # Not needed, there for speedup
| ';'.simple_stmt+ [';'] NEWLINE
# 註:賦值必須在運算式之前,否則剖析簡單賦值時會引發 SyntaxError。
simple_stmt:
| assignment
| type_alias
| star_expressions
| return_stmt
| import_stmt
| raise_stmt
| pass_stmt
| del_stmt
| yield_stmt
| assert_stmt
| break_stmt
| continue_stmt
| global_stmt
| nonlocal_stmt
compound_stmt:
| function_def
| if_stmt
| class_def
| with_stmt
| for_stmt
| try_stmt
| while_stmt
| match_stmt
# 簡單陳述式
# =========
# 註:annotated_rhs 可以用 'yield' 開頭;yield_expr 必須以 'yield' 開頭
assignment:
| NAME ':' expression ['=' annotated_rhs ]
| ('(' single_target ')'
| single_subscript_attribute_target) ':' expression ['=' annotated_rhs ]
| (star_targets '=' )+ annotated_rhs !'=' [TYPE_COMMENT]
| single_target augassign ~ annotated_rhs
annotated_rhs: yield_expr | star_expressions
augassign:
| '+='
| '-='
| '*='
| '@='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| '>>='
| '**='
| '//='
return_stmt:
| 'return' [star_expressions]
raise_stmt:
| 'raise' expression ['from' expression ]
| 'raise'
pass_stmt:
| 'pass'
break_stmt:
| 'break'
continue_stmt:
| 'continue'
global_stmt: 'global' ','.NAME+
nonlocal_stmt: 'nonlocal' ','.NAME+
del_stmt:
| 'del' del_targets &(';' | NEWLINE)
yield_stmt: yield_expr
assert_stmt: 'assert' expression [',' expression ]
import_stmt:
| import_name
| import_from
# Import 陳述式
# ------------
import_name: 'import' dotted_as_names
# 注意以下部分:('.' | '...') 是必須的,因為 '...' 是被 tokenize 為 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
# 複合陳述式
# ========
# 共用元素
# -------
block:
| NEWLINE INDENT statements DEDENT
| simple_stmts
decorators: ('@' named_expression NEWLINE )+
# 類別定義
# -------
class_def:
| decorators class_def_raw
| class_def_raw
class_def_raw:
| 'class' NAME [type_params] ['(' [arguments] ')' ] ':' block
# 函式定義
# -------
function_def:
| decorators function_def_raw
| function_def_raw
function_def_raw:
| 'def' NAME [type_params] '(' [params] ')' ['->' expression ] ':' [func_type_comment] block
| 'async' 'def' NAME [type_params] '(' [params] ')' ['->' expression ] ':' [func_type_comment] block
# 函式參數
# -------
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
# 這裡有些重複,因為我們不能寫 (',' | &')'),
# 這是因為我們(尚)不支援空替代方案。
slash_no_default:
| param_no_default+ '/' ','
| param_no_default+ '/' &')'
slash_with_default:
| param_no_default* param_with_default+ '/' ','
| param_no_default* param_with_default+ '/' &')'
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
# 一個參數。這 *包含* 後面的逗號和型別註解。
#
# 有三種風格:
# - 沒有預設值
# - 有預設值
# - 可能有預設值
#
# 每種都有兩種替代形式,用以處理型別註解:
# - 以逗號結尾,後面接可選的型別註解
# - 沒有逗號,可選的型別註解,後面必須接右括號
# 後者是用於沒有尾隨逗號的最後一個參數。
#
param_no_default:
| param ',' TYPE_COMMENT?
| param TYPE_COMMENT? &')'
param_no_default_star_annotation:
| param_star_annotation ',' TYPE_COMMENT?
| param_star_annotation TYPE_COMMENT? &')'
param_with_default:
| param default ',' TYPE_COMMENT?
| param default TYPE_COMMENT? &')'
param_maybe_default:
| param default? ',' TYPE_COMMENT?
| param default? TYPE_COMMENT? &')'
param: NAME annotation?
param_star_annotation: NAME star_annotation
annotation: ':' expression
star_annotation: ':' star_expression
default: '=' expression | invalid_default
# If 陳述式
# --------
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 陳述式
# -----------
while_stmt:
| 'while' named_expression ':' block [else_block]
# For 陳述式
# ---------
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 陳述式
# ----------
with_stmt:
| 'with' '(' ','.with_item+ ','? ')' ':' [TYPE_COMMENT] 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 &(',' | ')' | ':')
| expression
# Try 陳述式
# ---------
try_stmt:
| 'try' ':' block finally_block
| 'try' ':' block except_block+ [else_block] [finally_block]
| 'try' ':' block except_star_block+ [else_block] [finally_block]
# Except 陳述式
# ------------
except_block:
| 'except' expression ':' block
| 'except' expression 'as' NAME ':' block
| 'except' expressions ':' block
| 'except' ':' block
except_star_block:
| 'except' '*' expression ':' block
| 'except' '*' expression 'as' NAME ':' block
| 'except' '*' expressions ':' block
finally_block:
| 'finally' ':' block
# Match 陳述式
# -----------
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_pattern:
| signed_number !('+' | '-')
| complex_number
| strings
| 'None'
| 'True'
| 'False'
# 字面值運算式被用於限制允許的對映模式鍵
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 陳述式
# ----------
type_alias:
| "type" NAME [type_params] '=' expression
# Type 參數宣告
# ------------
type_params:
| '[' type_param_seq ']'
type_param_seq: ','.type_param+ [',']
type_param:
| NAME [type_param_bound] [type_param_default]
| '*' NAME [type_param_starred_default]
| '**' NAME [type_param_default]
type_param_bound: ':' expression
type_param_default: '=' expression
type_param_starred_default: '=' star_expression
# 運算式
# -----
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:
| 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: '<=' bitwise_or
lt_bitwise_or: '<' bitwise_or
gte_bitwise_or: '>=' bitwise_or
gt_bitwise_or: '>' 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_or:
| bitwise_or '|' bitwise_xor
| bitwise_xor
bitwise_xor:
| bitwise_xor '^' bitwise_and
| bitwise_and
bitwise_and:
| bitwise_and '&' shift_expr
| shift_expr
shift_expr:
| shift_expr '<<' sum
| shift_expr '>>' sum
| sum
# 算術運算子
# --------
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
# 主要元素
# -------
# 主要元素是像 "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 函式
# ----------
lambdef:
| 'lambda' [lambda_params] ':' expression
lambda_params:
| lambda_parameters
# lambda_parameters 等複製了參數但沒有註釋
# 或型別註解,而且如果參數後面沒有逗號,我們預期會有
# 冒號,而不是右括號。(更多資訊請參見上面的參數部分。)
#
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+ '/' &':'
lambda_slash_with_default:
| lambda_param_no_default* lambda_param_with_default+ '/' ','
| lambda_param_no_default* lambda_param_with_default+ '/' &':'
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 &':'
lambda_param_with_default:
| lambda_param default ','
| lambda_param default &':'
lambda_param_maybe_default:
| lambda_param default? ','
| lambda_param default? &':'
lambda_param: NAME
# 字面值
# =====
fstring_middle:
| fstring_replacement_field
| FSTRING_MIDDLE
fstring_replacement_field:
| '{' annotated_rhs '='? [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
tstring_format_spec_replacement_field:
| '{' annotated_rhs '='? [fstring_conversion] [tstring_full_format_spec] '}'
tstring_format_spec:
| TSTRING_MIDDLE
| tstring_format_spec_replacement_field
tstring_full_format_spec:
| ':' tstring_format_spec*
tstring_replacement_field:
| '{' annotated_rhs '='? [fstring_conversion] [tstring_full_format_spec] '}'
tstring_middle:
| tstring_replacement_field
| TSTRING_MIDDLE
tstring:
| TSTRING_START tstring_middle* TSTRING_END
string: STRING
strings:
| (fstring|string)+
| tstring+
list:
| '[' [star_named_expressions] ']'
tuple:
| '(' [star_named_expression ',' [star_named_expressions] ] ')'
set: '{' star_named_expressions '}'
# 字典
# ----
dict:
| '{' [double_starred_kvpairs] '}'
double_starred_kvpairs: ','.double_starred_kvpair+ [',']
double_starred_kvpair:
| '**' bitwise_or
| kvpair
kvpair: expression ':' expression
# 綜合運算式與產生器
# ---------------------------
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 '}'
# 函式呼叫引數
# ==========
arguments:
| args [','] &')'
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
# 賦值目標
# =======
# 泛用目標
# -------
# 注意:star_targets 可能包含 *bitwise_or,targets 則不可以。
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 &t_lookahead
| t_primary '[' slices ']' &t_lookahead
| t_primary genexp &t_lookahead
| t_primary '(' [arguments] ')' &t_lookahead
| atom &t_lookahead
t_lookahead: '(' | '[' | '.'
# del 陳述式的目標
# --------------
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] ']'
# 型別元素
# -------
# type_expressions 允許 */** 但會忽略他們
type_expressions:
| ','.expression+ ',' '*' expression ',' '**' expression
| ','.expression+ ',' '*' expression
| ','.expression+ ',' '**' expression
| '*' expression ',' '**' expression
| '*' expression
| '**' expression
| ','.expression+
func_type_comment:
| NEWLINE TYPE_COMMENT &(NEWLINE INDENT) # 後面必須接縮排區塊
| TYPE_COMMENT
# ========================= 文法結束 ===========================
# ========================= 無效規則開始 =======================
# 從這裡開始是用於無效語法的規則,具有專門的錯誤訊息
invalid_arguments:
| ((','.(starred_expression | ( assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' ','.(starred_expression !'=')+
| expression for_if_clauses ',' [args | expression for_if_clauses]
| NAME '=' expression for_if_clauses
| (args ',')? NAME '=' &(',' | ')')
| args for_if_clauses
| args ',' expression for_if_clauses
| args ',' args
invalid_kwarg:
| ('True'|'False'|'None') '='
| NAME '=' expression for_if_clauses
| !(NAME '=') expression '='
| '**' expression '=' expression
# 重要:請注意 "_without_invalid" 後綴會導致該規則不呼叫其下的無效規則
expression_without_invalid:
| disjunction 'if' disjunction 'else' expression
| disjunction
| lambdef
invalid_legacy_expression:
| NAME !'(' star_expressions
invalid_type_param:
| '*' NAME ':' expression
| '**' NAME ':' expression
invalid_expression:
| STRING (!STRING expression_without_invalid)+ STRING
# !(NAME STRING) 不匹配所以我們不會去顯示有著像是 kf"dsfsdf" 無效字串前綴的錯誤
# 軟關鍵字也需要被忽略,因為它們可以被剖析為 NAME NAME
| !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid
| disjunction 'if' disjunction !('else'|':')
| disjunction 'if' disjunction 'else' !expression
| (pass_stmt|break_stmt|continue_stmt) 'if' disjunction 'else' simple_stmt
| 'lambda' [lambda_params] ':' &FSTRING_MIDDLE
| 'lambda' [lambda_params] ':' &TSTRING_MIDDLE
invalid_named_expression:
| expression ':=' expression
| NAME '=' bitwise_or !('='|':=')
| !(list|tuple|genexp|'True'|'None'|'False') bitwise_or '=' bitwise_or !('='|':=')
invalid_assignment:
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
a,
"only single target (not %s) can be annotated",
_PyPegen_get_expr_name(a)
)}
| star_named_expression ',' star_named_expressions* ':' expression
| expression ':' expression
| (star_targets '=')* star_expressions '='
| (star_targets '=')* yield_expr '='
| star_expressions augassign annotated_rhs
invalid_ann_assign_target:
| list
| tuple
invalid_del_stmt:
| 'del' star_expressions
invalid_block:
| NEWLINE !INDENT
invalid_comprehension:
| ('[' | '(' | '{') starred_expression for_if_clauses
| ('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses
| ('[' | '{') star_named_expression ',' for_if_clauses
invalid_dict_comprehension:
| '{' '**' bitwise_or for_if_clauses '}'
invalid_parameters:
| "/" ','
| (slash_no_default | slash_with_default) param_maybe_default* '/'
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameter without a default follows parameter with a default") }
| param_no_default* '(' param_no_default+ ','? ')'
| (slash_no_default | slash_with_default)? param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'
| param_maybe_default+ '/' '*'
invalid_default:
| '=' &(')'|',')
invalid_star_etc:
| '*' (')' | ',' (')' | '**'))
| '*' ',' TYPE_COMMENT
| '*' param '='
| '*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')
invalid_kwds:
| '**' param '='
| '**' param ',' param
| '**' param ',' ('*'|'**'|'/')
invalid_parameters_helper: # 這是為了避免型別錯誤而存在的規則
| slash_with_default
| param_with_default+
invalid_lambda_parameters:
| "/" ','
| (lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameter without a default follows parameter with a default") }
| lambda_param_no_default* '(' ','.lambda_param+ ','? ')'
| (lambda_slash_no_default | lambda_slash_with_default)? lambda_param_maybe_default* '*' (',' | lambda_param_no_default) lambda_param_maybe_default* '/'
| lambda_param_maybe_default+ '/' '*'
invalid_lambda_parameters_helper:
| lambda_slash_with_default
| lambda_param_with_default+
invalid_lambda_star_etc:
| '*' (':' | ',' (':' | '**'))
| '*' lambda_param '='
| '*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')
invalid_lambda_kwds:
| '**' lambda_param '='
| '**' lambda_param ',' lambda_param
| '**' lambda_param ',' ('*'|'**'|'/')
invalid_double_type_comments:
| TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT
invalid_with_item:
| expression 'as' expression &(',' | ')' | ':')
invalid_for_if_clause:
| 'async'? 'for' (bitwise_or (',' bitwise_or)* [',']) !'in'
invalid_for_target:
| 'async'? 'for' star_expressions
invalid_group:
| '(' starred_expression ')'
| '(' '**' expression ')'
invalid_import:
| 'import' ','.dotted_name+ 'from' dotted_name
| 'import' NEWLINE
invalid_dotted_as_name:
| dotted_name 'as' !(NAME (',' | ')' | ';' | NEWLINE)) expression
invalid_import_from_as_name:
| NAME 'as' !(NAME (',' | ')' | ';' | NEWLINE)) expression
invalid_import_from_targets:
| import_from_as_names ',' NEWLINE
| NEWLINE
invalid_with_stmt:
| ['async'] 'with' ','.(expression ['as' star_target])+ NEWLINE
| ['async'] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE
invalid_with_stmt_indent:
| ['async'] 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT
| ['async'] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT
invalid_try_stmt:
| 'try' ':' NEWLINE !INDENT
| 'try' ':' block !('except' | 'finally')
| 'try' ':' block* except_block+ 'except' '*' expression ['as' NAME] ':'
| 'try' ':' block* except_star_block+ 'except' [expression ['as' NAME]] ':'
invalid_except_stmt:
| 'except' expression ',' expressions 'as' NAME ':'
| 'except' expression ['as' NAME ] NEWLINE
| 'except' NEWLINE
| 'except' expression 'as' expression ':' block
invalid_except_star_stmt:
| 'except' '*' expression ',' expressions 'as' NAME ':'
| 'except' '*' expression ['as' NAME ] NEWLINE
| 'except' '*' (NEWLINE | ':')
| 'except' '*' expression 'as' expression ':' block
invalid_finally_stmt:
| 'finally' ':' NEWLINE !INDENT
invalid_except_stmt_indent:
| 'except' expression ['as' NAME ] ':' NEWLINE !INDENT
| 'except' ':' NEWLINE !INDENT
invalid_except_star_stmt_indent:
| 'except' '*' expression ['as' NAME ] ':' NEWLINE !INDENT
invalid_match_stmt:
| "match" subject_expr NEWLINE
| "match" subject_expr ':' NEWLINE !INDENT
invalid_case_block:
| "case" patterns guard? NEWLINE
| "case" patterns guard? ':' NEWLINE !INDENT
invalid_as_pattern:
| or_pattern 'as' "_"
| or_pattern 'as' expression
invalid_class_pattern:
PyPegen_first_item(a, pattern_ty),
PyPegen_last_item(a, pattern_ty),
"positional patterns follow keyword patterns") }
invalid_class_argument_pattern:
| [positional_patterns ','] keyword_patterns ',' positional_patterns
invalid_if_stmt:
| 'if' named_expression NEWLINE
| 'if' named_expression ':' NEWLINE !INDENT
invalid_elif_stmt:
| 'elif' named_expression NEWLINE
| 'elif' named_expression ':' NEWLINE !INDENT
invalid_else_stmt:
| 'else' ':' NEWLINE !INDENT
| 'else' ':' block 'elif'
invalid_while_stmt:
| 'while' named_expression NEWLINE
| 'while' named_expression ':' NEWLINE !INDENT
invalid_for_stmt:
| ['async'] 'for' star_targets 'in' star_expressions NEWLINE
| ['async'] 'for' star_targets 'in' star_expressions ':' NEWLINE !INDENT
invalid_def_raw:
| ['async'] 'def' NAME [type_params] '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT
| ['async'] 'def' NAME [type_params] '(' [params] ')' ['->' expression] ':' [func_type_comment] block
invalid_class_def_raw:
| 'class' NAME [type_params] ['(' [arguments] ')'] NEWLINE
| 'class' NAME [type_params] ['(' [arguments] ')'] ':' NEWLINE !INDENT
invalid_double_starred_kvpairs:
| expression ':' '*' bitwise_or
| expression ':' &('}'|',')
invalid_kvpair:
| expression !(':')
| expression ':' '*' bitwise_or
| expression ':' &('}'|',')
invalid_starred_expression_unpacking:
| '*' expression '=' expression
invalid_starred_expression:
| '*'
invalid_fstring_replacement_field:
| '{' '='
| '{' '!'
| '{' ':'
| '{' '}' '") }
| '
| '{' annotated_rhs !('=' | '!' | ':' | '}') '") }
| '') '") }
| '') '") }
| '' ', or format specs") }
| '{' annotated_rhs '='? ['!' NAME] !'}' '") }
invalid_fstring_conversion_character:
| '!' &(':' | '}')
| '!' !NAME
invalid_tstring_replacement_field:
| '{' '='
| '{' '!'
| '{' ':'
| '{' '}' '") }
| '
| '{' annotated_rhs !('=' | '!' | ':' | '}') '") }
| '') '") }
| '') '") }
| '' ', or format specs") }
| '{' annotated_rhs '='? ['!' NAME] !'}' '") }
invalid_tstring_conversion_character:
| '!' &(':' | '}')
| '!' !NAME
invalid_string_tstring_concat:
| (fstring|string)+ tstring
| tstring+ (fstring|string)
invalid_arithmetic:
| sum ('+'|'-'|'*'|'/'|'%'|'//'|'@') 'not' inversion
invalid_factor:
| ('+' | '-' | '~') 'not' factor
invalid_type_params:
| '[' ']'