mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
bpo-40334: Correctly identify invalid target in assignment errors (GH-20076)
Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
This commit is contained in:
parent
7ba1f75f3f
commit
16ab07063c
10 changed files with 137 additions and 45 deletions
|
|
@ -10747,7 +10747,8 @@ invalid_named_expression_rule(Parser *p)
|
|||
// | tuple ':'
|
||||
// | star_named_expression ',' star_named_expressions* ':'
|
||||
// | expression ':' expression ['=' annotated_rhs]
|
||||
// | expression ('=' | augassign) (yield_expr | star_expressions)
|
||||
// | star_expressions '=' (yield_expr | star_expressions)
|
||||
// | star_expressions augassign (yield_expr | star_expressions)
|
||||
static void *
|
||||
invalid_assignment_rule(Parser *p)
|
||||
{
|
||||
|
|
@ -10841,19 +10842,40 @@ invalid_assignment_rule(Parser *p)
|
|||
}
|
||||
p->mark = _mark;
|
||||
}
|
||||
{ // expression ('=' | augassign) (yield_expr | star_expressions)
|
||||
{ // star_expressions '=' (yield_expr | star_expressions)
|
||||
Token * _literal;
|
||||
void *_tmp_128_var;
|
||||
void *_tmp_129_var;
|
||||
expr_ty a;
|
||||
if (
|
||||
(a = expression_rule(p)) // expression
|
||||
(a = star_expressions_rule(p)) // star_expressions
|
||||
&&
|
||||
(_tmp_128_var = _tmp_128_rule(p)) // '=' | augassign
|
||||
(_literal = _PyPegen_expect_token(p, 22)) // token='='
|
||||
&&
|
||||
(_tmp_128_var = _tmp_128_rule(p)) // yield_expr | star_expressions
|
||||
)
|
||||
{
|
||||
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( _PyPegen_get_invalid_target ( a ) , "cannot assign to %s" , _PyPegen_get_expr_name ( _PyPegen_get_invalid_target ( a ) ) );
|
||||
if (_res == NULL && PyErr_Occurred()) {
|
||||
p->error_indicator = 1;
|
||||
return NULL;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
p->mark = _mark;
|
||||
}
|
||||
{ // star_expressions augassign (yield_expr | star_expressions)
|
||||
void *_tmp_129_var;
|
||||
expr_ty a;
|
||||
AugOperator* augassign_var;
|
||||
if (
|
||||
(a = star_expressions_rule(p)) // star_expressions
|
||||
&&
|
||||
(augassign_var = augassign_rule(p)) // augassign
|
||||
&&
|
||||
(_tmp_129_var = _tmp_129_rule(p)) // yield_expr | star_expressions
|
||||
)
|
||||
{
|
||||
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "cannot assign to %s" , _PyPegen_get_expr_name ( a ) );
|
||||
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "'%s' is an illegal expression for augmented assignment" , _PyPegen_get_expr_name ( a ) );
|
||||
if (_res == NULL && PyErr_Occurred()) {
|
||||
p->error_indicator = 1;
|
||||
return NULL;
|
||||
|
|
@ -16675,7 +16697,7 @@ _tmp_127_rule(Parser *p)
|
|||
return _res;
|
||||
}
|
||||
|
||||
// _tmp_128: '=' | augassign
|
||||
// _tmp_128: yield_expr | star_expressions
|
||||
static void *
|
||||
_tmp_128_rule(Parser *p)
|
||||
{
|
||||
|
|
@ -16684,24 +16706,24 @@ _tmp_128_rule(Parser *p)
|
|||
}
|
||||
void * _res = NULL;
|
||||
int _mark = p->mark;
|
||||
{ // '='
|
||||
Token * _literal;
|
||||
{ // yield_expr
|
||||
expr_ty yield_expr_var;
|
||||
if (
|
||||
(_literal = _PyPegen_expect_token(p, 22)) // token='='
|
||||
(yield_expr_var = yield_expr_rule(p)) // yield_expr
|
||||
)
|
||||
{
|
||||
_res = _literal;
|
||||
_res = yield_expr_var;
|
||||
goto done;
|
||||
}
|
||||
p->mark = _mark;
|
||||
}
|
||||
{ // augassign
|
||||
AugOperator* augassign_var;
|
||||
{ // star_expressions
|
||||
expr_ty star_expressions_var;
|
||||
if (
|
||||
(augassign_var = augassign_rule(p)) // augassign
|
||||
(star_expressions_var = star_expressions_rule(p)) // star_expressions
|
||||
)
|
||||
{
|
||||
_res = augassign_var;
|
||||
_res = star_expressions_var;
|
||||
goto done;
|
||||
}
|
||||
p->mark = _mark;
|
||||
|
|
|
|||
|
|
@ -2054,3 +2054,49 @@ _PyPegen_make_module(Parser *p, asdl_seq *a) {
|
|||
}
|
||||
return Module(a, type_ignores, p->arena);
|
||||
}
|
||||
|
||||
// Error reporting helpers
|
||||
|
||||
expr_ty
|
||||
_PyPegen_get_invalid_target(expr_ty e)
|
||||
{
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define VISIT_CONTAINER(CONTAINER, TYPE) do { \
|
||||
Py_ssize_t len = asdl_seq_LEN(CONTAINER->v.TYPE.elts);\
|
||||
for (Py_ssize_t i = 0; i < len; i++) {\
|
||||
expr_ty other = asdl_seq_GET(CONTAINER->v.TYPE.elts, i);\
|
||||
expr_ty child = _PyPegen_get_invalid_target(other);\
|
||||
if (child != NULL) {\
|
||||
return child;\
|
||||
}\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
// We only need to visit List and Tuple nodes recursively as those
|
||||
// are the only ones that can contain valid names in targets when
|
||||
// they are parsed as expressions. Any other kind of expression
|
||||
// that is a container (like Sets or Dicts) is directly invalid and
|
||||
// we don't need to visit it recursively.
|
||||
|
||||
switch (e->kind) {
|
||||
case List_kind: {
|
||||
VISIT_CONTAINER(e, List);
|
||||
return NULL;
|
||||
}
|
||||
case Tuple_kind: {
|
||||
VISIT_CONTAINER(e, Tuple);
|
||||
return NULL;
|
||||
}
|
||||
case Starred_kind:
|
||||
return _PyPegen_get_invalid_target(e->v.Starred.value);
|
||||
case Name_kind:
|
||||
case Subscript_kind:
|
||||
case Attribute_kind:
|
||||
return NULL;
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
|
@ -260,6 +260,10 @@ void *_PyPegen_arguments_parsing_error(Parser *, expr_ty);
|
|||
int _PyPegen_check_barry_as_flufl(Parser *);
|
||||
mod_ty _PyPegen_make_module(Parser *, asdl_seq *);
|
||||
|
||||
// Error reporting helpers
|
||||
|
||||
expr_ty _PyPegen_get_invalid_target(expr_ty e);
|
||||
|
||||
void *_PyPegen_parse(Parser *);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue