bpo-42128: Structural Pattern Matching (PEP 634) (GH-22917) · devdanzin/cpython@145bf26 · GitHub
Skip to content

Commit 145bf26

Browse files
brandtbuchergvanrossumviridiapablogsal
authored
bpo-42128: Structural Pattern Matching (PEP 634) (pythonGH-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>
1 parent cc02b4f commit 145bf26

43 files changed

Lines changed: 16242 additions & 7982 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Doc/library/dis.rst

Lines changed: 56 additions & 0 deletions

Doc/tools/susp-ignored.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,4 @@ whatsnew/changelog,,::,default::DeprecationWarning
365365
library/importlib.metadata,,:main,"EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts')"
366366
library/importlib.metadata,,`,loading the metadata for packages for the indicated ``context``.
367367
library/re,,`,"`"
368+
library/dis,,:TOS1,TOS[x:TOS1 - 1 - y]

Grammar/python.gram

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ compound_stmt[stmt_ty]:
8585
| &('for' | ASYNC) for_stmt
8686
| &'try' try_stmt
8787
| &'while' while_stmt
88+
| match_stmt
8889

8990
# NOTE: annotated_rhs may start with 'yield'; yield_expr must start with 'yield'
9091
assignment[stmt_ty]:
@@ -207,6 +208,114 @@ except_block[excepthandler_ty]:
207208
| invalid_except_block
208209
finally_block[asdl_stmt_seq*]: 'finally' ':' a=block { a }
209210

211+
match_stmt[stmt_ty]:
212+
| "match" subject=subject_expr ':' NEWLINE INDENT cases[asdl_match_case_seq*]=case_block+ DEDENT {
213+
CHECK_VERSION(stmt_ty, 10, "Pattern matching is", _Py_Match(subject, cases, EXTRA)) }
214+
subject_expr[expr_ty]:
215+
| value=star_named_expression ',' values=star_named_expressions? {
216+
_Py_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, value, values)), Load, EXTRA) }
217+
| named_expression
218+
case_block[match_case_ty]:
219+
| "case" pattern=patterns guard=guard? ':' body=block {
220+
_Py_match_case(pattern, guard, body, p->arena) }
221+
guard[expr_ty]: 'if' guard=named_expression { guard }
222+
223+
patterns[expr_ty]:
224+
| values[asdl_expr_seq*]=open_sequence_pattern {
225+
_Py_Tuple(values, Load, EXTRA) }
226+
| pattern
227+
pattern[expr_ty]:
228+
| as_pattern
229+
| or_pattern
230+
as_pattern[expr_ty]:
231+
| pattern=or_pattern 'as' target=capture_pattern {
232+
_Py_MatchAs(pattern, target->v.Name.id, EXTRA) }
233+
or_pattern[expr_ty]:
234+
| patterns[asdl_expr_seq*]='|'.closed_pattern+ {
235+
asdl_seq_LEN(patterns) == 1 ? asdl_seq_GET(patterns, 0) : _Py_MatchOr(patterns, EXTRA) }
236+
closed_pattern[expr_ty]:
237+
| literal_pattern
238+
| capture_pattern
239+
| wildcard_pattern
240+
| value_pattern
241+
| group_pattern
242+
| sequence_pattern
243+
| mapping_pattern
244+
| class_pattern
245+
246+
literal_pattern[expr_ty]:
247+
| signed_number !('+' | '-')
248+
| real=signed_number '+' imag=NUMBER { _Py_BinOp(real, Add, imag, EXTRA) }
249+
| real=signed_number '-' imag=NUMBER { _Py_BinOp(real, Sub, imag, EXTRA) }
250+
| strings
251+
| 'None' { _Py_Constant(Py_None, NULL, EXTRA) }
252+
| 'True' { _Py_Constant(Py_True, NULL, EXTRA) }
253+
| 'False' { _Py_Constant(Py_False, NULL, EXTRA) }
254+
signed_number[expr_ty]:
255+
| NUMBER
256+
| '-' number=NUMBER { _Py_UnaryOp(USub, number, EXTRA) }
257+
258+
capture_pattern[expr_ty]:
259+
| !"_" name=NAME !('.' | '(' | '=') {
260+
_PyPegen_set_expr_context(p, name, Store) }
261+
262+
wildcard_pattern[expr_ty]:
263+
| "_" { _Py_Name(CHECK(PyObject*, _PyPegen_new_identifier(p, "_")), Store, EXTRA) }
264+
265+
value_pattern[expr_ty]:
266+
| attr=attr !('.' | '(' | '=') { attr }
267+
attr[expr_ty]:
268+
| value=name_or_attr '.' attr=NAME {
269+
_Py_Attribute(value, attr->v.Name.id, Load, EXTRA) }
270+
name_or_attr[expr_ty]:
271+
| attr
272+
| NAME
273+
274+
group_pattern[expr_ty]:
275+
| '(' pattern=pattern ')' { pattern }
276+
277+
sequence_pattern[expr_ty]:
278+
| '[' values=maybe_sequence_pattern? ']' { _Py_List(values, Load, EXTRA) }
279+
| '(' values=open_sequence_pattern? ')' { _Py_Tuple(values, Load, EXTRA) }
280+
open_sequence_pattern[asdl_seq*]:
281+
| value=maybe_star_pattern ',' values=maybe_sequence_pattern? {
282+
_PyPegen_seq_insert_in_front(p, value, values) }
283+
maybe_sequence_pattern[asdl_seq*]:
284+
| values=','.maybe_star_pattern+ ','? { values }
285+
maybe_star_pattern[expr_ty]:
286+
| star_pattern
287+
| pattern
288+
star_pattern[expr_ty]:
289+
| '*' value=(capture_pattern | wildcard_pattern) {
290+
_Py_Starred(value, Store, EXTRA) }
291+
292+
mapping_pattern[expr_ty]:
293+
| '{' items=items_pattern? '}' {
294+
_Py_Dict(CHECK(asdl_expr_seq*, _PyPegen_get_keys(p, items)), CHECK(asdl_expr_seq*, _PyPegen_get_values(p, items)), EXTRA) }
295+
items_pattern[asdl_seq*]:
296+
| items=','.key_value_pattern+ ','? { items }
297+
key_value_pattern[KeyValuePair*]:
298+
| key=(literal_pattern | value_pattern) ':' value=pattern {
299+
_PyPegen_key_value_pair(p, key, value) }
300+
| double_star_pattern
301+
double_star_pattern[KeyValuePair*]:
302+
| '**' value=capture_pattern { _PyPegen_key_value_pair(p, NULL, value) }
303+
304+
class_pattern[expr_ty]:
305+
| func=name_or_attr '(' ')' { _Py_Call(func, NULL, NULL, EXTRA) }
306+
| func=name_or_attr '(' args=positional_patterns ','? ')' {
307+
_Py_Call(func, args, NULL, EXTRA) }
308+
| func=name_or_attr '(' keywords=keyword_patterns ','? ')' {
309+
_Py_Call(func, NULL, keywords, EXTRA) }
310+
| func=name_or_attr '(' args=positional_patterns ',' keywords=keyword_patterns ','? ')' {
311+
_Py_Call(func, args, keywords, EXTRA) }
312+
positional_patterns[asdl_expr_seq*]:
313+
| args[asdl_expr_seq*]=','.pattern+ { args }
314+
keyword_patterns[asdl_keyword_seq*]:
315+
| keywords[asdl_keyword_seq*]=','.keyword_pattern+ { keywords }
316+
keyword_pattern[keyword_ty]:
317+
| arg=NAME '=' value=pattern { _Py_keyword(arg->v.Name.id, value, EXTRA) }
318+
210319
return_stmt[stmt_ty]:
211320
| 'return' a=[star_expressions] { _Py_Return(a, EXTRA) }
212321

@@ -676,7 +785,7 @@ invalid_assignment:
676785
RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) }
677786
| (star_targets '=')* a=yield_expr '=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "assignment to yield expression not possible") }
678787
| a=star_expressions augassign (yield_expr | star_expressions) {
679-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
788+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
680789
a,
681790
"'%s' is an illegal expression for augmented assignment",
682791
_PyPegen_get_expr_name(a)

Include/Python-ast.h

Lines changed: 50 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_ast.h

Lines changed: 10 additions & 0 deletions

0 commit comments

Comments
 (0)