Python

10. 전체 문법 규격

이것은 CPython 구문 분석기를 생성하는 데 사용되는 문법에서 직접 파생된, 전체 파이썬 문법 규칙입니다 (Grammar/python.gram을 참조하십시오). 이 버전은 코드 생성과 에러 복구와 관련된 세부 정보를 생략합니다.

여기서 사용된 표기법은 이전 문서를 따르며, notation\에서 설명합니다. 다만, 추가적인 복잡성이 있습니다:

  • ~ (“cut”): 현재 대안에 커밋합니다. 대안이 구문 분석에 실패하면 규칙에 실패합니다.

    Python은 주로 최적화나 향상된 오류 메시지를 위해 컷(cuts)을 사용합니다. 목록 아래에서는 종종 쓸모없어 보일 수 있습니다.

    현재 컷은 괄호, 대괄호, 전방 탐색 등 내부에서 나타나지 않습니다. 이러한 컨텍스트에서의 동작은 의도적으로 명시되지 않았습니다.

# Python용 PEG 문법



# ========================= 문법 시작 =========================

# 일반적인 문법 요소 및 규칙:
#
# * 큰따옴표(") 문자열은 SOFT KEYWORDS를 나타냅니다.
# * 작은따옴표(') 문자열은 KEYWORDS를 나타냅니다.
# * 대문자 이름(NAME)은 Grammar/Tokens 파일의 토큰을 나타냅니다.
# * "invalid_"로 시작하는 규칙 이름은 특수한 구문 오류에 사용됩니다.
#     - 이 규칙들은 파서의 첫 번째 패스에서는 사용되지 않습니다.
#     - 첫 번째 패스에서 파싱에 실패한 경우에만, invalid 규칙을 포함한 두 번째 패스가 실행됩니다.
#     - 두 번째 단계에서 파서가 일반적인 구문 오류로 실패하면, 첫 번째 패스의 일반적인 실패 위치가 사용됩니다 (이는 invalid 규칙으로 인해 잘못된 위치가 보고되는 것을 방지합니다).
#     - 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 ] 또는 e?
#   선택적으로 e와 매칭합니다.
# e*
#   e가 0번 이상 나타나는 것과 매칭합니다.
# e+
#   e가 1번 이상 나타나는 것과 매칭합니다.
# s.e+
#   s로 구분된 e가 1번 이상 나타나는 것과 매칭합니다. 생성된 파스 트리는 구분자를 포함하지 않습니다. 그 외에는 (e (s e)*)와 동일합니다.
# &e
#   입력을 소비하지 않고, e를 파싱할 수 있으면 성공합니다.
# !e
#   입력을 소비하지 않고, e를 파싱할 수 있으면 실패합니다.
# ~
#   파싱에 실패하더라도 현재 선택지를 확정(commit)합니다.
# &&e
#   e를 즉시(eager) 파싱합니다. 파서는 백트래킹하지 않으며, e를 파싱할 수 없으면 즉시 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  # 속도 향상을 위해 필요하지 않음
    | ';'.simple_stmt+ [';'] NEWLINE 

# 참고: 할당(assignment)은 반드시 식(expression)보다 앞에 와야 합니다. 그렇지 않으면 간단한 할당을 파싱할 때 SyntaxError가 발생합니다.
simple_stmt:
    | assignment
    | type_alias
    | import_stmt
    | star_expressions 
    | return_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' 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:
    | "lazy"? 'import' dotted_as_names 

# 아래 참고: '...'이 ELLIPSIS로 토큰화되기 때문에 ('.' | '...')가 필요합니다.
import_from:
    | "lazy"? 'from' ('.' | '...')* dotted_name 'import' import_from_targets 
    | "lazy"? '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

# 리터럴 패턴은 동등성(equality) 및 정체성(identity) 제약 조건에 사용됩니다.
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 
    | '-' NUMBER 

signed_real_number:
    | real_number
    | '+' real_number 
    | '-' real_number 

real_number:
    | NUMBER 

imaginary_number:
    | 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] [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)
# -----------

expressions:
    | expression (',' expression )+ [','] 
    | expression ',' 
    | expression

expression:
    | if_expression
    | disjunction
    | lambdef

if_expression:
    | disjunction 'if' disjunction 'else' expression 

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_expressions_sequence: ','.star_named_expression_sequence+ [','] 

star_named_expression:
    | '*' bitwise_or 
    | named_expression

star_named_expression_sequence:
    | star_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: '<=' 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 operators)
# ---------------

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

# 산술 연산자 (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)는 "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
    | (genexp | tuple | group)
    | (listcomp | list)
    | (dictcomp | setcomp | dict | set)
    | '...' 

group:
    | '(' (yield_expr | named_expression) ')' 

# 람다 함수 (Lambda functions)
# ---------------

lambdef:
    | 'lambda' [lambda_params] ':' expression 

lambda_params:
    | lambda_parameters

# lambda_parameters 등은 매개변수를 복제하지만 주석이나
# 타입 코멘트가 없으며, 매개변수 뒤에 쉼표가 없는 경우
# 닫는 괄호가 아닌 콜론을 기대합니다. (자세한 내용은 위의 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 

# 리터럴 (LITERALS)
# ========

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_sequence] ']' 

tuple:
    | '(' [star_named_expression_sequence ',' [star_named_expressions_sequence]  ] ')' 

set: '{' star_named_expressions_sequence '}' 

# 딕셔너리 (Dicts)
# -----

dict:
    | '{' [double_starred_kvpairs] '}' 

double_starred_kvpairs: ','.double_starred_kvpair+ [','] 

double_starred_kvpair:
    | '**' bitwise_or 
    | kvpair

kvpair: expression ':' expression 

# 컴프리헨션 및 제너레이터 (Comprehensions & 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:
    | '[' star_named_expression for_if_clauses ']' 

setcomp:
    | '{' star_named_expression for_if_clauses '}' 

genexp:
    | '(' ( assignment_expression | expression !':=' | starred_expression ) for_if_clauses ')' 

dictcomp:
    | '{' kvpair for_if_clauses '}' 
    | '{' '**' expression for_if_clauses '}' 

# 함수 호출 인자 (FUNCTION CALL ARGUMENTS)
# ========

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 

# 할당 대상 (ASSIGNMENT TARGETS)
# ========

# 일반적인 대상 (Generic targets)
# ---------------

# 참고: 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 문을 위한 대상 (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는 */**를 허용하지만 무시합니다
type_expressions:
    | ','.expression+ ',' '*' expression ',' '**' expression 
    | ','.expression+ ',' '*' expression 
    | ','.expression+ ',' '**' expression 
    | '*' expression ',' '**' expression 
    | '*' expression 
    | '**' expression 
    | ','.expression+ 

func_type_comment:
    | NEWLINE TYPE_COMMENT &(NEWLINE INDENT)   # 반드시 들여쓰기된 블록이 뒤따라야 함
    | TYPE_COMMENT

# ========================= END OF THE GRAMMAR ===========================



# ========================= START OF INVALID RULES =======================

# 여기서부터는 특수한 에러 메시지가 있는 잘못된 구문에 대한 규칙들입니다
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_if_expression:
   | disjunction 'if' disjunction 'else' '*' 
   | disjunction 'if' disjunction 'else' '**' 

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_raise_stmt:
    | 'raise' 'from' 
    | 'raise' expression 'from' 
invalid_del_stmt:
    | 'del' star_expressions 
invalid_assert_stmt:
    | 'assert' expression '=' expression 
    | 'assert' expression ',' expression '=' expression 
    | 'assert' expression ':=' expression 
    | 'assert' expression ',' expression ':=' expression 
invalid_block:
    | NEWLINE !INDENT 
invalid_comprehension:
    | '[' '**' expression for_if_clauses 
    | '(' '**' expression for_if_clauses 
    | ('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses 
    | ('[' | '{') star_named_expression ',' 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])+ ',' ':' 
    | ['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 
    | "case" patterns guard? ':' block 
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_mapping_pattern:
    | '{' (items_pattern ',')? double_star_pattern ',' items_pattern ','? '}' 
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 ':' &('}'|',') 
invalid_kvpair_unpacking:
    | '**' if_expression 
    | '*' bitwise_or ':' expression 
    | '**' bitwise_or ':' expression 
    | expression ':' '*' bitwise_or 
    | expression ':' '**' bitwise_or 
invalid_kvpair:
    | expression !(':') 
    | expression ':' '*' bitwise_or 
    | expression ':' '**' bitwise_or 
    | expression ':' &('}'|',') 
invalid_starred_expression_unpacking:
    | '*' if_expression 
    | '*' expression '=' expression 
invalid_starred_expression_unpacking_sequence:
    | '**' bitwise_or 
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:
    | '[' ']' 

분실물 보관소