]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-138716: Fix `assert a := b` syntax error message (#138718)
authorsobolevn <mail@sobolevn.me>
Wed, 10 Sep 2025 13:05:16 +0000 (16:05 +0300)
committerGitHub <noreply@github.com>
Wed, 10 Sep 2025 13:05:16 +0000 (16:05 +0300)
Grammar/python.gram
Lib/test/test_syntax.py
Misc/NEWS.d/next/Core_and_Builtins/2025-09-09-23-59-13.gh-issue-138716.UawDY0.rst [new file with mode: 0644]
Parser/parser.c

index 0d2e5940e4394316c20d4239adfb1473e48b00db..b9ecd2273a5cae52bc85090b534ee0a4e0089316 100644 (file)
@@ -1315,6 +1315,14 @@ invalid_assert_stmt:
             a, b,
             "cannot assign to %s here. Maybe you meant '==' instead of '='?",
             _PyPegen_get_expr_name(a)) }
+    | 'assert' a=expression ':=' b=expression {
+        RAISE_SYNTAX_ERROR_KNOWN_RANGE(
+            a, b,
+            "cannot use named expression without parentheses here") }
+    | 'assert' expression ',' a=expression ':=' b=expression {
+        RAISE_SYNTAX_ERROR_KNOWN_RANGE(
+            a, b,
+            "cannot use named expression without parentheses here") }
 invalid_block:
     | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
 invalid_comprehension:
index 52395cd64c186a61e0c304b7f1b7668c9a90ba44..e334f48179ec8448547b0a92ccffa3b06dcf34a9 100644 (file)
@@ -2690,10 +2690,15 @@ Invalid expressions in type scopes:
 Asserts:
 
     >>> assert (a := 1)  # ok
-    >>> # TODO(@sobolevn): improve this message in the next PR
+    >>> assert 1, (a := 1)  # ok
+
     >>> assert a := 1
     Traceback (most recent call last):
-    SyntaxError: invalid syntax
+    SyntaxError: cannot use named expression without parentheses here
+
+    >>> assert 1, a := 1
+    Traceback (most recent call last):
+    SyntaxError: cannot use named expression without parentheses here
 
     >>> assert 1 = 2 = 3
     Traceback (most recent call last):
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-09-23-59-13.gh-issue-138716.UawDY0.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-09-23-59-13.gh-issue-138716.UawDY0.rst
new file mode 100644 (file)
index 0000000..72b4603
--- /dev/null
@@ -0,0 +1,2 @@
+Improve :exc:`SyntaxError` message for :keyword:`assert` in cases like
+``assert a := b``.
index bc80cfbd54210977190bba27dd2fbd51dcb1b999..8242c4dfabba35cd879ab75309dc4f5c2a9875f6 100644 (file)
@@ -21,28 +21,28 @@ static KeywordToken *reserved_keywords[] = {
     (KeywordToken[]) {{NULL, -1}},
     (KeywordToken[]) {{NULL, -1}},
     (KeywordToken[]) {
-        {"if", 689},
-        {"as", 687},
-        {"in", 702},
+        {"if", 691},
+        {"as", 689},
+        {"in", 704},
         {"or", 589},
         {"is", 597},
         {NULL, -1},
     },
     (KeywordToken[]) {
         {"del", 630},
-        {"def", 706},
-        {"for", 701},
-        {"try", 663},
+        {"def", 708},
+        {"for", 703},
+        {"try", 665},
         {"and", 590},
-        {"not", 710},
+        {"not", 712},
         {NULL, -1},
     },
     (KeywordToken[]) {
-        {"from", 640},
+        {"from", 642},
         {"pass", 527},
-        {"with", 654},
-        {"elif", 694},
-        {"else", 693},
+        {"with", 656},
+        {"elif", 696},
+        {"else", 695},
         {"None", 624},
         {"True", 623},
         {NULL, -1},
@@ -51,24 +51,24 @@ static KeywordToken *reserved_keywords[] = {
         {"raise", 628},
         {"yield", 588},
         {"break", 528},
-        {"async", 705},
-        {"class", 708},
-        {"while", 696},
+        {"async", 707},
+        {"class", 710},
+        {"while", 698},
         {"False", 625},
         {"await", 598},
         {NULL, -1},
     },
     (KeywordToken[]) {
         {"return", 522},
-        {"import", 641},
-        {"assert", 632},
+        {"import", 643},
+        {"assert", 634},
         {"global", 530},
-        {"except", 684},
+        {"except", 686},
         {"lambda", 622},
         {NULL, -1},
     },
     (KeywordToken[]) {
-        {"finally", 680},
+        {"finally", 682},
         {NULL, -1},
     },
     (KeywordToken[]) {
@@ -1788,7 +1788,7 @@ simple_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'assert' assert_stmt"));
         stmt_ty assert_stmt_var;
         if (
-            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 632)  // token='assert'
+            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 634)  // token='assert'
             &&
             (assert_stmt_var = assert_stmt_rule(p))  // assert_stmt
         )
@@ -1942,7 +1942,7 @@ compound_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'if' if_stmt"));
         stmt_ty if_stmt_var;
         if (
-            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 689)  // token='if'
+            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 691)  // token='if'
             &&
             (if_stmt_var = if_stmt_rule(p))  // if_stmt
         )
@@ -2026,7 +2026,7 @@ compound_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'try' try_stmt"));
         stmt_ty try_stmt_var;
         if (
-            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 663)  // token='try'
+            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 665)  // token='try'
             &&
             (try_stmt_var = try_stmt_rule(p))  // try_stmt
         )
@@ -2047,7 +2047,7 @@ compound_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'while' while_stmt"));
         stmt_ty while_stmt_var;
         if (
-            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 696)  // token='while'
+            _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 698)  // token='while'
             &&
             (while_stmt_var = while_stmt_rule(p))  // while_stmt
         )
@@ -2814,7 +2814,7 @@ raise_stmt_rule(Parser *p)
             &&
             (a = expression_rule(p))  // expression
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 640))  // token='from'
+            (_keyword_1 = _PyPegen_expect_token(p, 642))  // token='from'
             &&
             (b = expression_rule(p))  // expression
         )
@@ -3443,7 +3443,7 @@ assert_stmt_rule(Parser *p)
         expr_ty a;
         void *b;
         if (
-            (_keyword = _PyPegen_expect_token(p, 632))  // token='assert'
+            (_keyword = _PyPegen_expect_token(p, 634))  // token='assert'
             &&
             (a = expression_rule(p))  // expression
             &&
@@ -3585,7 +3585,7 @@ import_name_rule(Parser *p)
         Token * _keyword;
         asdl_alias_seq* a;
         if (
-            (_keyword = _PyPegen_expect_token(p, 641))  // token='import'
+            (_keyword = _PyPegen_expect_token(p, 643))  // token='import'
             &&
             (a = dotted_as_names_rule(p))  // dotted_as_names
         )
@@ -3654,13 +3654,13 @@ import_from_rule(Parser *p)
         expr_ty b;
         asdl_alias_seq* c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 640))  // token='from'
+            (_keyword = _PyPegen_expect_token(p, 642))  // token='from'
             &&
             (a = _loop0_17_rule(p))  // (('.' | '...'))*
             &&
             (b = dotted_name_rule(p))  // dotted_name
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 641))  // token='import'
+            (_keyword_1 = _PyPegen_expect_token(p, 643))  // token='import'
             &&
             (c = import_from_targets_rule(p))  // import_from_targets
         )
@@ -3698,11 +3698,11 @@ import_from_rule(Parser *p)
         asdl_seq * a;
         asdl_alias_seq* b;
         if (
-            (_keyword = _PyPegen_expect_token(p, 640))  // token='from'
+            (_keyword = _PyPegen_expect_token(p, 642))  // token='from'
             &&
             (a = _loop1_18_rule(p))  // (('.' | '...'))+
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 641))  // token='import'
+            (_keyword_1 = _PyPegen_expect_token(p, 643))  // token='import'
             &&
             (b = import_from_targets_rule(p))  // import_from_targets
         )
@@ -4489,7 +4489,7 @@ class_def_raw_rule(Parser *p)
         asdl_stmt_seq* c;
         void *t;
         if (
-            (_keyword = _PyPegen_expect_token(p, 708))  // token='class'
+            (_keyword = _PyPegen_expect_token(p, 710))  // token='class'
             &&
             (a = _PyPegen_name_token(p))  // NAME
             &&
@@ -4656,7 +4656,7 @@ function_def_raw_rule(Parser *p)
         void *t;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 706))  // token='def'
+            (_keyword = _PyPegen_expect_token(p, 708))  // token='def'
             &&
             (n = _PyPegen_name_token(p))  // NAME
             &&
@@ -4717,9 +4717,9 @@ function_def_raw_rule(Parser *p)
         void *t;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 706))  // token='def'
+            (_keyword_1 = _PyPegen_expect_token(p, 708))  // token='def'
             &&
             (n = _PyPegen_name_token(p))  // NAME
             &&
@@ -6057,7 +6057,7 @@ if_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         stmt_ty c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (a = named_expression_rule(p))  // named_expression
             &&
@@ -6102,7 +6102,7 @@ if_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         void *c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (a = named_expression_rule(p))  // named_expression
             &&
@@ -6197,7 +6197,7 @@ elif_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         stmt_ty c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 694))  // token='elif'
+            (_keyword = _PyPegen_expect_token(p, 696))  // token='elif'
             &&
             (a = named_expression_rule(p))  // named_expression
             &&
@@ -6242,7 +6242,7 @@ elif_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         void *c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 694))  // token='elif'
+            (_keyword = _PyPegen_expect_token(p, 696))  // token='elif'
             &&
             (a = named_expression_rule(p))  // named_expression
             &&
@@ -6323,7 +6323,7 @@ else_block_rule(Parser *p)
         Token * _literal;
         asdl_stmt_seq* b;
         if (
-            (_keyword = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             (_literal = _PyPegen_expect_forced_token(p, 11, ":"))  // forced_token=':'
             &&
@@ -6402,7 +6402,7 @@ while_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         void *c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 696))  // token='while'
+            (_keyword = _PyPegen_expect_token(p, 698))  // token='while'
             &&
             (a = named_expression_rule(p))  // named_expression
             &&
@@ -6502,11 +6502,11 @@ for_stmt_rule(Parser *p)
         expr_ty t;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (t = star_targets_rule(p))  // star_targets
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword_1 = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (_cut_var = 1)
             &&
@@ -6564,13 +6564,13 @@ for_stmt_rule(Parser *p)
         expr_ty t;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword_1 = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (t = star_targets_rule(p))  // star_targets
             &&
-            (_keyword_2 = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword_2 = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (_cut_var = 1)
             &&
@@ -6699,7 +6699,7 @@ with_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (_literal = _PyPegen_expect_token(p, 7))  // token='('
             &&
@@ -6750,7 +6750,7 @@ with_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (a = (asdl_withitem_seq*)_gather_34_rule(p))  // ','.with_item+
             &&
@@ -6799,9 +6799,9 @@ with_stmt_rule(Parser *p)
         asdl_withitem_seq* a;
         asdl_stmt_seq* b;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword_1 = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (_literal = _PyPegen_expect_token(p, 7))  // token='('
             &&
@@ -6851,9 +6851,9 @@ with_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         void *tc;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword_1 = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (a = (asdl_withitem_seq*)_gather_34_rule(p))  // ','.with_item+
             &&
@@ -6939,7 +6939,7 @@ with_item_rule(Parser *p)
         if (
             (e = expression_rule(p))  // expression
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (t = star_target_rule(p))  // star_target
             &&
@@ -7064,7 +7064,7 @@ try_stmt_rule(Parser *p)
         asdl_stmt_seq* b;
         asdl_stmt_seq* f;
         if (
-            (_keyword = _PyPegen_expect_token(p, 663))  // token='try'
+            (_keyword = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_forced_token(p, 11, ":"))  // forced_token=':'
             &&
@@ -7108,7 +7108,7 @@ try_stmt_rule(Parser *p)
         asdl_excepthandler_seq* ex;
         void *f;
         if (
-            (_keyword = _PyPegen_expect_token(p, 663))  // token='try'
+            (_keyword = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_forced_token(p, 11, ":"))  // forced_token=':'
             &&
@@ -7156,7 +7156,7 @@ try_stmt_rule(Parser *p)
         asdl_excepthandler_seq* ex;
         void *f;
         if (
-            (_keyword = _PyPegen_expect_token(p, 663))  // token='try'
+            (_keyword = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_forced_token(p, 11, ":"))  // forced_token=':'
             &&
@@ -7255,7 +7255,7 @@ except_block_rule(Parser *p)
         asdl_stmt_seq* b;
         expr_ty e;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (e = expression_rule(p))  // expression
             &&
@@ -7299,11 +7299,11 @@ except_block_rule(Parser *p)
         expr_ty e;
         expr_ty t;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (e = expression_rule(p))  // expression
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword_1 = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (t = _PyPegen_name_token(p))  // NAME
             &&
@@ -7345,7 +7345,7 @@ except_block_rule(Parser *p)
         asdl_stmt_seq* b;
         expr_ty e;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (e = expressions_rule(p))  // expressions
             &&
@@ -7386,7 +7386,7 @@ except_block_rule(Parser *p)
         Token * _literal;
         asdl_stmt_seq* b;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -7498,7 +7498,7 @@ except_star_block_rule(Parser *p)
         asdl_stmt_seq* b;
         expr_ty e;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -7545,13 +7545,13 @@ except_star_block_rule(Parser *p)
         expr_ty e;
         expr_ty t;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
             (e = expression_rule(p))  // expression
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword_1 = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (t = _PyPegen_name_token(p))  // NAME
             &&
@@ -7594,7 +7594,7 @@ except_star_block_rule(Parser *p)
         asdl_stmt_seq* b;
         expr_ty e;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -7694,7 +7694,7 @@ finally_block_rule(Parser *p)
         Token * _literal;
         asdl_stmt_seq* a;
         if (
-            (_keyword = _PyPegen_expect_token(p, 680))  // token='finally'
+            (_keyword = _PyPegen_expect_token(p, 682))  // token='finally'
             &&
             (_literal = _PyPegen_expect_forced_token(p, 11, ":"))  // forced_token=':'
             &&
@@ -8002,7 +8002,7 @@ guard_rule(Parser *p)
         Token * _keyword;
         expr_ty guard;
         if (
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (guard = named_expression_rule(p))  // named_expression
         )
@@ -8197,7 +8197,7 @@ as_pattern_rule(Parser *p)
         if (
             (pattern = or_pattern_rule(p))  // or_pattern
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (target = pattern_capture_target_rule(p))  // pattern_capture_target
         )
@@ -11494,11 +11494,11 @@ expression_rule(Parser *p)
         if (
             (a = disjunction_rule(p))  // disjunction
             &&
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (b = disjunction_rule(p))  // disjunction
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword_1 = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             (c = expression_rule(p))  // expression
         )
@@ -11604,7 +11604,7 @@ yield_expr_rule(Parser *p)
         if (
             (_keyword = _PyPegen_expect_token(p, 588))  // token='yield'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 640))  // token='from'
+            (_keyword_1 = _PyPegen_expect_token(p, 642))  // token='from'
             &&
             (a = expression_rule(p))  // expression
         )
@@ -12380,7 +12380,7 @@ inversion_rule(Parser *p)
         Token * _keyword;
         expr_ty a;
         if (
-            (_keyword = _PyPegen_expect_token(p, 710))  // token='not'
+            (_keyword = _PyPegen_expect_token(p, 712))  // token='not'
             &&
             (a = inversion_rule(p))  // inversion
         )
@@ -13034,9 +13034,9 @@ notin_bitwise_or_rule(Parser *p)
         Token * _keyword_1;
         expr_ty a;
         if (
-            (_keyword = _PyPegen_expect_token(p, 710))  // token='not'
+            (_keyword = _PyPegen_expect_token(p, 712))  // token='not'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword_1 = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (a = bitwise_or_rule(p))  // bitwise_or
         )
@@ -13082,7 +13082,7 @@ in_bitwise_or_rule(Parser *p)
         Token * _keyword;
         expr_ty a;
         if (
-            (_keyword = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (a = bitwise_or_rule(p))  // bitwise_or
         )
@@ -13131,7 +13131,7 @@ isnot_bitwise_or_rule(Parser *p)
         if (
             (_keyword = _PyPegen_expect_token(p, 597))  // token='is'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 710))  // token='not'
+            (_keyword_1 = _PyPegen_expect_token(p, 712))  // token='not'
             &&
             (a = bitwise_or_rule(p))  // bitwise_or
         )
@@ -17790,13 +17790,13 @@ for_if_clause_rule(Parser *p)
         expr_ty b;
         asdl_expr_seq* c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword_1 = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (a = star_targets_rule(p))  // star_targets
             &&
-            (_keyword_2 = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword_2 = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (_cut_var = 1)
             &&
@@ -17835,11 +17835,11 @@ for_if_clause_rule(Parser *p)
         expr_ty b;
         asdl_expr_seq* c;
         if (
-            (_keyword = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (a = star_targets_rule(p))  // star_targets
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword_1 = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (_cut_var = 1)
             &&
@@ -21140,11 +21140,11 @@ expression_without_invalid_rule(Parser *p)
         if (
             (a = disjunction_rule(p))  // disjunction
             &&
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (b = disjunction_rule(p))  // disjunction
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword_1 = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             (c = expression_rule(p))  // expression
         )
@@ -21444,7 +21444,7 @@ invalid_expression_rule(Parser *p)
         if (
             (a = disjunction_rule(p))  // disjunction
             &&
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (b = disjunction_rule(p))  // disjunction
             &&
@@ -21477,11 +21477,11 @@ invalid_expression_rule(Parser *p)
         if (
             (a = disjunction_rule(p))  // disjunction
             &&
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (b = disjunction_rule(p))  // disjunction
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword_1 = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             _PyPegen_lookahead_for_expr(0, expression_rule, p)
         )
@@ -21513,11 +21513,11 @@ invalid_expression_rule(Parser *p)
         if (
             (a = (stmt_ty)_tmp_116_rule(p))  // pass_stmt | break_stmt | continue_stmt
             &&
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (b = disjunction_rule(p))  // disjunction
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword_1 = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             (c = simple_stmt_rule(p))  // simple_stmt
         )
@@ -22052,7 +22052,7 @@ invalid_raise_stmt_rule(Parser *p)
         if (
             (a = _PyPegen_expect_token(p, 628))  // token='raise'
             &&
-            (b = _PyPegen_expect_token(p, 640))  // token='from'
+            (b = _PyPegen_expect_token(p, 642))  // token='from'
         )
         {
             D(fprintf(stderr, "%*c+ invalid_raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' 'from'"));
@@ -22082,7 +22082,7 @@ invalid_raise_stmt_rule(Parser *p)
             &&
             (expression_var = expression_rule(p))  // expression
             &&
-            (a = _PyPegen_expect_token(p, 640))  // token='from'
+            (a = _PyPegen_expect_token(p, 642))  // token='from'
         )
         {
             D(fprintf(stderr, "%*c+ invalid_raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression 'from'"));
@@ -22153,6 +22153,8 @@ invalid_del_stmt_rule(Parser *p)
 // invalid_assert_stmt:
 //     | 'assert' expression '=' expression
 //     | 'assert' expression ',' expression '=' expression
+//     | 'assert' expression ':=' expression
+//     | 'assert' expression ',' expression ':=' expression
 static void *
 invalid_assert_stmt_rule(Parser *p)
 {
@@ -22176,7 +22178,7 @@ invalid_assert_stmt_rule(Parser *p)
         expr_ty a;
         expr_ty b;
         if (
-            (_keyword = _PyPegen_expect_token(p, 632))  // token='assert'
+            (_keyword = _PyPegen_expect_token(p, 634))  // token='assert'
             &&
             (a = expression_rule(p))  // expression
             &&
@@ -22211,7 +22213,7 @@ invalid_assert_stmt_rule(Parser *p)
         expr_ty b;
         expr_ty expression_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 632))  // token='assert'
+            (_keyword = _PyPegen_expect_token(p, 634))  // token='assert'
             &&
             (expression_var = expression_rule(p))  // expression
             &&
@@ -22237,6 +22239,78 @@ invalid_assert_stmt_rule(Parser *p)
         D(fprintf(stderr, "%*c%s invalid_assert_stmt[%d-%d]: %s failed!\n", p->level, ' ',
                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'assert' expression ',' expression '=' expression"));
     }
+    { // 'assert' expression ':=' expression
+        if (p->error_indicator) {
+            p->level--;
+            return NULL;
+        }
+        D(fprintf(stderr, "%*c> invalid_assert_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'assert' expression ':=' expression"));
+        Token * _keyword;
+        Token * _literal;
+        expr_ty a;
+        expr_ty b;
+        if (
+            (_keyword = _PyPegen_expect_token(p, 634))  // token='assert'
+            &&
+            (a = expression_rule(p))  // expression
+            &&
+            (_literal = _PyPegen_expect_token(p, 53))  // token=':='
+            &&
+            (b = expression_rule(p))  // expression
+        )
+        {
+            D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ':=' expression"));
+            _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use named expression without parentheses here" );
+            if (_res == NULL && PyErr_Occurred()) {
+                p->error_indicator = 1;
+                p->level--;
+                return NULL;
+            }
+            goto done;
+        }
+        p->mark = _mark;
+        D(fprintf(stderr, "%*c%s invalid_assert_stmt[%d-%d]: %s failed!\n", p->level, ' ',
+                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'assert' expression ':=' expression"));
+    }
+    { // 'assert' expression ',' expression ':=' expression
+        if (p->error_indicator) {
+            p->level--;
+            return NULL;
+        }
+        D(fprintf(stderr, "%*c> invalid_assert_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'assert' expression ',' expression ':=' expression"));
+        Token * _keyword;
+        Token * _literal;
+        Token * _literal_1;
+        expr_ty a;
+        expr_ty b;
+        expr_ty expression_var;
+        if (
+            (_keyword = _PyPegen_expect_token(p, 634))  // token='assert'
+            &&
+            (expression_var = expression_rule(p))  // expression
+            &&
+            (_literal = _PyPegen_expect_token(p, 12))  // token=','
+            &&
+            (a = expression_rule(p))  // expression
+            &&
+            (_literal_1 = _PyPegen_expect_token(p, 53))  // token=':='
+            &&
+            (b = expression_rule(p))  // expression
+        )
+        {
+            D(fprintf(stderr, "%*c+ invalid_assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression ',' expression ':=' expression"));
+            _res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "cannot use named expression without parentheses here" );
+            if (_res == NULL && PyErr_Occurred()) {
+                p->error_indicator = 1;
+                p->level--;
+                return NULL;
+            }
+            goto done;
+        }
+        p->mark = _mark;
+        D(fprintf(stderr, "%*c%s invalid_assert_stmt[%d-%d]: %s failed!\n", p->level, ' ',
+                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'assert' expression ',' expression ':=' expression"));
+    }
     _res = NULL;
   done:
     p->level--;
@@ -23655,7 +23729,7 @@ invalid_with_item_rule(Parser *p)
         if (
             (expression_var = expression_rule(p))  // expression
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (a = expression_rule(p))  // expression
             &&
@@ -23705,13 +23779,13 @@ invalid_for_if_clause_rule(Parser *p)
         UNUSED(_opt_var); // Silence compiler warnings
         void *_tmp_135_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (_keyword = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (_tmp_135_var = _tmp_135_rule(p))  // bitwise_or ((',' bitwise_or))* ','?
             &&
-            _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 702)  // token='in'
+            _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 704)  // token='in'
         )
         {
             D(fprintf(stderr, "%*c+ invalid_for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'? 'for' (bitwise_or ((',' bitwise_or))* ','?) !'in'"));
@@ -23757,9 +23831,9 @@ invalid_for_target_rule(Parser *p)
         UNUSED(_opt_var); // Silence compiler warnings
         expr_ty a;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (_keyword = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (a = star_expressions_rule(p))  // star_expressions
         )
@@ -23889,11 +23963,11 @@ invalid_import_rule(Parser *p)
         Token * a;
         expr_ty dotted_name_var;
         if (
-            (a = _PyPegen_expect_token(p, 641))  // token='import'
+            (a = _PyPegen_expect_token(p, 643))  // token='import'
             &&
             (_gather_137_var = _gather_137_rule(p))  // ','.dotted_name+
             &&
-            (_keyword = _PyPegen_expect_token(p, 640))  // token='from'
+            (_keyword = _PyPegen_expect_token(p, 642))  // token='from'
             &&
             (dotted_name_var = dotted_name_rule(p))  // dotted_name
         )
@@ -23920,7 +23994,7 @@ invalid_import_rule(Parser *p)
         Token * _keyword;
         Token * token;
         if (
-            (_keyword = _PyPegen_expect_token(p, 641))  // token='import'
+            (_keyword = _PyPegen_expect_token(p, 643))  // token='import'
             &&
             (token = _PyPegen_expect_token(p, NEWLINE))  // token='NEWLINE'
         )
@@ -23969,7 +24043,7 @@ invalid_dotted_as_name_rule(Parser *p)
         if (
             (dotted_name_var = dotted_name_rule(p))  // dotted_name
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             _PyPegen_lookahead(0, _tmp_138_rule, p)
             &&
@@ -24020,7 +24094,7 @@ invalid_import_from_as_name_rule(Parser *p)
         if (
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             _PyPegen_lookahead(0, _tmp_138_rule, p)
             &&
@@ -24146,9 +24220,9 @@ invalid_with_stmt_rule(Parser *p)
         UNUSED(_opt_var); // Silence compiler warnings
         Token * newline_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (_keyword = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (_gather_140_var = _gather_140_rule(p))  // ','.(expression ['as' star_target])+
             &&
@@ -24184,9 +24258,9 @@ invalid_with_stmt_rule(Parser *p)
         UNUSED(_opt_var_1); // Silence compiler warnings
         Token * newline_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (_keyword = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (_literal = _PyPegen_expect_token(p, 7))  // token='('
             &&
@@ -24246,9 +24320,9 @@ invalid_with_stmt_indent_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (a = _PyPegen_expect_token(p, 654))  // token='with'
+            (a = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (_gather_140_var = _gather_140_rule(p))  // ','.(expression ['as' star_target])+
             &&
@@ -24289,9 +24363,9 @@ invalid_with_stmt_indent_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (a = _PyPegen_expect_token(p, 654))  // token='with'
+            (a = _PyPegen_expect_token(p, 656))  // token='with'
             &&
             (_literal = _PyPegen_expect_token(p, 7))  // token='('
             &&
@@ -24354,7 +24428,7 @@ invalid_try_stmt_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 663))  // token='try'
+            (a = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -24386,7 +24460,7 @@ invalid_try_stmt_rule(Parser *p)
         Token * _literal;
         asdl_stmt_seq* block_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 663))  // token='try'
+            (_keyword = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -24425,7 +24499,7 @@ invalid_try_stmt_rule(Parser *p)
         Token * b;
         expr_ty expression_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 663))  // token='try'
+            (_keyword = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -24433,7 +24507,7 @@ invalid_try_stmt_rule(Parser *p)
             &&
             (_loop1_36_var = _loop1_36_rule(p))  // except_block+
             &&
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (b = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -24472,7 +24546,7 @@ invalid_try_stmt_rule(Parser *p)
         UNUSED(_opt_var); // Silence compiler warnings
         Token * a;
         if (
-            (_keyword = _PyPegen_expect_token(p, 663))  // token='try'
+            (_keyword = _PyPegen_expect_token(p, 665))  // token='try'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -24480,7 +24554,7 @@ invalid_try_stmt_rule(Parser *p)
             &&
             (_loop1_37_var = _loop1_37_rule(p))  // except_star_block+
             &&
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_opt_var = _tmp_145_rule(p), !p->error_indicator)  // [expression ['as' NAME]]
             &&
@@ -24537,7 +24611,7 @@ invalid_except_stmt_rule(Parser *p)
         expr_ty expressions_var;
         expr_ty name_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (a = expression_rule(p))  // expression
             &&
@@ -24545,7 +24619,7 @@ invalid_except_stmt_rule(Parser *p)
             &&
             (expressions_var = expressions_rule(p))  // expressions
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword_1 = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
@@ -24577,7 +24651,7 @@ invalid_except_stmt_rule(Parser *p)
         expr_ty expression_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (expression_var = expression_rule(p))  // expression
             &&
@@ -24608,7 +24682,7 @@ invalid_except_stmt_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (newline_var = _PyPegen_expect_token(p, NEWLINE))  // token='NEWLINE'
         )
@@ -24639,11 +24713,11 @@ invalid_except_stmt_rule(Parser *p)
         asdl_stmt_seq* block_var;
         expr_ty expression_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (expression_var = expression_rule(p))  // expression
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword_1 = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (a = expression_rule(p))  // expression
             &&
@@ -24703,7 +24777,7 @@ invalid_except_star_stmt_rule(Parser *p)
         expr_ty expressions_var;
         expr_ty name_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -24713,7 +24787,7 @@ invalid_except_star_stmt_rule(Parser *p)
             &&
             (expressions_var = expressions_rule(p))  // expressions
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword_1 = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
@@ -24746,7 +24820,7 @@ invalid_except_star_stmt_rule(Parser *p)
         expr_ty expression_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -24780,7 +24854,7 @@ invalid_except_star_stmt_rule(Parser *p)
         void *_tmp_146_var;
         Token * a;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -24814,13 +24888,13 @@ invalid_except_star_stmt_rule(Parser *p)
         asdl_stmt_seq* block_var;
         expr_ty expression_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
             (expression_var = expression_rule(p))  // expression
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword_1 = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (a = expression_rule(p))  // expression
             &&
@@ -24871,7 +24945,7 @@ invalid_finally_stmt_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 680))  // token='finally'
+            (a = _PyPegen_expect_token(p, 682))  // token='finally'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -24927,7 +25001,7 @@ invalid_except_stmt_indent_rule(Parser *p)
         expr_ty expression_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (expression_var = expression_rule(p))  // expression
             &&
@@ -24963,7 +25037,7 @@ invalid_except_stmt_indent_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -25019,7 +25093,7 @@ invalid_except_star_stmt_indent_rule(Parser *p)
         expr_ty expression_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 684))  // token='except'
+            (a = _PyPegen_expect_token(p, 686))  // token='except'
             &&
             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
             &&
@@ -25258,7 +25332,7 @@ invalid_as_pattern_rule(Parser *p)
         if (
             (or_pattern_var = or_pattern_rule(p))  // or_pattern
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (a = _PyPegen_expect_soft_keyword(p, "_"))  // soft_keyword='"_"'
         )
@@ -25288,7 +25362,7 @@ invalid_as_pattern_rule(Parser *p)
         if (
             (or_pattern_var = or_pattern_rule(p))  // or_pattern
             &&
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (a = expression_rule(p))  // expression
         )
@@ -25440,7 +25514,7 @@ invalid_if_stmt_rule(Parser *p)
         expr_ty named_expression_var;
         Token * newline_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (named_expression_var = named_expression_rule(p))  // named_expression
             &&
@@ -25471,7 +25545,7 @@ invalid_if_stmt_rule(Parser *p)
         expr_ty a_1;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 689))  // token='if'
+            (a = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (a_1 = named_expression_rule(p))  // named_expression
             &&
@@ -25526,7 +25600,7 @@ invalid_elif_stmt_rule(Parser *p)
         expr_ty named_expression_var;
         Token * newline_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 694))  // token='elif'
+            (_keyword = _PyPegen_expect_token(p, 696))  // token='elif'
             &&
             (named_expression_var = named_expression_rule(p))  // named_expression
             &&
@@ -25557,7 +25631,7 @@ invalid_elif_stmt_rule(Parser *p)
         expr_ty named_expression_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 694))  // token='elif'
+            (a = _PyPegen_expect_token(p, 696))  // token='elif'
             &&
             (named_expression_var = named_expression_rule(p))  // named_expression
             &&
@@ -25610,7 +25684,7 @@ invalid_else_stmt_rule(Parser *p)
         Token * a;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 693))  // token='else'
+            (a = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
@@ -25643,13 +25717,13 @@ invalid_else_stmt_rule(Parser *p)
         Token * _literal;
         asdl_stmt_seq* block_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword = _PyPegen_expect_token(p, 695))  // token='else'
             &&
             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
             &&
             (block_var = block_rule(p))  // block
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 694))  // token='elif'
+            (_keyword_1 = _PyPegen_expect_token(p, 696))  // token='elif'
         )
         {
             D(fprintf(stderr, "%*c+ invalid_else_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else' ':' block 'elif'"));
@@ -25696,7 +25770,7 @@ invalid_while_stmt_rule(Parser *p)
         expr_ty named_expression_var;
         Token * newline_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 696))  // token='while'
+            (_keyword = _PyPegen_expect_token(p, 698))  // token='while'
             &&
             (named_expression_var = named_expression_rule(p))  // named_expression
             &&
@@ -25727,7 +25801,7 @@ invalid_while_stmt_rule(Parser *p)
         expr_ty named_expression_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 696))  // token='while'
+            (a = _PyPegen_expect_token(p, 698))  // token='while'
             &&
             (named_expression_var = named_expression_rule(p))  // named_expression
             &&
@@ -25786,13 +25860,13 @@ invalid_for_stmt_rule(Parser *p)
         expr_ty star_expressions_var;
         expr_ty star_targets_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (_keyword = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (star_targets_var = star_targets_rule(p))  // star_targets
             &&
-            (_keyword_1 = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword_1 = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (star_expressions_var = star_expressions_rule(p))  // star_expressions
             &&
@@ -25827,13 +25901,13 @@ invalid_for_stmt_rule(Parser *p)
         expr_ty star_expressions_var;
         expr_ty star_targets_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (a = _PyPegen_expect_token(p, 701))  // token='for'
+            (a = _PyPegen_expect_token(p, 703))  // token='for'
             &&
             (star_targets_var = star_targets_rule(p))  // star_targets
             &&
-            (_keyword = _PyPegen_expect_token(p, 702))  // token='in'
+            (_keyword = _PyPegen_expect_token(p, 704))  // token='in'
             &&
             (star_expressions_var = star_expressions_rule(p))  // star_expressions
             &&
@@ -25899,9 +25973,9 @@ invalid_def_raw_rule(Parser *p)
         expr_ty name_var;
         Token * newline_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (a = _PyPegen_expect_token(p, 706))  // token='def'
+            (a = _PyPegen_expect_token(p, 708))  // token='def'
             &&
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
@@ -25958,9 +26032,9 @@ invalid_def_raw_rule(Parser *p)
         asdl_stmt_seq* block_var;
         expr_ty name_var;
         if (
-            (_opt_var = _PyPegen_expect_token(p, 705), !p->error_indicator)  // 'async'?
+            (_opt_var = _PyPegen_expect_token(p, 707), !p->error_indicator)  // 'async'?
             &&
-            (_keyword = _PyPegen_expect_token(p, 706))  // token='def'
+            (_keyword = _PyPegen_expect_token(p, 708))  // token='def'
             &&
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
@@ -26024,7 +26098,7 @@ invalid_class_def_raw_rule(Parser *p)
         expr_ty name_var;
         Token * newline_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 708))  // token='class'
+            (_keyword = _PyPegen_expect_token(p, 710))  // token='class'
             &&
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
@@ -26063,7 +26137,7 @@ invalid_class_def_raw_rule(Parser *p)
         expr_ty name_var;
         Token * newline_var;
         if (
-            (a = _PyPegen_expect_token(p, 708))  // token='class'
+            (a = _PyPegen_expect_token(p, 710))  // token='class'
             &&
             (name_var = _PyPegen_name_token(p))  // NAME
             &&
@@ -27398,7 +27472,7 @@ invalid_arithmetic_rule(Parser *p)
             &&
             (_tmp_154_var = _tmp_154_rule(p))  // '+' | '-' | '*' | '/' | '%' | '//' | '@'
             &&
-            (a = _PyPegen_expect_token(p, 710))  // token='not'
+            (a = _PyPegen_expect_token(p, 712))  // token='not'
             &&
             (b = inversion_rule(p))  // inversion
         )
@@ -27447,7 +27521,7 @@ invalid_factor_rule(Parser *p)
         if (
             (_tmp_155_var = _tmp_155_rule(p))  // '+' | '-' | '~'
             &&
-            (a = _PyPegen_expect_token(p, 710))  // token='not'
+            (a = _PyPegen_expect_token(p, 712))  // token='not'
             &&
             (b = factor_rule(p))  // factor
         )
@@ -27794,7 +27868,7 @@ _tmp_5_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 641))  // token='import'
+            (_keyword = _PyPegen_expect_token(p, 643))  // token='import'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_5[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import'"));
@@ -27813,7 +27887,7 @@ _tmp_5_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 640))  // token='from'
+            (_keyword = _PyPegen_expect_token(p, 642))  // token='from'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_5[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from'"));
@@ -27851,7 +27925,7 @@ _tmp_6_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 706))  // token='def'
+            (_keyword = _PyPegen_expect_token(p, 708))  // token='def'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'"));
@@ -27889,7 +27963,7 @@ _tmp_6_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'"));
@@ -27927,7 +28001,7 @@ _tmp_7_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 708))  // token='class'
+            (_keyword = _PyPegen_expect_token(p, 710))  // token='class'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'"));
@@ -27984,7 +28058,7 @@ _tmp_8_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 654))  // token='with'
+            (_keyword = _PyPegen_expect_token(p, 656))  // token='with'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'"));
@@ -28003,7 +28077,7 @@ _tmp_8_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'"));
@@ -28041,7 +28115,7 @@ _tmp_9_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 701))  // token='for'
+            (_keyword = _PyPegen_expect_token(p, 703))  // token='for'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'"));
@@ -28060,7 +28134,7 @@ _tmp_9_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 705))  // token='async'
+            (_keyword = _PyPegen_expect_token(p, 707))  // token='async'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'"));
@@ -28761,7 +28835,7 @@ _tmp_21_rule(Parser *p)
         Token * _keyword;
         expr_ty z;
         if (
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (z = _PyPegen_name_token(p))  // NAME
         )
@@ -34597,7 +34671,7 @@ _tmp_115_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 693))  // token='else'
+            (_keyword = _PyPegen_expect_token(p, 695))  // token='else'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'"));
@@ -36336,7 +36410,7 @@ _tmp_143_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 684))  // token='except'
+            (_keyword = _PyPegen_expect_token(p, 686))  // token='except'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'"));
@@ -36355,7 +36429,7 @@ _tmp_143_rule(Parser *p)
         D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'"));
         Token * _keyword;
         if (
-            (_keyword = _PyPegen_expect_token(p, 680))  // token='finally'
+            (_keyword = _PyPegen_expect_token(p, 682))  // token='finally'
         )
         {
             D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'"));
@@ -37559,7 +37633,7 @@ _tmp_163_rule(Parser *p)
         Token * _keyword;
         expr_ty z;
         if (
-            (_keyword = _PyPegen_expect_token(p, 689))  // token='if'
+            (_keyword = _PyPegen_expect_token(p, 691))  // token='if'
             &&
             (z = disjunction_rule(p))  // disjunction
         )
@@ -38217,7 +38291,7 @@ _tmp_176_rule(Parser *p)
         Token * _keyword;
         expr_ty star_target_var;
         if (
-            (_keyword = _PyPegen_expect_token(p, 687))  // token='as'
+            (_keyword = _PyPegen_expect_token(p, 689))  // token='as'
             &&
             (star_target_var = star_target_rule(p))  // star_target
         )