if (!listcomps) return NULL; ch = CHILD(n, 1); for (i = 0; i < n_fors; i++) { comprehension_ty lc; asdl_seq *t; expr_ty expression; node *for_ch; REQ(ch, list_for); for_ch = CHILD(ch, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; expression = ast_for_testlist(c, CHILD(ch, 3)); if (!expression) return NULL; /* Check the # of children rather than the length of t, since [x for x, in ... ] has 1 element in t, but still requires a Tuple. */ if (NCH(for_ch) == 1) lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, c->c_arena); else lc = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, c->c_arena), expression, NULL, c->c_arena); if (!lc) return NULL; if (NCH(ch) == 5) { int j, n_ifs; asdl_seq *ifs; expr_ty list_for_expr; ch = CHILD(ch, 4); n_ifs = count_list_ifs(ch); if (n_ifs == -1) return NULL; ifs = asdl_seq_new(n_ifs, c->c_arena); if (!ifs) return NULL; for (j = 0; j < n_ifs; j++) { REQ(ch, list_iter); ch = CHILD(ch, 0); REQ(ch, list_if); list_for_expr = ast_for_expr(c, CHILD(ch, 1)); if (!list_for_expr) return NULL; asdl_seq_SET(ifs, j, list_for_expr); if (NCH(ch) == 3) ch = CHILD(ch, 2); } /* on exit, must guarantee that ch is a list_for */ if (TYPE(ch) == list_iter) ch = CHILD(ch, 0); lc->ifs = ifs; } asdl_seq_SET(listcomps, i, lc); } return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena);} /* Count the number of 'for' loops in a generator expression. Helper for ast_for_genexp().*/ static intcount_gen_fors(const node *n){ int n_fors = 0; node *ch = CHILD(n, 1); count_gen_for: n_fors++; REQ(ch, gen_for); if (NCH(ch) == 5) ch = CHILD(ch, 4); else return n_fors; count_gen_iter: REQ(ch, gen_iter); ch = CHILD(ch, 0); if (TYPE(ch) == gen_for) goto count_gen_for; else if (TYPE(ch) == gen_if) { if (NCH(ch) == 3) { ch = CHILD(ch, 2); goto count_gen_iter; } else return n_fors; } /* Should never be reached */ PyErr_SetString(PyExc_SystemError, "logic error in count_gen_fors"); return -1;} /* Count the number of 'if' statements in a generator expression. Helper for ast_for_genexp().*/ static intcount_gen_ifs(const node *n){ int n_ifs = 0; while (1) { REQ(n, gen_iter); if (TYPE(CHILD(n, 0)) == gen_for) return n_ifs; n = CHILD(n, 0); REQ(n, gen_if); n_ifs++; if (NCH(n) == 2) return n_ifs; n = CHILD(n, 2); }} /* TODO(jhylton): Combine with list comprehension code? */static expr_tyast_for_genexp(struct compiling *c, const node *n){ /* testlist_gexp: test ( gen_for | (',' test)* [','] ) argument: [test '='] test [gen_for] # Really [keyword '='] test */ expr_ty elt; asdl_seq *genexps; int i, n_fors; node *ch; assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument)); assert(NCH(n) > 1); elt = ast_for_expr(c, CHILD(n, 0)); if (!elt) return NULL; n_fors = count_gen_fors(n); if (n_fors == -1) return NULL; genexps = asdl_seq_new(n_fors, c->c_arena); if (!genexps) return NULL; ch = CHILD(n, 1); for (i = 0; i < n_fors; i++) { comprehension_ty ge; asdl_seq *t; expr_ty expression; node *for_ch; REQ(ch, gen_for); for_ch = CHILD(ch, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; expression = ast_for_expr(c, CHILD(ch, 3)); if (!expression) return NULL; /* Check the # of children rather than the length of t, since (x for x, in ...) has 1 element in t, but still requires a Tuple. */ if (NCH(for_ch) == 1) ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, c->c_arena); else ge = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, c->c_arena), expression, NULL, c->c_arena); if (!ge) return NULL; if (NCH(ch) == 5) { int j, n_ifs; asdl_seq *ifs; ch = CHILD(ch, 4); n_ifs = count_gen_ifs(ch); if (n_ifs == -1) return NULL; ifs = asdl_seq_new(n_ifs, c->c_arena); if (!ifs) return NULL; for (j = 0; j < n_ifs; j++) { REQ(ch, gen_iter); ch = CHILD(ch, 0); REQ(ch, gen_if); expression = ast_for_expr(c, CHILD(ch, 1)); if (!expression) return NULL; asdl_seq_SET(ifs, j, expression); if (NCH(ch) == 3) ch = CHILD(ch, 2); } /* on exit, must guarantee that ch is a gen_for */ if (TYPE(ch) == gen_iter) ch = CHILD(ch, 0); ge->ifs = ifs; } asdl_seq_SET(genexps, i, ge); } return GeneratorExp(elt, genexps, LINENO(n), n->n_col_offset, c->c_arena);} static expr_tyast_for_atom(struct compiling *c, const node *n){ /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+ */ node *ch = CHILD(n, 0); switch (TYPE(ch)) { case NAME: /* All names start in Load context, but may later be changed. */ return Name(NEW_IDENTIFIER(ch), Load, LINENO(n), n->n_col_offset, c->c_arena); case STRING: { PyObject *str = parsestrplus(c, n); if (!str) return NULL; PyArena_AddPyObject(c->c_arena, str); return Str(str, LINENO(n), n->n_col_offset, c->c_arena); } case NUMBER: { PyObject *pynum = parsenumber(STR(ch)); if (!pynum) return NULL; PyArena_AddPyObject(c->c_arena, pynum); return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); } case LPAR: /* some parenthesized expressions */ ch = CHILD(n, 1); if (TYPE(ch) == RPAR) return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); if (TYPE(ch) == yield_expr) return ast_for_expr(c, ch); if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) return ast_for_genexp(c, ch); return ast_for_testlist_gexp(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); if (TYPE(ch) == RSQB) return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); REQ(ch, listmaker); if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { asdl_seq *elts = seq_for_testlist(c, ch); if (!elts) return NULL; return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena); } else return ast_for_listcomp(c, ch); case LBRACE: { /* dictmaker: test ':' test (',' test ':' test)* [','] */ int i, size; asdl_seq *keys, *values; ch = CHILD(n, 1); size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ keys = asdl_seq_new(size, c->c_arena); if (!keys) return NULL; values = asdl_seq_new(size, c->c_arena); if (!values) return NULL; for (i = 0; i < NCH(ch); i += 4) { expr_ty expression; expression = ast_for_expr(c, CHILD(ch, i)); if (!expression) return NULL; asdl_seq_SET(keys, i / 4, expression); expression = ast_for_expr(c, CHILD(ch, i + 2)); if (!expression) return NULL; asdl_seq_SET(values, i / 4, expression); } return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena); } case BACKQUOTE: { /* repr */ expr_ty expression = ast_for_testlist(c, CHILD(n, 1)); if (!expression) return NULL; return Repr(expression, LINENO(n), n->n_col_offset, c->c_arena); } default: PyErr_Format(PyExc_SystemError, "unhandled atom %d", TYPE(ch)); return NULL; }} static slice_tyast_for_slice(struct compiling *c, const node *n){ node *ch; expr_ty lower = NULL, upper = NULL, step = NULL; REQ(n, subscript); /* subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] sliceop: ':' [test] */ ch = CHILD(n, 0); if (TYPE(ch) == DOT) return Ellipsis(c->c_arena); if (NCH(n) == 1 && TYPE(ch) == test) { /* 'step' variable hold no significance in terms of being used over other vars */ step = ast_for_expr(c, ch); if (!step) return NULL; return Index(step, c->c_arena); } if (TYPE(ch) == test) { lower = ast_for_expr(c, ch); if (!lower) return NULL; } /* If there's an upper bound it's in the second or third position. */ if (TYPE(ch) == COLON) { if (NCH(n) > 1) { node *n2 = CHILD(n, 1); if (TYPE(n2) == test) { upper = ast_for_expr(c, n2); if (!upper) return NULL; } } } else if (NCH(n) > 2) { node *n2 = CHILD(n, 2); if (TYPE(n2) == test) { upper = ast_for_expr(c, n2); if (!upper) return NULL; } } ch = CHILD(n, NCH(n) - 1); if (TYPE(ch) == sliceop) { if (NCH(ch) == 1) { /* No expression, so step is None */ ch = CHILD(ch, 0); step = Name(new_identifier("None", c->c_arena), Load, LINENO(ch), ch->n_col_offset, c->c_arena); if (!step) return NULL; } else { ch = CHILD(ch, 1); if (TYPE(ch) == test) { step = ast_for_expr(c, ch); if (!step) return NULL; } } } return Slice(lower, upper, step, c->c_arena);} static expr_tyast_for_binop(struct compiling *c, const node *n){ /* Must account for a sequence of expressions. How should A op B op C by represented? BinOp(BinOp(A, op, B), op, C). */ int i, nops; expr_ty expr1, expr2, result; operator_ty newoperator; expr1 = ast_for_expr(c, CHILD(n, 0)); if (!expr1) return NULL; expr2 = ast_for_expr(c, CHILD(n, 2)); if (!expr2) return NULL; newoperator = get_operator(CHILD(n, 1)); if (!newoperator) return NULL; result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, c->c_arena); if (!result) return NULL; nops = (NCH(n) - 1) / 2; for (i = 1; i < nops; i++) { expr_ty tmp_result, tmp; const node* next_oper = CHILD(n, i * 2 + 1); newoperator = get_operator(next_oper); if (!newoperator) return NULL; tmp = ast_for_expr(c, CHILD(n, i * 2 + 2)); if (!tmp) return NULL; tmp_result = BinOp(result, newoperator, tmp, LINENO(next_oper), next_oper->n_col_offset, c->c_arena); if (!tmp) return NULL; result = tmp_result; } return result;} static expr_tyast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr){ /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] */ REQ(n, trailer); if (TYPE(CHILD(n, 0)) == LPAR) { if (NCH(n) == 2) return Call(left_expr, NULL, NULL, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); else return ast_for_call(c, CHILD(n, 1), left_expr); } else if (TYPE(CHILD(n, 0)) == DOT ) { return Attribute(left_expr, NEW_IDENTIFIER(CHILD(n, 1)), Load, LINENO(n), n->n_col_offset, c->c_arena); } else { REQ(CHILD(n, 0), LSQB); REQ(CHILD(n, 2), RSQB); n = CHILD(n, 1); if (NCH(n) == 1) { slice_ty slc = ast_for_slice(c, CHILD(n, 0)); if (!slc) return NULL; return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset, c->c_arena); } else { /* The grammar is ambiguous here. The ambiguity is resolved by treating the sequence as a tuple literal if there are no slice features. */ int j; slice_ty slc; expr_ty e; bool simple = true; asdl_seq *slices, *elts; slices = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); if (!slices) return NULL; for (j = 0; j < NCH(n); j += 2) { slc = ast_for_slice(c, CHILD(n, j)); if (!slc)Lines 1001–1500 of 3292. Previous lines Load more
if (!listcomps) return NULL; ch = CHILD(n, 1); for (i = 0; i < n_fors; i++) { comprehension_ty lc; asdl_seq *t; expr_ty expression; node *for_ch; REQ(ch, list_for); for_ch = CHILD(ch, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; expression = ast_for_testlist(c, CHILD(ch, 3)); if (!expression) return NULL; /* Check the # of children rather than the length of t, since [x for x, in ... ] has 1 element in t, but still requires a Tuple. */ if (NCH(for_ch) == 1) lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, c->c_arena); else lc = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, c->c_arena), expression, NULL, c->c_arena); if (!lc) return NULL; if (NCH(ch) == 5) { int j, n_ifs; asdl_seq *ifs; expr_ty list_for_expr; ch = CHILD(ch, 4); n_ifs = count_list_ifs(ch); if (n_ifs == -1) return NULL; ifs = asdl_seq_new(n_ifs, c->c_arena); if (!ifs) return NULL; for (j = 0; j < n_ifs; j++) { REQ(ch, list_iter); ch = CHILD(ch, 0); REQ(ch, list_if); list_for_expr = ast_for_expr(c, CHILD(ch, 1)); if (!list_for_expr) return NULL; asdl_seq_SET(ifs, j, list_for_expr); if (NCH(ch) == 3) ch = CHILD(ch, 2); } /* on exit, must guarantee that ch is a list_for */ if (TYPE(ch) == list_iter) ch = CHILD(ch, 0); lc->ifs = ifs; } asdl_seq_SET(listcomps, i, lc); } return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena); } /* Count the number of 'for' loops in a generator expression. Helper for ast_for_genexp(). */ static int count_gen_fors(const node *n) { int n_fors = 0; node *ch = CHILD(n, 1); count_gen_for: n_fors++; REQ(ch, gen_for); if (NCH(ch) == 5) ch = CHILD(ch, 4); else return n_fors; count_gen_iter: REQ(ch, gen_iter); ch = CHILD(ch, 0); if (TYPE(ch) == gen_for) goto count_gen_for; else if (TYPE(ch) == gen_if) { if (NCH(ch) == 3) { ch = CHILD(ch, 2); goto count_gen_iter; } else return n_fors; } /* Should never be reached */ PyErr_SetString(PyExc_SystemError, "logic error in count_gen_fors"); return -1; } /* Count the number of 'if' statements in a generator expression. Helper for ast_for_genexp(). */ static int count_gen_ifs(const node *n) { int n_ifs = 0; while (1) { REQ(n, gen_iter); if (TYPE(CHILD(n, 0)) == gen_for) return n_ifs; n = CHILD(n, 0); REQ(n, gen_if); n_ifs++; if (NCH(n) == 2) return n_ifs; n = CHILD(n, 2); } } /* TODO(jhylton): Combine with list comprehension code? */ static expr_ty ast_for_genexp(struct compiling *c, const node *n) { /* testlist_gexp: test ( gen_for | (',' test)* [','] ) argument: [test '='] test [gen_for] # Really [keyword '='] test */ expr_ty elt; asdl_seq *genexps; int i, n_fors; node *ch; assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument)); assert(NCH(n) > 1); elt = ast_for_expr(c, CHILD(n, 0)); if (!elt) return NULL; n_fors = count_gen_fors(n); if (n_fors == -1) return NULL; genexps = asdl_seq_new(n_fors, c->c_arena); if (!genexps) return NULL; ch = CHILD(n, 1); for (i = 0; i < n_fors; i++) { comprehension_ty ge; asdl_seq *t; expr_ty expression; node *for_ch; REQ(ch, gen_for); for_ch = CHILD(ch, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; expression = ast_for_expr(c, CHILD(ch, 3)); if (!expression) return NULL; /* Check the # of children rather than the length of t, since (x for x, in ...) has 1 element in t, but still requires a Tuple. */ if (NCH(for_ch) == 1) ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, c->c_arena); else ge = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, c->c_arena), expression, NULL, c->c_arena); if (!ge) return NULL; if (NCH(ch) == 5) { int j, n_ifs; asdl_seq *ifs; ch = CHILD(ch, 4); n_ifs = count_gen_ifs(ch); if (n_ifs == -1) return NULL; ifs = asdl_seq_new(n_ifs, c->c_arena); if (!ifs) return NULL; for (j = 0; j < n_ifs; j++) { REQ(ch, gen_iter); ch = CHILD(ch, 0); REQ(ch, gen_if); expression = ast_for_expr(c, CHILD(ch, 1)); if (!expression) return NULL; asdl_seq_SET(ifs, j, expression); if (NCH(ch) == 3) ch = CHILD(ch, 2); } /* on exit, must guarantee that ch is a gen_for */ if (TYPE(ch) == gen_iter) ch = CHILD(ch, 0); ge->ifs = ifs; } asdl_seq_SET(genexps, i, ge); } return GeneratorExp(elt, genexps, LINENO(n), n->n_col_offset, c->c_arena); } static expr_ty ast_for_atom(struct compiling *c, const node *n) { /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+ */ node *ch = CHILD(n, 0); switch (TYPE(ch)) { case NAME: /* All names start in Load context, but may later be changed. */ return Name(NEW_IDENTIFIER(ch), Load, LINENO(n), n->n_col_offset, c->c_arena); case STRING: { PyObject *str = parsestrplus(c, n); if (!str) return NULL; PyArena_AddPyObject(c->c_arena, str); return Str(str, LINENO(n), n->n_col_offset, c->c_arena); } case NUMBER: { PyObject *pynum = parsenumber(STR(ch)); if (!pynum) return NULL; PyArena_AddPyObject(c->c_arena, pynum); return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); } case LPAR: /* some parenthesized expressions */ ch = CHILD(n, 1); if (TYPE(ch) == RPAR) return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); if (TYPE(ch) == yield_expr) return ast_for_expr(c, ch); if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) return ast_for_genexp(c, ch); return ast_for_testlist_gexp(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); if (TYPE(ch) == RSQB) return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); REQ(ch, listmaker); if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { asdl_seq *elts = seq_for_testlist(c, ch); if (!elts) return NULL; return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena); } else return ast_for_listcomp(c, ch); case LBRACE: { /* dictmaker: test ':' test (',' test ':' test)* [','] */ int i, size; asdl_seq *keys, *values; ch = CHILD(n, 1); size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ keys = asdl_seq_new(size, c->c_arena); if (!keys) return NULL; values = asdl_seq_new(size, c->c_arena); if (!values) return NULL; for (i = 0; i < NCH(ch); i += 4) { expr_ty expression; expression = ast_for_expr(c, CHILD(ch, i)); if (!expression) return NULL; asdl_seq_SET(keys, i / 4, expression); expression = ast_for_expr(c, CHILD(ch, i + 2)); if (!expression) return NULL; asdl_seq_SET(values, i / 4, expression); } return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena); } case BACKQUOTE: { /* repr */ expr_ty expression = ast_for_testlist(c, CHILD(n, 1)); if (!expression) return NULL; return Repr(expression, LINENO(n), n->n_col_offset, c->c_arena); } default: PyErr_Format(PyExc_SystemError, "unhandled atom %d", TYPE(ch)); return NULL; } } static slice_ty ast_for_slice(struct compiling *c, const node *n) { node *ch; expr_ty lower = NULL, upper = NULL, step = NULL; REQ(n, subscript); /* subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] sliceop: ':' [test] */ ch = CHILD(n, 0); if (TYPE(ch) == DOT) return Ellipsis(c->c_arena); if (NCH(n) == 1 && TYPE(ch) == test) { /* 'step' variable hold no significance in terms of being used over other vars */ step = ast_for_expr(c, ch); if (!step) return NULL; return Index(step, c->c_arena); } if (TYPE(ch) == test) { lower = ast_for_expr(c, ch); if (!lower) return NULL; } /* If there's an upper bound it's in the second or third position. */ if (TYPE(ch) == COLON) { if (NCH(n) > 1) { node *n2 = CHILD(n, 1); if (TYPE(n2) == test) { upper = ast_for_expr(c, n2); if (!upper) return NULL; } } } else if (NCH(n) > 2) { node *n2 = CHILD(n, 2); if (TYPE(n2) == test) { upper = ast_for_expr(c, n2); if (!upper) return NULL; } } ch = CHILD(n, NCH(n) - 1); if (TYPE(ch) == sliceop) { if (NCH(ch) == 1) { /* No expression, so step is None */ ch = CHILD(ch, 0); step = Name(new_identifier("None", c->c_arena), Load, LINENO(ch), ch->n_col_offset, c->c_arena); if (!step) return NULL; } else { ch = CHILD(ch, 1); if (TYPE(ch) == test) { step = ast_for_expr(c, ch); if (!step) return NULL; } } } return Slice(lower, upper, step, c->c_arena); } static expr_ty ast_for_binop(struct compiling *c, const node *n) { /* Must account for a sequence of expressions. How should A op B op C by represented? BinOp(BinOp(A, op, B), op, C). */ int i, nops; expr_ty expr1, expr2, result; operator_ty newoperator; expr1 = ast_for_expr(c, CHILD(n, 0)); if (!expr1) return NULL; expr2 = ast_for_expr(c, CHILD(n, 2)); if (!expr2) return NULL; newoperator = get_operator(CHILD(n, 1)); if (!newoperator) return NULL; result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, c->c_arena); if (!result) return NULL; nops = (NCH(n) - 1) / 2; for (i = 1; i < nops; i++) { expr_ty tmp_result, tmp; const node* next_oper = CHILD(n, i * 2 + 1); newoperator = get_operator(next_oper); if (!newoperator) return NULL; tmp = ast_for_expr(c, CHILD(n, i * 2 + 2)); if (!tmp) return NULL; tmp_result = BinOp(result, newoperator, tmp, LINENO(next_oper), next_oper->n_col_offset, c->c_arena); if (!tmp) return NULL; result = tmp_result; } return result; } static expr_ty ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) { /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] */ REQ(n, trailer); if (TYPE(CHILD(n, 0)) == LPAR) { if (NCH(n) == 2) return Call(left_expr, NULL, NULL, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); else return ast_for_call(c, CHILD(n, 1), left_expr); } else if (TYPE(CHILD(n, 0)) == DOT ) { return Attribute(left_expr, NEW_IDENTIFIER(CHILD(n, 1)), Load, LINENO(n), n->n_col_offset, c->c_arena); } else { REQ(CHILD(n, 0), LSQB); REQ(CHILD(n, 2), RSQB); n = CHILD(n, 1); if (NCH(n) == 1) { slice_ty slc = ast_for_slice(c, CHILD(n, 0)); if (!slc) return NULL; return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset, c->c_arena); } else { /* The grammar is ambiguous here. The ambiguity is resolved by treating the sequence as a tuple literal if there are no slice features. */ int j; slice_ty slc; expr_ty e; bool simple = true; asdl_seq *slices, *elts; slices = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); if (!slices) return NULL; for (j = 0; j < NCH(n); j += 2) { slc = ast_for_slice(c, CHILD(n, j)); if (!slc)