+++ /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