diff options
author | Brandt Bucher <brandtbucher@gmail.com> | 2021-02-26 22:51:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-26 22:51:55 (GMT) |
commit | 145bf269df3530176f6ebeab1324890ef7070bf8 (patch) | |
tree | 4c4928d6250785372171a52be0b7269aa444511b /Grammar | |
parent | cc02b4f2e810ab524d845daa18bc94df5b092dd8 (diff) | |
download | cpython-145bf269df3530176f6ebeab1324890ef7070bf8.zip cpython-145bf269df3530176f6ebeab1324890ef7070bf8.tar.gz cpython-145bf269df3530176f6ebeab1324890ef7070bf8.tar.bz2 |
bpo-42128: Structural Pattern Matching (PEP 634) (GH-22917)
Co-authored-by: Guido van Rossum <guido@python.org>
Co-authored-by: Talin <viridia@gmail.com>
Co-authored-by: Pablo Galindo <pablogsal@gmail.com>
Diffstat (limited to 'Grammar')
-rw-r--r-- | Grammar/python.gram | 111 |
1 files changed, 110 insertions, 1 deletions
diff --git a/Grammar/python.gram b/Grammar/python.gram index bb70bbb..a225664 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -85,6 +85,7 @@ compound_stmt[stmt_ty]: | &('for' | ASYNC) for_stmt | &'try' try_stmt | &'while' while_stmt + | match_stmt # NOTE: annotated_rhs may start with 'yield'; yield_expr must start with 'yield' assignment[stmt_ty]: @@ -207,6 +208,114 @@ except_block[excepthandler_ty]: | invalid_except_block finally_block[asdl_stmt_seq*]: 'finally' ':' a=block { a } +match_stmt[stmt_ty]: + | "match" subject=subject_expr ':' NEWLINE INDENT cases[asdl_match_case_seq*]=case_block+ DEDENT { + CHECK_VERSION(stmt_ty, 10, "Pattern matching is", _Py_Match(subject, cases, EXTRA)) } +subject_expr[expr_ty]: + | value=star_named_expression ',' values=star_named_expressions? { + _Py_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, value, values)), Load, EXTRA) } + | named_expression +case_block[match_case_ty]: + | "case" pattern=patterns guard=guard? ':' body=block { + _Py_match_case(pattern, guard, body, p->arena) } +guard[expr_ty]: 'if' guard=named_expression { guard } + +patterns[expr_ty]: + | values[asdl_expr_seq*]=open_sequence_pattern { + _Py_Tuple(values, Load, EXTRA) } + | pattern +pattern[expr_ty]: + | as_pattern + | or_pattern +as_pattern[expr_ty]: + | pattern=or_pattern 'as' target=capture_pattern { + _Py_MatchAs(pattern, target->v.Name.id, EXTRA) } +or_pattern[expr_ty]: + | patterns[asdl_expr_seq*]='|'.closed_pattern+ { + asdl_seq_LEN(patterns) == 1 ? asdl_seq_GET(patterns, 0) : _Py_MatchOr(patterns, EXTRA) } +closed_pattern[expr_ty]: + | literal_pattern + | capture_pattern + | wildcard_pattern + | value_pattern + | group_pattern + | sequence_pattern + | mapping_pattern + | class_pattern + +literal_pattern[expr_ty]: + | signed_number !('+' | '-') + | real=signed_number '+' imag=NUMBER { _Py_BinOp(real, Add, imag, EXTRA) } + | real=signed_number '-' imag=NUMBER { _Py_BinOp(real, Sub, imag, EXTRA) } + | strings + | 'None' { _Py_Constant(Py_None, NULL, EXTRA) } + | 'True' { _Py_Constant(Py_True, NULL, EXTRA) } + | 'False' { _Py_Constant(Py_False, NULL, EXTRA) } +signed_number[expr_ty]: + | NUMBER + | '-' number=NUMBER { _Py_UnaryOp(USub, number, EXTRA) } + +capture_pattern[expr_ty]: + | !"_" name=NAME !('.' | '(' | '=') { + _PyPegen_set_expr_context(p, name, Store) } + +wildcard_pattern[expr_ty]: + | "_" { _Py_Name(CHECK(PyObject*, _PyPegen_new_identifier(p, "_")), Store, EXTRA) } + +value_pattern[expr_ty]: + | attr=attr !('.' | '(' | '=') { attr } +attr[expr_ty]: + | value=name_or_attr '.' attr=NAME { + _Py_Attribute(value, attr->v.Name.id, Load, EXTRA) } +name_or_attr[expr_ty]: + | attr + | NAME + +group_pattern[expr_ty]: + | '(' pattern=pattern ')' { pattern } + +sequence_pattern[expr_ty]: + | '[' values=maybe_sequence_pattern? ']' { _Py_List(values, Load, EXTRA) } + | '(' values=open_sequence_pattern? ')' { _Py_Tuple(values, Load, EXTRA) } +open_sequence_pattern[asdl_seq*]: + | value=maybe_star_pattern ',' values=maybe_sequence_pattern? { + _PyPegen_seq_insert_in_front(p, value, values) } +maybe_sequence_pattern[asdl_seq*]: + | values=','.maybe_star_pattern+ ','? { values } +maybe_star_pattern[expr_ty]: + | star_pattern + | pattern +star_pattern[expr_ty]: + | '*' value=(capture_pattern | wildcard_pattern) { + _Py_Starred(value, Store, EXTRA) } + +mapping_pattern[expr_ty]: + | '{' items=items_pattern? '}' { + _Py_Dict(CHECK(asdl_expr_seq*, _PyPegen_get_keys(p, items)), CHECK(asdl_expr_seq*, _PyPegen_get_values(p, items)), EXTRA) } +items_pattern[asdl_seq*]: + | items=','.key_value_pattern+ ','? { items } +key_value_pattern[KeyValuePair*]: + | key=(literal_pattern | value_pattern) ':' value=pattern { + _PyPegen_key_value_pair(p, key, value) } + | double_star_pattern +double_star_pattern[KeyValuePair*]: + | '**' value=capture_pattern { _PyPegen_key_value_pair(p, NULL, value) } + +class_pattern[expr_ty]: + | func=name_or_attr '(' ')' { _Py_Call(func, NULL, NULL, EXTRA) } + | func=name_or_attr '(' args=positional_patterns ','? ')' { + _Py_Call(func, args, NULL, EXTRA) } + | func=name_or_attr '(' keywords=keyword_patterns ','? ')' { + _Py_Call(func, NULL, keywords, EXTRA) } + | func=name_or_attr '(' args=positional_patterns ',' keywords=keyword_patterns ','? ')' { + _Py_Call(func, args, keywords, EXTRA) } +positional_patterns[asdl_expr_seq*]: + | args[asdl_expr_seq*]=','.pattern+ { args } +keyword_patterns[asdl_keyword_seq*]: + | keywords[asdl_keyword_seq*]=','.keyword_pattern+ { keywords } +keyword_pattern[keyword_ty]: + | arg=NAME '=' value=pattern { _Py_keyword(arg->v.Name.id, value, EXTRA) } + return_stmt[stmt_ty]: | 'return' a=[star_expressions] { _Py_Return(a, EXTRA) } @@ -676,7 +785,7 @@ invalid_assignment: RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) } | (star_targets '=')* a=yield_expr '=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "assignment to yield expression not possible") } | a=star_expressions augassign (yield_expr | star_expressions) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + RAISE_SYNTAX_ERROR_KNOWN_LOCATION( a, "'%s' is an illegal expression for augmented assignment", _PyPegen_get_expr_name(a) |