3292 lines · 89.5 KB · C
RawDownload
/* * This file includes functions to transform a concrete syntax tree (CST) to * an abstract syntax tree (AST).  The main function is PyAST_FromNode(). * */#include "Python.h"#include "Python-ast.h"#include "grammar.h"#include "node.h"#include "pyarena.h"#include "ast.h"#include "token.h"#include "parsetok.h"#include "graminit.h" #include <assert.h> /* XXX TO DO   - re-indent this file (should be done)   - internal error checking (freeing memory, etc.)   - syntax errors*/ /* Data structure used internally */struct compiling {    char *c_encoding; /* source encoding */    PyArena *c_arena; /* arena for allocating memeory */}; static asdl_seq *seq_for_testlist(struct compiling *, const node *);static expr_ty ast_for_expr(struct compiling *, const node *);static stmt_ty ast_for_stmt(struct compiling *, const node *);static asdl_seq *ast_for_suite(struct compiling *, const node *);static asdl_seq *ast_for_exprlist(struct compiling *, const node *, expr_context_ty);static expr_ty ast_for_testlist(struct compiling *, const node *);static expr_ty ast_for_testlist_gexp(struct compiling *, const node *); /* Note different signature for ast_for_call */static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); static PyObject *parsenumber(const char *);static PyObject *parsestr(const char *s, const char *encoding);static PyObject *parsestrplus(struct compiling *, const node *n); #ifndef LINENO#define LINENO(n)	((n)->n_lineno)#endif static identifiernew_identifier(const char* n, PyArena *arena) {    PyObject* id = PyString_InternFromString(n);    PyArena_AddPyObject(arena, id);    return id;} #define NEW_IDENTIFIER(n) new_identifier(STR(n), c->c_arena) /* This routine provides an invalid object for the syntax error.   The outermost routine must unpack this error and create the   proper object.  We do this so that we don't have to pass   the filename to everything function.    XXX Maybe we should just pass the filename...*/ static intast_error(const node *n, const char *errstr){    PyObject *u = Py_BuildValue("zi", errstr, LINENO(n));    if (!u)	return 0;    PyErr_SetObject(PyExc_SyntaxError, u);    Py_DECREF(u);    return 0;} static voidast_error_finish(const char *filename){    PyObject *type, *value, *tback, *errstr, *loc, *tmp;    long lineno;     assert(PyErr_Occurred());    if (!PyErr_ExceptionMatches(PyExc_SyntaxError))	return;     PyErr_Fetch(&type, &value, &tback);    errstr = PyTuple_GetItem(value, 0);    if (!errstr)	return;    Py_INCREF(errstr);    lineno = PyInt_AsLong(PyTuple_GetItem(value, 1));    if (lineno == -1) {	Py_DECREF(errstr);	return;    }    Py_DECREF(value);     loc = PyErr_ProgramText(filename, lineno);    if (!loc) {	Py_INCREF(Py_None);	loc = Py_None;    }    tmp = Py_BuildValue("(zlOO)", filename, lineno, Py_None, loc);    Py_DECREF(loc);    if (!tmp) {	Py_DECREF(errstr);	return;    }    value = PyTuple_Pack(2, errstr, tmp);    Py_DECREF(errstr);    Py_DECREF(tmp);    if (!value)	return;    PyErr_Restore(type, value, tback);} /* num_stmts() returns number of contained statements.    Use this routine to determine how big a sequence is needed for   the statements in a parse tree.  Its raison d'etre is this bit of   grammar:    stmt: simple_stmt | compound_stmt   simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE    A simple_stmt can contain multiple small_stmt elements joined   by semicolons.  If the arg is a simple_stmt, the number of   small_stmt elements is returned.*/ static intnum_stmts(const node *n){    int i, l;    node *ch;     switch (TYPE(n)) {        case single_input:            if (TYPE(CHILD(n, 0)) == NEWLINE)                return 0;            else                return num_stmts(CHILD(n, 0));        case file_input:            l = 0;            for (i = 0; i < NCH(n); i++) {                ch = CHILD(n, i);                if (TYPE(ch) == stmt)                    l += num_stmts(ch);            }            return l;        case stmt:            return num_stmts(CHILD(n, 0));        case compound_stmt:            return 1;        case simple_stmt:            return NCH(n) / 2; /* Divide by 2 to remove count of semi-colons */        case suite:            if (NCH(n) == 1)                return num_stmts(CHILD(n, 0));            else {                l = 0;                for (i = 2; i < (NCH(n) - 1); i++)                    l += num_stmts(CHILD(n, i));                return l;            }        default: {            char buf[128];             sprintf(buf, "Non-statement found: %d %d\n",                    TYPE(n), NCH(n));            Py_FatalError(buf);        }    }    assert(0);    return 0;} /* Transform the CST rooted at node * to the appropriate AST*/ mod_tyPyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,               PyArena *arena){    int i, j, k, num;    asdl_seq *stmts = NULL;    stmt_ty s;    node *ch;    struct compiling c;     if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {        c.c_encoding = "utf-8";        if (TYPE(n) == encoding_decl) {                ast_error(n, "encoding declaration in Unicode string");                goto error;        }    } else if (TYPE(n) == encoding_decl) {        c.c_encoding = STR(n);        n = CHILD(n, 0);    } else {        c.c_encoding = NULL;    }    c.c_arena = arena;     k = 0;    switch (TYPE(n)) {        case file_input:            stmts = asdl_seq_new(num_stmts(n), arena);            if (!stmts)                    return NULL;            for (i = 0; i < NCH(n) - 1; i++) {                ch = CHILD(n, i);                if (TYPE(ch) == NEWLINE)                    continue;                REQ(ch, stmt);                num = num_stmts(ch);                if (num == 1) {                    s = ast_for_stmt(&c, ch);                    if (!s)                        goto error;                    asdl_seq_SET(stmts, k++, s);                }                else {                    ch = CHILD(ch, 0);                    REQ(ch, simple_stmt);                    for (j = 0; j < num; j++) {                        s = ast_for_stmt(&c, CHILD(ch, j * 2));                        if (!s)                            goto error;                        asdl_seq_SET(stmts, k++, s);                    }                }            }            return Module(stmts, arena);        case eval_input: {            expr_ty testlist_ast;             /* XXX Why not gen_for here? */            testlist_ast = ast_for_testlist(&c, CHILD(n, 0));            if (!testlist_ast)                goto error;            return Expression(testlist_ast, arena);        }        case single_input:            if (TYPE(CHILD(n, 0)) == NEWLINE) {                stmts = asdl_seq_new(1, arena);                if (!stmts)		    goto error;                asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset,                                            arena));                return Interactive(stmts, arena);            }            else {                n = CHILD(n, 0);                num = num_stmts(n);                stmts = asdl_seq_new(num, arena);                if (!stmts)		    goto error;                if (num == 1) {		    s = ast_for_stmt(&c, n);		    if (!s)			goto error;                    asdl_seq_SET(stmts, 0, s);                }                else {                    /* Only a simple_stmt can contain multiple statements. */                    REQ(n, simple_stmt);                    for (i = 0; i < NCH(n); i += 2) {                        if (TYPE(CHILD(n, i)) == NEWLINE)                            break;                        s = ast_for_stmt(&c, CHILD(n, i));                        if (!s)                            goto error;                        asdl_seq_SET(stmts, i / 2, s);                    }                }                 return Interactive(stmts, arena);            }        default:            goto error;    } error:    ast_error_finish(filename);    return NULL;} /* Return the AST repr. of the operator represented as syntax (|, ^, etc.)*/ static operator_tyget_operator(const node *n){    switch (TYPE(n)) {        case VBAR:            return BitOr;        case CIRCUMFLEX:            return BitXor;        case AMPER:            return BitAnd;        case LEFTSHIFT:            return LShift;        case RIGHTSHIFT:            return RShift;        case PLUS:            return Add;        case MINUS:            return Sub;        case STAR:            return Mult;        case SLASH:            return Div;        case DOUBLESLASH:            return FloorDiv;        case PERCENT:            return Mod;        default:            return (operator_ty)0;    }} /* Set the context ctx for expr_ty e, recursively traversing e.    Only sets context for expr kinds that "can appear in assignment context"   (according to ../Parser/Python.asdl).  For other expr kinds, it sets   an appropriate syntax error and returns false.*/ static intset_context(expr_ty e, expr_context_ty ctx, const node *n){    asdl_seq *s = NULL;    /* If a particular expression type can't be used for assign / delete,       set expr_name to its name and an error message will be generated.    */    const char* expr_name = NULL;     /* The ast defines augmented store and load contexts, but the       implementation here doesn't actually use them.  The code may be       a little more complex than necessary as a result.  It also means       that expressions in an augmented assignment have a Store context.       Consider restructuring so that augmented assignment uses       set_context(), too.    */    assert(ctx != AugStore && ctx != AugLoad);     switch (e->kind) {        case Attribute_kind:	    if (ctx == Store &&		    !strcmp(PyString_AS_STRING(e->v.Attribute.attr), "None")) {		    return ast_error(n, "assignment to None");	    }	    e->v.Attribute.ctx = ctx;	    break;        case Subscript_kind:	    e->v.Subscript.ctx = ctx;	    break;        case Name_kind:	    if (ctx == Store &&		!strcmp(PyString_AS_STRING(e->v.Name.id), "None")) {		    return ast_error(n, "assignment to None");	    }	    e->v.Name.ctx = ctx;	    break;        case List_kind:	    e->v.List.ctx = ctx;	    s = e->v.List.elts;	    break;        case Tuple_kind:            if (asdl_seq_LEN(e->v.Tuple.elts) == 0)                 return ast_error(n, "can't assign to ()");	    e->v.Tuple.ctx = ctx;	    s = e->v.Tuple.elts;	    break;        case Lambda_kind:            expr_name = "lambda";            break;        case Call_kind:            expr_name = "function call";	    break;        case BoolOp_kind:        case BinOp_kind:        case UnaryOp_kind:            expr_name = "operator";            break;        case GeneratorExp_kind:            expr_name = "generator expression";            break;        case Yield_kind:            expr_name = "yield expression";            break;        case ListComp_kind:            expr_name = "list comprehension";            break;        case Dict_kind:        case Num_kind:        case Str_kind:            expr_name = "literal";            break;        case Compare_kind:            expr_name = "comparison";            break;        case Repr_kind:            expr_name = "repr";            break;        case IfExp_kind:            expr_name = "conditional expression";            break;        default:            PyErr_Format(PyExc_SystemError,                          "unexpected expression in assignment %d (line %d)",                          e->kind, e->lineno);            return 0;    }    /* Check for error string set by switch */    if (expr_name) {        char buf[300];        PyOS_snprintf(buf, sizeof(buf),                      "can't %s %s",                      ctx == Store ? "assign to" : "delete",                      expr_name);        return ast_error(n, buf);    }     /* If the LHS is a list or tuple, we need to set the assignment       context for all the contained elements.      */    if (s) {	int i; 	for (i = 0; i < asdl_seq_LEN(s); i++) {	    if (!set_context((expr_ty)asdl_seq_GET(s, i), ctx, n))		return 0;	}    }    return 1;} static operator_tyast_for_augassign(const node *n){    REQ(n, augassign);    n = CHILD(n, 0);    switch (STR(n)[0]) {        case '+':            return Add;        case '-':            return Sub;        case '/':            if (STR(n)[1] == '/')                return FloorDiv;            else                return Div;        case '%':            return Mod;        case '<':            return LShift;        case '>':            return RShift;        case '&':            return BitAnd;        case '^':            return BitXor;        case '|':            return BitOr;        case '*':            if (STR(n)[1] == '*')                return Pow;            else                return Mult;        default:            PyErr_Format(PyExc_SystemError, "invalid augassign: %s", STR(n));            return (operator_ty)0;    }} static cmpop_tyast_for_comp_op(const node *n){    /* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'               |'is' 'not'    */    REQ(n, comp_op);    if (NCH(n) == 1) {	n = CHILD(n, 0);	switch (TYPE(n)) {            case LESS:                return Lt;            case GREATER:                return Gt;            case EQEQUAL:			/* == */                return Eq;            case LESSEQUAL:                return LtE;            case GREATEREQUAL:                return GtE;            case NOTEQUAL:                return NotEq;            case NAME:

Lines 1–500 of 3292.