gh-92858: Improve error message for some suites with syntax error before ':' (#92894)

This commit is contained in:
wookie184 2022-06-23 17:31:09 +01:00 committed by GitHub
parent b4e0d6124a
commit 2fc83ac3af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 728 additions and 566 deletions

View File

@ -249,7 +249,7 @@ class_def[stmt_ty]:
class_def_raw[stmt_ty]: class_def_raw[stmt_ty]:
| invalid_class_def_raw | invalid_class_def_raw
| 'class' a=NAME b=['(' z=[arguments] ')' { z }] &&':' c=block { | 'class' a=NAME b=['(' z=[arguments] ')' { z }] ':' c=block {
_PyAST_ClassDef(a->v.Name.id, _PyAST_ClassDef(a->v.Name.id,
(b) ? ((expr_ty) b)->v.Call.args : NULL, (b) ? ((expr_ty) b)->v.Call.args : NULL,
(b) ? ((expr_ty) b)->v.Call.keywords : NULL, (b) ? ((expr_ty) b)->v.Call.keywords : NULL,
@ -379,9 +379,9 @@ while_stmt[stmt_ty]:
for_stmt[stmt_ty]: for_stmt[stmt_ty]:
| invalid_for_stmt | invalid_for_stmt
| 'for' t=star_targets 'in' ~ ex=star_expressions &&':' tc=[TYPE_COMMENT] b=block el=[else_block] { | 'for' t=star_targets 'in' ~ ex=star_expressions ':' tc=[TYPE_COMMENT] b=block el=[else_block] {
_PyAST_For(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA) } _PyAST_For(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA) }
| ASYNC 'for' t=star_targets 'in' ~ ex=star_expressions &&':' tc=[TYPE_COMMENT] b=block el=[else_block] { | ASYNC 'for' t=star_targets 'in' ~ ex=star_expressions ':' tc=[TYPE_COMMENT] b=block el=[else_block] {
CHECK_VERSION(stmt_ty, 5, "Async for loops are", _PyAST_AsyncFor(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA)) } CHECK_VERSION(stmt_ty, 5, "Async for loops are", _PyAST_AsyncFor(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
| invalid_for_target | invalid_for_target
@ -1231,8 +1231,8 @@ invalid_import_from_targets:
RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") } RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }
invalid_with_stmt: invalid_with_stmt:
| [ASYNC] 'with' ','.(expression ['as' star_target])+ &&':' | [ASYNC] 'with' ','.(expression ['as' star_target])+ NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| [ASYNC] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':' | [ASYNC] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
invalid_with_stmt_indent: invalid_with_stmt_indent:
| [ASYNC] a='with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT { | [ASYNC] a='with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'with' statement on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after 'with' statement on line %d", a->lineno) }
@ -1262,11 +1262,11 @@ invalid_except_star_stmt_indent:
| a='except' '*' expression ['as' NAME ] ':' NEWLINE !INDENT { | a='except' '*' expression ['as' NAME ] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'except*' statement on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after 'except*' statement on line %d", a->lineno) }
invalid_match_stmt: invalid_match_stmt:
| "match" subject_expr !':' { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) } | "match" subject_expr NEWLINE { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) }
| a="match" subject=subject_expr ':' NEWLINE !INDENT { | a="match" subject=subject_expr ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'match' statement on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after 'match' statement on line %d", a->lineno) }
invalid_case_block: invalid_case_block:
| "case" patterns guard? !':' { RAISE_SYNTAX_ERROR("expected ':'") } | "case" patterns guard? NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| a="case" patterns guard? ':' NEWLINE !INDENT { | a="case" patterns guard? ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'case' statement on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after 'case' statement on line %d", a->lineno) }
invalid_as_pattern: invalid_as_pattern:
@ -1295,12 +1295,14 @@ invalid_while_stmt:
| a='while' named_expression ':' NEWLINE !INDENT { | a='while' named_expression ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'while' statement on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after 'while' statement on line %d", a->lineno) }
invalid_for_stmt: invalid_for_stmt:
| [ASYNC] 'for' star_targets 'in' star_expressions NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| [ASYNC] a='for' star_targets 'in' star_expressions ':' NEWLINE !INDENT { | [ASYNC] a='for' star_targets 'in' star_expressions ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after 'for' statement on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after 'for' statement on line %d", a->lineno) }
invalid_def_raw: invalid_def_raw:
| [ASYNC] a='def' NAME '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT { | [ASYNC] a='def' NAME '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) }
invalid_class_def_raw: invalid_class_def_raw:
| 'class' NAME ['(' [arguments] ')'] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
| a='class' NAME ['(' [arguments] ')'] ':' NEWLINE !INDENT { | a='class' NAME ['(' [arguments] ')'] ':' NEWLINE !INDENT {
RAISE_INDENTATION_ERROR("expected an indented block after class definition on line %d", a->lineno) } RAISE_INDENTATION_ERROR("expected an indented block after class definition on line %d", a->lineno) }

View File

@ -607,7 +607,7 @@ SyntaxError: Generator expression must be parenthesized
>>> class C(x for x in L): >>> class C(x for x in L):
... pass ... pass
Traceback (most recent call last): Traceback (most recent call last):
SyntaxError: expected ':' SyntaxError: invalid syntax
>>> def g(*args, **kwargs): >>> def g(*args, **kwargs):
... print(args, sorted(kwargs.items())) ... print(args, sorted(kwargs.items()))
@ -975,6 +975,11 @@ leading to spurious errors.
Traceback (most recent call last): Traceback (most recent call last):
SyntaxError: expected ':' SyntaxError: expected ':'
>>> class R&D:
... pass
Traceback (most recent call last):
SyntaxError: invalid syntax
>>> if 1 >>> if 1
... pass ... pass
... elif 1: ... elif 1:
@ -1007,6 +1012,11 @@ leading to spurious errors.
Traceback (most recent call last): Traceback (most recent call last):
SyntaxError: expected ':' SyntaxError: expected ':'
>>> for x in range 10:
... pass
Traceback (most recent call last):
SyntaxError: invalid syntax
>>> while True >>> while True
... pass ... pass
Traceback (most recent call last): Traceback (most recent call last):
@ -1052,6 +1062,11 @@ leading to spurious errors.
Traceback (most recent call last): Traceback (most recent call last):
SyntaxError: expected ':' SyntaxError: expected ':'
>>> with block ad something:
... pass
Traceback (most recent call last):
SyntaxError: invalid syntax
>>> try >>> try
... pass ... pass
Traceback (most recent call last): Traceback (most recent call last):
@ -1070,6 +1085,12 @@ leading to spurious errors.
Traceback (most recent call last): Traceback (most recent call last):
SyntaxError: expected ':' SyntaxError: expected ':'
>>> match x x:
... case list():
... pass
Traceback (most recent call last):
SyntaxError: invalid syntax
>>> match x: >>> match x:
... case list() ... case list()
... pass ... pass

View File

@ -0,0 +1 @@
Improve error message for some suites with syntax error before ':'

1234
Parser/parser.c generated

File diff suppressed because it is too large Load Diff