--- /dev/null
+/*\r
+ * This file includes functions to transform a concrete syntax tree (CST) to\r
+ * an abstract syntax tree (AST). The main function is PyAST_FromNode().\r
+ *\r
+ */\r
+#include "Python.h"\r
+#include "Python-ast.h"\r
+#include "grammar.h"\r
+#include "node.h"\r
+#include "pyarena.h"\r
+#include "ast.h"\r
+#include "token.h"\r
+#include "parsetok.h"\r
+#include "graminit.h"\r
+\r
+#include <assert.h>\r
+\r
+/* Data structure used internally */\r
+struct compiling {\r
+ char *c_encoding; /* source encoding */\r
+ int c_future_unicode; /* __future__ unicode literals flag */\r
+ PyArena *c_arena; /* arena for allocating memeory */\r
+ const char *c_filename; /* filename */\r
+};\r
+\r
+static asdl_seq *seq_for_testlist(struct compiling *, const node *);\r
+static expr_ty ast_for_expr(struct compiling *, const node *);\r
+static stmt_ty ast_for_stmt(struct compiling *, const node *);\r
+static asdl_seq *ast_for_suite(struct compiling *, const node *);\r
+static asdl_seq *ast_for_exprlist(struct compiling *, const node *,\r
+ expr_context_ty);\r
+static expr_ty ast_for_testlist(struct compiling *, const node *);\r
+static stmt_ty ast_for_classdef(struct compiling *, const node *, asdl_seq *);\r
+static expr_ty ast_for_testlist_comp(struct compiling *, const node *);\r
+\r
+/* Note different signature for ast_for_call */\r
+static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);\r
+\r
+static PyObject *parsenumber(struct compiling *, const char *);\r
+static PyObject *parsestr(struct compiling *, const node *n, const char *);\r
+static PyObject *parsestrplus(struct compiling *, const node *n);\r
+\r
+#ifndef LINENO\r
+#define LINENO(n) ((n)->n_lineno)\r
+#endif\r
+\r
+#define COMP_GENEXP 0\r
+#define COMP_SETCOMP 1\r
+\r
+static identifier\r
+new_identifier(const char* n, PyArena *arena) {\r
+ PyObject* id = PyString_InternFromString(n);\r
+ if (id != NULL)\r
+ PyArena_AddPyObject(arena, id);\r
+ return id;\r
+}\r
+\r
+#define NEW_IDENTIFIER(n) new_identifier(STR(n), c->c_arena)\r
+\r
+/* This routine provides an invalid object for the syntax error.\r
+ The outermost routine must unpack this error and create the\r
+ proper object. We do this so that we don't have to pass\r
+ the filename to everything function.\r
+\r
+ XXX Maybe we should just pass the filename...\r
+*/\r
+\r
+static int\r
+ast_error(const node *n, const char *errstr)\r
+{\r
+ PyObject *u = Py_BuildValue("zi", errstr, LINENO(n));\r
+ if (!u)\r
+ return 0;\r
+ PyErr_SetObject(PyExc_SyntaxError, u);\r
+ Py_DECREF(u);\r
+ return 0;\r
+}\r
+\r
+static void\r
+ast_error_finish(const char *filename)\r
+{\r
+ PyObject *type, *value, *tback, *errstr, *loc, *tmp;\r
+ long lineno;\r
+\r
+ assert(PyErr_Occurred());\r
+ if (!PyErr_ExceptionMatches(PyExc_SyntaxError))\r
+ return;\r
+\r
+ PyErr_Fetch(&type, &value, &tback);\r
+ errstr = PyTuple_GetItem(value, 0);\r
+ if (!errstr)\r
+ return;\r
+ Py_INCREF(errstr);\r
+ lineno = PyInt_AsLong(PyTuple_GetItem(value, 1));\r
+ if (lineno == -1) {\r
+ Py_DECREF(errstr);\r
+ return;\r
+ }\r
+ Py_DECREF(value);\r
+\r
+ loc = PyErr_ProgramText(filename, lineno);\r
+ if (!loc) {\r
+ Py_INCREF(Py_None);\r
+ loc = Py_None;\r
+ }\r
+ tmp = Py_BuildValue("(zlOO)", filename, lineno, Py_None, loc);\r
+ Py_DECREF(loc);\r
+ if (!tmp) {\r
+ Py_DECREF(errstr);\r
+ return;\r
+ }\r
+ value = PyTuple_Pack(2, errstr, tmp);\r
+ Py_DECREF(errstr);\r
+ Py_DECREF(tmp);\r
+ if (!value)\r
+ return;\r
+ PyErr_Restore(type, value, tback);\r
+}\r
+\r
+static int\r
+ast_warn(struct compiling *c, const node *n, char *msg)\r
+{\r
+ if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename, LINENO(n),\r
+ NULL, NULL) < 0) {\r
+ /* if -Werr, change it to a SyntaxError */\r
+ if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SyntaxWarning))\r
+ ast_error(n, msg);\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+static int\r
+forbidden_check(struct compiling *c, const node *n, const char *x)\r
+{\r
+ if (!strcmp(x, "None"))\r
+ return ast_error(n, "cannot assign to None");\r
+ if (!strcmp(x, "__debug__"))\r
+ return ast_error(n, "cannot assign to __debug__");\r
+ if (Py_Py3kWarningFlag) {\r
+ if (!(strcmp(x, "True") && strcmp(x, "False")) &&\r
+ !ast_warn(c, n, "assignment to True or False is forbidden in 3.x"))\r
+ return 0;\r
+ if (!strcmp(x, "nonlocal") &&\r
+ !ast_warn(c, n, "nonlocal is a keyword in 3.x"))\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+/* num_stmts() returns number of contained statements.\r
+\r
+ Use this routine to determine how big a sequence is needed for\r
+ the statements in a parse tree. Its raison d'etre is this bit of\r
+ grammar:\r
+\r
+ stmt: simple_stmt | compound_stmt\r
+ simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE\r
+\r
+ A simple_stmt can contain multiple small_stmt elements joined\r
+ by semicolons. If the arg is a simple_stmt, the number of\r
+ small_stmt elements is returned.\r
+*/\r
+\r
+static int\r
+num_stmts(const node *n)\r
+{\r
+ int i, l;\r
+ node *ch;\r
+\r
+ switch (TYPE(n)) {\r
+ case single_input:\r
+ if (TYPE(CHILD(n, 0)) == NEWLINE)\r
+ return 0;\r
+ else\r
+ return num_stmts(CHILD(n, 0));\r
+ case file_input:\r
+ l = 0;\r
+ for (i = 0; i < NCH(n); i++) {\r
+ ch = CHILD(n, i);\r
+ if (TYPE(ch) == stmt)\r
+ l += num_stmts(ch);\r
+ }\r
+ return l;\r
+ case stmt:\r
+ return num_stmts(CHILD(n, 0));\r
+ case compound_stmt:\r
+ return 1;\r
+ case simple_stmt:\r
+ return NCH(n) / 2; /* Divide by 2 to remove count of semi-colons */\r
+ case suite:\r
+ if (NCH(n) == 1)\r
+ return num_stmts(CHILD(n, 0));\r
+ else {\r
+ l = 0;\r
+ for (i = 2; i < (NCH(n) - 1); i++)\r
+ l += num_stmts(CHILD(n, i));\r
+ return l;\r
+ }\r
+ default: {\r
+ char buf[128];\r
+\r
+ sprintf(buf, "Non-statement found: %d %d",\r
+ TYPE(n), NCH(n));\r
+ Py_FatalError(buf);\r
+ }\r
+ }\r
+ assert(0);\r
+ return 0;\r
+}\r
+\r
+/* Transform the CST rooted at node * to the appropriate AST\r
+*/\r
+\r
+mod_ty\r
+PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,\r
+ PyArena *arena)\r
+{\r
+ int i, j, k, num;\r
+ asdl_seq *stmts = NULL;\r
+ stmt_ty s;\r
+ node *ch;\r
+ struct compiling c;\r
+\r
+ if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {\r
+ c.c_encoding = "utf-8";\r
+ if (TYPE(n) == encoding_decl) {\r
+ ast_error(n, "encoding declaration in Unicode string");\r
+ goto error;\r
+ }\r
+ } else if (TYPE(n) == encoding_decl) {\r
+ c.c_encoding = STR(n);\r
+ n = CHILD(n, 0);\r
+ } else {\r
+ c.c_encoding = NULL;\r
+ }\r
+ c.c_future_unicode = flags && flags->cf_flags & CO_FUTURE_UNICODE_LITERALS;\r
+ c.c_arena = arena;\r
+ c.c_filename = filename;\r
+\r
+ k = 0;\r
+ switch (TYPE(n)) {\r
+ case file_input:\r
+ stmts = asdl_seq_new(num_stmts(n), arena);\r
+ if (!stmts)\r
+ return NULL;\r
+ for (i = 0; i < NCH(n) - 1; i++) {\r
+ ch = CHILD(n, i);\r
+ if (TYPE(ch) == NEWLINE)\r
+ continue;\r
+ REQ(ch, stmt);\r
+ num = num_stmts(ch);\r
+ if (num == 1) {\r
+ s = ast_for_stmt(&c, ch);\r
+ if (!s)\r
+ goto error;\r
+ asdl_seq_SET(stmts, k++, s);\r
+ }\r
+ else {\r
+ ch = CHILD(ch, 0);\r
+ REQ(ch, simple_stmt);\r
+ for (j = 0; j < num; j++) {\r
+ s = ast_for_stmt(&c, CHILD(ch, j * 2));\r
+ if (!s)\r
+ goto error;\r
+ asdl_seq_SET(stmts, k++, s);\r
+ }\r
+ }\r
+ }\r
+ return Module(stmts, arena);\r
+ case eval_input: {\r
+ expr_ty testlist_ast;\r
+\r
+ /* XXX Why not comp_for here? */\r
+ testlist_ast = ast_for_testlist(&c, CHILD(n, 0));\r
+ if (!testlist_ast)\r
+ goto error;\r
+ return Expression(testlist_ast, arena);\r
+ }\r
+ case single_input:\r
+ if (TYPE(CHILD(n, 0)) == NEWLINE) {\r
+ stmts = asdl_seq_new(1, arena);\r
+ if (!stmts)\r
+ goto error;\r
+ asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset,\r
+ arena));\r
+ if (!asdl_seq_GET(stmts, 0))\r
+ goto error;\r
+ return Interactive(stmts, arena);\r
+ }\r
+ else {\r
+ n = CHILD(n, 0);\r
+ num = num_stmts(n);\r
+ stmts = asdl_seq_new(num, arena);\r
+ if (!stmts)\r
+ goto error;\r
+ if (num == 1) {\r
+ s = ast_for_stmt(&c, n);\r
+ if (!s)\r
+ goto error;\r
+ asdl_seq_SET(stmts, 0, s);\r
+ }\r
+ else {\r
+ /* Only a simple_stmt can contain multiple statements. */\r
+ REQ(n, simple_stmt);\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ if (TYPE(CHILD(n, i)) == NEWLINE)\r
+ break;\r
+ s = ast_for_stmt(&c, CHILD(n, i));\r
+ if (!s)\r
+ goto error;\r
+ asdl_seq_SET(stmts, i / 2, s);\r
+ }\r
+ }\r
+\r
+ return Interactive(stmts, arena);\r
+ }\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "invalid node %d for PyAST_FromNode", TYPE(n));\r
+ goto error;\r
+ }\r
+ error:\r
+ ast_error_finish(filename);\r
+ return NULL;\r
+}\r
+\r
+/* Return the AST repr. of the operator represented as syntax (|, ^, etc.)\r
+*/\r
+\r
+static operator_ty\r
+get_operator(const node *n)\r
+{\r
+ switch (TYPE(n)) {\r
+ case VBAR:\r
+ return BitOr;\r
+ case CIRCUMFLEX:\r
+ return BitXor;\r
+ case AMPER:\r
+ return BitAnd;\r
+ case LEFTSHIFT:\r
+ return LShift;\r
+ case RIGHTSHIFT:\r
+ return RShift;\r
+ case PLUS:\r
+ return Add;\r
+ case MINUS:\r
+ return Sub;\r
+ case STAR:\r
+ return Mult;\r
+ case SLASH:\r
+ return Div;\r
+ case DOUBLESLASH:\r
+ return FloorDiv;\r
+ case PERCENT:\r
+ return Mod;\r
+ default:\r
+ return (operator_ty)0;\r
+ }\r
+}\r
+\r
+/* Set the context ctx for expr_ty e, recursively traversing e.\r
+\r
+ Only sets context for expr kinds that "can appear in assignment context"\r
+ (according to ../Parser/Python.asdl). For other expr kinds, it sets\r
+ an appropriate syntax error and returns false.\r
+*/\r
+\r
+static int\r
+set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)\r
+{\r
+ asdl_seq *s = NULL;\r
+ /* If a particular expression type can't be used for assign / delete,\r
+ set expr_name to its name and an error message will be generated.\r
+ */\r
+ const char* expr_name = NULL;\r
+\r
+ /* The ast defines augmented store and load contexts, but the\r
+ implementation here doesn't actually use them. The code may be\r
+ a little more complex than necessary as a result. It also means\r
+ that expressions in an augmented assignment have a Store context.\r
+ Consider restructuring so that augmented assignment uses\r
+ set_context(), too.\r
+ */\r
+ assert(ctx != AugStore && ctx != AugLoad);\r
+\r
+ switch (e->kind) {\r
+ case Attribute_kind:\r
+ if (ctx == Store && !forbidden_check(c, n,\r
+ PyBytes_AS_STRING(e->v.Attribute.attr)))\r
+ return 0;\r
+ e->v.Attribute.ctx = ctx;\r
+ break;\r
+ case Subscript_kind:\r
+ e->v.Subscript.ctx = ctx;\r
+ break;\r
+ case Name_kind:\r
+ if (ctx == Store && !forbidden_check(c, n,\r
+ PyBytes_AS_STRING(e->v.Name.id)))\r
+ return 0;\r
+ e->v.Name.ctx = ctx;\r
+ break;\r
+ case List_kind:\r
+ e->v.List.ctx = ctx;\r
+ s = e->v.List.elts;\r
+ break;\r
+ case Tuple_kind:\r
+ if (asdl_seq_LEN(e->v.Tuple.elts)) {\r
+ e->v.Tuple.ctx = ctx;\r
+ s = e->v.Tuple.elts;\r
+ }\r
+ else {\r
+ expr_name = "()";\r
+ }\r
+ break;\r
+ case Lambda_kind:\r
+ expr_name = "lambda";\r
+ break;\r
+ case Call_kind:\r
+ expr_name = "function call";\r
+ break;\r
+ case BoolOp_kind:\r
+ case BinOp_kind:\r
+ case UnaryOp_kind:\r
+ expr_name = "operator";\r
+ break;\r
+ case GeneratorExp_kind:\r
+ expr_name = "generator expression";\r
+ break;\r
+ case Yield_kind:\r
+ expr_name = "yield expression";\r
+ break;\r
+ case ListComp_kind:\r
+ expr_name = "list comprehension";\r
+ break;\r
+ case SetComp_kind:\r
+ expr_name = "set comprehension";\r
+ break;\r
+ case DictComp_kind:\r
+ expr_name = "dict comprehension";\r
+ break;\r
+ case Dict_kind:\r
+ case Set_kind:\r
+ case Num_kind:\r
+ case Str_kind:\r
+ expr_name = "literal";\r
+ break;\r
+ case Compare_kind:\r
+ expr_name = "comparison";\r
+ break;\r
+ case Repr_kind:\r
+ expr_name = "repr";\r
+ break;\r
+ case IfExp_kind:\r
+ expr_name = "conditional expression";\r
+ break;\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unexpected expression in assignment %d (line %d)",\r
+ e->kind, e->lineno);\r
+ return 0;\r
+ }\r
+ /* Check for error string set by switch */\r
+ if (expr_name) {\r
+ char buf[300];\r
+ PyOS_snprintf(buf, sizeof(buf),\r
+ "can't %s %s",\r
+ ctx == Store ? "assign to" : "delete",\r
+ expr_name);\r
+ return ast_error(n, buf);\r
+ }\r
+\r
+ /* If the LHS is a list or tuple, we need to set the assignment\r
+ context for all the contained elements.\r
+ */\r
+ if (s) {\r
+ int i;\r
+\r
+ for (i = 0; i < asdl_seq_LEN(s); i++) {\r
+ if (!set_context(c, (expr_ty)asdl_seq_GET(s, i), ctx, n))\r
+ return 0;\r
+ }\r
+ }\r
+ return 1;\r
+}\r
+\r
+static operator_ty\r
+ast_for_augassign(struct compiling *c, const node *n)\r
+{\r
+ REQ(n, augassign);\r
+ n = CHILD(n, 0);\r
+ switch (STR(n)[0]) {\r
+ case '+':\r
+ return Add;\r
+ case '-':\r
+ return Sub;\r
+ case '/':\r
+ if (STR(n)[1] == '/')\r
+ return FloorDiv;\r
+ else\r
+ return Div;\r
+ case '%':\r
+ return Mod;\r
+ case '<':\r
+ return LShift;\r
+ case '>':\r
+ return RShift;\r
+ case '&':\r
+ return BitAnd;\r
+ case '^':\r
+ return BitXor;\r
+ case '|':\r
+ return BitOr;\r
+ case '*':\r
+ if (STR(n)[1] == '*')\r
+ return Pow;\r
+ else\r
+ return Mult;\r
+ default:\r
+ PyErr_Format(PyExc_SystemError, "invalid augassign: %s", STR(n));\r
+ return (operator_ty)0;\r
+ }\r
+}\r
+\r
+static cmpop_ty\r
+ast_for_comp_op(struct compiling *c, const node *n)\r
+{\r
+ /* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'\r
+ |'is' 'not'\r
+ */\r
+ REQ(n, comp_op);\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ switch (TYPE(n)) {\r
+ case LESS:\r
+ return Lt;\r
+ case GREATER:\r
+ return Gt;\r
+ case EQEQUAL: /* == */\r
+ return Eq;\r
+ case LESSEQUAL:\r
+ return LtE;\r
+ case GREATEREQUAL:\r
+ return GtE;\r
+ case NOTEQUAL:\r
+ return NotEq;\r
+ case NAME:\r
+ if (strcmp(STR(n), "in") == 0)\r
+ return In;\r
+ if (strcmp(STR(n), "is") == 0)\r
+ return Is;\r
+ default:\r
+ PyErr_Format(PyExc_SystemError, "invalid comp_op: %s",\r
+ STR(n));\r
+ return (cmpop_ty)0;\r
+ }\r
+ }\r
+ else if (NCH(n) == 2) {\r
+ /* handle "not in" and "is not" */\r
+ switch (TYPE(CHILD(n, 0))) {\r
+ case NAME:\r
+ if (strcmp(STR(CHILD(n, 1)), "in") == 0)\r
+ return NotIn;\r
+ if (strcmp(STR(CHILD(n, 0)), "is") == 0)\r
+ return IsNot;\r
+ default:\r
+ PyErr_Format(PyExc_SystemError, "invalid comp_op: %s %s",\r
+ STR(CHILD(n, 0)), STR(CHILD(n, 1)));\r
+ return (cmpop_ty)0;\r
+ }\r
+ }\r
+ PyErr_Format(PyExc_SystemError, "invalid comp_op: has %d children",\r
+ NCH(n));\r
+ return (cmpop_ty)0;\r
+}\r
+\r
+static asdl_seq *\r
+seq_for_testlist(struct compiling *c, const node *n)\r
+{\r
+ /* testlist: test (',' test)* [','] */\r
+ asdl_seq *seq;\r
+ expr_ty expression;\r
+ int i;\r
+ assert(TYPE(n) == testlist ||\r
+ TYPE(n) == listmaker ||\r
+ TYPE(n) == testlist_comp ||\r
+ TYPE(n) == testlist_safe ||\r
+ TYPE(n) == testlist1);\r
+\r
+ seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);\r
+ if (!seq)\r
+ return NULL;\r
+\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == old_test);\r
+\r
+ expression = ast_for_expr(c, CHILD(n, i));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ assert(i / 2 < seq->size);\r
+ asdl_seq_SET(seq, i / 2, expression);\r
+ }\r
+ return seq;\r
+}\r
+\r
+static expr_ty\r
+compiler_complex_args(struct compiling *c, const node *n)\r
+{\r
+ int i, len = (NCH(n) + 1) / 2;\r
+ expr_ty result;\r
+ asdl_seq *args = asdl_seq_new(len, c->c_arena);\r
+ if (!args)\r
+ return NULL;\r
+\r
+ /* fpdef: NAME | '(' fplist ')'\r
+ fplist: fpdef (',' fpdef)* [',']\r
+ */\r
+ REQ(n, fplist);\r
+ for (i = 0; i < len; i++) {\r
+ PyObject *arg_id;\r
+ const node *fpdef_node = CHILD(n, 2*i);\r
+ const node *child;\r
+ expr_ty arg;\r
+set_name:\r
+ /* fpdef_node is either a NAME or an fplist */\r
+ child = CHILD(fpdef_node, 0);\r
+ if (TYPE(child) == NAME) {\r
+ if (!forbidden_check(c, n, STR(child)))\r
+ return NULL;\r
+ arg_id = NEW_IDENTIFIER(child);\r
+ if (!arg_id)\r
+ return NULL;\r
+ arg = Name(arg_id, Store, LINENO(child), child->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else {\r
+ assert(TYPE(fpdef_node) == fpdef);\r
+ /* fpdef_node[0] is not a name, so it must be '(', get CHILD[1] */\r
+ child = CHILD(fpdef_node, 1);\r
+ assert(TYPE(child) == fplist);\r
+ /* NCH == 1 means we have (x), we need to elide the extra parens */\r
+ if (NCH(child) == 1) {\r
+ fpdef_node = CHILD(child, 0);\r
+ assert(TYPE(fpdef_node) == fpdef);\r
+ goto set_name;\r
+ }\r
+ arg = compiler_complex_args(c, child);\r
+ }\r
+ asdl_seq_SET(args, i, arg);\r
+ }\r
+\r
+ result = Tuple(args, Store, LINENO(n), n->n_col_offset, c->c_arena);\r
+ if (!set_context(c, result, Store, n))\r
+ return NULL;\r
+ return result;\r
+}\r
+\r
+\r
+/* Create AST for argument list. */\r
+\r
+static arguments_ty\r
+ast_for_arguments(struct compiling *c, const node *n)\r
+{\r
+ /* parameters: '(' [varargslist] ')'\r
+ varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME]\r
+ | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [',']\r
+ */\r
+ int i, j, k, n_args = 0, n_defaults = 0, found_default = 0;\r
+ asdl_seq *args, *defaults;\r
+ identifier vararg = NULL, kwarg = NULL;\r
+ node *ch;\r
+\r
+ if (TYPE(n) == parameters) {\r
+ if (NCH(n) == 2) /* () as argument list */\r
+ return arguments(NULL, NULL, NULL, NULL, c->c_arena);\r
+ n = CHILD(n, 1);\r
+ }\r
+ REQ(n, varargslist);\r
+\r
+ /* first count the number of normal args & defaults */\r
+ for (i = 0; i < NCH(n); i++) {\r
+ ch = CHILD(n, i);\r
+ if (TYPE(ch) == fpdef)\r
+ n_args++;\r
+ if (TYPE(ch) == EQUAL)\r
+ n_defaults++;\r
+ }\r
+ args = (n_args ? asdl_seq_new(n_args, c->c_arena) : NULL);\r
+ if (!args && n_args)\r
+ return NULL;\r
+ defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL);\r
+ if (!defaults && n_defaults)\r
+ return NULL;\r
+\r
+ /* fpdef: NAME | '(' fplist ')'\r
+ fplist: fpdef (',' fpdef)* [',']\r
+ */\r
+ i = 0;\r
+ j = 0; /* index for defaults */\r
+ k = 0; /* index for args */\r
+ while (i < NCH(n)) {\r
+ ch = CHILD(n, i);\r
+ switch (TYPE(ch)) {\r
+ case fpdef: {\r
+ int complex_args = 0, parenthesized = 0;\r
+ handle_fpdef:\r
+ /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is\r
+ anything other than EQUAL or a comma? */\r
+ /* XXX Should NCH(n) check be made a separate check? */\r
+ if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) {\r
+ expr_ty expression = ast_for_expr(c, CHILD(n, i + 2));\r
+ if (!expression)\r
+ return NULL;\r
+ assert(defaults != NULL);\r
+ asdl_seq_SET(defaults, j++, expression);\r
+ i += 2;\r
+ found_default = 1;\r
+ }\r
+ else if (found_default) {\r
+ /* def f((x)=4): pass should raise an error.\r
+ def f((x, (y))): pass will just incur the tuple unpacking warning. */\r
+ if (parenthesized && !complex_args) {\r
+ ast_error(n, "parenthesized arg with default");\r
+ return NULL;\r
+ }\r
+ ast_error(n,\r
+ "non-default argument follows default argument");\r
+ return NULL;\r
+ }\r
+ if (NCH(ch) == 3) {\r
+ ch = CHILD(ch, 1);\r
+ /* def foo((x)): is not complex, special case. */\r
+ if (NCH(ch) != 1) {\r
+ /* We have complex arguments, setup for unpacking. */\r
+ if (Py_Py3kWarningFlag && !ast_warn(c, ch,\r
+ "tuple parameter unpacking has been removed in 3.x"))\r
+ return NULL;\r
+ complex_args = 1;\r
+ asdl_seq_SET(args, k++, compiler_complex_args(c, ch));\r
+ if (!asdl_seq_GET(args, k-1))\r
+ return NULL;\r
+ } else {\r
+ /* def foo((x)): setup for checking NAME below. */\r
+ /* Loop because there can be many parens and tuple\r
+ unpacking mixed in. */\r
+ parenthesized = 1;\r
+ ch = CHILD(ch, 0);\r
+ assert(TYPE(ch) == fpdef);\r
+ goto handle_fpdef;\r
+ }\r
+ }\r
+ if (TYPE(CHILD(ch, 0)) == NAME) {\r
+ PyObject *id;\r
+ expr_ty name;\r
+ if (!forbidden_check(c, n, STR(CHILD(ch, 0))))\r
+ return NULL;\r
+ id = NEW_IDENTIFIER(CHILD(ch, 0));\r
+ if (!id)\r
+ return NULL;\r
+ name = Name(id, Param, LINENO(ch), ch->n_col_offset,\r
+ c->c_arena);\r
+ if (!name)\r
+ return NULL;\r
+ asdl_seq_SET(args, k++, name);\r
+\r
+ }\r
+ i += 2; /* the name and the comma */\r
+ if (parenthesized && Py_Py3kWarningFlag &&\r
+ !ast_warn(c, ch, "parenthesized argument names "\r
+ "are invalid in 3.x"))\r
+ return NULL;\r
+\r
+ break;\r
+ }\r
+ case STAR:\r
+ if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1))))\r
+ return NULL;\r
+ vararg = NEW_IDENTIFIER(CHILD(n, i+1));\r
+ if (!vararg)\r
+ return NULL;\r
+ i += 3;\r
+ break;\r
+ case DOUBLESTAR:\r
+ if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1))))\r
+ return NULL;\r
+ kwarg = NEW_IDENTIFIER(CHILD(n, i+1));\r
+ if (!kwarg)\r
+ return NULL;\r
+ i += 3;\r
+ break;\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unexpected node in varargslist: %d @ %d",\r
+ TYPE(ch), i);\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ return arguments(args, vararg, kwarg, defaults, c->c_arena);\r
+}\r
+\r
+static expr_ty\r
+ast_for_dotted_name(struct compiling *c, const node *n)\r
+{\r
+ expr_ty e;\r
+ identifier id;\r
+ int lineno, col_offset;\r
+ int i;\r
+\r
+ REQ(n, dotted_name);\r
+\r
+ lineno = LINENO(n);\r
+ col_offset = n->n_col_offset;\r
+\r
+ id = NEW_IDENTIFIER(CHILD(n, 0));\r
+ if (!id)\r
+ return NULL;\r
+ e = Name(id, Load, lineno, col_offset, c->c_arena);\r
+ if (!e)\r
+ return NULL;\r
+\r
+ for (i = 2; i < NCH(n); i+=2) {\r
+ id = NEW_IDENTIFIER(CHILD(n, i));\r
+ if (!id)\r
+ return NULL;\r
+ e = Attribute(e, id, Load, lineno, col_offset, c->c_arena);\r
+ if (!e)\r
+ return NULL;\r
+ }\r
+\r
+ return e;\r
+}\r
+\r
+static expr_ty\r
+ast_for_decorator(struct compiling *c, const node *n)\r
+{\r
+ /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */\r
+ expr_ty d = NULL;\r
+ expr_ty name_expr;\r
+\r
+ REQ(n, decorator);\r
+ REQ(CHILD(n, 0), AT);\r
+ REQ(RCHILD(n, -1), NEWLINE);\r
+\r
+ name_expr = ast_for_dotted_name(c, CHILD(n, 1));\r
+ if (!name_expr)\r
+ return NULL;\r
+\r
+ if (NCH(n) == 3) { /* No arguments */\r
+ d = name_expr;\r
+ name_expr = NULL;\r
+ }\r
+ else if (NCH(n) == 5) { /* Call with no arguments */\r
+ d = Call(name_expr, NULL, NULL, NULL, NULL, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ if (!d)\r
+ return NULL;\r
+ name_expr = NULL;\r
+ }\r
+ else {\r
+ d = ast_for_call(c, CHILD(n, 3), name_expr);\r
+ if (!d)\r
+ return NULL;\r
+ name_expr = NULL;\r
+ }\r
+\r
+ return d;\r
+}\r
+\r
+static asdl_seq*\r
+ast_for_decorators(struct compiling *c, const node *n)\r
+{\r
+ asdl_seq* decorator_seq;\r
+ expr_ty d;\r
+ int i;\r
+\r
+ REQ(n, decorators);\r
+ decorator_seq = asdl_seq_new(NCH(n), c->c_arena);\r
+ if (!decorator_seq)\r
+ return NULL;\r
+\r
+ for (i = 0; i < NCH(n); i++) {\r
+ d = ast_for_decorator(c, CHILD(n, i));\r
+ if (!d)\r
+ return NULL;\r
+ asdl_seq_SET(decorator_seq, i, d);\r
+ }\r
+ return decorator_seq;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)\r
+{\r
+ /* funcdef: 'def' NAME parameters ':' suite */\r
+ identifier name;\r
+ arguments_ty args;\r
+ asdl_seq *body;\r
+ int name_i = 1;\r
+\r
+ REQ(n, funcdef);\r
+\r
+ name = NEW_IDENTIFIER(CHILD(n, name_i));\r
+ if (!name)\r
+ return NULL;\r
+ else if (!forbidden_check(c, CHILD(n, name_i), STR(CHILD(n, name_i))))\r
+ return NULL;\r
+ args = ast_for_arguments(c, CHILD(n, name_i + 1));\r
+ if (!args)\r
+ return NULL;\r
+ body = ast_for_suite(c, CHILD(n, name_i + 3));\r
+ if (!body)\r
+ return NULL;\r
+\r
+ return FunctionDef(name, args, body, decorator_seq, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static stmt_ty\r
+ast_for_decorated(struct compiling *c, const node *n)\r
+{\r
+ /* decorated: decorators (classdef | funcdef) */\r
+ stmt_ty thing = NULL;\r
+ asdl_seq *decorator_seq = NULL;\r
+\r
+ REQ(n, decorated);\r
+\r
+ decorator_seq = ast_for_decorators(c, CHILD(n, 0));\r
+ if (!decorator_seq)\r
+ return NULL;\r
+\r
+ assert(TYPE(CHILD(n, 1)) == funcdef ||\r
+ TYPE(CHILD(n, 1)) == classdef);\r
+\r
+ if (TYPE(CHILD(n, 1)) == funcdef) {\r
+ thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);\r
+ } else if (TYPE(CHILD(n, 1)) == classdef) {\r
+ thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq);\r
+ }\r
+ /* we count the decorators in when talking about the class' or\r
+ function's line number */\r
+ if (thing) {\r
+ thing->lineno = LINENO(n);\r
+ thing->col_offset = n->n_col_offset;\r
+ }\r
+ return thing;\r
+}\r
+\r
+static expr_ty\r
+ast_for_lambdef(struct compiling *c, const node *n)\r
+{\r
+ /* lambdef: 'lambda' [varargslist] ':' test */\r
+ arguments_ty args;\r
+ expr_ty expression;\r
+\r
+ if (NCH(n) == 3) {\r
+ args = arguments(NULL, NULL, NULL, NULL, c->c_arena);\r
+ if (!args)\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(n, 2));\r
+ if (!expression)\r
+ return NULL;\r
+ }\r
+ else {\r
+ args = ast_for_arguments(c, CHILD(n, 1));\r
+ if (!args)\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(n, 3));\r
+ if (!expression)\r
+ return NULL;\r
+ }\r
+\r
+ return Lambda(args, expression, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static expr_ty\r
+ast_for_ifexpr(struct compiling *c, const node *n)\r
+{\r
+ /* test: or_test 'if' or_test 'else' test */\r
+ expr_ty expression, body, orelse;\r
+\r
+ assert(NCH(n) == 5);\r
+ body = ast_for_expr(c, CHILD(n, 0));\r
+ if (!body)\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(n, 2));\r
+ if (!expression)\r
+ return NULL;\r
+ orelse = ast_for_expr(c, CHILD(n, 4));\r
+ if (!orelse)\r
+ return NULL;\r
+ return IfExp(expression, body, orelse, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+}\r
+\r
+/* XXX(nnorwitz): the listcomp and genexpr code should be refactored\r
+ so there is only a single version. Possibly for loops can also re-use\r
+ the code.\r
+*/\r
+\r
+/* Count the number of 'for' loop in a list comprehension.\r
+\r
+ Helper for ast_for_listcomp().\r
+*/\r
+\r
+static int\r
+count_list_fors(struct compiling *c, const node *n)\r
+{\r
+ int n_fors = 0;\r
+ node *ch = CHILD(n, 1);\r
+\r
+ count_list_for:\r
+ n_fors++;\r
+ REQ(ch, list_for);\r
+ if (NCH(ch) == 5)\r
+ ch = CHILD(ch, 4);\r
+ else\r
+ return n_fors;\r
+ count_list_iter:\r
+ REQ(ch, list_iter);\r
+ ch = CHILD(ch, 0);\r
+ if (TYPE(ch) == list_for)\r
+ goto count_list_for;\r
+ else if (TYPE(ch) == list_if) {\r
+ if (NCH(ch) == 3) {\r
+ ch = CHILD(ch, 2);\r
+ goto count_list_iter;\r
+ }\r
+ else\r
+ return n_fors;\r
+ }\r
+\r
+ /* Should never be reached */\r
+ PyErr_SetString(PyExc_SystemError, "logic error in count_list_fors");\r
+ return -1;\r
+}\r
+\r
+/* Count the number of 'if' statements in a list comprehension.\r
+\r
+ Helper for ast_for_listcomp().\r
+*/\r
+\r
+static int\r
+count_list_ifs(struct compiling *c, const node *n)\r
+{\r
+ int n_ifs = 0;\r
+\r
+ count_list_iter:\r
+ REQ(n, list_iter);\r
+ if (TYPE(CHILD(n, 0)) == list_for)\r
+ return n_ifs;\r
+ n = CHILD(n, 0);\r
+ REQ(n, list_if);\r
+ n_ifs++;\r
+ if (NCH(n) == 2)\r
+ return n_ifs;\r
+ n = CHILD(n, 2);\r
+ goto count_list_iter;\r
+}\r
+\r
+static expr_ty\r
+ast_for_listcomp(struct compiling *c, const node *n)\r
+{\r
+ /* listmaker: test ( list_for | (',' test)* [','] )\r
+ list_for: 'for' exprlist 'in' testlist_safe [list_iter]\r
+ list_iter: list_for | list_if\r
+ list_if: 'if' test [list_iter]\r
+ testlist_safe: test [(',' test)+ [',']]\r
+ */\r
+ expr_ty elt, first;\r
+ asdl_seq *listcomps;\r
+ int i, n_fors;\r
+ node *ch;\r
+\r
+ REQ(n, listmaker);\r
+ assert(NCH(n) > 1);\r
+\r
+ elt = ast_for_expr(c, CHILD(n, 0));\r
+ if (!elt)\r
+ return NULL;\r
+\r
+ n_fors = count_list_fors(c, n);\r
+ if (n_fors == -1)\r
+ return NULL;\r
+\r
+ listcomps = asdl_seq_new(n_fors, c->c_arena);\r
+ if (!listcomps)\r
+ return NULL;\r
+\r
+ ch = CHILD(n, 1);\r
+ for (i = 0; i < n_fors; i++) {\r
+ comprehension_ty lc;\r
+ asdl_seq *t;\r
+ expr_ty expression;\r
+ node *for_ch;\r
+\r
+ REQ(ch, list_for);\r
+\r
+ for_ch = CHILD(ch, 1);\r
+ t = ast_for_exprlist(c, for_ch, Store);\r
+ if (!t)\r
+ return NULL;\r
+ expression = ast_for_testlist(c, CHILD(ch, 3));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ /* Check the # of children rather than the length of t, since\r
+ [x for x, in ... ] has 1 element in t, but still requires a Tuple.\r
+ */\r
+ first = (expr_ty)asdl_seq_GET(t, 0);\r
+ if (NCH(for_ch) == 1)\r
+ lc = comprehension(first, expression, NULL, c->c_arena);\r
+ else\r
+ lc = comprehension(Tuple(t, Store, first->lineno, first->col_offset,\r
+ c->c_arena),\r
+ expression, NULL, c->c_arena);\r
+ if (!lc)\r
+ return NULL;\r
+\r
+ if (NCH(ch) == 5) {\r
+ int j, n_ifs;\r
+ asdl_seq *ifs;\r
+ expr_ty list_for_expr;\r
+\r
+ ch = CHILD(ch, 4);\r
+ n_ifs = count_list_ifs(c, ch);\r
+ if (n_ifs == -1)\r
+ return NULL;\r
+\r
+ ifs = asdl_seq_new(n_ifs, c->c_arena);\r
+ if (!ifs)\r
+ return NULL;\r
+\r
+ for (j = 0; j < n_ifs; j++) {\r
+ REQ(ch, list_iter);\r
+ ch = CHILD(ch, 0);\r
+ REQ(ch, list_if);\r
+\r
+ list_for_expr = ast_for_expr(c, CHILD(ch, 1));\r
+ if (!list_for_expr)\r
+ return NULL;\r
+\r
+ asdl_seq_SET(ifs, j, list_for_expr);\r
+ if (NCH(ch) == 3)\r
+ ch = CHILD(ch, 2);\r
+ }\r
+ /* on exit, must guarantee that ch is a list_for */\r
+ if (TYPE(ch) == list_iter)\r
+ ch = CHILD(ch, 0);\r
+ lc->ifs = ifs;\r
+ }\r
+ asdl_seq_SET(listcomps, i, lc);\r
+ }\r
+\r
+ return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+/*\r
+ Count the number of 'for' loops in a comprehension.\r
+\r
+ Helper for ast_for_comprehension().\r
+*/\r
+\r
+static int\r
+count_comp_fors(struct compiling *c, const node *n)\r
+{\r
+ int n_fors = 0;\r
+\r
+ count_comp_for:\r
+ n_fors++;\r
+ REQ(n, comp_for);\r
+ if (NCH(n) == 5)\r
+ n = CHILD(n, 4);\r
+ else\r
+ return n_fors;\r
+ count_comp_iter:\r
+ REQ(n, comp_iter);\r
+ n = CHILD(n, 0);\r
+ if (TYPE(n) == comp_for)\r
+ goto count_comp_for;\r
+ else if (TYPE(n) == comp_if) {\r
+ if (NCH(n) == 3) {\r
+ n = CHILD(n, 2);\r
+ goto count_comp_iter;\r
+ }\r
+ else\r
+ return n_fors;\r
+ }\r
+\r
+ /* Should never be reached */\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "logic error in count_comp_fors");\r
+ return -1;\r
+}\r
+\r
+/* Count the number of 'if' statements in a comprehension.\r
+\r
+ Helper for ast_for_comprehension().\r
+*/\r
+\r
+static int\r
+count_comp_ifs(struct compiling *c, const node *n)\r
+{\r
+ int n_ifs = 0;\r
+\r
+ while (1) {\r
+ REQ(n, comp_iter);\r
+ if (TYPE(CHILD(n, 0)) == comp_for)\r
+ return n_ifs;\r
+ n = CHILD(n, 0);\r
+ REQ(n, comp_if);\r
+ n_ifs++;\r
+ if (NCH(n) == 2)\r
+ return n_ifs;\r
+ n = CHILD(n, 2);\r
+ }\r
+}\r
+\r
+static asdl_seq *\r
+ast_for_comprehension(struct compiling *c, const node *n)\r
+{\r
+ int i, n_fors;\r
+ asdl_seq *comps;\r
+\r
+ n_fors = count_comp_fors(c, n);\r
+ if (n_fors == -1)\r
+ return NULL;\r
+\r
+ comps = asdl_seq_new(n_fors, c->c_arena);\r
+ if (!comps)\r
+ return NULL;\r
+\r
+ for (i = 0; i < n_fors; i++) {\r
+ comprehension_ty comp;\r
+ asdl_seq *t;\r
+ expr_ty expression, first;\r
+ node *for_ch;\r
+\r
+ REQ(n, comp_for);\r
+\r
+ for_ch = CHILD(n, 1);\r
+ t = ast_for_exprlist(c, for_ch, Store);\r
+ if (!t)\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(n, 3));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ /* Check the # of children rather than the length of t, since\r
+ (x for x, in ...) has 1 element in t, but still requires a Tuple. */\r
+ first = (expr_ty)asdl_seq_GET(t, 0);\r
+ if (NCH(for_ch) == 1)\r
+ comp = comprehension(first, expression, NULL, c->c_arena);\r
+ else\r
+ comp = comprehension(Tuple(t, Store, first->lineno, first->col_offset,\r
+ c->c_arena),\r
+ expression, NULL, c->c_arena);\r
+ if (!comp)\r
+ return NULL;\r
+\r
+ if (NCH(n) == 5) {\r
+ int j, n_ifs;\r
+ asdl_seq *ifs;\r
+\r
+ n = CHILD(n, 4);\r
+ n_ifs = count_comp_ifs(c, n);\r
+ if (n_ifs == -1)\r
+ return NULL;\r
+\r
+ ifs = asdl_seq_new(n_ifs, c->c_arena);\r
+ if (!ifs)\r
+ return NULL;\r
+\r
+ for (j = 0; j < n_ifs; j++) {\r
+ REQ(n, comp_iter);\r
+ n = CHILD(n, 0);\r
+ REQ(n, comp_if);\r
+\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ asdl_seq_SET(ifs, j, expression);\r
+ if (NCH(n) == 3)\r
+ n = CHILD(n, 2);\r
+ }\r
+ /* on exit, must guarantee that n is a comp_for */\r
+ if (TYPE(n) == comp_iter)\r
+ n = CHILD(n, 0);\r
+ comp->ifs = ifs;\r
+ }\r
+ asdl_seq_SET(comps, i, comp);\r
+ }\r
+ return comps;\r
+}\r
+\r
+static expr_ty\r
+ast_for_itercomp(struct compiling *c, const node *n, int type)\r
+{\r
+ expr_ty elt;\r
+ asdl_seq *comps;\r
+\r
+ assert(NCH(n) > 1);\r
+\r
+ elt = ast_for_expr(c, CHILD(n, 0));\r
+ if (!elt)\r
+ return NULL;\r
+\r
+ comps = ast_for_comprehension(c, CHILD(n, 1));\r
+ if (!comps)\r
+ return NULL;\r
+\r
+ if (type == COMP_GENEXP)\r
+ return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);\r
+ else if (type == COMP_SETCOMP)\r
+ return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena);\r
+ else\r
+ /* Should never happen */\r
+ return NULL;\r
+}\r
+\r
+static expr_ty\r
+ast_for_dictcomp(struct compiling *c, const node *n)\r
+{\r
+ expr_ty key, value;\r
+ asdl_seq *comps;\r
+\r
+ assert(NCH(n) > 3);\r
+ REQ(CHILD(n, 1), COLON);\r
+\r
+ key = ast_for_expr(c, CHILD(n, 0));\r
+ if (!key)\r
+ return NULL;\r
+\r
+ value = ast_for_expr(c, CHILD(n, 2));\r
+ if (!value)\r
+ return NULL;\r
+\r
+ comps = ast_for_comprehension(c, CHILD(n, 3));\r
+ if (!comps)\r
+ return NULL;\r
+\r
+ return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static expr_ty\r
+ast_for_genexp(struct compiling *c, const node *n)\r
+{\r
+ assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument));\r
+ return ast_for_itercomp(c, n, COMP_GENEXP);\r
+}\r
+\r
+static expr_ty\r
+ast_for_setcomp(struct compiling *c, const node *n)\r
+{\r
+ assert(TYPE(n) == (dictorsetmaker));\r
+ return ast_for_itercomp(c, n, COMP_SETCOMP);\r
+}\r
+\r
+static expr_ty\r
+ast_for_atom(struct compiling *c, const node *n)\r
+{\r
+ /* atom: '(' [yield_expr|testlist_comp] ')' | '[' [listmaker] ']'\r
+ | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+\r
+ */\r
+ node *ch = CHILD(n, 0);\r
+\r
+ switch (TYPE(ch)) {\r
+ case NAME: {\r
+ /* All names start in Load context, but may later be\r
+ changed. */\r
+ PyObject *name = NEW_IDENTIFIER(ch);\r
+ if (!name)\r
+ return NULL;\r
+ return Name(name, Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ case STRING: {\r
+ PyObject *str = parsestrplus(c, n);\r
+ if (!str) {\r
+#ifdef Py_USING_UNICODE\r
+ if (PyErr_ExceptionMatches(PyExc_UnicodeError)){\r
+ PyObject *type, *value, *tback, *errstr;\r
+ PyErr_Fetch(&type, &value, &tback);\r
+ errstr = PyObject_Str(value);\r
+ if (errstr) {\r
+ char *s = "";\r
+ char buf[128];\r
+ s = PyString_AsString(errstr);\r
+ PyOS_snprintf(buf, sizeof(buf), "(unicode error) %s", s);\r
+ ast_error(n, buf);\r
+ Py_DECREF(errstr);\r
+ } else {\r
+ ast_error(n, "(unicode error) unknown error");\r
+ }\r
+ Py_DECREF(type);\r
+ Py_DECREF(value);\r
+ Py_XDECREF(tback);\r
+ }\r
+#endif\r
+ return NULL;\r
+ }\r
+ PyArena_AddPyObject(c->c_arena, str);\r
+ return Str(str, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ case NUMBER: {\r
+ PyObject *pynum = parsenumber(c, STR(ch));\r
+ if (!pynum)\r
+ return NULL;\r
+\r
+ PyArena_AddPyObject(c->c_arena, pynum);\r
+ return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ case LPAR: /* some parenthesized expressions */\r
+ ch = CHILD(n, 1);\r
+\r
+ if (TYPE(ch) == RPAR)\r
+ return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+\r
+ if (TYPE(ch) == yield_expr)\r
+ return ast_for_expr(c, ch);\r
+\r
+ return ast_for_testlist_comp(c, ch);\r
+ case LSQB: /* list (or list comprehension) */\r
+ ch = CHILD(n, 1);\r
+\r
+ if (TYPE(ch) == RSQB)\r
+ return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+\r
+ REQ(ch, listmaker);\r
+ if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {\r
+ asdl_seq *elts = seq_for_testlist(c, ch);\r
+ if (!elts)\r
+ return NULL;\r
+\r
+ return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ else\r
+ return ast_for_listcomp(c, ch);\r
+ case LBRACE: {\r
+ /* dictorsetmaker:\r
+ * (test ':' test (comp_for | (',' test ':' test)* [','])) |\r
+ * (test (comp_for | (',' test)* [',']))\r
+ */\r
+ int i, size;\r
+ asdl_seq *keys, *values;\r
+\r
+ ch = CHILD(n, 1);\r
+ if (TYPE(ch) == RBRACE) {\r
+ /* it's an empty dict */\r
+ return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);\r
+ } else if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {\r
+ /* it's a simple set */\r
+ asdl_seq *elts;\r
+ size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */\r
+ elts = asdl_seq_new(size, c->c_arena);\r
+ if (!elts)\r
+ return NULL;\r
+ for (i = 0; i < NCH(ch); i += 2) {\r
+ expr_ty expression;\r
+ expression = ast_for_expr(c, CHILD(ch, i));\r
+ if (!expression)\r
+ return NULL;\r
+ asdl_seq_SET(elts, i / 2, expression);\r
+ }\r
+ return Set(elts, LINENO(n), n->n_col_offset, c->c_arena);\r
+ } else if (TYPE(CHILD(ch, 1)) == comp_for) {\r
+ /* it's a set comprehension */\r
+ return ast_for_setcomp(c, ch);\r
+ } else if (NCH(ch) > 3 && TYPE(CHILD(ch, 3)) == comp_for) {\r
+ return ast_for_dictcomp(c, ch);\r
+ } else {\r
+ /* it's a dict */\r
+ size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */\r
+ keys = asdl_seq_new(size, c->c_arena);\r
+ if (!keys)\r
+ return NULL;\r
+\r
+ values = asdl_seq_new(size, c->c_arena);\r
+ if (!values)\r
+ return NULL;\r
+\r
+ for (i = 0; i < NCH(ch); i += 4) {\r
+ expr_ty expression;\r
+\r
+ expression = ast_for_expr(c, CHILD(ch, i));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ asdl_seq_SET(keys, i / 4, expression);\r
+\r
+ expression = ast_for_expr(c, CHILD(ch, i + 2));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ asdl_seq_SET(values, i / 4, expression);\r
+ }\r
+ return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ }\r
+ case BACKQUOTE: { /* repr */\r
+ expr_ty expression;\r
+ if (Py_Py3kWarningFlag &&\r
+ !ast_warn(c, n, "backquote not supported in 3.x; use repr()"))\r
+ return NULL;\r
+ expression = ast_for_testlist(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ return Repr(expression, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ default:\r
+ PyErr_Format(PyExc_SystemError, "unhandled atom %d", TYPE(ch));\r
+ return NULL;\r
+ }\r
+}\r
+\r
+static slice_ty\r
+ast_for_slice(struct compiling *c, const node *n)\r
+{\r
+ node *ch;\r
+ expr_ty lower = NULL, upper = NULL, step = NULL;\r
+\r
+ REQ(n, subscript);\r
+\r
+ /*\r
+ subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]\r
+ sliceop: ':' [test]\r
+ */\r
+ ch = CHILD(n, 0);\r
+ if (TYPE(ch) == DOT)\r
+ return Ellipsis(c->c_arena);\r
+\r
+ if (NCH(n) == 1 && TYPE(ch) == test) {\r
+ /* 'step' variable hold no significance in terms of being used over\r
+ other vars */\r
+ step = ast_for_expr(c, ch);\r
+ if (!step)\r
+ return NULL;\r
+\r
+ return Index(step, c->c_arena);\r
+ }\r
+\r
+ if (TYPE(ch) == test) {\r
+ lower = ast_for_expr(c, ch);\r
+ if (!lower)\r
+ return NULL;\r
+ }\r
+\r
+ /* If there's an upper bound it's in the second or third position. */\r
+ if (TYPE(ch) == COLON) {\r
+ if (NCH(n) > 1) {\r
+ node *n2 = CHILD(n, 1);\r
+\r
+ if (TYPE(n2) == test) {\r
+ upper = ast_for_expr(c, n2);\r
+ if (!upper)\r
+ return NULL;\r
+ }\r
+ }\r
+ } else if (NCH(n) > 2) {\r
+ node *n2 = CHILD(n, 2);\r
+\r
+ if (TYPE(n2) == test) {\r
+ upper = ast_for_expr(c, n2);\r
+ if (!upper)\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ ch = CHILD(n, NCH(n) - 1);\r
+ if (TYPE(ch) == sliceop) {\r
+ if (NCH(ch) == 1) {\r
+ /*\r
+ This is an extended slice (ie "x[::]") with no expression in the\r
+ step field. We set this literally to "None" in order to\r
+ disambiguate it from x[:]. (The interpreter might have to call\r
+ __getslice__ for x[:], but it must call __getitem__ for x[::].)\r
+ */\r
+ identifier none = new_identifier("None", c->c_arena);\r
+ if (!none)\r
+ return NULL;\r
+ ch = CHILD(ch, 0);\r
+ step = Name(none, Load, LINENO(ch), ch->n_col_offset, c->c_arena);\r
+ if (!step)\r
+ return NULL;\r
+ } else {\r
+ ch = CHILD(ch, 1);\r
+ if (TYPE(ch) == test) {\r
+ step = ast_for_expr(c, ch);\r
+ if (!step)\r
+ return NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+ return Slice(lower, upper, step, c->c_arena);\r
+}\r
+\r
+static expr_ty\r
+ast_for_binop(struct compiling *c, const node *n)\r
+{\r
+ /* Must account for a sequence of expressions.\r
+ How should A op B op C by represented?\r
+ BinOp(BinOp(A, op, B), op, C).\r
+ */\r
+\r
+ int i, nops;\r
+ expr_ty expr1, expr2, result;\r
+ operator_ty newoperator;\r
+\r
+ expr1 = ast_for_expr(c, CHILD(n, 0));\r
+ if (!expr1)\r
+ return NULL;\r
+\r
+ expr2 = ast_for_expr(c, CHILD(n, 2));\r
+ if (!expr2)\r
+ return NULL;\r
+\r
+ newoperator = get_operator(CHILD(n, 1));\r
+ if (!newoperator)\r
+ return NULL;\r
+\r
+ result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ if (!result)\r
+ return NULL;\r
+\r
+ nops = (NCH(n) - 1) / 2;\r
+ for (i = 1; i < nops; i++) {\r
+ expr_ty tmp_result, tmp;\r
+ const node* next_oper = CHILD(n, i * 2 + 1);\r
+\r
+ newoperator = get_operator(next_oper);\r
+ if (!newoperator)\r
+ return NULL;\r
+\r
+ tmp = ast_for_expr(c, CHILD(n, i * 2 + 2));\r
+ if (!tmp)\r
+ return NULL;\r
+\r
+ tmp_result = BinOp(result, newoperator, tmp,\r
+ LINENO(next_oper), next_oper->n_col_offset,\r
+ c->c_arena);\r
+ if (!tmp_result)\r
+ return NULL;\r
+ result = tmp_result;\r
+ }\r
+ return result;\r
+}\r
+\r
+static expr_ty\r
+ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)\r
+{\r
+ /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME\r
+ subscriptlist: subscript (',' subscript)* [',']\r
+ subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]\r
+ */\r
+ REQ(n, trailer);\r
+ if (TYPE(CHILD(n, 0)) == LPAR) {\r
+ if (NCH(n) == 2)\r
+ return Call(left_expr, NULL, NULL, NULL, NULL, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ else\r
+ return ast_for_call(c, CHILD(n, 1), left_expr);\r
+ }\r
+ else if (TYPE(CHILD(n, 0)) == DOT ) {\r
+ PyObject *attr_id = NEW_IDENTIFIER(CHILD(n, 1));\r
+ if (!attr_id)\r
+ return NULL;\r
+ return Attribute(left_expr, attr_id, Load,\r
+ LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ else {\r
+ REQ(CHILD(n, 0), LSQB);\r
+ REQ(CHILD(n, 2), RSQB);\r
+ n = CHILD(n, 1);\r
+ if (NCH(n) == 1) {\r
+ slice_ty slc = ast_for_slice(c, CHILD(n, 0));\r
+ if (!slc)\r
+ return NULL;\r
+ return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else {\r
+ /* The grammar is ambiguous here. The ambiguity is resolved\r
+ by treating the sequence as a tuple literal if there are\r
+ no slice features.\r
+ */\r
+ int j;\r
+ slice_ty slc;\r
+ expr_ty e;\r
+ bool simple = true;\r
+ asdl_seq *slices, *elts;\r
+ slices = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);\r
+ if (!slices)\r
+ return NULL;\r
+ for (j = 0; j < NCH(n); j += 2) {\r
+ slc = ast_for_slice(c, CHILD(n, j));\r
+ if (!slc)\r
+ return NULL;\r
+ if (slc->kind != Index_kind)\r
+ simple = false;\r
+ asdl_seq_SET(slices, j / 2, slc);\r
+ }\r
+ if (!simple) {\r
+ return Subscript(left_expr, ExtSlice(slices, c->c_arena),\r
+ Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ /* extract Index values and put them in a Tuple */\r
+ elts = asdl_seq_new(asdl_seq_LEN(slices), c->c_arena);\r
+ if (!elts)\r
+ return NULL;\r
+ for (j = 0; j < asdl_seq_LEN(slices); ++j) {\r
+ slc = (slice_ty)asdl_seq_GET(slices, j);\r
+ assert(slc->kind == Index_kind && slc->v.Index.value);\r
+ asdl_seq_SET(elts, j, slc->v.Index.value);\r
+ }\r
+ e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+ if (!e)\r
+ return NULL;\r
+ return Subscript(left_expr, Index(e, c->c_arena),\r
+ Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ }\r
+}\r
+\r
+static expr_ty\r
+ast_for_factor(struct compiling *c, const node *n)\r
+{\r
+ node *pfactor, *ppower, *patom, *pnum;\r
+ expr_ty expression;\r
+\r
+ /* If the unary - operator is applied to a constant, don't generate\r
+ a UNARY_NEGATIVE opcode. Just store the approriate value as a\r
+ constant. The peephole optimizer already does something like\r
+ this but it doesn't handle the case where the constant is\r
+ (sys.maxint - 1). In that case, we want a PyIntObject, not a\r
+ PyLongObject.\r
+ */\r
+ if (TYPE(CHILD(n, 0)) == MINUS &&\r
+ NCH(n) == 2 &&\r
+ TYPE((pfactor = CHILD(n, 1))) == factor &&\r
+ NCH(pfactor) == 1 &&\r
+ TYPE((ppower = CHILD(pfactor, 0))) == power &&\r
+ NCH(ppower) == 1 &&\r
+ TYPE((patom = CHILD(ppower, 0))) == atom &&\r
+ TYPE((pnum = CHILD(patom, 0))) == NUMBER) {\r
+ PyObject *pynum;\r
+ char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2);\r
+ if (s == NULL)\r
+ return NULL;\r
+ s[0] = '-';\r
+ strcpy(s + 1, STR(pnum));\r
+ pynum = parsenumber(c, s);\r
+ PyObject_FREE(s);\r
+ if (!pynum)\r
+ return NULL;\r
+\r
+ PyArena_AddPyObject(c->c_arena, pynum);\r
+ return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ switch (TYPE(CHILD(n, 0))) {\r
+ case PLUS:\r
+ return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ case MINUS:\r
+ return UnaryOp(USub, expression, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ case TILDE:\r
+ return UnaryOp(Invert, expression, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ }\r
+ PyErr_Format(PyExc_SystemError, "unhandled factor: %d",\r
+ TYPE(CHILD(n, 0)));\r
+ return NULL;\r
+}\r
+\r
+static expr_ty\r
+ast_for_power(struct compiling *c, const node *n)\r
+{\r
+ /* power: atom trailer* ('**' factor)*\r
+ */\r
+ int i;\r
+ expr_ty e, tmp;\r
+ REQ(n, power);\r
+ e = ast_for_atom(c, CHILD(n, 0));\r
+ if (!e)\r
+ return NULL;\r
+ if (NCH(n) == 1)\r
+ return e;\r
+ for (i = 1; i < NCH(n); i++) {\r
+ node *ch = CHILD(n, i);\r
+ if (TYPE(ch) != trailer)\r
+ break;\r
+ tmp = ast_for_trailer(c, ch, e);\r
+ if (!tmp)\r
+ return NULL;\r
+ tmp->lineno = e->lineno;\r
+ tmp->col_offset = e->col_offset;\r
+ e = tmp;\r
+ }\r
+ if (TYPE(CHILD(n, NCH(n) - 1)) == factor) {\r
+ expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1));\r
+ if (!f)\r
+ return NULL;\r
+ tmp = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena);\r
+ if (!tmp)\r
+ return NULL;\r
+ e = tmp;\r
+ }\r
+ return e;\r
+}\r
+\r
+/* Do not name a variable 'expr'! Will cause a compile error.\r
+*/\r
+\r
+static expr_ty\r
+ast_for_expr(struct compiling *c, const node *n)\r
+{\r
+ /* handle the full range of simple expressions\r
+ test: or_test ['if' or_test 'else' test] | lambdef\r
+ or_test: and_test ('or' and_test)*\r
+ and_test: not_test ('and' not_test)*\r
+ not_test: 'not' not_test | comparison\r
+ comparison: expr (comp_op expr)*\r
+ expr: xor_expr ('|' xor_expr)*\r
+ xor_expr: and_expr ('^' and_expr)*\r
+ and_expr: shift_expr ('&' shift_expr)*\r
+ shift_expr: arith_expr (('<<'|'>>') arith_expr)*\r
+ arith_expr: term (('+'|'-') term)*\r
+ term: factor (('*'|'/'|'%'|'//') factor)*\r
+ factor: ('+'|'-'|'~') factor | power\r
+ power: atom trailer* ('**' factor)*\r
+\r
+ As well as modified versions that exist for backward compatibility,\r
+ to explicitly allow:\r
+ [ x for x in lambda: 0, lambda: 1 ]\r
+ (which would be ambiguous without these extra rules)\r
+\r
+ old_test: or_test | old_lambdef\r
+ old_lambdef: 'lambda' [vararglist] ':' old_test\r
+\r
+ */\r
+\r
+ asdl_seq *seq;\r
+ int i;\r
+\r
+ loop:\r
+ switch (TYPE(n)) {\r
+ case test:\r
+ case old_test:\r
+ if (TYPE(CHILD(n, 0)) == lambdef ||\r
+ TYPE(CHILD(n, 0)) == old_lambdef)\r
+ return ast_for_lambdef(c, CHILD(n, 0));\r
+ else if (NCH(n) > 1)\r
+ return ast_for_ifexpr(c, n);\r
+ /* Fallthrough */\r
+ case or_test:\r
+ case and_test:\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ goto loop;\r
+ }\r
+ seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);\r
+ if (!seq)\r
+ return NULL;\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ expr_ty e = ast_for_expr(c, CHILD(n, i));\r
+ if (!e)\r
+ return NULL;\r
+ asdl_seq_SET(seq, i / 2, e);\r
+ }\r
+ if (!strcmp(STR(CHILD(n, 1)), "and"))\r
+ return BoolOp(And, seq, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ assert(!strcmp(STR(CHILD(n, 1)), "or"));\r
+ return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena);\r
+ case not_test:\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ goto loop;\r
+ }\r
+ else {\r
+ expr_ty expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+\r
+ return UnaryOp(Not, expression, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ case comparison:\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ goto loop;\r
+ }\r
+ else {\r
+ expr_ty expression;\r
+ asdl_int_seq *ops;\r
+ asdl_seq *cmps;\r
+ ops = asdl_int_seq_new(NCH(n) / 2, c->c_arena);\r
+ if (!ops)\r
+ return NULL;\r
+ cmps = asdl_seq_new(NCH(n) / 2, c->c_arena);\r
+ if (!cmps) {\r
+ return NULL;\r
+ }\r
+ for (i = 1; i < NCH(n); i += 2) {\r
+ cmpop_ty newoperator;\r
+\r
+ newoperator = ast_for_comp_op(c, CHILD(n, i));\r
+ if (!newoperator) {\r
+ return NULL;\r
+ }\r
+\r
+ expression = ast_for_expr(c, CHILD(n, i + 1));\r
+ if (!expression) {\r
+ return NULL;\r
+ }\r
+\r
+ asdl_seq_SET(ops, i / 2, newoperator);\r
+ asdl_seq_SET(cmps, i / 2, expression);\r
+ }\r
+ expression = ast_for_expr(c, CHILD(n, 0));\r
+ if (!expression) {\r
+ return NULL;\r
+ }\r
+\r
+ return Compare(expression, ops, cmps, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ }\r
+ break;\r
+\r
+ /* The next five cases all handle BinOps. The main body of code\r
+ is the same in each case, but the switch turned inside out to\r
+ reuse the code for each type of operator.\r
+ */\r
+ case expr:\r
+ case xor_expr:\r
+ case and_expr:\r
+ case shift_expr:\r
+ case arith_expr:\r
+ case term:\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ goto loop;\r
+ }\r
+ return ast_for_binop(c, n);\r
+ case yield_expr: {\r
+ expr_ty exp = NULL;\r
+ if (NCH(n) == 2) {\r
+ exp = ast_for_testlist(c, CHILD(n, 1));\r
+ if (!exp)\r
+ return NULL;\r
+ }\r
+ return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ case factor:\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ goto loop;\r
+ }\r
+ return ast_for_factor(c, n);\r
+ case power:\r
+ return ast_for_power(c, n);\r
+ default:\r
+ PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n));\r
+ return NULL;\r
+ }\r
+ /* should never get here unless if error is set */\r
+ return NULL;\r
+}\r
+\r
+static expr_ty\r
+ast_for_call(struct compiling *c, const node *n, expr_ty func)\r
+{\r
+ /*\r
+ arglist: (argument ',')* (argument [',']| '*' test [',' '**' test]\r
+ | '**' test)\r
+ argument: [test '='] test [comp_for] # Really [keyword '='] test\r
+ */\r
+\r
+ int i, nargs, nkeywords, ngens;\r
+ asdl_seq *args;\r
+ asdl_seq *keywords;\r
+ expr_ty vararg = NULL, kwarg = NULL;\r
+\r
+ REQ(n, arglist);\r
+\r
+ nargs = 0;\r
+ nkeywords = 0;\r
+ ngens = 0;\r
+ for (i = 0; i < NCH(n); i++) {\r
+ node *ch = CHILD(n, i);\r
+ if (TYPE(ch) == argument) {\r
+ if (NCH(ch) == 1)\r
+ nargs++;\r
+ else if (TYPE(CHILD(ch, 1)) == comp_for)\r
+ ngens++;\r
+ else\r
+ nkeywords++;\r
+ }\r
+ }\r
+ if (ngens > 1 || (ngens && (nargs || nkeywords))) {\r
+ ast_error(n, "Generator expression must be parenthesized "\r
+ "if not sole argument");\r
+ return NULL;\r
+ }\r
+\r
+ if (nargs + nkeywords + ngens > 255) {\r
+ ast_error(n, "more than 255 arguments");\r
+ return NULL;\r
+ }\r
+\r
+ args = asdl_seq_new(nargs + ngens, c->c_arena);\r
+ if (!args)\r
+ return NULL;\r
+ keywords = asdl_seq_new(nkeywords, c->c_arena);\r
+ if (!keywords)\r
+ return NULL;\r
+ nargs = 0;\r
+ nkeywords = 0;\r
+ for (i = 0; i < NCH(n); i++) {\r
+ node *ch = CHILD(n, i);\r
+ if (TYPE(ch) == argument) {\r
+ expr_ty e;\r
+ if (NCH(ch) == 1) {\r
+ if (nkeywords) {\r
+ ast_error(CHILD(ch, 0),\r
+ "non-keyword arg after keyword arg");\r
+ return NULL;\r
+ }\r
+ if (vararg) {\r
+ ast_error(CHILD(ch, 0),\r
+ "only named arguments may follow *expression");\r
+ return NULL;\r
+ }\r
+ e = ast_for_expr(c, CHILD(ch, 0));\r
+ if (!e)\r
+ return NULL;\r
+ asdl_seq_SET(args, nargs++, e);\r
+ }\r
+ else if (TYPE(CHILD(ch, 1)) == comp_for) {\r
+ e = ast_for_genexp(c, ch);\r
+ if (!e)\r
+ return NULL;\r
+ asdl_seq_SET(args, nargs++, e);\r
+ }\r
+ else {\r
+ keyword_ty kw;\r
+ identifier key;\r
+ int k;\r
+ char *tmp;\r
+\r
+ /* CHILD(ch, 0) is test, but must be an identifier? */\r
+ e = ast_for_expr(c, CHILD(ch, 0));\r
+ if (!e)\r
+ return NULL;\r
+ /* f(lambda x: x[0] = 3) ends up getting parsed with\r
+ * LHS test = lambda x: x[0], and RHS test = 3.\r
+ * SF bug 132313 points out that complaining about a keyword\r
+ * then is very confusing.\r
+ */\r
+ if (e->kind == Lambda_kind) {\r
+ ast_error(CHILD(ch, 0),\r
+ "lambda cannot contain assignment");\r
+ return NULL;\r
+ } else if (e->kind != Name_kind) {\r
+ ast_error(CHILD(ch, 0), "keyword can't be an expression");\r
+ return NULL;\r
+ }\r
+ key = e->v.Name.id;\r
+ if (!forbidden_check(c, CHILD(ch, 0), PyBytes_AS_STRING(key)))\r
+ return NULL;\r
+ for (k = 0; k < nkeywords; k++) {\r
+ tmp = PyString_AS_STRING(\r
+ ((keyword_ty)asdl_seq_GET(keywords, k))->arg);\r
+ if (!strcmp(tmp, PyString_AS_STRING(key))) {\r
+ ast_error(CHILD(ch, 0), "keyword argument repeated");\r
+ return NULL;\r
+ }\r
+ }\r
+ e = ast_for_expr(c, CHILD(ch, 2));\r
+ if (!e)\r
+ return NULL;\r
+ kw = keyword(key, e, c->c_arena);\r
+ if (!kw)\r
+ return NULL;\r
+ asdl_seq_SET(keywords, nkeywords++, kw);\r
+ }\r
+ }\r
+ else if (TYPE(ch) == STAR) {\r
+ vararg = ast_for_expr(c, CHILD(n, i+1));\r
+ if (!vararg)\r
+ return NULL;\r
+ i++;\r
+ }\r
+ else if (TYPE(ch) == DOUBLESTAR) {\r
+ kwarg = ast_for_expr(c, CHILD(n, i+1));\r
+ if (!kwarg)\r
+ return NULL;\r
+ i++;\r
+ }\r
+ }\r
+\r
+ return Call(func, args, keywords, vararg, kwarg, func->lineno,\r
+ func->col_offset, c->c_arena);\r
+}\r
+\r
+static expr_ty\r
+ast_for_testlist(struct compiling *c, const node* n)\r
+{\r
+ /* testlist_comp: test (',' test)* [','] */\r
+ /* testlist: test (',' test)* [','] */\r
+ /* testlist_safe: test (',' test)+ [','] */\r
+ /* testlist1: test (',' test)* */\r
+ assert(NCH(n) > 0);\r
+ if (TYPE(n) == testlist_comp) {\r
+ if (NCH(n) > 1)\r
+ assert(TYPE(CHILD(n, 1)) != comp_for);\r
+ }\r
+ else {\r
+ assert(TYPE(n) == testlist ||\r
+ TYPE(n) == testlist_safe ||\r
+ TYPE(n) == testlist1);\r
+ }\r
+ if (NCH(n) == 1)\r
+ return ast_for_expr(c, CHILD(n, 0));\r
+ else {\r
+ asdl_seq *tmp = seq_for_testlist(c, n);\r
+ if (!tmp)\r
+ return NULL;\r
+ return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+}\r
+\r
+static expr_ty\r
+ast_for_testlist_comp(struct compiling *c, const node* n)\r
+{\r
+ /* testlist_comp: test ( comp_for | (',' test)* [','] ) */\r
+ /* argument: test [ comp_for ] */\r
+ assert(TYPE(n) == testlist_comp || TYPE(n) == argument);\r
+ if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == comp_for)\r
+ return ast_for_genexp(c, n);\r
+ return ast_for_testlist(c, n);\r
+}\r
+\r
+/* like ast_for_testlist() but returns a sequence */\r
+static asdl_seq*\r
+ast_for_class_bases(struct compiling *c, const node* n)\r
+{\r
+ /* testlist: test (',' test)* [','] */\r
+ assert(NCH(n) > 0);\r
+ REQ(n, testlist);\r
+ if (NCH(n) == 1) {\r
+ expr_ty base;\r
+ asdl_seq *bases = asdl_seq_new(1, c->c_arena);\r
+ if (!bases)\r
+ return NULL;\r
+ base = ast_for_expr(c, CHILD(n, 0));\r
+ if (!base)\r
+ return NULL;\r
+ asdl_seq_SET(bases, 0, base);\r
+ return bases;\r
+ }\r
+\r
+ return seq_for_testlist(c, n);\r
+}\r
+\r
+static stmt_ty\r
+ast_for_expr_stmt(struct compiling *c, const node *n)\r
+{\r
+ REQ(n, expr_stmt);\r
+ /* expr_stmt: testlist (augassign (yield_expr|testlist)\r
+ | ('=' (yield_expr|testlist))*)\r
+ testlist: test (',' test)* [',']\r
+ augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^='\r
+ | '<<=' | '>>=' | '**=' | '//='\r
+ test: ... here starts the operator precendence dance\r
+ */\r
+\r
+ if (NCH(n) == 1) {\r
+ expr_ty e = ast_for_testlist(c, CHILD(n, 0));\r
+ if (!e)\r
+ return NULL;\r
+\r
+ return Expr(e, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ else if (TYPE(CHILD(n, 1)) == augassign) {\r
+ expr_ty expr1, expr2;\r
+ operator_ty newoperator;\r
+ node *ch = CHILD(n, 0);\r
+\r
+ expr1 = ast_for_testlist(c, ch);\r
+ if (!expr1)\r
+ return NULL;\r
+ if(!set_context(c, expr1, Store, ch))\r
+ return NULL;\r
+ /* set_context checks that most expressions are not the left side.\r
+ Augmented assignments can only have a name, a subscript, or an\r
+ attribute on the left, though, so we have to explicitly check for\r
+ those. */\r
+ switch (expr1->kind) {\r
+ case Name_kind:\r
+ case Attribute_kind:\r
+ case Subscript_kind:\r
+ break;\r
+ default:\r
+ ast_error(ch, "illegal expression for augmented assignment");\r
+ return NULL;\r
+ }\r
+\r
+ ch = CHILD(n, 2);\r
+ if (TYPE(ch) == testlist)\r
+ expr2 = ast_for_testlist(c, ch);\r
+ else\r
+ expr2 = ast_for_expr(c, ch);\r
+ if (!expr2)\r
+ return NULL;\r
+\r
+ newoperator = ast_for_augassign(c, CHILD(n, 1));\r
+ if (!newoperator)\r
+ return NULL;\r
+\r
+ return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else {\r
+ int i;\r
+ asdl_seq *targets;\r
+ node *value;\r
+ expr_ty expression;\r
+\r
+ /* a normal assignment */\r
+ REQ(CHILD(n, 1), EQUAL);\r
+ targets = asdl_seq_new(NCH(n) / 2, c->c_arena);\r
+ if (!targets)\r
+ return NULL;\r
+ for (i = 0; i < NCH(n) - 2; i += 2) {\r
+ expr_ty e;\r
+ node *ch = CHILD(n, i);\r
+ if (TYPE(ch) == yield_expr) {\r
+ ast_error(ch, "assignment to yield expression not possible");\r
+ return NULL;\r
+ }\r
+ e = ast_for_testlist(c, ch);\r
+ if (!e)\r
+ return NULL;\r
+\r
+ /* set context to assign */\r
+ if (!set_context(c, e, Store, CHILD(n, i)))\r
+ return NULL;\r
+\r
+ asdl_seq_SET(targets, i / 2, e);\r
+ }\r
+ value = CHILD(n, NCH(n) - 1);\r
+ if (TYPE(value) == testlist)\r
+ expression = ast_for_testlist(c, value);\r
+ else\r
+ expression = ast_for_expr(c, value);\r
+ if (!expression)\r
+ return NULL;\r
+ return Assign(targets, expression, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+}\r
+\r
+static stmt_ty\r
+ast_for_print_stmt(struct compiling *c, const node *n)\r
+{\r
+ /* print_stmt: 'print' ( [ test (',' test)* [','] ]\r
+ | '>>' test [ (',' test)+ [','] ] )\r
+ */\r
+ expr_ty dest = NULL, expression;\r
+ asdl_seq *seq = NULL;\r
+ bool nl;\r
+ int i, j, values_count, start = 1;\r
+\r
+ REQ(n, print_stmt);\r
+ if (NCH(n) >= 2 && TYPE(CHILD(n, 1)) == RIGHTSHIFT) {\r
+ dest = ast_for_expr(c, CHILD(n, 2));\r
+ if (!dest)\r
+ return NULL;\r
+ start = 4;\r
+ }\r
+ values_count = (NCH(n) + 1 - start) / 2;\r
+ if (values_count) {\r
+ seq = asdl_seq_new(values_count, c->c_arena);\r
+ if (!seq)\r
+ return NULL;\r
+ for (i = start, j = 0; i < NCH(n); i += 2, ++j) {\r
+ expression = ast_for_expr(c, CHILD(n, i));\r
+ if (!expression)\r
+ return NULL;\r
+ asdl_seq_SET(seq, j, expression);\r
+ }\r
+ }\r
+ nl = (TYPE(CHILD(n, NCH(n) - 1)) == COMMA) ? false : true;\r
+ return Print(dest, seq, nl, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static asdl_seq *\r
+ast_for_exprlist(struct compiling *c, const node *n, expr_context_ty context)\r
+{\r
+ asdl_seq *seq;\r
+ int i;\r
+ expr_ty e;\r
+\r
+ REQ(n, exprlist);\r
+\r
+ seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);\r
+ if (!seq)\r
+ return NULL;\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ e = ast_for_expr(c, CHILD(n, i));\r
+ if (!e)\r
+ return NULL;\r
+ asdl_seq_SET(seq, i / 2, e);\r
+ if (context && !set_context(c, e, context, CHILD(n, i)))\r
+ return NULL;\r
+ }\r
+ return seq;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_del_stmt(struct compiling *c, const node *n)\r
+{\r
+ asdl_seq *expr_list;\r
+\r
+ /* del_stmt: 'del' exprlist */\r
+ REQ(n, del_stmt);\r
+\r
+ expr_list = ast_for_exprlist(c, CHILD(n, 1), Del);\r
+ if (!expr_list)\r
+ return NULL;\r
+ return Delete(expr_list, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static stmt_ty\r
+ast_for_flow_stmt(struct compiling *c, const node *n)\r
+{\r
+ /*\r
+ flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt\r
+ | yield_stmt\r
+ break_stmt: 'break'\r
+ continue_stmt: 'continue'\r
+ return_stmt: 'return' [testlist]\r
+ yield_stmt: yield_expr\r
+ yield_expr: 'yield' testlist\r
+ raise_stmt: 'raise' [test [',' test [',' test]]]\r
+ */\r
+ node *ch;\r
+\r
+ REQ(n, flow_stmt);\r
+ ch = CHILD(n, 0);\r
+ switch (TYPE(ch)) {\r
+ case break_stmt:\r
+ return Break(LINENO(n), n->n_col_offset, c->c_arena);\r
+ case continue_stmt:\r
+ return Continue(LINENO(n), n->n_col_offset, c->c_arena);\r
+ case yield_stmt: { /* will reduce to yield_expr */\r
+ expr_ty exp = ast_for_expr(c, CHILD(ch, 0));\r
+ if (!exp)\r
+ return NULL;\r
+ return Expr(exp, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ case return_stmt:\r
+ if (NCH(ch) == 1)\r
+ return Return(NULL, LINENO(n), n->n_col_offset, c->c_arena);\r
+ else {\r
+ expr_ty expression = ast_for_testlist(c, CHILD(ch, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ return Return(expression, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ case raise_stmt:\r
+ if (NCH(ch) == 1)\r
+ return Raise(NULL, NULL, NULL, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ else if (NCH(ch) == 2) {\r
+ expr_ty expression = ast_for_expr(c, CHILD(ch, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ return Raise(expression, NULL, NULL, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ }\r
+ else if (NCH(ch) == 4) {\r
+ expr_ty expr1, expr2;\r
+\r
+ expr1 = ast_for_expr(c, CHILD(ch, 1));\r
+ if (!expr1)\r
+ return NULL;\r
+ expr2 = ast_for_expr(c, CHILD(ch, 3));\r
+ if (!expr2)\r
+ return NULL;\r
+\r
+ return Raise(expr1, expr2, NULL, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else if (NCH(ch) == 6) {\r
+ expr_ty expr1, expr2, expr3;\r
+\r
+ expr1 = ast_for_expr(c, CHILD(ch, 1));\r
+ if (!expr1)\r
+ return NULL;\r
+ expr2 = ast_for_expr(c, CHILD(ch, 3));\r
+ if (!expr2)\r
+ return NULL;\r
+ expr3 = ast_for_expr(c, CHILD(ch, 5));\r
+ if (!expr3)\r
+ return NULL;\r
+\r
+ return Raise(expr1, expr2, expr3, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unexpected flow_stmt: %d", TYPE(ch));\r
+ return NULL;\r
+ }\r
+\r
+ PyErr_SetString(PyExc_SystemError, "unhandled flow statement");\r
+ return NULL;\r
+}\r
+\r
+static alias_ty\r
+alias_for_import_name(struct compiling *c, const node *n, int store)\r
+{\r
+ /*\r
+ import_as_name: NAME ['as' NAME]\r
+ dotted_as_name: dotted_name ['as' NAME]\r
+ dotted_name: NAME ('.' NAME)*\r
+ */\r
+ PyObject *str, *name;\r
+\r
+ loop:\r
+ switch (TYPE(n)) {\r
+ case import_as_name: {\r
+ node *name_node = CHILD(n, 0);\r
+ str = NULL;\r
+ if (NCH(n) == 3) {\r
+ node *str_node = CHILD(n, 2);\r
+ if (store && !forbidden_check(c, str_node, STR(str_node)))\r
+ return NULL;\r
+ str = NEW_IDENTIFIER(str_node);\r
+ if (!str)\r
+ return NULL;\r
+ }\r
+ else {\r
+ if (!forbidden_check(c, name_node, STR(name_node)))\r
+ return NULL;\r
+ }\r
+ name = NEW_IDENTIFIER(name_node);\r
+ if (!name)\r
+ return NULL;\r
+ return alias(name, str, c->c_arena);\r
+ }\r
+ case dotted_as_name:\r
+ if (NCH(n) == 1) {\r
+ n = CHILD(n, 0);\r
+ goto loop;\r
+ }\r
+ else {\r
+ node *asname_node = CHILD(n, 2);\r
+ alias_ty a = alias_for_import_name(c, CHILD(n, 0), 0);\r
+ if (!a)\r
+ return NULL;\r
+ assert(!a->asname);\r
+ if (!forbidden_check(c, asname_node, STR(asname_node)))\r
+ return NULL;\r
+ a->asname = NEW_IDENTIFIER(asname_node);\r
+ if (!a->asname)\r
+ return NULL;\r
+ return a;\r
+ }\r
+ break;\r
+ case dotted_name:\r
+ if (NCH(n) == 1) {\r
+ node *name_node = CHILD(n, 0);\r
+ if (store && !forbidden_check(c, name_node, STR(name_node)))\r
+ return NULL;\r
+ name = NEW_IDENTIFIER(name_node);\r
+ if (!name)\r
+ return NULL;\r
+ return alias(name, NULL, c->c_arena);\r
+ }\r
+ else {\r
+ /* Create a string of the form "a.b.c" */\r
+ int i;\r
+ size_t len;\r
+ char *s;\r
+\r
+ len = 0;\r
+ for (i = 0; i < NCH(n); i += 2)\r
+ /* length of string plus one for the dot */\r
+ len += strlen(STR(CHILD(n, i))) + 1;\r
+ len--; /* the last name doesn't have a dot */\r
+ str = PyString_FromStringAndSize(NULL, len);\r
+ if (!str)\r
+ return NULL;\r
+ s = PyString_AS_STRING(str);\r
+ if (!s)\r
+ return NULL;\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ char *sch = STR(CHILD(n, i));\r
+ strcpy(s, STR(CHILD(n, i)));\r
+ s += strlen(sch);\r
+ *s++ = '.';\r
+ }\r
+ --s;\r
+ *s = '\0';\r
+ PyString_InternInPlace(&str);\r
+ PyArena_AddPyObject(c->c_arena, str);\r
+ return alias(str, NULL, c->c_arena);\r
+ }\r
+ break;\r
+ case STAR:\r
+ str = PyString_InternFromString("*");\r
+ PyArena_AddPyObject(c->c_arena, str);\r
+ return alias(str, NULL, c->c_arena);\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unexpected import name: %d", TYPE(n));\r
+ return NULL;\r
+ }\r
+\r
+ PyErr_SetString(PyExc_SystemError, "unhandled import name condition");\r
+ return NULL;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_import_stmt(struct compiling *c, const node *n)\r
+{\r
+ /*\r
+ import_stmt: import_name | import_from\r
+ import_name: 'import' dotted_as_names\r
+ import_from: 'from' ('.'* dotted_name | '.') 'import'\r
+ ('*' | '(' import_as_names ')' | import_as_names)\r
+ */\r
+ int lineno;\r
+ int col_offset;\r
+ int i;\r
+ asdl_seq *aliases;\r
+\r
+ REQ(n, import_stmt);\r
+ lineno = LINENO(n);\r
+ col_offset = n->n_col_offset;\r
+ n = CHILD(n, 0);\r
+ if (TYPE(n) == import_name) {\r
+ n = CHILD(n, 1);\r
+ REQ(n, dotted_as_names);\r
+ aliases = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena);\r
+ if (!aliases)\r
+ return NULL;\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1);\r
+ if (!import_alias)\r
+ return NULL;\r
+ asdl_seq_SET(aliases, i / 2, import_alias);\r
+ }\r
+ return Import(aliases, lineno, col_offset, c->c_arena);\r
+ }\r
+ else if (TYPE(n) == import_from) {\r
+ int n_children;\r
+ int idx, ndots = 0;\r
+ alias_ty mod = NULL;\r
+ identifier modname = NULL;\r
+\r
+ /* Count the number of dots (for relative imports) and check for the\r
+ optional module name */\r
+ for (idx = 1; idx < NCH(n); idx++) {\r
+ if (TYPE(CHILD(n, idx)) == dotted_name) {\r
+ mod = alias_for_import_name(c, CHILD(n, idx), 0);\r
+ if (!mod)\r
+ return NULL;\r
+ idx++;\r
+ break;\r
+ } else if (TYPE(CHILD(n, idx)) != DOT) {\r
+ break;\r
+ }\r
+ ndots++;\r
+ }\r
+ idx++; /* skip over the 'import' keyword */\r
+ switch (TYPE(CHILD(n, idx))) {\r
+ case STAR:\r
+ /* from ... import * */\r
+ n = CHILD(n, idx);\r
+ n_children = 1;\r
+ break;\r
+ case LPAR:\r
+ /* from ... import (x, y, z) */\r
+ n = CHILD(n, idx + 1);\r
+ n_children = NCH(n);\r
+ break;\r
+ case import_as_names:\r
+ /* from ... import x, y, z */\r
+ n = CHILD(n, idx);\r
+ n_children = NCH(n);\r
+ if (n_children % 2 == 0) {\r
+ ast_error(n, "trailing comma not allowed without"\r
+ " surrounding parentheses");\r
+ return NULL;\r
+ }\r
+ break;\r
+ default:\r
+ ast_error(n, "Unexpected node-type in from-import");\r
+ return NULL;\r
+ }\r
+\r
+ aliases = asdl_seq_new((n_children + 1) / 2, c->c_arena);\r
+ if (!aliases)\r
+ return NULL;\r
+\r
+ /* handle "from ... import *" special b/c there's no children */\r
+ if (TYPE(n) == STAR) {\r
+ alias_ty import_alias = alias_for_import_name(c, n, 1);\r
+ if (!import_alias)\r
+ return NULL;\r
+ asdl_seq_SET(aliases, 0, import_alias);\r
+ }\r
+ else {\r
+ for (i = 0; i < NCH(n); i += 2) {\r
+ alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1);\r
+ if (!import_alias)\r
+ return NULL;\r
+ asdl_seq_SET(aliases, i / 2, import_alias);\r
+ }\r
+ }\r
+ if (mod != NULL)\r
+ modname = mod->name;\r
+ return ImportFrom(modname, aliases, ndots, lineno, col_offset,\r
+ c->c_arena);\r
+ }\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unknown import statement: starts with command '%s'",\r
+ STR(CHILD(n, 0)));\r
+ return NULL;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_global_stmt(struct compiling *c, const node *n)\r
+{\r
+ /* global_stmt: 'global' NAME (',' NAME)* */\r
+ identifier name;\r
+ asdl_seq *s;\r
+ int i;\r
+\r
+ REQ(n, global_stmt);\r
+ s = asdl_seq_new(NCH(n) / 2, c->c_arena);\r
+ if (!s)\r
+ return NULL;\r
+ for (i = 1; i < NCH(n); i += 2) {\r
+ name = NEW_IDENTIFIER(CHILD(n, i));\r
+ if (!name)\r
+ return NULL;\r
+ asdl_seq_SET(s, i / 2, name);\r
+ }\r
+ return Global(s, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static stmt_ty\r
+ast_for_exec_stmt(struct compiling *c, const node *n)\r
+{\r
+ expr_ty expr1, globals = NULL, locals = NULL;\r
+ int n_children = NCH(n);\r
+ if (n_children != 2 && n_children != 4 && n_children != 6) {\r
+ PyErr_Format(PyExc_SystemError,\r
+ "poorly formed 'exec' statement: %d parts to statement",\r
+ n_children);\r
+ return NULL;\r
+ }\r
+\r
+ /* exec_stmt: 'exec' expr ['in' test [',' test]] */\r
+ REQ(n, exec_stmt);\r
+ expr1 = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expr1)\r
+ return NULL;\r
+\r
+ if (expr1->kind == Tuple_kind && n_children < 4 &&\r
+ (asdl_seq_LEN(expr1->v.Tuple.elts) == 2 ||\r
+ asdl_seq_LEN(expr1->v.Tuple.elts) == 3)) {\r
+ /* Backwards compatibility: passing exec args as a tuple */\r
+ globals = asdl_seq_GET(expr1->v.Tuple.elts, 1);\r
+ if (asdl_seq_LEN(expr1->v.Tuple.elts) == 3) {\r
+ locals = asdl_seq_GET(expr1->v.Tuple.elts, 2);\r
+ }\r
+ expr1 = asdl_seq_GET(expr1->v.Tuple.elts, 0);\r
+ }\r
+\r
+ if (n_children >= 4) {\r
+ globals = ast_for_expr(c, CHILD(n, 3));\r
+ if (!globals)\r
+ return NULL;\r
+ }\r
+ if (n_children == 6) {\r
+ locals = ast_for_expr(c, CHILD(n, 5));\r
+ if (!locals)\r
+ return NULL;\r
+ }\r
+\r
+ return Exec(expr1, globals, locals, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+}\r
+\r
+static stmt_ty\r
+ast_for_assert_stmt(struct compiling *c, const node *n)\r
+{\r
+ /* assert_stmt: 'assert' test [',' test] */\r
+ REQ(n, assert_stmt);\r
+ if (NCH(n) == 2) {\r
+ expr_ty expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ return Assert(expression, NULL, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else if (NCH(n) == 4) {\r
+ expr_ty expr1, expr2;\r
+\r
+ expr1 = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expr1)\r
+ return NULL;\r
+ expr2 = ast_for_expr(c, CHILD(n, 3));\r
+ if (!expr2)\r
+ return NULL;\r
+\r
+ return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+ PyErr_Format(PyExc_SystemError,\r
+ "improper number of parts to 'assert' statement: %d",\r
+ NCH(n));\r
+ return NULL;\r
+}\r
+\r
+static asdl_seq *\r
+ast_for_suite(struct compiling *c, const node *n)\r
+{\r
+ /* suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT */\r
+ asdl_seq *seq;\r
+ stmt_ty s;\r
+ int i, total, num, end, pos = 0;\r
+ node *ch;\r
+\r
+ REQ(n, suite);\r
+\r
+ total = num_stmts(n);\r
+ seq = asdl_seq_new(total, c->c_arena);\r
+ if (!seq)\r
+ return NULL;\r
+ if (TYPE(CHILD(n, 0)) == simple_stmt) {\r
+ n = CHILD(n, 0);\r
+ /* simple_stmt always ends with a NEWLINE,\r
+ and may have a trailing SEMI\r
+ */\r
+ end = NCH(n) - 1;\r
+ if (TYPE(CHILD(n, end - 1)) == SEMI)\r
+ end--;\r
+ /* loop by 2 to skip semi-colons */\r
+ for (i = 0; i < end; i += 2) {\r
+ ch = CHILD(n, i);\r
+ s = ast_for_stmt(c, ch);\r
+ if (!s)\r
+ return NULL;\r
+ asdl_seq_SET(seq, pos++, s);\r
+ }\r
+ }\r
+ else {\r
+ for (i = 2; i < (NCH(n) - 1); i++) {\r
+ ch = CHILD(n, i);\r
+ REQ(ch, stmt);\r
+ num = num_stmts(ch);\r
+ if (num == 1) {\r
+ /* small_stmt or compound_stmt with only one child */\r
+ s = ast_for_stmt(c, ch);\r
+ if (!s)\r
+ return NULL;\r
+ asdl_seq_SET(seq, pos++, s);\r
+ }\r
+ else {\r
+ int j;\r
+ ch = CHILD(ch, 0);\r
+ REQ(ch, simple_stmt);\r
+ for (j = 0; j < NCH(ch); j += 2) {\r
+ /* statement terminates with a semi-colon ';' */\r
+ if (NCH(CHILD(ch, j)) == 0) {\r
+ assert((j + 1) == NCH(ch));\r
+ break;\r
+ }\r
+ s = ast_for_stmt(c, CHILD(ch, j));\r
+ if (!s)\r
+ return NULL;\r
+ asdl_seq_SET(seq, pos++, s);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ assert(pos == seq->size);\r
+ return seq;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_if_stmt(struct compiling *c, const node *n)\r
+{\r
+ /* if_stmt: 'if' test ':' suite ('elif' test ':' suite)*\r
+ ['else' ':' suite]\r
+ */\r
+ char *s;\r
+\r
+ REQ(n, if_stmt);\r
+\r
+ if (NCH(n) == 4) {\r
+ expr_ty expression;\r
+ asdl_seq *suite_seq;\r
+\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, CHILD(n, 3));\r
+ if (!suite_seq)\r
+ return NULL;\r
+\r
+ return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+\r
+ s = STR(CHILD(n, 4));\r
+ /* s[2], the third character in the string, will be\r
+ 's' for el_s_e, or\r
+ 'i' for el_i_f\r
+ */\r
+ if (s[2] == 's') {\r
+ expr_ty expression;\r
+ asdl_seq *seq1, *seq2;\r
+\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ seq1 = ast_for_suite(c, CHILD(n, 3));\r
+ if (!seq1)\r
+ return NULL;\r
+ seq2 = ast_for_suite(c, CHILD(n, 6));\r
+ if (!seq2)\r
+ return NULL;\r
+\r
+ return If(expression, seq1, seq2, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else if (s[2] == 'i') {\r
+ int i, n_elif, has_else = 0;\r
+ expr_ty expression;\r
+ asdl_seq *suite_seq;\r
+ asdl_seq *orelse = NULL;\r
+ n_elif = NCH(n) - 4;\r
+ /* must reference the child n_elif+1 since 'else' token is third,\r
+ not fourth, child from the end. */\r
+ if (TYPE(CHILD(n, (n_elif + 1))) == NAME\r
+ && STR(CHILD(n, (n_elif + 1)))[2] == 's') {\r
+ has_else = 1;\r
+ n_elif -= 3;\r
+ }\r
+ n_elif /= 4;\r
+\r
+ if (has_else) {\r
+ asdl_seq *suite_seq2;\r
+\r
+ orelse = asdl_seq_new(1, c->c_arena);\r
+ if (!orelse)\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(n, NCH(n) - 6));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, CHILD(n, NCH(n) - 4));\r
+ if (!suite_seq)\r
+ return NULL;\r
+ suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));\r
+ if (!suite_seq2)\r
+ return NULL;\r
+\r
+ asdl_seq_SET(orelse, 0,\r
+ If(expression, suite_seq, suite_seq2,\r
+ LINENO(CHILD(n, NCH(n) - 6)),\r
+ CHILD(n, NCH(n) - 6)->n_col_offset,\r
+ c->c_arena));\r
+ /* the just-created orelse handled the last elif */\r
+ n_elif--;\r
+ }\r
+\r
+ for (i = 0; i < n_elif; i++) {\r
+ int off = 5 + (n_elif - i - 1) * 4;\r
+ asdl_seq *newobj = asdl_seq_new(1, c->c_arena);\r
+ if (!newobj)\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(n, off));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, CHILD(n, off + 2));\r
+ if (!suite_seq)\r
+ return NULL;\r
+\r
+ asdl_seq_SET(newobj, 0,\r
+ If(expression, suite_seq, orelse,\r
+ LINENO(CHILD(n, off)),\r
+ CHILD(n, off)->n_col_offset, c->c_arena));\r
+ orelse = newobj;\r
+ }\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, CHILD(n, 3));\r
+ if (!suite_seq)\r
+ return NULL;\r
+ return If(expression, suite_seq, orelse,\r
+ LINENO(n), n->n_col_offset, c->c_arena);\r
+ }\r
+\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unexpected token in 'if' statement: %s", s);\r
+ return NULL;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_while_stmt(struct compiling *c, const node *n)\r
+{\r
+ /* while_stmt: 'while' test ':' suite ['else' ':' suite] */\r
+ REQ(n, while_stmt);\r
+\r
+ if (NCH(n) == 4) {\r
+ expr_ty expression;\r
+ asdl_seq *suite_seq;\r
+\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, CHILD(n, 3));\r
+ if (!suite_seq)\r
+ return NULL;\r
+ return While(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+ else if (NCH(n) == 7) {\r
+ expr_ty expression;\r
+ asdl_seq *seq1, *seq2;\r
+\r
+ expression = ast_for_expr(c, CHILD(n, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ seq1 = ast_for_suite(c, CHILD(n, 3));\r
+ if (!seq1)\r
+ return NULL;\r
+ seq2 = ast_for_suite(c, CHILD(n, 6));\r
+ if (!seq2)\r
+ return NULL;\r
+\r
+ return While(expression, seq1, seq2, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+ }\r
+\r
+ PyErr_Format(PyExc_SystemError,\r
+ "wrong number of tokens for 'while' statement: %d",\r
+ NCH(n));\r
+ return NULL;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_for_stmt(struct compiling *c, const node *n)\r
+{\r
+ asdl_seq *_target, *seq = NULL, *suite_seq;\r
+ expr_ty expression;\r
+ expr_ty target, first;\r
+ const node *node_target;\r
+ /* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */\r
+ REQ(n, for_stmt);\r
+\r
+ if (NCH(n) == 9) {\r
+ seq = ast_for_suite(c, CHILD(n, 8));\r
+ if (!seq)\r
+ return NULL;\r
+ }\r
+\r
+ node_target = CHILD(n, 1);\r
+ _target = ast_for_exprlist(c, node_target, Store);\r
+ if (!_target)\r
+ return NULL;\r
+ /* Check the # of children rather than the length of _target, since\r
+ for x, in ... has 1 element in _target, but still requires a Tuple. */\r
+ first = (expr_ty)asdl_seq_GET(_target, 0);\r
+ if (NCH(node_target) == 1)\r
+ target = first;\r
+ else\r
+ target = Tuple(_target, Store, first->lineno, first->col_offset, c->c_arena);\r
+\r
+ expression = ast_for_testlist(c, CHILD(n, 3));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, CHILD(n, 5));\r
+ if (!suite_seq)\r
+ return NULL;\r
+\r
+ return For(target, expression, suite_seq, seq, LINENO(n), n->n_col_offset,\r
+ c->c_arena);\r
+}\r
+\r
+static excepthandler_ty\r
+ast_for_except_clause(struct compiling *c, const node *exc, node *body)\r
+{\r
+ /* except_clause: 'except' [test [(',' | 'as') test]] */\r
+ REQ(exc, except_clause);\r
+ REQ(body, suite);\r
+\r
+ if (NCH(exc) == 1) {\r
+ asdl_seq *suite_seq = ast_for_suite(c, body);\r
+ if (!suite_seq)\r
+ return NULL;\r
+\r
+ return ExceptHandler(NULL, NULL, suite_seq, LINENO(exc),\r
+ exc->n_col_offset, c->c_arena);\r
+ }\r
+ else if (NCH(exc) == 2) {\r
+ expr_ty expression;\r
+ asdl_seq *suite_seq;\r
+\r
+ expression = ast_for_expr(c, CHILD(exc, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, body);\r
+ if (!suite_seq)\r
+ return NULL;\r
+\r
+ return ExceptHandler(expression, NULL, suite_seq, LINENO(exc),\r
+ exc->n_col_offset, c->c_arena);\r
+ }\r
+ else if (NCH(exc) == 4) {\r
+ asdl_seq *suite_seq;\r
+ expr_ty expression;\r
+ expr_ty e = ast_for_expr(c, CHILD(exc, 3));\r
+ if (!e)\r
+ return NULL;\r
+ if (!set_context(c, e, Store, CHILD(exc, 3)))\r
+ return NULL;\r
+ expression = ast_for_expr(c, CHILD(exc, 1));\r
+ if (!expression)\r
+ return NULL;\r
+ suite_seq = ast_for_suite(c, body);\r
+ if (!suite_seq)\r
+ return NULL;\r
+\r
+ return ExceptHandler(expression, e, suite_seq, LINENO(exc),\r
+ exc->n_col_offset, c->c_arena);\r
+ }\r
+\r
+ PyErr_Format(PyExc_SystemError,\r
+ "wrong number of children for 'except' clause: %d",\r
+ NCH(exc));\r
+ return NULL;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_try_stmt(struct compiling *c, const node *n)\r
+{\r
+ const int nch = NCH(n);\r
+ int n_except = (nch - 3)/3;\r
+ asdl_seq *body, *orelse = NULL, *finally = NULL;\r
+\r
+ REQ(n, try_stmt);\r
+\r
+ body = ast_for_suite(c, CHILD(n, 2));\r
+ if (body == NULL)\r
+ return NULL;\r
+\r
+ if (TYPE(CHILD(n, nch - 3)) == NAME) {\r
+ if (strcmp(STR(CHILD(n, nch - 3)), "finally") == 0) {\r
+ if (nch >= 9 && TYPE(CHILD(n, nch - 6)) == NAME) {\r
+ /* we can assume it's an "else",\r
+ because nch >= 9 for try-else-finally and\r
+ it would otherwise have a type of except_clause */\r
+ orelse = ast_for_suite(c, CHILD(n, nch - 4));\r
+ if (orelse == NULL)\r
+ return NULL;\r
+ n_except--;\r
+ }\r
+\r
+ finally = ast_for_suite(c, CHILD(n, nch - 1));\r
+ if (finally == NULL)\r
+ return NULL;\r
+ n_except--;\r
+ }\r
+ else {\r
+ /* we can assume it's an "else",\r
+ otherwise it would have a type of except_clause */\r
+ orelse = ast_for_suite(c, CHILD(n, nch - 1));\r
+ if (orelse == NULL)\r
+ return NULL;\r
+ n_except--;\r
+ }\r
+ }\r
+ else if (TYPE(CHILD(n, nch - 3)) != except_clause) {\r
+ ast_error(n, "malformed 'try' statement");\r
+ return NULL;\r
+ }\r
+\r
+ if (n_except > 0) {\r
+ int i;\r
+ stmt_ty except_st;\r
+ /* process except statements to create a try ... except */\r
+ asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena);\r
+ if (handlers == NULL)\r
+ return NULL;\r
+\r
+ for (i = 0; i < n_except; i++) {\r
+ excepthandler_ty e = ast_for_except_clause(c, CHILD(n, 3 + i * 3),\r
+ CHILD(n, 5 + i * 3));\r
+ if (!e)\r
+ return NULL;\r
+ asdl_seq_SET(handlers, i, e);\r
+ }\r
+\r
+ except_st = TryExcept(body, handlers, orelse, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ if (!finally)\r
+ return except_st;\r
+\r
+ /* if a 'finally' is present too, we nest the TryExcept within a\r
+ TryFinally to emulate try ... except ... finally */\r
+ body = asdl_seq_new(1, c->c_arena);\r
+ if (body == NULL)\r
+ return NULL;\r
+ asdl_seq_SET(body, 0, except_st);\r
+ }\r
+\r
+ /* must be a try ... finally (except clauses are in body, if any exist) */\r
+ assert(finally != NULL);\r
+ return TryFinally(body, finally, LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+/* with_item: test ['as' expr] */\r
+static stmt_ty\r
+ast_for_with_item(struct compiling *c, const node *n, asdl_seq *content)\r
+{\r
+ expr_ty context_expr, optional_vars = NULL;\r
+\r
+ REQ(n, with_item);\r
+ context_expr = ast_for_expr(c, CHILD(n, 0));\r
+ if (!context_expr)\r
+ return NULL;\r
+ if (NCH(n) == 3) {\r
+ optional_vars = ast_for_expr(c, CHILD(n, 2));\r
+\r
+ if (!optional_vars) {\r
+ return NULL;\r
+ }\r
+ if (!set_context(c, optional_vars, Store, n)) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ return With(context_expr, optional_vars, content, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+}\r
+\r
+/* with_stmt: 'with' with_item (',' with_item)* ':' suite */\r
+static stmt_ty\r
+ast_for_with_stmt(struct compiling *c, const node *n)\r
+{\r
+ int i;\r
+ stmt_ty ret;\r
+ asdl_seq *inner;\r
+\r
+ REQ(n, with_stmt);\r
+\r
+ /* process the with items inside-out */\r
+ i = NCH(n) - 1;\r
+ /* the suite of the innermost with item is the suite of the with stmt */\r
+ inner = ast_for_suite(c, CHILD(n, i));\r
+ if (!inner)\r
+ return NULL;\r
+\r
+ for (;;) {\r
+ i -= 2;\r
+ ret = ast_for_with_item(c, CHILD(n, i), inner);\r
+ if (!ret)\r
+ return NULL;\r
+ /* was this the last item? */\r
+ if (i == 1)\r
+ break;\r
+ /* if not, wrap the result so far in a new sequence */\r
+ inner = asdl_seq_new(1, c->c_arena);\r
+ if (!inner)\r
+ return NULL;\r
+ asdl_seq_SET(inner, 0, ret);\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+static stmt_ty\r
+ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)\r
+{\r
+ /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */\r
+ PyObject *classname;\r
+ asdl_seq *bases, *s;\r
+\r
+ REQ(n, classdef);\r
+\r
+ if (!forbidden_check(c, n, STR(CHILD(n, 1))))\r
+ return NULL;\r
+\r
+ if (NCH(n) == 4) {\r
+ s = ast_for_suite(c, CHILD(n, 3));\r
+ if (!s)\r
+ return NULL;\r
+ classname = NEW_IDENTIFIER(CHILD(n, 1));\r
+ if (!classname)\r
+ return NULL;\r
+ return ClassDef(classname, NULL, s, decorator_seq, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ }\r
+ /* check for empty base list */\r
+ if (TYPE(CHILD(n,3)) == RPAR) {\r
+ s = ast_for_suite(c, CHILD(n,5));\r
+ if (!s)\r
+ return NULL;\r
+ classname = NEW_IDENTIFIER(CHILD(n, 1));\r
+ if (!classname)\r
+ return NULL;\r
+ return ClassDef(classname, NULL, s, decorator_seq, LINENO(n),\r
+ n->n_col_offset, c->c_arena);\r
+ }\r
+\r
+ /* else handle the base class list */\r
+ bases = ast_for_class_bases(c, CHILD(n, 3));\r
+ if (!bases)\r
+ return NULL;\r
+\r
+ s = ast_for_suite(c, CHILD(n, 6));\r
+ if (!s)\r
+ return NULL;\r
+ classname = NEW_IDENTIFIER(CHILD(n, 1));\r
+ if (!classname)\r
+ return NULL;\r
+ return ClassDef(classname, bases, s, decorator_seq,\r
+ LINENO(n), n->n_col_offset, c->c_arena);\r
+}\r
+\r
+static stmt_ty\r
+ast_for_stmt(struct compiling *c, const node *n)\r
+{\r
+ if (TYPE(n) == stmt) {\r
+ assert(NCH(n) == 1);\r
+ n = CHILD(n, 0);\r
+ }\r
+ if (TYPE(n) == simple_stmt) {\r
+ assert(num_stmts(n) == 1);\r
+ n = CHILD(n, 0);\r
+ }\r
+ if (TYPE(n) == small_stmt) {\r
+ n = CHILD(n, 0);\r
+ /* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt\r
+ | flow_stmt | import_stmt | global_stmt | exec_stmt\r
+ | assert_stmt\r
+ */\r
+ switch (TYPE(n)) {\r
+ case expr_stmt:\r
+ return ast_for_expr_stmt(c, n);\r
+ case print_stmt:\r
+ return ast_for_print_stmt(c, n);\r
+ case del_stmt:\r
+ return ast_for_del_stmt(c, n);\r
+ case pass_stmt:\r
+ return Pass(LINENO(n), n->n_col_offset, c->c_arena);\r
+ case flow_stmt:\r
+ return ast_for_flow_stmt(c, n);\r
+ case import_stmt:\r
+ return ast_for_import_stmt(c, n);\r
+ case global_stmt:\r
+ return ast_for_global_stmt(c, n);\r
+ case exec_stmt:\r
+ return ast_for_exec_stmt(c, n);\r
+ case assert_stmt:\r
+ return ast_for_assert_stmt(c, n);\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unhandled small_stmt: TYPE=%d NCH=%d\n",\r
+ TYPE(n), NCH(n));\r
+ return NULL;\r
+ }\r
+ }\r
+ else {\r
+ /* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt\r
+ | funcdef | classdef | decorated\r
+ */\r
+ node *ch = CHILD(n, 0);\r
+ REQ(n, compound_stmt);\r
+ switch (TYPE(ch)) {\r
+ case if_stmt:\r
+ return ast_for_if_stmt(c, ch);\r
+ case while_stmt:\r
+ return ast_for_while_stmt(c, ch);\r
+ case for_stmt:\r
+ return ast_for_for_stmt(c, ch);\r
+ case try_stmt:\r
+ return ast_for_try_stmt(c, ch);\r
+ case with_stmt:\r
+ return ast_for_with_stmt(c, ch);\r
+ case funcdef:\r
+ return ast_for_funcdef(c, ch, NULL);\r
+ case classdef:\r
+ return ast_for_classdef(c, ch, NULL);\r
+ case decorated:\r
+ return ast_for_decorated(c, ch);\r
+ default:\r
+ PyErr_Format(PyExc_SystemError,\r
+ "unhandled small_stmt: TYPE=%d NCH=%d\n",\r
+ TYPE(n), NCH(n));\r
+ return NULL;\r
+ }\r
+ }\r
+}\r
+\r
+static PyObject *\r
+parsenumber(struct compiling *c, const char *s)\r
+{\r
+ const char *end;\r
+ long x;\r
+ double dx;\r
+#ifndef WITHOUT_COMPLEX\r
+ Py_complex complex;\r
+ int imflag;\r
+#endif\r
+\r
+ assert(s != NULL);\r
+ errno = 0;\r
+ end = s + strlen(s) - 1;\r
+#ifndef WITHOUT_COMPLEX\r
+ imflag = *end == 'j' || *end == 'J';\r
+#endif\r
+ if (*end == 'l' || *end == 'L')\r
+ return PyLong_FromString((char *)s, (char **)0, 0);\r
+ x = PyOS_strtol((char *)s, (char **)&end, 0);\r
+ if (*end == '\0') {\r
+ if (errno != 0)\r
+ return PyLong_FromString((char *)s, (char **)0, 0);\r
+ return PyInt_FromLong(x);\r
+ }\r
+ /* XXX Huge floats may silently fail */\r
+#ifndef WITHOUT_COMPLEX\r
+ if (imflag) {\r
+ complex.real = 0.;\r
+ complex.imag = PyOS_string_to_double(s, (char **)&end, NULL);\r
+ if (complex.imag == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyComplex_FromCComplex(complex);\r
+ }\r
+ else\r
+#endif\r
+ {\r
+ dx = PyOS_string_to_double(s, NULL, NULL);\r
+ if (dx == -1.0 && PyErr_Occurred())\r
+ return NULL;\r
+ return PyFloat_FromDouble(dx);\r
+ }\r
+}\r
+\r
+static PyObject *\r
+decode_utf8(struct compiling *c, const char **sPtr, const char *end, char* encoding)\r
+{\r
+#ifndef Py_USING_UNICODE\r
+ Py_FatalError("decode_utf8 should not be called in this build.");\r
+ return NULL;\r
+#else\r
+ PyObject *u, *v;\r
+ char *s, *t;\r
+ t = s = (char *)*sPtr;\r
+ /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */\r
+ while (s < end && (*s & 0x80)) s++;\r
+ *sPtr = s;\r
+ u = PyUnicode_DecodeUTF8(t, s - t, NULL);\r
+ if (u == NULL)\r
+ return NULL;\r
+ v = PyUnicode_AsEncodedString(u, encoding, NULL);\r
+ Py_DECREF(u);\r
+ return v;\r
+#endif\r
+}\r
+\r
+#ifdef Py_USING_UNICODE\r
+static PyObject *\r
+decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, const char *encoding)\r
+{\r
+ PyObject *v;\r
+ PyObject *u = NULL;\r
+ char *buf;\r
+ char *p;\r
+ const char *end;\r
+ if (encoding != NULL && strcmp(encoding, "iso-8859-1")) {\r
+ /* check for integer overflow */\r
+ if (len > PY_SIZE_MAX / 6)\r
+ return NULL;\r
+ /* "<C3><A4>" (2 bytes) may become "\U000000E4" (10 bytes), or 1:5\r
+ "\รค" (3 bytes) may become "\u005c\U000000E4" (16 bytes), or ~1:6 */\r
+ u = PyString_FromStringAndSize((char *)NULL, len * 6);\r
+ if (u == NULL)\r
+ return NULL;\r
+ p = buf = PyString_AsString(u);\r
+ end = s + len;\r
+ while (s < end) {\r
+ if (*s == '\\') {\r
+ *p++ = *s++;\r
+ if (*s & 0x80) {\r
+ strcpy(p, "u005c");\r
+ p += 5;\r
+ }\r
+ }\r
+ if (*s & 0x80) { /* XXX inefficient */\r
+ PyObject *w;\r
+ char *r;\r
+ Py_ssize_t rn, i;\r
+ w = decode_utf8(c, &s, end, "utf-32-be");\r
+ if (w == NULL) {\r
+ Py_DECREF(u);\r
+ return NULL;\r
+ }\r
+ r = PyString_AsString(w);\r
+ rn = PyString_Size(w);\r
+ assert(rn % 4 == 0);\r
+ for (i = 0; i < rn; i += 4) {\r
+ sprintf(p, "\\U%02x%02x%02x%02x",\r
+ r[i + 0] & 0xFF,\r
+ r[i + 1] & 0xFF,\r
+ r[i + 2] & 0xFF,\r
+ r[i + 3] & 0xFF);\r
+ p += 10;\r
+ }\r
+ Py_DECREF(w);\r
+ } else {\r
+ *p++ = *s++;\r
+ }\r
+ }\r
+ len = p - buf;\r
+ s = buf;\r
+ }\r
+ if (rawmode)\r
+ v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL);\r
+ else\r
+ v = PyUnicode_DecodeUnicodeEscape(s, len, NULL);\r
+ Py_XDECREF(u);\r
+ return v;\r
+}\r
+#endif\r
+\r
+/* s is a Python string literal, including the bracketing quote characters,\r
+ * and r &/or u prefixes (if any), and embedded escape sequences (if any).\r
+ * parsestr parses it, and returns the decoded Python string object.\r
+ */\r
+static PyObject *\r
+parsestr(struct compiling *c, const node *n, const char *s)\r
+{\r
+ size_t len, i;\r
+ int quote = Py_CHARMASK(*s);\r
+ int rawmode = 0;\r
+ int need_encoding;\r
+ int unicode = c->c_future_unicode;\r
+ int bytes = 0;\r
+\r
+ if (isalpha(quote) || quote == '_') {\r
+ if (quote == 'u' || quote == 'U') {\r
+ quote = *++s;\r
+ unicode = 1;\r
+ }\r
+ if (quote == 'b' || quote == 'B') {\r
+ quote = *++s;\r
+ unicode = 0;\r
+ bytes = 1;\r
+ }\r
+ if (quote == 'r' || quote == 'R') {\r
+ quote = *++s;\r
+ rawmode = 1;\r
+ }\r
+ }\r
+ if (quote != '\'' && quote != '\"') {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ s++;\r
+ len = strlen(s);\r
+ if (len > INT_MAX) {\r
+ PyErr_SetString(PyExc_OverflowError,\r
+ "string to parse is too long");\r
+ return NULL;\r
+ }\r
+ if (s[--len] != quote) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ if (len >= 4 && s[0] == quote && s[1] == quote) {\r
+ s += 2;\r
+ len -= 2;\r
+ if (s[--len] != quote || s[--len] != quote) {\r
+ PyErr_BadInternalCall();\r
+ return NULL;\r
+ }\r
+ }\r
+ if (Py_Py3kWarningFlag && bytes) {\r
+ for (i = 0; i < len; i++) {\r
+ if ((unsigned char)s[i] > 127) {\r
+ if (!ast_warn(c, n,\r
+ "non-ascii bytes literals not supported in 3.x"))\r
+ return NULL;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ if (unicode || Py_UnicodeFlag) {\r
+ return decode_unicode(c, s, len, rawmode, c->c_encoding);\r
+ }\r
+#endif\r
+ need_encoding = (c->c_encoding != NULL &&\r
+ strcmp(c->c_encoding, "utf-8") != 0 &&\r
+ strcmp(c->c_encoding, "iso-8859-1") != 0);\r
+ if (rawmode || strchr(s, '\\') == NULL) {\r
+ if (need_encoding) {\r
+#ifndef Py_USING_UNICODE\r
+ /* This should not happen - we never see any other\r
+ encoding. */\r
+ Py_FatalError(\r
+ "cannot deal with encodings in this build.");\r
+#else\r
+ PyObject *v, *u = PyUnicode_DecodeUTF8(s, len, NULL);\r
+ if (u == NULL)\r
+ return NULL;\r
+ v = PyUnicode_AsEncodedString(u, c->c_encoding, NULL);\r
+ Py_DECREF(u);\r
+ return v;\r
+#endif\r
+ } else {\r
+ return PyString_FromStringAndSize(s, len);\r
+ }\r
+ }\r
+\r
+ return PyString_DecodeEscape(s, len, NULL, unicode,\r
+ need_encoding ? c->c_encoding : NULL);\r
+}\r
+\r
+/* Build a Python string object out of a STRING atom. This takes care of\r
+ * compile-time literal catenation, calling parsestr() on each piece, and\r
+ * pasting the intermediate results together.\r
+ */\r
+static PyObject *\r
+parsestrplus(struct compiling *c, const node *n)\r
+{\r
+ PyObject *v;\r
+ int i;\r
+ REQ(CHILD(n, 0), STRING);\r
+ if ((v = parsestr(c, n, STR(CHILD(n, 0)))) != NULL) {\r
+ /* String literal concatenation */\r
+ for (i = 1; i < NCH(n); i++) {\r
+ PyObject *s;\r
+ s = parsestr(c, n, STR(CHILD(n, i)));\r
+ if (s == NULL)\r
+ goto onError;\r
+ if (PyString_Check(v) && PyString_Check(s)) {\r
+ PyString_ConcatAndDel(&v, s);\r
+ if (v == NULL)\r
+ goto onError;\r
+ }\r
+#ifdef Py_USING_UNICODE\r
+ else {\r
+ PyObject *temp = PyUnicode_Concat(v, s);\r
+ Py_DECREF(s);\r
+ Py_DECREF(v);\r
+ v = temp;\r
+ if (v == NULL)\r
+ goto onError;\r
+ }\r
+#endif\r
+ }\r
+ }\r
+ return v;\r
+\r
+ onError:\r
+ Py_XDECREF(v);\r
+ return NULL;\r
+}\r