[3.9] bpo-41690: Use a loop to collect args in the parser instead of recursion (GH-22053) (GH-22067)

This program can segfault the parser by stack overflow:

```
import ast

code = "f(" + ",".join(['a' for _ in range(100000)]) + ")"
print("Ready!")
ast.parse(code)
```

the reason is that the rule for arguments has a simple recursion when collecting args:

args[expr_ty]:
    [...]
    | a=named_expression b=[',' c=args { c }] {
        [...] }.
(cherry picked from commit 4a97b1517a6b5ff22e2984b677a680b07ff0ce11)

Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c
index 184cadc..6b71b2e 100644
--- a/Parser/pegen/pegen.c
+++ b/Parser/pegen/pegen.c
@@ -2216,3 +2216,38 @@
         "Generator expression must be parenthesized"
     );
 }
+
+
+expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b) {
+    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));
+
+    }
+
+    asdl_seq *starreds = _PyPegen_seq_extract_starred_exprs(p, b);
+    asdl_seq *keywords = _PyPegen_seq_delete_starred_exprs(p, b);
+
+    if (starreds) {
+        total_len += asdl_seq_LEN(starreds);
+    }
+
+    asdl_seq *args = _Py_asdl_seq_new(total_len, p->arena);
+
+    Py_ssize_t i = 0;
+    for (i = 0; i < args_len; i++) {
+        asdl_seq_SET(args, i, asdl_seq_GET(a, i));
+    }
+    for (; i < total_len; i++) {
+        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, EXTRA_EXPR(first, last));
+}