bpo-44792: Improve syntax errors for if expressions (GH-27506)

This commit is contained in:
Miguel Brito 2021-08-02 18:11:37 +01:00 committed by GitHub
parent aa0894b379
commit 28b6dc9dd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 0 deletions

View file

@ -1083,6 +1083,7 @@ invalid_expression:
# Soft keywords need to also be ignored because they can be parsed as NAME NAME
| !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid {
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
| a=disjunction 'if' b=disjunction !'else' { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") }
invalid_named_expression:
| a=expression ':=' expression {

View file

@ -140,6 +140,18 @@
Traceback (most recent call last):
SyntaxError: cannot assign to conditional expression
>>> a = 42 if True
Traceback (most recent call last):
SyntaxError: expected 'else' after 'if' expression
>>> a = (42 if True)
Traceback (most recent call last):
SyntaxError: expected 'else' after 'if' expression
>>> a = [1, 42 if True, 4]
Traceback (most recent call last):
SyntaxError: expected 'else' after 'if' expression
>>> True = True = 3
Traceback (most recent call last):
SyntaxError: cannot assign to True

View file

@ -227,6 +227,7 @@ Tom Bridgman
Anthony Briggs
Keith Briggs
Tobias Brink
Miguel Brito
Dillon Brock
Richard Brodie
Michael Broghton

View file

@ -0,0 +1 @@
Improve syntax errors for if expressions. Patch by Miguel Brito

View file

@ -18207,6 +18207,7 @@ invalid_legacy_expression_rule(Parser *p)
// invalid_expression:
// | invalid_legacy_expression
// | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid
// | disjunction 'if' disjunction !'else'
static void *
invalid_expression_rule(Parser *p)
{
@ -18265,6 +18266,38 @@ invalid_expression_rule(Parser *p)
D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid"));
}
{ // disjunction 'if' disjunction !'else'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !'else'"));
Token * _keyword;
expr_ty a;
expr_ty b;
if (
(a = disjunction_rule(p)) // disjunction
&&
(_keyword = _PyPegen_expect_token(p, 510)) // token='if'
&&
(b = disjunction_rule(p)) // disjunction
&&
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 518) // token='else'
)
{
D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !'else'"));
_res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
D(p->level--);
return NULL;
}
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "disjunction 'if' disjunction !'else'"));
}
_res = NULL;
done:
D(p->level--);