mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-40334: Produce better error messages on invalid targets (GH-20106)
The following error messages get produced: - `cannot delete ...` for invalid `del` targets - `... is an illegal 'for' target` for invalid targets in for statements - `... is an illegal 'with' target` for invalid targets in with statements Additionally, a few `cut`s were added in various places before the invocation of the `invalid_*` rule, in order to speed things up. Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
This commit is contained in:
parent
d906f0ec1a
commit
01ece63d42
6 changed files with 2651 additions and 2256 deletions
|
@ -380,7 +380,6 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
|
||||
Py_ssize_t lineno, Py_ssize_t col_offset,
|
||||
|
@ -2086,7 +2085,7 @@ _PyPegen_make_module(Parser *p, asdl_seq *a) {
|
|||
// Error reporting helpers
|
||||
|
||||
expr_ty
|
||||
_PyPegen_get_invalid_target(expr_ty e)
|
||||
_PyPegen_get_invalid_target(expr_ty e, TARGETS_TYPE targets_type)
|
||||
{
|
||||
if (e == NULL) {
|
||||
return NULL;
|
||||
|
@ -2096,7 +2095,7 @@ _PyPegen_get_invalid_target(expr_ty e)
|
|||
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);\
|
||||
expr_ty child = _PyPegen_get_invalid_target(other, targets_type);\
|
||||
if (child != NULL) {\
|
||||
return child;\
|
||||
}\
|
||||
|
@ -2110,16 +2109,29 @@ _PyPegen_get_invalid_target(expr_ty e)
|
|||
// we don't need to visit it recursively.
|
||||
|
||||
switch (e->kind) {
|
||||
case List_kind: {
|
||||
case List_kind:
|
||||
VISIT_CONTAINER(e, List);
|
||||
return NULL;
|
||||
}
|
||||
case Tuple_kind: {
|
||||
case Tuple_kind:
|
||||
VISIT_CONTAINER(e, Tuple);
|
||||
return NULL;
|
||||
}
|
||||
case Starred_kind:
|
||||
return _PyPegen_get_invalid_target(e->v.Starred.value);
|
||||
if (targets_type == DEL_TARGETS) {
|
||||
return e;
|
||||
}
|
||||
return _PyPegen_get_invalid_target(e->v.Starred.value, targets_type);
|
||||
case Compare_kind:
|
||||
// This is needed, because the `a in b` in `for a in b` gets parsed
|
||||
// as a comparison, and so we need to search the left side of the comparison
|
||||
// for invalid targets.
|
||||
if (targets_type == FOR_TARGETS) {
|
||||
cmpop_ty cmpop = (cmpop_ty) asdl_seq_GET(e->v.Compare.ops, 0);
|
||||
if (cmpop == In) {
|
||||
return _PyPegen_get_invalid_target(e->v.Compare.left, targets_type);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return e;
|
||||
case Name_kind:
|
||||
case Subscript_kind:
|
||||
case Attribute_kind:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue