gh-138857: Improve error message for case outside of match (#138858)
* gh-138857: Improve error message for `case` outside of `match` --------- Co-authored-by: Bartosz Sławecki <bartosz@ilikepython.com>
This commit is contained in:
@@ -1477,6 +1477,10 @@ invalid_match_stmt:
|
||||
| "match" subject_expr NEWLINE { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) }
|
||||
| a="match" subject=subject_expr ':' NEWLINE !INDENT {
|
||||
RAISE_INDENTATION_ERROR("expected an indented block after 'match' statement on line %d", a->lineno) }
|
||||
| a="case" patterns guard? b=':' block {
|
||||
RAISE_SYNTAX_ERROR_KNOWN_RANGE(
|
||||
a, b,
|
||||
"case statement must be inside match statement") }
|
||||
invalid_case_block:
|
||||
| "case" patterns guard? NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
||||
| a="case" patterns guard? ':' NEWLINE !INDENT {
|
||||
|
||||
@@ -376,6 +376,42 @@ SyntaxError: invalid syntax
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: invalid syntax
|
||||
|
||||
# Check incorrect "case" placement with specialized error messages
|
||||
|
||||
>>> case "pattern": ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> case 1 | 2: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> case klass(attr=1) | {}: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> case [] if x > 1: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> case match: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> case case: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> if some:
|
||||
... case 1: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
>>> case some:
|
||||
... case 1: ...
|
||||
Traceback (most recent call last):
|
||||
SyntaxError: case statement must be inside match statement
|
||||
|
||||
# But prefixes of soft keywords should
|
||||
# still raise specialized errors
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Improve :exc:`SyntaxError` message for ``case`` keyword placed outside
|
||||
:keyword:`match` body.
|
||||
38
Parser/parser.c
generated
38
Parser/parser.c
generated
@@ -25154,6 +25154,7 @@ invalid_except_star_stmt_indent_rule(Parser *p)
|
||||
// invalid_match_stmt:
|
||||
// | "match" subject_expr NEWLINE
|
||||
// | "match" subject_expr ':' NEWLINE !INDENT
|
||||
// | "case" patterns guard? ':' block
|
||||
static void *
|
||||
invalid_match_stmt_rule(Parser *p)
|
||||
{
|
||||
@@ -25231,6 +25232,43 @@ invalid_match_stmt_rule(Parser *p)
|
||||
D(fprintf(stderr, "%*c%s invalid_match_stmt[%d-%d]: %s failed!\n", p->level, ' ',
|
||||
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"match\" subject_expr ':' NEWLINE !INDENT"));
|
||||
}
|
||||
{ // "case" patterns guard? ':' block
|
||||
if (p->error_indicator) {
|
||||
p->level--;
|
||||
return NULL;
|
||||
}
|
||||
D(fprintf(stderr, "%*c> invalid_match_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block"));
|
||||
void *_opt_var;
|
||||
UNUSED(_opt_var); // Silence compiler warnings
|
||||
expr_ty a;
|
||||
Token * b;
|
||||
asdl_stmt_seq* block_var;
|
||||
pattern_ty patterns_var;
|
||||
if (
|
||||
(a = _PyPegen_expect_soft_keyword(p, "case")) // soft_keyword='"case"'
|
||||
&&
|
||||
(patterns_var = patterns_rule(p)) // patterns
|
||||
&&
|
||||
(_opt_var = guard_rule(p), !p->error_indicator) // guard?
|
||||
&&
|
||||
(b = _PyPegen_expect_token(p, 11)) // token=':'
|
||||
&&
|
||||
(block_var = block_rule(p)) // block
|
||||
)
|
||||
{
|
||||
D(fprintf(stderr, "%*c+ invalid_match_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "\"case\" patterns guard? ':' block"));
|
||||
_res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "case statement must be inside match statement" );
|
||||
if (_res == NULL && PyErr_Occurred()) {
|
||||
p->error_indicator = 1;
|
||||
p->level--;
|
||||
return NULL;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
p->mark = _mark;
|
||||
D(fprintf(stderr, "%*c%s invalid_match_stmt[%d-%d]: %s failed!\n", p->level, ' ',
|
||||
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "\"case\" patterns guard? ':' block"));
|
||||
}
|
||||
_res = NULL;
|
||||
done:
|
||||
p->level--;
|
||||
|
||||
Reference in New Issue
Block a user