From 445c7fd4b7e5bb4ea78b445968a893a566538914 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 13 May 2020 23:22:43 +0100 Subject: [PATCH 1/9] bpo-40334: Correctly identify invalid target in assignment errors --- Grammar/python.gram | 5 ++++- Lib/test/test_foo.py | 16 ++++++++++++++++ Lib/test/test_syntax.py | 25 ++++++++++++------------- Parser/pegen/parse.c | 2 +- Parser/pegen/pegen.c | 39 +++++++++++++++++++++++++++++++++++++++ Parser/pegen/pegen.h | 5 +++++ 6 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 Lib/test/test_foo.py diff --git a/Grammar/python.gram b/Grammar/python.gram index 9087c7aa718b17..bbaf4600a0b3a1 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -641,7 +641,10 @@ invalid_assignment: | a=expression ':' expression ['=' annotated_rhs] { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") } | a=expression ('=' | augassign) (yield_expr | star_expressions) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot assign to %s", _PyPegen_get_expr_name(a)) } + RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + _PyPegen_get_invalid_target(a), + "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a)) + )} invalid_block: | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") } invalid_comprehension: diff --git a/Lib/test/test_foo.py b/Lib/test/test_foo.py new file mode 100644 index 00000000000000..32e0e1a5c8f0b0 --- /dev/null +++ b/Lib/test/test_foo.py @@ -0,0 +1,16 @@ +import unittest +import zoneinfo +import tracemalloc + +class Test(unittest.TestCase): + def test_foo(self): + # snapshot1 = tracemalloc.take_snapshot() + zoneinfo.ZoneInfo.no_cache("America/Los_Angeles") + # snapshot2 = tracemalloc.take_snapshot() + # top_stats = snapshot2.compare_to(snapshot1, 'lineno') + + # print("[ Top 10 differences ]") + # for stat in top_stats[:10]: + # print(stat) + + diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index a3a101534628a2..51a5f42416ccea 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -100,30 +100,29 @@ This test just checks a couple of cases rather than enumerating all of them. -# All of the following also produce different error messages with pegen -# >>> (a, "b", c) = (1, 2, 3) -# Traceback (most recent call last): -# SyntaxError: cannot assign to literal +>>> (a, "b", c) = (1, 2, 3) +Traceback (most recent call last): +SyntaxError: cannot assign to literal -# >>> (a, True, c) = (1, 2, 3) -# Traceback (most recent call last): -# SyntaxError: cannot assign to True +>>> (a, True, c) = (1, 2, 3) +Traceback (most recent call last): +SyntaxError: cannot assign to True >>> (a, __debug__, c) = (1, 2, 3) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ -# >>> (a, *True, c) = (1, 2, 3) -# Traceback (most recent call last): -# SyntaxError: cannot assign to True +>>> (a, *True, c) = (1, 2, 3) +Traceback (most recent call last): +SyntaxError: cannot assign to True >>> (a, *__debug__, c) = (1, 2, 3) Traceback (most recent call last): SyntaxError: cannot assign to __debug__ -# >>> [a, b, c + 1] = [1, 2, 3] -# Traceback (most recent call last): -# SyntaxError: cannot assign to operator +>>> [a, b, c + 1] = [1, 2, 3] +Traceback (most recent call last): +SyntaxError: cannot assign to operator >>> a if 1 else b = 1 Traceback (most recent call last): diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index 851d17226d162f..10b966db066ead 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -10853,7 +10853,7 @@ invalid_assignment_rule(Parser *p) (_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 ( _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; diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 8b79a7364758e4..d1e51a9429073a 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2054,3 +2054,42 @@ _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; + } + switch (e->kind) { + case List_kind: { + Py_ssize_t len = asdl_seq_LEN(e->v.List.elts); + for (Py_ssize_t i = 0; i < len; i++) { + expr_ty other = asdl_seq_GET(e->v.List.elts, i); + if (_PyPegen_get_invalid_target(other)) { + return other; + } + } + return NULL; + } + case Tuple_kind: { + Py_ssize_t len = asdl_seq_LEN(e->v.Tuple.elts); + for (Py_ssize_t i = 0; i < len; i++) { + expr_ty other = asdl_seq_GET(e->v.Tuple.elts, i); + expr_ty child = _PyPegen_get_invalid_target(other); + if (child != NULL) { + return child; + } + } + return NULL; + } + case Starred_kind: + return _PyPegen_get_invalid_target(e->v.Starred.value); + case Name_kind: + return NULL; + default: + return e; + } +} \ No newline at end of file diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h index e5b1b757bd894b..964b5599f3d644 100644 --- a/Parser/pegen/pegen.h +++ b/Parser/pegen/pegen.h @@ -260,6 +260,11 @@ 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 From d385c2928d57cac20052b71261278a46487d4b2c Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 14 May 2020 00:12:53 +0100 Subject: [PATCH 2/9] Update Grammar/python.gram Co-authored-by: Lysandros Nikolaou --- Grammar/python.gram | 12 +- Lib/test/test_foo.py | 16 --- Lib/test/test_syntax.py | 8 ++ Parser/pegen/parse.c | 308 +++++++++++++++++++++++++--------------- Parser/pegen/pegen.c | 7 +- 5 files changed, 219 insertions(+), 132 deletions(-) delete mode 100644 Lib/test/test_foo.py diff --git a/Grammar/python.gram b/Grammar/python.gram index bbaf4600a0b3a1..a2e82f3ef82d75 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -640,11 +640,21 @@ invalid_assignment: RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "only single target (not tuple) can be annotated") } | a=expression ':' expression ['=' annotated_rhs] { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") } - | a=expression ('=' | augassign) (yield_expr | star_expressions) { + | a=star_expressions '=' (yield_expr | star_expressions) { RAISE_SYNTAX_ERROR_KNOWN_LOCATION( _PyPegen_get_invalid_target(a), "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a)) )} + | a=expression augassign (yield_expr | star_expressions) { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + _PyPegen_get_invalid_target(a), + "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a)) + )} + | a=star_expressions augassign (yield_expr | star_expressions) { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + a, + "illegal expression for augmented assignment" + )} invalid_block: | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") } invalid_comprehension: diff --git a/Lib/test/test_foo.py b/Lib/test/test_foo.py deleted file mode 100644 index 32e0e1a5c8f0b0..00000000000000 --- a/Lib/test/test_foo.py +++ /dev/null @@ -1,16 +0,0 @@ -import unittest -import zoneinfo -import tracemalloc - -class Test(unittest.TestCase): - def test_foo(self): - # snapshot1 = tracemalloc.take_snapshot() - zoneinfo.ZoneInfo.no_cache("America/Los_Angeles") - # snapshot2 = tracemalloc.take_snapshot() - # top_stats = snapshot2.compare_to(snapshot1, 'lineno') - - # print("[ Top 10 differences ]") - # for stat in top_stats[:10]: - # print(stat) - - diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 51a5f42416ccea..258152dabed9cb 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -124,6 +124,14 @@ Traceback (most recent call last): SyntaxError: cannot assign to operator +>>> [a, b[1], c + 1] = [1, 2, 3] +Traceback (most recent call last): +SyntaxError: cannot assign to operator + +>>> [a, b.c.d, c + 1] = [1, 2, 3] +Traceback (most recent call last): +SyntaxError: cannot assign to operator + >>> a if 1 else b = 1 Traceback (most recent call last): SyntaxError: cannot assign to conditional expression diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index 10b966db066ead..a068d047d314c7 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -351,8 +351,8 @@ static KeywordToken *reserved_keywords[] = { #define _tmp_128_type 1280 #define _tmp_129_type 1281 #define _tmp_130_type 1282 -#define _loop0_131_type 1283 -#define _tmp_132_type 1284 +#define _tmp_131_type 1283 +#define _loop0_132_type 1284 #define _tmp_133_type 1285 #define _tmp_134_type 1286 #define _tmp_135_type 1287 @@ -366,9 +366,10 @@ static KeywordToken *reserved_keywords[] = { #define _tmp_143_type 1295 #define _tmp_144_type 1296 #define _tmp_145_type 1297 -#define _loop1_146_type 1298 -#define _tmp_147_type 1299 +#define _tmp_146_type 1298 +#define _loop1_147_type 1299 #define _tmp_148_type 1300 +#define _tmp_149_type 1301 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -653,8 +654,8 @@ static void *_tmp_127_rule(Parser *p); static void *_tmp_128_rule(Parser *p); static void *_tmp_129_rule(Parser *p); static void *_tmp_130_rule(Parser *p); -static asdl_seq *_loop0_131_rule(Parser *p); -static void *_tmp_132_rule(Parser *p); +static void *_tmp_131_rule(Parser *p); +static asdl_seq *_loop0_132_rule(Parser *p); static void *_tmp_133_rule(Parser *p); static void *_tmp_134_rule(Parser *p); static void *_tmp_135_rule(Parser *p); @@ -668,9 +669,10 @@ static void *_tmp_142_rule(Parser *p); static void *_tmp_143_rule(Parser *p); static void *_tmp_144_rule(Parser *p); static void *_tmp_145_rule(Parser *p); -static asdl_seq *_loop1_146_rule(Parser *p); -static void *_tmp_147_rule(Parser *p); +static void *_tmp_146_rule(Parser *p); +static asdl_seq *_loop1_147_rule(Parser *p); static void *_tmp_148_rule(Parser *p); +static void *_tmp_149_rule(Parser *p); // file: statements? $ @@ -10747,7 +10749,9 @@ 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) +// | expression augassign (yield_expr | star_expressions) +// | star_expressions augassign (yield_expr | star_expressions) static void * invalid_assignment_rule(Parser *p) { @@ -10841,14 +10845,35 @@ 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; + expr_ty a; + if ( + (a = star_expressions_rule(p)) // star_expressions + && + (_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; + } + { // expression augassign (yield_expr | star_expressions) void *_tmp_129_var; expr_ty a; + AugOperator* augassign_var; if ( (a = expression_rule(p)) // expression && - (_tmp_128_var = _tmp_128_rule(p)) // '=' | augassign + (augassign_var = augassign_rule(p)) // augassign && (_tmp_129_var = _tmp_129_rule(p)) // yield_expr | star_expressions ) @@ -10862,6 +10887,27 @@ invalid_assignment_rule(Parser *p) } p->mark = _mark; } + { // star_expressions augassign (yield_expr | star_expressions) + void *_tmp_130_var; + expr_ty a; + AugOperator* augassign_var; + if ( + (a = star_expressions_rule(p)) // star_expressions + && + (augassign_var = augassign_rule(p)) // augassign + && + (_tmp_130_var = _tmp_130_rule(p)) // yield_expr | star_expressions + ) + { + _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal expression for augmented assignment" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + return NULL; + } + goto done; + } + p->mark = _mark; + } _res = NULL; done: return _res; @@ -10908,11 +10954,11 @@ invalid_comprehension_rule(Parser *p) void * _res = NULL; int _mark = p->mark; { // ('[' | '(' | '{') starred_expression for_if_clauses - void *_tmp_130_var; + void *_tmp_131_var; expr_ty a; asdl_seq* for_if_clauses_var; if ( - (_tmp_130_var = _tmp_130_rule(p)) // '[' | '(' | '{' + (_tmp_131_var = _tmp_131_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -10944,13 +10990,13 @@ invalid_parameters_rule(Parser *p) void * _res = NULL; int _mark = p->mark; { // param_no_default* (slash_with_default | param_with_default+) param_no_default - asdl_seq * _loop0_131_var; - void *_tmp_132_var; + asdl_seq * _loop0_132_var; + void *_tmp_133_var; arg_ty param_no_default_var; if ( - (_loop0_131_var = _loop0_131_rule(p)) // param_no_default* + (_loop0_132_var = _loop0_132_rule(p)) // param_no_default* && - (_tmp_132_var = _tmp_132_rule(p)) // slash_with_default | param_with_default+ + (_tmp_133_var = _tmp_133_rule(p)) // slash_with_default | param_with_default+ && (param_no_default_var = param_no_default_rule(p)) // param_no_default ) @@ -10980,11 +11026,11 @@ invalid_star_etc_rule(Parser *p) int _mark = p->mark; { // '*' (')' | ',' (')' | '**')) Token * _literal; - void *_tmp_133_var; + void *_tmp_134_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_133_var = _tmp_133_rule(p)) // ')' | ',' (')' | '**') + (_tmp_134_var = _tmp_134_rule(p)) // ')' | ',' (')' | '**') ) { _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); @@ -11012,11 +11058,11 @@ invalid_lambda_star_etc_rule(Parser *p) int _mark = p->mark; { // '*' (':' | ',' (':' | '**')) Token * _literal; - void *_tmp_134_var; + void *_tmp_135_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_134_var = _tmp_134_rule(p)) // ':' | ',' (':' | '**') + (_tmp_135_var = _tmp_135_rule(p)) // ':' | ',' (':' | '**') ) { _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); @@ -12000,12 +12046,12 @@ _loop1_22_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (star_targets '=') - void *_tmp_135_var; + void *_tmp_136_var; while ( - (_tmp_135_var = _tmp_135_rule(p)) // star_targets '=' + (_tmp_136_var = _tmp_136_rule(p)) // star_targets '=' ) { - _res = _tmp_135_var; + _res = _tmp_136_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -12327,12 +12373,12 @@ _loop0_30_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('.' | '...') - void *_tmp_136_var; + void *_tmp_137_var; while ( - (_tmp_136_var = _tmp_136_rule(p)) // '.' | '...' + (_tmp_137_var = _tmp_137_rule(p)) // '.' | '...' ) { - _res = _tmp_136_var; + _res = _tmp_137_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -12376,12 +12422,12 @@ _loop1_31_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('.' | '...') - void *_tmp_137_var; + void *_tmp_138_var; while ( - (_tmp_137_var = _tmp_137_rule(p)) // '.' | '...' + (_tmp_138_var = _tmp_138_rule(p)) // '.' | '...' ) { - _res = _tmp_137_var; + _res = _tmp_138_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -13958,12 +14004,12 @@ _loop1_67_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('@' named_expression NEWLINE) - void *_tmp_138_var; + void *_tmp_139_var; while ( - (_tmp_138_var = _tmp_138_rule(p)) // '@' named_expression NEWLINE + (_tmp_139_var = _tmp_139_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_138_var; + _res = _tmp_139_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -14131,12 +14177,12 @@ _loop1_71_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_expression) - void *_tmp_139_var; + void *_tmp_140_var; while ( - (_tmp_139_var = _tmp_139_rule(p)) // ',' star_expression + (_tmp_140_var = _tmp_140_rule(p)) // ',' star_expression ) { - _res = _tmp_139_var; + _res = _tmp_140_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -14269,12 +14315,12 @@ _loop1_74_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' expression) - void *_tmp_140_var; + void *_tmp_141_var; while ( - (_tmp_140_var = _tmp_140_rule(p)) // ',' expression + (_tmp_141_var = _tmp_141_rule(p)) // ',' expression ) { - _res = _tmp_140_var; + _res = _tmp_141_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15036,12 +15082,12 @@ _loop1_89_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('or' conjunction) - void *_tmp_141_var; + void *_tmp_142_var; while ( - (_tmp_141_var = _tmp_141_rule(p)) // 'or' conjunction + (_tmp_142_var = _tmp_142_rule(p)) // 'or' conjunction ) { - _res = _tmp_141_var; + _res = _tmp_142_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15089,12 +15135,12 @@ _loop1_90_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('and' inversion) - void *_tmp_142_var; + void *_tmp_143_var; while ( - (_tmp_142_var = _tmp_142_rule(p)) // 'and' inversion + (_tmp_143_var = _tmp_143_rule(p)) // 'and' inversion ) { - _res = _tmp_142_var; + _res = _tmp_143_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15744,12 +15790,12 @@ _loop0_105_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('if' disjunction) - void *_tmp_143_var; + void *_tmp_144_var; while ( - (_tmp_143_var = _tmp_143_rule(p)) // 'if' disjunction + (_tmp_144_var = _tmp_144_rule(p)) // 'if' disjunction ) { - _res = _tmp_143_var; + _res = _tmp_144_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15793,12 +15839,12 @@ _loop0_106_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('if' disjunction) - void *_tmp_144_var; + void *_tmp_145_var; while ( - (_tmp_144_var = _tmp_144_rule(p)) // 'if' disjunction + (_tmp_145_var = _tmp_145_rule(p)) // 'if' disjunction ) { - _res = _tmp_144_var; + _res = _tmp_145_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -16246,12 +16292,12 @@ _loop0_117_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_target) - void *_tmp_145_var; + void *_tmp_146_var; while ( - (_tmp_145_var = _tmp_145_rule(p)) // ',' star_target + (_tmp_146_var = _tmp_146_rule(p)) // ',' star_target ) { - _res = _tmp_145_var; + _res = _tmp_146_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -16675,7 +16721,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 +16730,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; @@ -16747,9 +16793,45 @@ _tmp_129_rule(Parser *p) return _res; } -// _tmp_130: '[' | '(' | '{' +// _tmp_130: yield_expr | star_expressions static void * _tmp_130_rule(Parser *p) +{ + if (p->error_indicator) { + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // yield_expr + expr_ty yield_expr_var; + if ( + (yield_expr_var = yield_expr_rule(p)) // yield_expr + ) + { + _res = yield_expr_var; + goto done; + } + p->mark = _mark; + } + { // star_expressions + expr_ty star_expressions_var; + if ( + (star_expressions_var = star_expressions_rule(p)) // star_expressions + ) + { + _res = star_expressions_var; + goto done; + } + p->mark = _mark; + } + _res = NULL; + done: + return _res; +} + +// _tmp_131: '[' | '(' | '{' +static void * +_tmp_131_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16794,9 +16876,9 @@ _tmp_130_rule(Parser *p) return _res; } -// _loop0_131: param_no_default +// _loop0_132: param_no_default static asdl_seq * -_loop0_131_rule(Parser *p) +_loop0_132_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16833,19 +16915,19 @@ _loop0_131_rule(Parser *p) } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); if (!_seq) { - PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop0_131"); + PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop0_132"); PyMem_Free(_children); return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_132_type, _seq); return _seq; } -// _tmp_132: slash_with_default | param_with_default+ +// _tmp_133: slash_with_default | param_with_default+ static void * -_tmp_132_rule(Parser *p) +_tmp_133_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16864,12 +16946,12 @@ _tmp_132_rule(Parser *p) p->mark = _mark; } { // param_with_default+ - asdl_seq * _loop1_146_var; + asdl_seq * _loop1_147_var; if ( - (_loop1_146_var = _loop1_146_rule(p)) // param_with_default+ + (_loop1_147_var = _loop1_147_rule(p)) // param_with_default+ ) { - _res = _loop1_146_var; + _res = _loop1_147_var; goto done; } p->mark = _mark; @@ -16879,9 +16961,9 @@ _tmp_132_rule(Parser *p) return _res; } -// _tmp_133: ')' | ',' (')' | '**') +// _tmp_134: ')' | ',' (')' | '**') static void * -_tmp_133_rule(Parser *p) +_tmp_134_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16901,14 +16983,14 @@ _tmp_133_rule(Parser *p) } { // ',' (')' | '**') Token * _literal; - void *_tmp_147_var; + void *_tmp_148_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_147_var = _tmp_147_rule(p)) // ')' | '**' + (_tmp_148_var = _tmp_148_rule(p)) // ')' | '**' ) { - _res = _PyPegen_dummy_name(p, _literal, _tmp_147_var); + _res = _PyPegen_dummy_name(p, _literal, _tmp_148_var); goto done; } p->mark = _mark; @@ -16918,9 +17000,9 @@ _tmp_133_rule(Parser *p) return _res; } -// _tmp_134: ':' | ',' (':' | '**') +// _tmp_135: ':' | ',' (':' | '**') static void * -_tmp_134_rule(Parser *p) +_tmp_135_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16940,14 +17022,14 @@ _tmp_134_rule(Parser *p) } { // ',' (':' | '**') Token * _literal; - void *_tmp_148_var; + void *_tmp_149_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_148_var = _tmp_148_rule(p)) // ':' | '**' + (_tmp_149_var = _tmp_149_rule(p)) // ':' | '**' ) { - _res = _PyPegen_dummy_name(p, _literal, _tmp_148_var); + _res = _PyPegen_dummy_name(p, _literal, _tmp_149_var); goto done; } p->mark = _mark; @@ -16957,9 +17039,9 @@ _tmp_134_rule(Parser *p) return _res; } -// _tmp_135: star_targets '=' +// _tmp_136: star_targets '=' static void * -_tmp_135_rule(Parser *p) +_tmp_136_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16989,9 +17071,9 @@ _tmp_135_rule(Parser *p) return _res; } -// _tmp_136: '.' | '...' +// _tmp_137: '.' | '...' static void * -_tmp_136_rule(Parser *p) +_tmp_137_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17025,9 +17107,9 @@ _tmp_136_rule(Parser *p) return _res; } -// _tmp_137: '.' | '...' +// _tmp_138: '.' | '...' static void * -_tmp_137_rule(Parser *p) +_tmp_138_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17061,9 +17143,9 @@ _tmp_137_rule(Parser *p) return _res; } -// _tmp_138: '@' named_expression NEWLINE +// _tmp_139: '@' named_expression NEWLINE static void * -_tmp_138_rule(Parser *p) +_tmp_139_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17096,9 +17178,9 @@ _tmp_138_rule(Parser *p) return _res; } -// _tmp_139: ',' star_expression +// _tmp_140: ',' star_expression static void * -_tmp_139_rule(Parser *p) +_tmp_140_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17128,9 +17210,9 @@ _tmp_139_rule(Parser *p) return _res; } -// _tmp_140: ',' expression +// _tmp_141: ',' expression static void * -_tmp_140_rule(Parser *p) +_tmp_141_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17160,9 +17242,9 @@ _tmp_140_rule(Parser *p) return _res; } -// _tmp_141: 'or' conjunction +// _tmp_142: 'or' conjunction static void * -_tmp_141_rule(Parser *p) +_tmp_142_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17192,9 +17274,9 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: 'and' inversion +// _tmp_143: 'and' inversion static void * -_tmp_142_rule(Parser *p) +_tmp_143_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17224,9 +17306,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: 'if' disjunction +// _tmp_144: 'if' disjunction static void * -_tmp_143_rule(Parser *p) +_tmp_144_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17256,9 +17338,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: 'if' disjunction +// _tmp_145: 'if' disjunction static void * -_tmp_144_rule(Parser *p) +_tmp_145_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17288,9 +17370,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: ',' star_target +// _tmp_146: ',' star_target static void * -_tmp_145_rule(Parser *p) +_tmp_146_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17320,9 +17402,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _loop1_146: param_with_default +// _loop1_147: param_with_default static asdl_seq * -_loop1_146_rule(Parser *p) +_loop1_147_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17363,19 +17445,19 @@ _loop1_146_rule(Parser *p) } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); if (!_seq) { - PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop1_146"); + PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop1_147"); PyMem_Free(_children); return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_146_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_147_type, _seq); return _seq; } -// _tmp_147: ')' | '**' +// _tmp_148: ')' | '**' static void * -_tmp_147_rule(Parser *p) +_tmp_148_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17409,9 +17491,9 @@ _tmp_147_rule(Parser *p) return _res; } -// _tmp_148: ':' | '**' +// _tmp_149: ':' | '**' static void * -_tmp_148_rule(Parser *p) +_tmp_149_rule(Parser *p) { if (p->error_indicator) { return NULL; diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index d1e51a9429073a..aa1c5a5fb33972 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2068,8 +2068,9 @@ _PyPegen_get_invalid_target(expr_ty e) Py_ssize_t len = asdl_seq_LEN(e->v.List.elts); for (Py_ssize_t i = 0; i < len; i++) { expr_ty other = asdl_seq_GET(e->v.List.elts, i); - if (_PyPegen_get_invalid_target(other)) { - return other; + expr_ty child = _PyPegen_get_invalid_target(other); + if (child != NULL) { + return child; } } return NULL; @@ -2088,6 +2089,8 @@ _PyPegen_get_invalid_target(expr_ty e) 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; From b596bbaa83af39fa7b46d3d9c147f15ee2841ba1 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 14 May 2020 03:20:28 +0100 Subject: [PATCH 3/9] Deduplicate code with macro --- Parser/pegen/pegen.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index aa1c5a5fb33972..e0073cf138ad17 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2063,27 +2063,25 @@ _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) + switch (e->kind) { case List_kind: { - Py_ssize_t len = asdl_seq_LEN(e->v.List.elts); - for (Py_ssize_t i = 0; i < len; i++) { - expr_ty other = asdl_seq_GET(e->v.List.elts, i); - expr_ty child = _PyPegen_get_invalid_target(other); - if (child != NULL) { - return child; - } - } + VISIT_CONTAINER(e, List); return NULL; } case Tuple_kind: { - Py_ssize_t len = asdl_seq_LEN(e->v.Tuple.elts); - for (Py_ssize_t i = 0; i < len; i++) { - expr_ty other = asdl_seq_GET(e->v.Tuple.elts, i); - expr_ty child = _PyPegen_get_invalid_target(other); - if (child != NULL) { - return child; - } - } + VISIT_CONTAINER(e, Tuple); return NULL; } case Starred_kind: From 4f2cb72b5ae98e5c24c3b4dfc94b0f121cc70769 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 00:38:07 +0100 Subject: [PATCH 4/9] Fix error for augassign --- Grammar/python.gram | 19 ++++++------------- Lib/test/test_syntax.py | 6 +++--- Parser/pegen/parse.c | 2 +- Parser/pegen/pegen.c | 16 +++++++++++++++- Parser/pegen/pegen.h | 2 +- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index a2e82f3ef82d75..3dcbba926d7546 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -641,20 +641,13 @@ invalid_assignment: | a=expression ':' expression ['=' annotated_rhs] { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") } | a=star_expressions '=' (yield_expr | star_expressions) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION( - _PyPegen_get_invalid_target(a), - "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a)) - )} - | a=expression augassign (yield_expr | star_expressions) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION( - _PyPegen_get_invalid_target(a), - "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a)) - )} + RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + _PyPegen_get_invalid_target(a), + "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a))) } + | a=expression augassign (yield_expr | star_expressions) { _PyPegen_raise_syntax_error_for_augassign(p, a) } | a=star_expressions augassign (yield_expr | star_expressions) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION( - a, - "illegal expression for augmented assignment" - )} + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal expression for augmented assignment") } + invalid_block: | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") } invalid_comprehension: diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 258152dabed9cb..b471f88c91f42f 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -138,15 +138,15 @@ >>> a, b += 1, 2 Traceback (most recent call last): -SyntaxError: invalid syntax +SyntaxError: illegal expression for augmented assignment >>> (a, b) += 1, 2 Traceback (most recent call last): -SyntaxError: cannot assign to tuple +SyntaxError: illegal expression for augmented assignment >>> [a, b] += 1, 2 Traceback (most recent call last): -SyntaxError: cannot assign to list +SyntaxError: illegal expression for augmented assignment From compiler_complex_args(): diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index a068d047d314c7..ddf377a5376608 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -10878,7 +10878,7 @@ invalid_assignment_rule(Parser *p) (_tmp_129_var = _tmp_129_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 ) ) ); + _res = _PyPegen_raise_syntax_error_for_augassign ( p , a ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; return NULL; diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index e0073cf138ad17..e10eae5c2dd01c 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2093,4 +2093,18 @@ _PyPegen_get_invalid_target(expr_ty e) default: return e; } -} \ No newline at end of file +} + +void * +_PyPegen_raise_syntax_error_for_augassign(Parser *p, expr_ty e) { + expr_ty invalid_target = _PyPegen_get_invalid_target(e); + + if (invalid_target != NULL) { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(invalid_target, + "cannot assign to %s", _PyPegen_get_expr_name(invalid_target)); + } else { + RAISE_SYNTAX_ERROR_KNOWN_LOCATION(e, "illegal expression for augmented assignment"); + } + return NULL; +} + diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h index 964b5599f3d644..4e7f8adc692093 100644 --- a/Parser/pegen/pegen.h +++ b/Parser/pegen/pegen.h @@ -263,7 +263,7 @@ mod_ty _PyPegen_make_module(Parser *, asdl_seq *); // Error reporting helpers expr_ty _PyPegen_get_invalid_target(expr_ty e); - +void *_PyPegen_raise_syntax_error_for_augassign(Parser *p, expr_ty e); void *_PyPegen_parse(Parser *); From c74ecceea9c9673ff0f04d4d92c6b52170e67cf6 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 01:02:19 +0100 Subject: [PATCH 5/9] Address Lysandros's feedback --- Grammar/python.gram | 7 +- Lib/test/test_syntax.py | 13 +- Parser/pegen/parse.c | 268 ++++++++++++++++------------------------ Parser/pegen/pegen.c | 16 +-- Parser/pegen/pegen.h | 1 - Python/ast.c | 13 +- 6 files changed, 125 insertions(+), 193 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index 3dcbba926d7546..9c511fa576303e 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -644,9 +644,12 @@ invalid_assignment: RAISE_SYNTAX_ERROR_KNOWN_LOCATION( _PyPegen_get_invalid_target(a), "cannot assign to %s", _PyPegen_get_expr_name(_PyPegen_get_invalid_target(a))) } - | a=expression augassign (yield_expr | star_expressions) { _PyPegen_raise_syntax_error_for_augassign(p, a) } | a=star_expressions augassign (yield_expr | star_expressions) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal expression for augmented assignment") } + RAISE_SYNTAX_ERROR_KNOWN_LOCATION( + a, + "%s is an illegal expression for augmented assignment", + _PyPegen_get_expr_name(a) + )} invalid_block: | NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") } diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index b471f88c91f42f..5ae2c61e9abb6e 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -138,15 +138,15 @@ >>> a, b += 1, 2 Traceback (most recent call last): -SyntaxError: illegal expression for augmented assignment +SyntaxError: tuple is an illegal expression for augmented assignment >>> (a, b) += 1, 2 Traceback (most recent call last): -SyntaxError: illegal expression for augmented assignment +SyntaxError: tuple is an illegal expression for augmented assignment >>> [a, b] += 1, 2 Traceback (most recent call last): -SyntaxError: illegal expression for augmented assignment +SyntaxError: list is an illegal expression for augmented assignment From compiler_complex_args(): @@ -353,16 +353,16 @@ >>> (x for x in x) += 1 Traceback (most recent call last): -SyntaxError: cannot assign to generator expression +SyntaxError: generator expression is an illegal expression for augmented assignment >>> None += 1 Traceback (most recent call last): -SyntaxError: cannot assign to None +SyntaxError: None is an illegal expression for augmented assignment >>> __debug__ += 1 Traceback (most recent call last): SyntaxError: cannot assign to __debug__ >>> f() += 1 Traceback (most recent call last): -SyntaxError: cannot assign to function call +SyntaxError: function call is an illegal expression for augmented assignment Test continue in finally in weird combinations. @@ -695,6 +695,7 @@ def _check_error(self, code, errtext, def test_assign_call(self): self._check_error("f() = 1", "assign") + @unittest.skipIf(support.use_old_parser(), "The old parser cannot generate these error messages") def test_assign_del(self): self._check_error("del (,)", "invalid syntax") self._check_error("del 1", "delete literal") diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index ddf377a5376608..1bd43410801c9f 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -351,8 +351,8 @@ static KeywordToken *reserved_keywords[] = { #define _tmp_128_type 1280 #define _tmp_129_type 1281 #define _tmp_130_type 1282 -#define _tmp_131_type 1283 -#define _loop0_132_type 1284 +#define _loop0_131_type 1283 +#define _tmp_132_type 1284 #define _tmp_133_type 1285 #define _tmp_134_type 1286 #define _tmp_135_type 1287 @@ -366,10 +366,9 @@ static KeywordToken *reserved_keywords[] = { #define _tmp_143_type 1295 #define _tmp_144_type 1296 #define _tmp_145_type 1297 -#define _tmp_146_type 1298 -#define _loop1_147_type 1299 +#define _loop1_146_type 1298 +#define _tmp_147_type 1299 #define _tmp_148_type 1300 -#define _tmp_149_type 1301 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -654,8 +653,8 @@ static void *_tmp_127_rule(Parser *p); static void *_tmp_128_rule(Parser *p); static void *_tmp_129_rule(Parser *p); static void *_tmp_130_rule(Parser *p); -static void *_tmp_131_rule(Parser *p); -static asdl_seq *_loop0_132_rule(Parser *p); +static asdl_seq *_loop0_131_rule(Parser *p); +static void *_tmp_132_rule(Parser *p); static void *_tmp_133_rule(Parser *p); static void *_tmp_134_rule(Parser *p); static void *_tmp_135_rule(Parser *p); @@ -669,10 +668,9 @@ static void *_tmp_142_rule(Parser *p); static void *_tmp_143_rule(Parser *p); static void *_tmp_144_rule(Parser *p); static void *_tmp_145_rule(Parser *p); -static void *_tmp_146_rule(Parser *p); -static asdl_seq *_loop1_147_rule(Parser *p); +static asdl_seq *_loop1_146_rule(Parser *p); +static void *_tmp_147_rule(Parser *p); static void *_tmp_148_rule(Parser *p); -static void *_tmp_149_rule(Parser *p); // file: statements? $ @@ -10750,7 +10748,6 @@ invalid_named_expression_rule(Parser *p) // | star_named_expression ',' star_named_expressions* ':' // | expression ':' expression ['=' annotated_rhs] // | star_expressions '=' (yield_expr | star_expressions) -// | expression augassign (yield_expr | star_expressions) // | star_expressions augassign (yield_expr | star_expressions) static void * invalid_assignment_rule(Parser *p) @@ -10866,29 +10863,8 @@ invalid_assignment_rule(Parser *p) } p->mark = _mark; } - { // expression augassign (yield_expr | star_expressions) - void *_tmp_129_var; - expr_ty a; - AugOperator* augassign_var; - if ( - (a = expression_rule(p)) // expression - && - (augassign_var = augassign_rule(p)) // augassign - && - (_tmp_129_var = _tmp_129_rule(p)) // yield_expr | star_expressions - ) - { - _res = _PyPegen_raise_syntax_error_for_augassign ( p , 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_130_var; + void *_tmp_129_var; expr_ty a; AugOperator* augassign_var; if ( @@ -10896,10 +10872,10 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_130_var = _tmp_130_rule(p)) // yield_expr | star_expressions + (_tmp_129_var = _tmp_129_rule(p)) // yield_expr | star_expressions ) { - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "illegal expression for augmented assignment" ); + _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; @@ -10954,11 +10930,11 @@ invalid_comprehension_rule(Parser *p) void * _res = NULL; int _mark = p->mark; { // ('[' | '(' | '{') starred_expression for_if_clauses - void *_tmp_131_var; + void *_tmp_130_var; expr_ty a; asdl_seq* for_if_clauses_var; if ( - (_tmp_131_var = _tmp_131_rule(p)) // '[' | '(' | '{' + (_tmp_130_var = _tmp_130_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -10990,13 +10966,13 @@ invalid_parameters_rule(Parser *p) void * _res = NULL; int _mark = p->mark; { // param_no_default* (slash_with_default | param_with_default+) param_no_default - asdl_seq * _loop0_132_var; - void *_tmp_133_var; + asdl_seq * _loop0_131_var; + void *_tmp_132_var; arg_ty param_no_default_var; if ( - (_loop0_132_var = _loop0_132_rule(p)) // param_no_default* + (_loop0_131_var = _loop0_131_rule(p)) // param_no_default* && - (_tmp_133_var = _tmp_133_rule(p)) // slash_with_default | param_with_default+ + (_tmp_132_var = _tmp_132_rule(p)) // slash_with_default | param_with_default+ && (param_no_default_var = param_no_default_rule(p)) // param_no_default ) @@ -11026,11 +11002,11 @@ invalid_star_etc_rule(Parser *p) int _mark = p->mark; { // '*' (')' | ',' (')' | '**')) Token * _literal; - void *_tmp_134_var; + void *_tmp_133_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_134_var = _tmp_134_rule(p)) // ')' | ',' (')' | '**') + (_tmp_133_var = _tmp_133_rule(p)) // ')' | ',' (')' | '**') ) { _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); @@ -11058,11 +11034,11 @@ invalid_lambda_star_etc_rule(Parser *p) int _mark = p->mark; { // '*' (':' | ',' (':' | '**')) Token * _literal; - void *_tmp_135_var; + void *_tmp_134_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_135_var = _tmp_135_rule(p)) // ':' | ',' (':' | '**') + (_tmp_134_var = _tmp_134_rule(p)) // ':' | ',' (':' | '**') ) { _res = RAISE_SYNTAX_ERROR ( "named arguments must follow bare *" ); @@ -12046,12 +12022,12 @@ _loop1_22_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (star_targets '=') - void *_tmp_136_var; + void *_tmp_135_var; while ( - (_tmp_136_var = _tmp_136_rule(p)) // star_targets '=' + (_tmp_135_var = _tmp_135_rule(p)) // star_targets '=' ) { - _res = _tmp_136_var; + _res = _tmp_135_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -12373,12 +12349,12 @@ _loop0_30_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('.' | '...') - void *_tmp_137_var; + void *_tmp_136_var; while ( - (_tmp_137_var = _tmp_137_rule(p)) // '.' | '...' + (_tmp_136_var = _tmp_136_rule(p)) // '.' | '...' ) { - _res = _tmp_137_var; + _res = _tmp_136_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -12422,12 +12398,12 @@ _loop1_31_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('.' | '...') - void *_tmp_138_var; + void *_tmp_137_var; while ( - (_tmp_138_var = _tmp_138_rule(p)) // '.' | '...' + (_tmp_137_var = _tmp_137_rule(p)) // '.' | '...' ) { - _res = _tmp_138_var; + _res = _tmp_137_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -14004,12 +13980,12 @@ _loop1_67_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('@' named_expression NEWLINE) - void *_tmp_139_var; + void *_tmp_138_var; while ( - (_tmp_139_var = _tmp_139_rule(p)) // '@' named_expression NEWLINE + (_tmp_138_var = _tmp_138_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_139_var; + _res = _tmp_138_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -14177,12 +14153,12 @@ _loop1_71_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_expression) - void *_tmp_140_var; + void *_tmp_139_var; while ( - (_tmp_140_var = _tmp_140_rule(p)) // ',' star_expression + (_tmp_139_var = _tmp_139_rule(p)) // ',' star_expression ) { - _res = _tmp_140_var; + _res = _tmp_139_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -14315,12 +14291,12 @@ _loop1_74_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' expression) - void *_tmp_141_var; + void *_tmp_140_var; while ( - (_tmp_141_var = _tmp_141_rule(p)) // ',' expression + (_tmp_140_var = _tmp_140_rule(p)) // ',' expression ) { - _res = _tmp_141_var; + _res = _tmp_140_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15082,12 +15058,12 @@ _loop1_89_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('or' conjunction) - void *_tmp_142_var; + void *_tmp_141_var; while ( - (_tmp_142_var = _tmp_142_rule(p)) // 'or' conjunction + (_tmp_141_var = _tmp_141_rule(p)) // 'or' conjunction ) { - _res = _tmp_142_var; + _res = _tmp_141_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15135,12 +15111,12 @@ _loop1_90_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('and' inversion) - void *_tmp_143_var; + void *_tmp_142_var; while ( - (_tmp_143_var = _tmp_143_rule(p)) // 'and' inversion + (_tmp_142_var = _tmp_142_rule(p)) // 'and' inversion ) { - _res = _tmp_143_var; + _res = _tmp_142_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15790,12 +15766,12 @@ _loop0_105_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('if' disjunction) - void *_tmp_144_var; + void *_tmp_143_var; while ( - (_tmp_144_var = _tmp_144_rule(p)) // 'if' disjunction + (_tmp_143_var = _tmp_143_rule(p)) // 'if' disjunction ) { - _res = _tmp_144_var; + _res = _tmp_143_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -15839,12 +15815,12 @@ _loop0_106_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // ('if' disjunction) - void *_tmp_145_var; + void *_tmp_144_var; while ( - (_tmp_145_var = _tmp_145_rule(p)) // 'if' disjunction + (_tmp_144_var = _tmp_144_rule(p)) // 'if' disjunction ) { - _res = _tmp_145_var; + _res = _tmp_144_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -16292,12 +16268,12 @@ _loop0_117_rule(Parser *p) ssize_t _children_capacity = 1; ssize_t _n = 0; { // (',' star_target) - void *_tmp_146_var; + void *_tmp_145_var; while ( - (_tmp_146_var = _tmp_146_rule(p)) // ',' star_target + (_tmp_145_var = _tmp_145_rule(p)) // ',' star_target ) { - _res = _tmp_146_var; + _res = _tmp_145_var; if (_n == _children_capacity) { _children_capacity *= 2; _children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -16793,45 +16769,9 @@ _tmp_129_rule(Parser *p) return _res; } -// _tmp_130: yield_expr | star_expressions +// _tmp_130: '[' | '(' | '{' static void * _tmp_130_rule(Parser *p) -{ - if (p->error_indicator) { - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - } - { // star_expressions - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - } - _res = NULL; - done: - return _res; -} - -// _tmp_131: '[' | '(' | '{' -static void * -_tmp_131_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16876,9 +16816,9 @@ _tmp_131_rule(Parser *p) return _res; } -// _loop0_132: param_no_default +// _loop0_131: param_no_default static asdl_seq * -_loop0_132_rule(Parser *p) +_loop0_131_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16915,19 +16855,19 @@ _loop0_132_rule(Parser *p) } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); if (!_seq) { - PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop0_132"); + PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop0_131"); PyMem_Free(_children); return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_132_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq); return _seq; } -// _tmp_133: slash_with_default | param_with_default+ +// _tmp_132: slash_with_default | param_with_default+ static void * -_tmp_133_rule(Parser *p) +_tmp_132_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16946,12 +16886,12 @@ _tmp_133_rule(Parser *p) p->mark = _mark; } { // param_with_default+ - asdl_seq * _loop1_147_var; + asdl_seq * _loop1_146_var; if ( - (_loop1_147_var = _loop1_147_rule(p)) // param_with_default+ + (_loop1_146_var = _loop1_146_rule(p)) // param_with_default+ ) { - _res = _loop1_147_var; + _res = _loop1_146_var; goto done; } p->mark = _mark; @@ -16961,9 +16901,9 @@ _tmp_133_rule(Parser *p) return _res; } -// _tmp_134: ')' | ',' (')' | '**') +// _tmp_133: ')' | ',' (')' | '**') static void * -_tmp_134_rule(Parser *p) +_tmp_133_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -16983,14 +16923,14 @@ _tmp_134_rule(Parser *p) } { // ',' (')' | '**') Token * _literal; - void *_tmp_148_var; + void *_tmp_147_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_148_var = _tmp_148_rule(p)) // ')' | '**' + (_tmp_147_var = _tmp_147_rule(p)) // ')' | '**' ) { - _res = _PyPegen_dummy_name(p, _literal, _tmp_148_var); + _res = _PyPegen_dummy_name(p, _literal, _tmp_147_var); goto done; } p->mark = _mark; @@ -17000,9 +16940,9 @@ _tmp_134_rule(Parser *p) return _res; } -// _tmp_135: ':' | ',' (':' | '**') +// _tmp_134: ':' | ',' (':' | '**') static void * -_tmp_135_rule(Parser *p) +_tmp_134_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17022,14 +16962,14 @@ _tmp_135_rule(Parser *p) } { // ',' (':' | '**') Token * _literal; - void *_tmp_149_var; + void *_tmp_148_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_149_var = _tmp_149_rule(p)) // ':' | '**' + (_tmp_148_var = _tmp_148_rule(p)) // ':' | '**' ) { - _res = _PyPegen_dummy_name(p, _literal, _tmp_149_var); + _res = _PyPegen_dummy_name(p, _literal, _tmp_148_var); goto done; } p->mark = _mark; @@ -17039,9 +16979,9 @@ _tmp_135_rule(Parser *p) return _res; } -// _tmp_136: star_targets '=' +// _tmp_135: star_targets '=' static void * -_tmp_136_rule(Parser *p) +_tmp_135_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17071,9 +17011,9 @@ _tmp_136_rule(Parser *p) return _res; } -// _tmp_137: '.' | '...' +// _tmp_136: '.' | '...' static void * -_tmp_137_rule(Parser *p) +_tmp_136_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17107,9 +17047,9 @@ _tmp_137_rule(Parser *p) return _res; } -// _tmp_138: '.' | '...' +// _tmp_137: '.' | '...' static void * -_tmp_138_rule(Parser *p) +_tmp_137_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17143,9 +17083,9 @@ _tmp_138_rule(Parser *p) return _res; } -// _tmp_139: '@' named_expression NEWLINE +// _tmp_138: '@' named_expression NEWLINE static void * -_tmp_139_rule(Parser *p) +_tmp_138_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17178,9 +17118,9 @@ _tmp_139_rule(Parser *p) return _res; } -// _tmp_140: ',' star_expression +// _tmp_139: ',' star_expression static void * -_tmp_140_rule(Parser *p) +_tmp_139_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17210,9 +17150,9 @@ _tmp_140_rule(Parser *p) return _res; } -// _tmp_141: ',' expression +// _tmp_140: ',' expression static void * -_tmp_141_rule(Parser *p) +_tmp_140_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17242,9 +17182,9 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: 'or' conjunction +// _tmp_141: 'or' conjunction static void * -_tmp_142_rule(Parser *p) +_tmp_141_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17274,9 +17214,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: 'and' inversion +// _tmp_142: 'and' inversion static void * -_tmp_143_rule(Parser *p) +_tmp_142_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17306,9 +17246,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: 'if' disjunction +// _tmp_143: 'if' disjunction static void * -_tmp_144_rule(Parser *p) +_tmp_143_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17338,9 +17278,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: 'if' disjunction +// _tmp_144: 'if' disjunction static void * -_tmp_145_rule(Parser *p) +_tmp_144_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17370,9 +17310,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _tmp_146: ',' star_target +// _tmp_145: ',' star_target static void * -_tmp_146_rule(Parser *p) +_tmp_145_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17402,9 +17342,9 @@ _tmp_146_rule(Parser *p) return _res; } -// _loop1_147: param_with_default +// _loop1_146: param_with_default static asdl_seq * -_loop1_147_rule(Parser *p) +_loop1_146_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17445,19 +17385,19 @@ _loop1_147_rule(Parser *p) } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); if (!_seq) { - PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop1_147"); + PyErr_Format(PyExc_MemoryError, "asdl_seq_new _loop1_146"); PyMem_Free(_children); return NULL; } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_147_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_146_type, _seq); return _seq; } -// _tmp_148: ')' | '**' +// _tmp_147: ')' | '**' static void * -_tmp_148_rule(Parser *p) +_tmp_147_rule(Parser *p) { if (p->error_indicator) { return NULL; @@ -17491,9 +17431,9 @@ _tmp_148_rule(Parser *p) return _res; } -// _tmp_149: ':' | '**' +// _tmp_148: ':' | '**' static void * -_tmp_149_rule(Parser *p) +_tmp_148_rule(Parser *p) { if (p->error_indicator) { return NULL; diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index e10eae5c2dd01c..e0073cf138ad17 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2093,18 +2093,4 @@ _PyPegen_get_invalid_target(expr_ty e) default: return e; } -} - -void * -_PyPegen_raise_syntax_error_for_augassign(Parser *p, expr_ty e) { - expr_ty invalid_target = _PyPegen_get_invalid_target(e); - - if (invalid_target != NULL) { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(invalid_target, - "cannot assign to %s", _PyPegen_get_expr_name(invalid_target)); - } else { - RAISE_SYNTAX_ERROR_KNOWN_LOCATION(e, "illegal expression for augmented assignment"); - } - return NULL; -} - +} \ No newline at end of file diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h index 4e7f8adc692093..b9d4c048bb52b0 100644 --- a/Parser/pegen/pegen.h +++ b/Parser/pegen/pegen.h @@ -263,7 +263,6 @@ mod_ty _PyPegen_make_module(Parser *, asdl_seq *); // Error reporting helpers expr_ty _PyPegen_get_invalid_target(expr_ty e); -void *_PyPegen_raise_syntax_error_for_augassign(Parser *p, expr_ty e); void *_PyPegen_parse(Parser *); diff --git a/Python/ast.c b/Python/ast.c index 1a4a3110e69559..cef464039c2f7a 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3164,10 +3164,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) expr1 = ast_for_testlist(c, ch); if (!expr1) return NULL; - if(!set_context(c, expr1, Store, ch)) - return NULL; - /* set_context checks that most expressions are not the left side. - Augmented assignments can only have a name, a subscript, or an + /* Augmented assignments can only have a name, a subscript, or an attribute on the left, though, so we have to explicitly check for those. */ switch (expr1->kind) { @@ -3176,10 +3173,16 @@ ast_for_expr_stmt(struct compiling *c, const node *n) case Subscript_kind: break; default: - ast_error(c, ch, "illegal expression for augmented assignment"); + ast_error(c, ch, "%s is an illegal expression for augmented assignment", + get_expr_name(expr1)); return NULL; } + /* set_context checks that most expressions are not the left side. */ + if(!set_context(c, expr1, Store, ch)) { + return NULL; + } + ch = CHILD(n, 2); if (TYPE(ch) == testlist) expr2 = ast_for_testlist(c, ch); From 6d1d63cfe9cb6067cbd00546d27537b0f7e85506 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 01:13:23 +0100 Subject: [PATCH 6/9] Add quotes around the node type --- Grammar/python.gram | 2 +- Lib/test/test_syntax.py | 12 ++++++------ Parser/pegen/parse.c | 2 +- Python/ast.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index 9c511fa576303e..cca92090546265 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -647,7 +647,7 @@ invalid_assignment: | a=star_expressions augassign (yield_expr | star_expressions) { RAISE_SYNTAX_ERROR_KNOWN_LOCATION( a, - "%s is an illegal expression for augmented assignment", + "'%s' is an illegal expression for augmented assignment", _PyPegen_get_expr_name(a) )} diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 5ae2c61e9abb6e..60c7d9fd3868e8 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -138,15 +138,15 @@ >>> a, b += 1, 2 Traceback (most recent call last): -SyntaxError: tuple is an illegal expression for augmented assignment +SyntaxError: 'tuple' is an illegal expression for augmented assignment >>> (a, b) += 1, 2 Traceback (most recent call last): -SyntaxError: tuple is an illegal expression for augmented assignment +SyntaxError: 'tuple' is an illegal expression for augmented assignment >>> [a, b] += 1, 2 Traceback (most recent call last): -SyntaxError: list is an illegal expression for augmented assignment +SyntaxError: 'list' is an illegal expression for augmented assignment From compiler_complex_args(): @@ -353,16 +353,16 @@ >>> (x for x in x) += 1 Traceback (most recent call last): -SyntaxError: generator expression is an illegal expression for augmented assignment +SyntaxError: 'generator expression' is an illegal expression for augmented assignment >>> None += 1 Traceback (most recent call last): -SyntaxError: None is an illegal expression for augmented assignment +SyntaxError: 'None' is an illegal expression for augmented assignment >>> __debug__ += 1 Traceback (most recent call last): SyntaxError: cannot assign to __debug__ >>> f() += 1 Traceback (most recent call last): -SyntaxError: function call is an illegal expression for augmented assignment +SyntaxError: 'function call' is an illegal expression for augmented assignment Test continue in finally in weird combinations. diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index 1bd43410801c9f..f4c5692212768d 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -10875,7 +10875,7 @@ invalid_assignment_rule(Parser *p) (_tmp_129_var = _tmp_129_rule(p)) // yield_expr | star_expressions ) { - _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "%s is an illegal expression for augmented assignment" , _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; diff --git a/Python/ast.c b/Python/ast.c index cef464039c2f7a..2d20ca62aa8378 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3173,7 +3173,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n) case Subscript_kind: break; default: - ast_error(c, ch, "%s is an illegal expression for augmented assignment", + ast_error(c, ch, "'%s' is an illegal expression for augmented assignment", get_expr_name(expr1)); return NULL; } From 00a2205b87f8a43358407212241a4fc0f6e82af3 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 01:26:29 +0100 Subject: [PATCH 7/9] Update test_dictcomps, test_genexps and test_generators --- Lib/test/test_dictcomps.py | 2 +- Lib/test/test_generators.py | 2 +- Lib/test/test_genexps.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_dictcomps.py b/Lib/test/test_dictcomps.py index 16aa651b93c46b..472e3dfa0d8a0a 100644 --- a/Lib/test/test_dictcomps.py +++ b/Lib/test/test_dictcomps.py @@ -77,7 +77,7 @@ def test_illegal_assignment(self): compile("{x: y for y, x in ((1, 2), (3, 4))} = 5", "", "exec") - with self.assertRaisesRegex(SyntaxError, "cannot assign"): + with self.assertRaisesRegex(SyntaxError, "illegal expression"): compile("{x: y for y, x in ((1, 2), (3, 4))} += 5", "", "exec") diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 1081107ee64ace..13070c39b75c00 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1921,7 +1921,7 @@ def printsolution(self, x): >>> def f(): (yield bar) += y Traceback (most recent call last): ... -SyntaxError: cannot assign to yield expression +SyntaxError: yield expression is an illegal expression for augmented assignment Now check some throw() conditions: diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py index 86e4e195f55ec5..ea41a63ff5f7f1 100644 --- a/Lib/test/test_genexps.py +++ b/Lib/test/test_genexps.py @@ -158,7 +158,7 @@ >>> (y for y in (1,2)) += 10 Traceback (most recent call last): ... - SyntaxError: cannot assign to generator expression + SyntaxError: generator expression is an illegal expression for augmented assignment ########### Tests borrowed from or inspired by test_generators.py ############ From 349ea59b84f34d5ad3af3c23cfe4876e8d4d6443 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 01:32:47 +0100 Subject: [PATCH 8/9] Update some tests to the new errors --- Lib/test/test_generators.py | 2 +- Lib/test/test_genexps.py | 2 +- Lib/test/test_peg_parser.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 13070c39b75c00..348ae15aa6532b 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1921,7 +1921,7 @@ def printsolution(self, x): >>> def f(): (yield bar) += y Traceback (most recent call last): ... -SyntaxError: yield expression is an illegal expression for augmented assignment +SyntaxError: 'yield expression' is an illegal expression for augmented assignment Now check some throw() conditions: diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py index ea41a63ff5f7f1..5c1a209b0e9908 100644 --- a/Lib/test/test_genexps.py +++ b/Lib/test/test_genexps.py @@ -158,7 +158,7 @@ >>> (y for y in (1,2)) += 10 Traceback (most recent call last): ... - SyntaxError: generator expression is an illegal expression for augmented assignment + SyntaxError: 'generator expression' is an illegal expression for augmented assignment ########### Tests borrowed from or inspired by test_generators.py ############ diff --git a/Lib/test/test_peg_parser.py b/Lib/test/test_peg_parser.py index 71e071940de2f4..9614e45799dd8c 100644 --- a/Lib/test/test_peg_parser.py +++ b/Lib/test/test_peg_parser.py @@ -625,7 +625,7 @@ def f(): ("(a, b): int", "only single target (not tuple) can be annotated"), ("[a, b]: int", "only single target (not list) can be annotated"), ("a(): int", "illegal target for annotation"), - ("1 += 1", "cannot assign to literal"), + ("1 += 1", "'literal' is an illegal expression for augmented assignment"), ("pass\n pass", "unexpected indent"), ("def f():\npass", "expected an indented block"), ("def f(*): pass", "named arguments must follow bare *"), From 6a5c4edb3c34d9debf7d93a368443347c8d3ec7c Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 15 May 2020 01:42:18 +0100 Subject: [PATCH 9/9] Add a comment explaining why we only visit Tuples and Lists --- Parser/pegen/pegen.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index e0073cf138ad17..7f3e4561de6055 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -2075,6 +2075,12 @@ _PyPegen_get_invalid_target(expr_ty e) }\ } 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);