From 6035080b3feda1dfe2ea999ad880b4b80f337d0c Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 30 Dec 2020 21:22:43 +0000 Subject: [PATCH] bpo-40631: Improve error message when deleting single starred element --- Grammar/python.gram | 2 ++ Lib/test/test_syntax.py | 5 ++++- Parser/parser.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index 05ddce520fbae1e..59243696f2562af 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -724,6 +724,8 @@ invalid_for_target: RAISE_SYNTAX_ERROR_INVALID_TARGET(FOR_TARGETS, a) } invalid_group: + | '(' a=star_expression ')' { + RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) } | '(' a=starred_expression ')' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "can't use starred expression here") } invalid_import_from_targets: diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index c8d191df4cc495c..8988b816f5643bf 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -789,6 +789,7 @@ def _check_error(self, code, errtext, try: compile(code, filename, mode) except SyntaxError as err: + print(err) if subclass and not isinstance(err, subclass): self.fail("SyntaxError is not a %s" % subclass.__name__) mo = re.search(errtext, str(err)) @@ -821,7 +822,9 @@ def test_assign_del(self): self._check_error("del (1, 2)", "delete literal") self._check_error("del None", "delete None") self._check_error("del *x", "delete starred") - self._check_error("del (*x)", "use starred expression") + self._check_error("del (*x)", "delete starred") + self._check_error("del (*x, *y)", "delete starred") + self._check_error("del (x, *y)", "delete starred") self._check_error("del (*x,)", "delete starred") self._check_error("del [*x,]", "delete starred") self._check_error("del f()", "delete function call") diff --git a/Parser/parser.c b/Parser/parser.c index f7794e715b918f0..9e3f91def750bb1 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -15777,7 +15777,7 @@ invalid_for_target_rule(Parser *p) return _res; } -// invalid_group: '(' starred_expression ')' +// invalid_group: '(' star_expression ')' | '(' starred_expression ')' static void * invalid_group_rule(Parser *p) { @@ -15788,6 +15788,36 @@ invalid_group_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; + { // '(' star_expression ')' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> invalid_group[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_expression ')'")); + Token * _literal; + Token * _literal_1; + expr_ty a; + if ( + (_literal = _PyPegen_expect_token(p, 7)) // token='(' + && + (a = star_expression_rule(p)) // star_expression + && + (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' + ) + { + D(fprintf(stderr, "%*c+ invalid_group[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_expression ')'")); + _res = RAISE_SYNTAX_ERROR_INVALID_TARGET ( DEL_TARGETS , a ); + 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_group[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' star_expression ')'")); + } { // '(' starred_expression ')' if (p->error_indicator) { D(p->level--);