(original) (raw)

Index: Python/ast.c =================================================================== --- Python/ast.c (revision 42335) +++ Python/ast.c (working copy) @@ -1059,7 +1059,7 @@ static expr_ty ast_for_genexp(struct compiling *c, const node *n) { - /* testlist_gexp: test ( gen_for | (',' test)* [','] ) + /* testlist_gexp: test ( gen_for | given | (',' test)* [','] ) argument: [test '='] test [gen_for] # Really [keyword '='] test */ expr_ty elt; asdl_seq *genexps; @@ -1143,6 +1143,43 @@ } static expr_ty +ast_for_given(struct compiling *c, const node *n) +{ + /* testlist_gexp: test ( gen_for | given | (',' test)* [','] ) + argument: [test '='] test [gen_for | given] # Really [keyword '='] test */ + arguments_ty args; + expr_ty expression; + + assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument)); + assert(NCH(n) == 2); + + expression = ast_for_expr(c, CHILD(n, 0)); + if (!expression) + return NULL; + + const node *gn = CHILD(n, 1); + assert(NCH(gn) >= 2 && NCH(gn) <= 4); + const node *an; + if (NCH(gn) == 3) { + // Empty argument list + args = arguments(NULL, NULL, NULL, NULL, c->c_arena); + } else { + if (NCH(gn) == 2) + // Argument list with parens + an = CHILD(gn, 1); + else + // Bare argument list + an = CHILD(gn, 2); + REQ(an, varargslist); + args = ast_for_arguments(c, an); + if (!args) + return NULL; + } + + return Lambda(args, expression, LINENO(n), c->c_arena); +} + +static expr_ty ast_for_atom(struct compiling *c, const node *n) { /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' @@ -1183,6 +1220,9 @@ if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) return ast_for_genexp(c, ch); + if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == given)) + return ast_for_given(c, ch); + return ast_for_testlist_gexp(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); @@ -1634,6 +1674,8 @@ nargs++; else if (TYPE(CHILD(ch, 1)) == gen_for) ngens++; + else if (TYPE(CHILD(ch, 1)) == given) + nargs++; else nkeywords++; } @@ -1673,6 +1715,12 @@ return NULL; asdl_seq_SET(args, nargs++, e); } + else if (TYPE(CHILD(ch, 1)) == given) { + e = ast_for_given(c, ch); + if (!e) + return NULL; + asdl_seq_SET(args, nargs++, e); + } else { keyword_ty kw; identifier key; @@ -1751,6 +1799,8 @@ assert(TYPE(n) == testlist_gexp || TYPE(n) == argument); if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for) return ast_for_genexp(c, n); + if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == given) + return ast_for_given(c, n); return ast_for_testlist(c, n); } Index: Grammar/Grammar =================================================================== --- Grammar/Grammar (revision 42335) +++ Grammar/Grammar (working copy) @@ -102,7 +102,7 @@ '`' testlist1 '`' | NAME | NUMBER | STRING+) listmaker: test ( list_for | (',' test)* [','] ) -testlist_gexp: test ( gen_for | (',' test)* [','] ) +testlist_gexp: test ( gen_for | given | (',' test)* [','] ) lambdef: 'lambda' [varargslist] ':' test trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] @@ -116,7 +116,7 @@ classdef: 'class' NAME ['(' [testlist] ')'] ':' suite arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) -argument: test [gen_for] | test '=' test ['(' gen_for ')'] # Really [keyword '='] test +argument: test [gen_for | given] | test '=' test ['(' gen_for | given ')'] # Really [keyword '='] test list_iter: list_for | list_if list_for: 'for' exprlist 'in' testlist_safe [list_iter] @@ -126,6 +126,7 @@ gen_for: 'for' exprlist 'in' test [gen_iter] gen_if: 'if' test [gen_iter] +given: 'given' ( varargslist | '(' [varargslist] ')' ) testlist1: test (',' test)* # not used in grammar, but may appear in "node" passed from Parser to Compiler