[3.9] bpo-41697: Correctly handle KeywordOrStarred when parsing arguments in the parser (GH-22077) (GH-22079)
(cherry picked from commit 315a61f7a9418d904e0eea14b1f054fac3a90e9f)
Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
diff --git a/Grammar/python.gram b/Grammar/python.gram
index c9f478c..44d435c 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -537,7 +537,7 @@
| a=args [','] &')' { a }
| incorrect_arguments
args[expr_ty]:
- | a=','.(starred_expression | named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b) }
+ | a=','.(starred_expression | named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) }
| a=kwargs { _Py_Call(_PyPegen_dummy_name(p),
CHECK_NULL_ALLOWED(_PyPegen_seq_extract_starred_exprs(p, a)),
CHECK_NULL_ALLOWED(_PyPegen_seq_delete_starred_exprs(p, a)),
diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c
index c7304ed..f74b6f2 100644
--- a/Parser/pegen/parse.c
+++ b/Parser/pegen/parse.c
@@ -12271,7 +12271,16 @@
)
{
D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]"));
- _res = _PyPegen_collect_call_seqs ( p , a , b );
+ Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
+ if (_token == NULL) {
+ D(p->level--);
+ return NULL;
+ }
+ int _end_lineno = _token->end_lineno;
+ UNUSED(_end_lineno); // Only used by EXTRA macro
+ int _end_col_offset = _token->end_col_offset;
+ UNUSED(_end_col_offset); // Only used by EXTRA macro
+ _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
D(p->level--);
diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c
index 6b71b2e..2c435fb 100644
--- a/Parser/pegen/pegen.c
+++ b/Parser/pegen/pegen.c
@@ -2218,14 +2218,15 @@
}
-expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b) {
+expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b,
+ int lineno, int col_offset, int end_lineno,
+ int end_col_offset, PyArena *arena) {
Py_ssize_t args_len = asdl_seq_LEN(a);
Py_ssize_t total_len = args_len;
if (b == NULL) {
- expr_ty first = asdl_seq_GET(a, 0);
- expr_ty last = asdl_seq_GET(a, args_len - 1);
- return _Py_Call(_PyPegen_dummy_name(p), a, NULL, EXTRA_EXPR(first, last));
+ return _Py_Call(_PyPegen_dummy_name(p), a, NULL, lineno, col_offset,
+ end_lineno, end_col_offset, arena);
}
@@ -2236,7 +2237,7 @@
total_len += asdl_seq_LEN(starreds);
}
- asdl_seq *args = _Py_asdl_seq_new(total_len, p->arena);
+ asdl_seq *args = _Py_asdl_seq_new(total_len, arena);
Py_ssize_t i = 0;
for (i = 0; i < args_len; i++) {
@@ -2246,8 +2247,8 @@
asdl_seq_SET(args, i, asdl_seq_GET(starreds, i - args_len));
}
- expr_ty first = asdl_seq_GET(args, 0);
- expr_ty last = asdl_seq_GET(b, asdl_seq_LEN(b)-1);
+ return _Py_Call(_PyPegen_dummy_name(p), args, keywords, lineno,
+ col_offset, end_lineno, end_col_offset, arena);
- return _Py_Call(_PyPegen_dummy_name(p), args, keywords, EXTRA_EXPR(first, last));
+
}
diff --git a/Parser/pegen/pegen.h b/Parser/pegen/pegen.h
index 4ae8d4c..bd35d4f 100644
--- a/Parser/pegen/pegen.h
+++ b/Parser/pegen/pegen.h
@@ -257,7 +257,9 @@
KeywordOrStarred *_PyPegen_keyword_or_starred(Parser *, void *, int);
asdl_seq *_PyPegen_seq_extract_starred_exprs(Parser *, asdl_seq *);
asdl_seq *_PyPegen_seq_delete_starred_exprs(Parser *, asdl_seq *);
-expr_ty _PyPegen_collect_call_seqs(Parser *, asdl_seq *, asdl_seq *);
+expr_ty _PyPegen_collect_call_seqs(Parser *, asdl_seq *, asdl_seq *,
+ int lineno, int col_offset, int end_lineno,
+ int end_col_offset, PyArena *arena);
expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_seq *);
asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *);
int _PyPegen_check_barry_as_flufl(Parser *);