diff --git a/Grammar/python.gram b/Grammar/python.gram index cca92090546..40e7818d496 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -661,6 +661,7 @@ invalid_parameters: RAISE_SYNTAX_ERROR("non-default argument follows default argument") } invalid_star_etc: | '*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") } + | '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") } invalid_lambda_star_etc: | '*' (':' | ',' (':' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") } invalid_double_type_comments: diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 87ceced6c62..a82b444b67a 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -178,6 +178,16 @@ SyntaxError: invalid syntax Traceback (most recent call last): SyntaxError: invalid syntax +>>> import ast; ast.parse(''' +... def f( +... *, # type: int +... a, # type: int +... ): +... pass +... ''', type_comments=True) +Traceback (most recent call last): +SyntaxError: bare * has associated type comment + From ast_for_funcdef(): diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c index e9c20327c15..fe95d274f37 100644 --- a/Parser/pegen/parse.c +++ b/Parser/pegen/parse.c @@ -12041,7 +12041,7 @@ invalid_parameters_rule(Parser *p) return _res; } -// invalid_star_etc: '*' (')' | ',' (')' | '**')) +// invalid_star_etc: '*' (')' | ',' (')' | '**')) | '*' ',' TYPE_COMMENT static void * invalid_star_etc_rule(Parser *p) { @@ -12071,6 +12071,27 @@ invalid_star_etc_rule(Parser *p) } p->mark = _mark; } + { // '*' ',' TYPE_COMMENT + Token * _literal; + Token * _literal_1; + Token * type_comment_var; + if ( + (_literal = _PyPegen_expect_token(p, 16)) // token='*' + && + (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' + && + (type_comment_var = _PyPegen_expect_token(p, TYPE_COMMENT)) // token='TYPE_COMMENT' + ) + { + _res = RAISE_SYNTAX_ERROR ( "bare * has associated type comment" ); + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + return NULL; + } + goto done; + } + p->mark = _mark; + } _res = NULL; done: return _res; diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index 7f3e4561de6..ca4ea824b3f 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -431,25 +431,6 @@ error: return NULL; } -void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) { - int kwarg_unpacking = 0; - for (Py_ssize_t i = 0, l = asdl_seq_LEN(e->v.Call.keywords); i < l; i++) { - keyword_ty keyword = asdl_seq_GET(e->v.Call.keywords, i); - if (!keyword->arg) { - kwarg_unpacking = 1; - } - } - - const char *msg = NULL; - if (kwarg_unpacking) { - msg = "positional argument follows keyword argument unpacking"; - } else { - msg = "positional argument follows keyword argument"; - } - - return RAISE_SYNTAX_ERROR(msg); -} - #if 0 static const char * token_name(int type) @@ -2099,4 +2080,23 @@ _PyPegen_get_invalid_target(expr_ty e) default: return e; } -} \ No newline at end of file +} + +void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) { + int kwarg_unpacking = 0; + for (Py_ssize_t i = 0, l = asdl_seq_LEN(e->v.Call.keywords); i < l; i++) { + keyword_ty keyword = asdl_seq_GET(e->v.Call.keywords, i); + if (!keyword->arg) { + kwarg_unpacking = 1; + } + } + + const char *msg = NULL; + if (kwarg_unpacking) { + msg = "positional argument follows keyword argument unpacking"; + } else { + msg = "positional argument follows keyword argument"; + } + + return RAISE_SYNTAX_ERROR(msg); +} diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h index b9d4c048bb5..146804a896f 100644 --- a/Parser/pegen/pegen.h +++ b/Parser/pegen/pegen.h @@ -256,13 +256,13 @@ asdl_seq *_PyPegen_seq_extract_starred_exprs(Parser *, asdl_seq *); asdl_seq *_PyPegen_seq_delete_starred_exprs(Parser *, asdl_seq *); expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_seq *); asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *); -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_arguments_parsing_error(Parser *, expr_ty); + void *_PyPegen_parse(Parser *);