Skip to content

Commit 05cae26

Browse files
pablogsalwookie184
andauthored
[3.10] gh-92858: Improve error message for some suites with syntax error before ':' (GH-92894). (#94183)
(cherry picked from commit 2fc83ac) Co-authored-by: wookie184 <[email protected]> Co-authored-by: wookie184 <[email protected]>
1 parent 34be807 commit 05cae26

File tree

4 files changed

+472
-310
lines changed

4 files changed

+472
-310
lines changed

Grammar/python.gram

+9-7
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ while_stmt[stmt_ty]:
183183

184184
for_stmt[stmt_ty]:
185185
| invalid_for_stmt
186-
| 'for' t=star_targets 'in' ~ ex=star_expressions &&':' tc=[TYPE_COMMENT] b=block el=[else_block] {
186+
| 'for' t=star_targets 'in' ~ ex=star_expressions ':' tc=[TYPE_COMMENT] b=block el=[else_block] {
187187
_PyAST_For(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA) }
188-
| ASYNC 'for' t=star_targets 'in' ~ ex=star_expressions &&':' tc=[TYPE_COMMENT] b=block el=[else_block] {
188+
| ASYNC 'for' t=star_targets 'in' ~ ex=star_expressions ':' tc=[TYPE_COMMENT] b=block el=[else_block] {
189189
CHECK_VERSION(stmt_ty, 5, "Async for loops are", _PyAST_AsyncFor(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
190190
| invalid_for_target
191191

@@ -488,7 +488,7 @@ class_def[stmt_ty]:
488488
| class_def_raw
489489
class_def_raw[stmt_ty]:
490490
| invalid_class_def_raw
491-
| 'class' a=NAME b=['(' z=[arguments] ')' { z }] &&':' c=block {
491+
| 'class' a=NAME b=['(' z=[arguments] ')' { z }] ':' c=block {
492492
_PyAST_ClassDef(a->v.Name.id,
493493
(b) ? ((expr_ty) b)->v.Call.args : NULL,
494494
(b) ? ((expr_ty) b)->v.Call.keywords : NULL,
@@ -954,8 +954,8 @@ invalid_import_from_targets:
954954
RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }
955955

956956
invalid_with_stmt:
957-
| [ASYNC] 'with' ','.(expression ['as' star_target])+ &&':'
958-
| [ASYNC] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'
957+
| [ASYNC] 'with' ','.(expression ['as' star_target])+ NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
958+
| [ASYNC] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
959959
invalid_with_stmt_indent:
960960
| [ASYNC] a='with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT {
961961
RAISE_INDENTATION_ERROR("expected an indented block after 'with' statement on line %d", a->lineno) }
@@ -979,11 +979,11 @@ invalid_except_stmt_indent:
979979
RAISE_INDENTATION_ERROR("expected an indented block after 'except' statement on line %d", a->lineno) }
980980
| a='except' ':' NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block after 'except' statement on line %d", a->lineno) }
981981
invalid_match_stmt:
982-
| "match" subject_expr !':' { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) }
982+
| "match" subject_expr NEWLINE { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) }
983983
| a="match" subject=subject_expr ':' NEWLINE !INDENT {
984984
RAISE_INDENTATION_ERROR("expected an indented block after 'match' statement on line %d", a->lineno) }
985985
invalid_case_block:
986-
| "case" patterns guard? !':' { RAISE_SYNTAX_ERROR("expected ':'") }
986+
| "case" patterns guard? NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
987987
| a="case" patterns guard? ':' NEWLINE !INDENT {
988988
RAISE_INDENTATION_ERROR("expected an indented block after 'case' statement on line %d", a->lineno) }
989989
invalid_as_pattern:
@@ -1012,12 +1012,14 @@ invalid_while_stmt:
10121012
| a='while' named_expression ':' NEWLINE !INDENT {
10131013
RAISE_INDENTATION_ERROR("expected an indented block after 'while' statement on line %d", a->lineno) }
10141014
invalid_for_stmt:
1015+
| [ASYNC] 'for' star_targets 'in' star_expressions NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
10151016
| [ASYNC] a='for' star_targets 'in' star_expressions ':' NEWLINE !INDENT {
10161017
RAISE_INDENTATION_ERROR("expected an indented block after 'for' statement on line %d", a->lineno) }
10171018
invalid_def_raw:
10181019
| [ASYNC] a='def' NAME '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT {
10191020
RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) }
10201021
invalid_class_def_raw:
1022+
| 'class' NAME ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
10211023
| a='class' NAME ['('[arguments] ')'] ':' NEWLINE !INDENT {
10221024
RAISE_INDENTATION_ERROR("expected an indented block after class definition on line %d", a->lineno) }
10231025

Lib/test/test_syntax.py

+31-10
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@
403403
>>> class C(x for x in L):
404404
... pass
405405
Traceback (most recent call last):
406-
SyntaxError: expected ':'
406+
SyntaxError: invalid syntax
407407
408408
>>> def g(*args, **kwargs):
409409
... print(args, sorted(kwargs.items()))
@@ -759,17 +759,22 @@
759759
...
760760
SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='?
761761
762-
Missing ':' before suites:
762+
Missing ':' before suites:
763763
764-
>>> def f()
765-
... pass
766-
Traceback (most recent call last):
767-
SyntaxError: expected ':'
764+
>>> def f()
765+
... pass
766+
Traceback (most recent call last):
767+
SyntaxError: expected ':'
768768
769-
>>> class A
770-
... pass
771-
Traceback (most recent call last):
772-
SyntaxError: expected ':'
769+
>>> class A
770+
... pass
771+
Traceback (most recent call last):
772+
SyntaxError: expected ':'
773+
774+
>>> class R&D:
775+
... pass
776+
Traceback (most recent call last):
777+
SyntaxError: invalid syntax
773778
774779
>>> if 1
775780
... pass
@@ -803,6 +808,11 @@
803808
Traceback (most recent call last):
804809
SyntaxError: expected ':'
805810
811+
>>> for x in range 10:
812+
... pass
813+
Traceback (most recent call last):
814+
SyntaxError: invalid syntax
815+
806816
>>> while True
807817
... pass
808818
Traceback (most recent call last):
@@ -848,6 +858,11 @@
848858
Traceback (most recent call last):
849859
SyntaxError: expected ':'
850860
861+
>>> with block ad something:
862+
... pass
863+
Traceback (most recent call last):
864+
SyntaxError: invalid syntax
865+
851866
>>> try
852867
... pass
853868
Traceback (most recent call last):
@@ -866,6 +881,12 @@
866881
Traceback (most recent call last):
867882
SyntaxError: expected ':'
868883
884+
>>> match x x:
885+
... case list():
886+
... pass
887+
Traceback (most recent call last):
888+
SyntaxError: invalid syntax
889+
869890
>>> match x:
870891
... case list()
871892
... pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve error message for some suites with syntax error before ':'

0 commit comments

Comments
 (0)