Skip to content

Commit 5671762

Browse files
bpo-44792: Improve syntax errors for if expressions (GH-27506) (GH-27565)
(cherry picked from commit 28b6dc9) Co-authored-by: Miguel Brito <5544985+miguendes@users.noreply.github.com>
1 parent c6e7c98 commit 5671762

File tree

5 files changed

+48
-0
lines changed

5 files changed

+48
-0
lines changed

Grammar/python.gram

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@ invalid_expression:
859859
# Soft keywords need to also be ignored because they can be parsed as NAME NAME
860860
| !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression_without_invalid {
861861
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
862+
| a=disjunction 'if' b=disjunction !'else' { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") }
862863

863864
invalid_named_expression:
864865
| a=expression ':=' expression {

Lib/test/test_syntax.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,18 @@
140140
Traceback (most recent call last):
141141
SyntaxError: cannot assign to conditional expression
142142
143+
>>> a = 42 if True
144+
Traceback (most recent call last):
145+
SyntaxError: expected 'else' after 'if' expression
146+
147+
>>> a = (42 if True)
148+
Traceback (most recent call last):
149+
SyntaxError: expected 'else' after 'if' expression
150+
151+
>>> a = [1, 42 if True, 4]
152+
Traceback (most recent call last):
153+
SyntaxError: expected 'else' after 'if' expression
154+
143155
>>> True = True = 3
144156
Traceback (most recent call last):
145157
SyntaxError: cannot assign to True

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ Tom Bridgman
227227
Anthony Briggs
228228
Keith Briggs
229229
Tobias Brink
230+
Miguel Brito
230231
Dillon Brock
231232
Richard Brodie
232233
Michael Broghton
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve syntax errors for if expressions. Patch by Miguel Brito

Parser/parser.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18229,6 +18229,7 @@ invalid_legacy_expression_rule(Parser *p)
1822918229
// invalid_expression:
1823018230
// | invalid_legacy_expression
1823118231
// | !(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid
18232+
// | disjunction 'if' disjunction !'else'
1823218233
static void *
1823318234
invalid_expression_rule(Parser *p)
1823418235
{
@@ -18287,6 +18288,38 @@ invalid_expression_rule(Parser *p)
1828718288
D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ',
1828818289
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!(NAME STRING | SOFT_KEYWORD) disjunction expression_without_invalid"));
1828918290
}
18291+
{ // disjunction 'if' disjunction !'else'
18292+
if (p->error_indicator) {
18293+
D(p->level--);
18294+
return NULL;
18295+
}
18296+
D(fprintf(stderr, "%*c> invalid_expression[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !'else'"));
18297+
Token * _keyword;
18298+
expr_ty a;
18299+
expr_ty b;
18300+
if (
18301+
(a = disjunction_rule(p)) // disjunction
18302+
&&
18303+
(_keyword = _PyPegen_expect_token(p, 510)) // token='if'
18304+
&&
18305+
(b = disjunction_rule(p)) // disjunction
18306+
&&
18307+
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 516) // token='else'
18308+
)
18309+
{
18310+
D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !'else'"));
18311+
_res = RAISE_SYNTAX_ERROR_KNOWN_RANGE ( a , b , "expected 'else' after 'if' expression" );
18312+
if (_res == NULL && PyErr_Occurred()) {
18313+
p->error_indicator = 1;
18314+
D(p->level--);
18315+
return NULL;
18316+
}
18317+
goto done;
18318+
}
18319+
p->mark = _mark;
18320+
D(fprintf(stderr, "%*c%s invalid_expression[%d-%d]: %s failed!\n", p->level, ' ',
18321+
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "disjunction 'if' disjunction !'else'"));
18322+
}
1829018323
_res = NULL;
1829118324
done:
1829218325
D(p->level--);

0 commit comments

Comments
 (0)