diff options
Diffstat (limited to 'Modules/parsermodule.c')
-rw-r--r-- | Modules/parsermodule.c | 744 |
1 files changed, 428 insertions, 316 deletions
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index bc6f516..94e22ec 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -1,21 +1,22 @@ /* parsermodule.c * - * Copyright 1995 by Fred L. Drake, Jr. and Virginia Polytechnic Institute - * and State University, Blacksburg, Virginia, USA. Portions copyright - * 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands. - * Copying is permitted under the terms associated with the main Python - * distribution, with the additional restriction that this additional notice - * be included and maintained on all distributed copies. + * Copyright 1995-1996 by Fred L. Drake, Jr. and Virginia Polytechnic + * Institute and State University, Blacksburg, Virginia, USA. + * Portions copyright 1991-1995 by Stichting Mathematisch Centrum, + * Amsterdam, The Netherlands. Copying is permitted under the terms + * associated with the main Python distribution, with the additional + * restriction that this additional notice be included and maintained + * on all distributed copies. * - * This module serves to replace the original parser module written by - * Guido. The functionality is not matched precisely, but the original - * may be implemented on top of this. This is desirable since the source - * of the text to be parsed is now divorced from this interface. - * - * Unlike the prior interface, the ability to give a parse tree produced - * by Python code as a tuple to the compiler is enabled by this module. - * See the documentation for more details. + * This module serves to replace the original parser module written + * by Guido. The functionality is not matched precisely, but the + * original may be implemented on top of this. This is desirable + * since the source of the text to be parsed is now divorced from + * this interface. * + * Unlike the prior interface, the ability to give a parse tree + * produced by Python code as a tuple to the compiler is enabled by + * this module. See the documentation for more details. */ #include "Python.h" /* general Python API */ @@ -34,15 +35,15 @@ extern char* strdup(); - /* String constants used to initialize module attributes. * */ static char* parser_copyright_string -= "Copyright 1995 by Virginia Polytechnic Institute & State University and\n" - "Fred L. Drake, Jr., Blacksburg, Virginia, USA. Portions copyright\n" - "1991-1995 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands."; += "Copyright 1995-1996 by Virginia Polytechnic Institute & State\n" + "University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n" + "Virginia, USA. Portions copyright 1991-1995 by Stichting Mathematisch\n" + "Centrum, Amsterdam, The Netherlands."; static char* @@ -50,8 +51,11 @@ parser_doc_string = "This is an interface to Python's internal parser."; static char* -parser_version_string = "0.3"; /* changed to match python version */ +parser_version_string = "0.4"; + +typedef PyObject* (*SeqMaker) (int length); +typedef void (*SeqInserter) (PyObject* sequence, int index, PyObject* element); /* The function below is copyrigthed by Stichting Mathematisch Centrum. The * original copyright statement is included below, and continues to apply @@ -86,9 +90,12 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ static PyObject* -node2tuple(n) - node *n; - { +node2tuple(n, mkseq, addelem, lineno) + node *n; /* node to convert */ + SeqMaker mkseq; /* create sequence */ + SeqInserter addelem; /* func. to add elem. in seq. */ + int lineno; /* include line numbers? */ +{ if (n == NULL) { Py_INCREF(Py_None); return Py_None; @@ -96,7 +103,7 @@ node2tuple(n) if (ISNONTERMINAL(TYPE(n))) { int i; PyObject *v, *w; - v = PyTuple_New(1 + NCH(n)); + v = mkseq(1 + NCH(n)); if (v == NULL) return v; w = PyInt_FromLong(TYPE(n)); @@ -104,26 +111,33 @@ node2tuple(n) Py_DECREF(v); return NULL; } - PyTuple_SetItem(v, 0, w); + addelem(v, 0, w); for (i = 0; i < NCH(n); i++) { - w = node2tuple(CHILD(n, i)); + w = node2tuple(CHILD(n, i), mkseq, addelem, lineno); if (w == NULL) { Py_DECREF(v); return NULL; } - PyTuple_SetItem(v, i+1, w); + addelem(v, i+1, w); } - return v; + return (v); } else if (ISTERMINAL(TYPE(n))) { - return Py_BuildValue("(is)", TYPE(n), STR(n)); + PyObject *result = mkseq(2 + lineno); + if (result != NULL) { + addelem(result, 0, PyInt_FromLong(TYPE(n))); + addelem(result, 1, PyString_FromString(STR(n))); + if (lineno == 1) + addelem(result, 2, PyInt_FromLong(n->n_lineno)); + } + return (result); } else { PyErr_SetString(PyExc_SystemError, "unrecognized parse tree node type"); return NULL; } -} +} /* node2tuple() */ /* * End of material copyrighted by Stichting Mathematisch Centrum. */ @@ -195,7 +209,7 @@ static int parser_compare_nodes(left, right) node *left; node *right; - { +{ int j; if (TYPE(left) < TYPE(right)) @@ -235,8 +249,7 @@ static int parser_compare(left, right) PyAST_Object *left; PyAST_Object *right; - { - +{ if (left == right) return (0); @@ -259,8 +272,7 @@ static PyObject* parser_newastobject(ast, type) node *ast; int type; - { - +{ PyAST_Object* o = PyObject_NEW(PyAST_Object, &PyAST_Type); if (o != 0) { @@ -280,8 +292,7 @@ parser_newastobject(ast, type) static void parser_free(ast) PyAST_Object *ast; - { - +{ PyNode_Free(ast->ast_node); PyMem_DEL(ast); @@ -298,21 +309,62 @@ static PyObject* parser_ast2tuple(self, args) PyObject *self; PyObject *args; - { +{ + PyObject *ast; + PyObject *line_option = 0; + PyObject *res = 0; + + if (PyArg_ParseTuple(args, "O!|O:ast2tuple", &PyAST_Type, &ast, + &line_option)) { + int lineno = 0; + if (line_option != 0) { + lineno = PyObject_IsTrue(line_option); + lineno = lineno ? 1 : 0; + } + /* + * Convert AST into a tuple representation. Use Guido's function, + * since it's known to work already. + */ + res = node2tuple(((PyAST_Object*)ast)->ast_node, + PyTuple_New, PyTuple_SetItem, lineno); + } + return (res); + +} /* parser_ast2tuple() */ - PyObject* ast; - PyObject* res = 0; - if (PyArg_ParseTuple(args, "O!:ast2tuple", &PyAST_Type, &ast)) { +/* parser_ast2tuple(PyObject* self, PyObject* args) + * + * This provides conversion from a node* to a tuple object that can be + * returned to the Python-level caller. The AST object is not modified. + * + */ +static PyObject* +parser_ast2list(self, args) + PyObject *self; + PyObject *args; +{ + PyObject *ast; + PyObject *line_option = 0; + PyObject *res = 0; + + if (PyArg_ParseTuple(args, "O!|O:ast2list", &PyAST_Type, &ast, + &line_option)) { + int lineno = 0; + if (line_option != 0) { + lineno = PyObject_IsTrue(line_option); + lineno = lineno ? 1 : 0; + } /* * Convert AST into a tuple representation. Use Guido's function, * since it's known to work already. */ - res = node2tuple(((PyAST_Object*)ast)->ast_node); + res = node2tuple(((PyAST_Object*)ast)->ast_node, + PyList_New, PyList_SetItem, lineno); } return (res); -} /* parser_ast2tuple() */ +} /* parser_ast2list() */ /* parser_compileast(PyObject* self, PyObject* args) @@ -325,8 +377,7 @@ static PyObject* parser_compileast(self, args) PyObject *self; PyObject *args; - { - +{ PyAST_Object* ast; PyObject* res = 0; char* str = "<ast>"; @@ -350,7 +401,7 @@ static PyObject* parser_isexpr(self, args) PyObject *self; PyObject *args; - { +{ PyAST_Object* ast; PyObject* res = 0; @@ -370,8 +421,7 @@ static PyObject* parser_issuite(self, args) PyObject *self; PyObject *args; - { - +{ PyAST_Object* ast; PyObject* res = 0; @@ -395,7 +445,7 @@ parser_issuite(self, args) static void err_string(message) char *message; - { +{ PyErr_SetString(parser_error, message); } /* err_string() */ @@ -411,8 +461,7 @@ static PyObject* parser_do_parse(args, type) PyObject *args; int type; - { - +{ char* string = 0; PyObject* res = 0; @@ -443,8 +492,7 @@ static PyObject* parser_expr(self, args) PyObject *self; PyObject *args; - { - +{ return (parser_do_parse(args, PyAST_EXPR)); } /* parser_expr() */ @@ -454,8 +502,7 @@ static PyObject* parser_suite(self, args) PyObject *self; PyObject *args; - { - +{ return (parser_do_parse(args, PyAST_SUITE)); } /* parser_suite() */ @@ -501,60 +548,87 @@ static PyObject* parser_tuple2ast(self, args) PyObject *self; PyObject *args; - { - - PyObject* ast = 0; - PyObject* tuple = 0; - - if ((PyObject_Length(args) == 1) - && (tuple = PySequence_GetItem(args, 0)) - && PySequence_Check(tuple) - && (PyObject_Length(tuple) >= 2) - && PyInt_Check(PySequence_GetItem(tuple, 0)) - && PySequence_Check(PySequence_GetItem(tuple, 1)) - && (PyObject_Length(PySequence_GetItem(tuple, 1)) >= 2) - && PyInt_Check(PySequence_GetItem(PySequence_GetItem(tuple, 1), 0))) { - - /* - * This might be a valid parse tree, but let's do a quick check - * before we jump the gun. - */ - - int start_sym = PyInt_AsLong(PySequence_GetItem(tuple, 0)); - - if (start_sym == eval_input) { - /* - * Might be an eval form. - */ - node* expression = build_node_tree(PySequence_GetItem(args, 0)); +{ + PyObject *ast = 0; + PyObject *tuple = 0; + PyObject *temp = 0; + int ok; + int start_sym; - if ((expression != 0) && validate_expr_tree(expression)) - ast = parser_newastobject(expression, PyAST_EXPR); + if (!PyArg_ParseTuple(args, "O:tuple2ast", &tuple)) + return (0); + if (!PySequence_Check(tuple)) { + PyErr_SetString(PyExc_ValueError, + "tuple2ast() requires a single sequence argument"); + return (0); + } + /* + * This mess of tests is written this way so we can use the abstract + * object interface (AOI). Unfortunately, the AOI increments reference + * counts, which requires that we store a pointer to retrieved object + * so we can DECREF it after the check. But we really should accept + * lists as well as tuples at the very least. + */ + ok = PyObject_Length(tuple) >= 2; + if (ok) { + temp = PySequence_GetItem(tuple, 0); + ok = (temp != NULL) && PyInt_Check(temp); + if (ok) + /* this is used after the initial checks: */ + start_sym = PyInt_AsLong(temp); + Py_XDECREF(temp); + } + if (ok) { + temp = PySequence_GetItem(tuple, 1); + ok = (temp != NULL) && PySequence_Check(temp); + Py_XDECREF(temp); + } + if (ok) { + temp = PySequence_GetItem(tuple, 1); + ok = (temp != NULL) && PyObject_Length(temp) >= 2; + if (ok) { + PyObject *temp2 = PySequence_GetItem(temp, 0); + if (temp2 != NULL) { + ok = PyInt_Check(temp2); + Py_DECREF(temp2); + } } - else if (start_sym == file_input) { - /* - * This looks like an exec form so far. - */ - node* suite_tree = build_node_tree(PySequence_GetItem(args, 0)); + Py_XDECREF(temp); + } + /* If we've failed at some point, get out of here. */ + if (!ok) { + err_string("malformed sequence for tuple2ast()"); + return (0); + } + /* + * This might be a valid parse tree, but let's do a quick check + * before we jump the gun. + */ + if (start_sym == eval_input) { + /* Might be an eval form. */ + node* expression = build_node_tree(tuple); - if ((suite_tree != 0) && validate_file_input(suite_tree)) - ast = parser_newastobject(suite_tree, PyAST_SUITE); - } - else - /* This is a fragment, and is not yet supported. Maybe they - * will be if I find a use for them. - */ - err_string("Fragmentary parse trees not supported."); + if ((expression != 0) && validate_expr_tree(expression)) + ast = parser_newastobject(expression, PyAST_EXPR); + } + else if (start_sym == file_input) { + /* This looks like an exec form so far. */ + node* suite_tree = build_node_tree(tuple); - /* Make sure we throw an exception on all errors. We should never - * get this, but we'd do well to be sure something is done. - */ - if ((ast == 0) && !PyErr_Occurred()) - err_string("Unspecified ast error occurred."); + if ((suite_tree != 0) && validate_file_input(suite_tree)) + ast = parser_newastobject(suite_tree, PyAST_SUITE); } else - PyErr_SetString(PyExc_TypeError, - "parser.tuple2ast(): expected single tuple."); + /* This is a fragment, and is not yet supported. Maybe they + * will be if I find a use for them. + */ + err_string("Fragmentary parse trees not supported."); + + /* Make sure we throw an exception on all errors. We should never + * get this, but we'd do well to be sure something is done. + */ + if ((ast == 0) && !PyErr_Occurred()) + err_string("Unspecified ast error occurred."); return (ast); @@ -563,36 +637,43 @@ parser_tuple2ast(self, args) /* int check_terminal_tuple() * - * Check a tuple to determine that it is indeed a valid terminal node. The - * node is known to be required as a terminal, so we throw an exception if - * there is a failure. The portion of the resulting node tree already built - * is passed in so we can deallocate it in the event of a failure. - * - * The format of an acceptable terminal tuple is "(is)": the fact that elem - * is a tuple and the integer is a valid terminal symbol has been established - * before this function is called. We must check the length of the tuple and - * the type of the second element. We do *NOT* check the actual text of the - * string element, which we could do in many cases. This is done by the - * validate_*() functions which operate on the internal representation. + * Check a tuple to determine that it is indeed a valid terminal + * node. The node is known to be required as a terminal, so we throw + * an exception if there is a failure. * + * The format of an acceptable terminal tuple is "(is[i])": the fact + * that elem is a tuple and the integer is a valid terminal symbol + * has been established before this function is called. We must + * check the length of the tuple and the type of the second element + * and optional third element. We do *NOT* check the actual text of + * the string element, which we could do in many cases. This is done + * by the validate_*() functions which operate on the internal + * representation. */ static int -check_terminal_tuple(elem, result) +check_terminal_tuple(elem) PyObject *elem; - node *result; - { - - int res = 0; - char* str = 0; +{ + int len = PyObject_Length(elem); + int res = 1; + char* str = "Illegal terminal symbol; bad node length."; - if (PyObject_Length(elem) != 2) - str = "Illegal terminal symbol; node too long."; - else if (!PyString_Check(PySequence_GetItem(elem, 1))) + if ((len == 2) || (len == 3)) { + PyObject *temp = PySequence_GetItem(elem, 1); + res = PyString_Check(temp); str = "Illegal terminal symbol; expected a string."; - else - res = 1; - - if ((res == 0) && (result != 0)) { + if (res && (len == 3)) { + PyObject* third = PySequence_GetItem(elem, 2); + res = PyInt_Check(third); + str = "Invalid third element of terminal node."; + Py_XDECREF(third); + } + Py_XDECREF(temp); + } + else { + res = 0; + } + if (!res) { elem = Py_BuildValue("(os)", elem, str); PyErr_SetObject(parser_error, elem); } @@ -614,31 +695,54 @@ build_node_children(tuple, root, line_num) PyObject *tuple; node *root; int *line_num; - { - +{ int len = PyObject_Length(tuple); int i; for (i = 1; i < len; ++i) { /* elem must always be a tuple, however simple */ PyObject* elem = PySequence_GetItem(tuple, i); - long type = 0; - char* strn = 0; - - if ((!PySequence_Check(elem)) - || !PyInt_Check(PySequence_GetItem(elem, 0))) { + int ok = elem != NULL; + long type = 0; + char *strn = 0; + + if (ok) + ok = PySequence_Check(elem); + if (ok) { + PyObject *temp = PySequence_GetItem(elem, 0); + if (temp == NULL) + ok = 0; + else { + ok = PyInt_Check(temp); + if (ok) + type = PyInt_AsLong(temp); + Py_DECREF(temp); + } + } + if (!ok) { PyErr_SetObject(parser_error, Py_BuildValue("(os)", elem, "Illegal node construct.")); + Py_XDECREF(elem); return (0); } - type = PyInt_AsLong(PySequence_GetItem(elem, 0)); - if (ISTERMINAL(type)) { - if (check_terminal_tuple(elem, root)) - strn = strdup(PyString_AsString(PySequence_GetItem(elem, 1))); - else + if (check_terminal_tuple(elem)) { + PyObject *temp = PySequence_GetItem(elem, 1); + + strn = strdup(PyString_AsString(temp)); + Py_XDECREF(temp); + + if (PyObject_Length(elem) == 3) { + PyObject* temp = PySequence_GetItem(elem, 2); + *line_num = PyInt_AsLong(temp); + Py_DECREF(temp); + } + } + else { + Py_XDECREF(elem); return (0); + } } else if (!ISNONTERMINAL(type)) { /* @@ -648,6 +752,7 @@ build_node_children(tuple, root, line_num) PyErr_SetObject(parser_error, Py_BuildValue("(os)", elem, "Unknown node type.")); + Py_XDECREF(elem); return (0); } PyNode_AddChild(root, type, strn, *line_num); @@ -655,11 +760,15 @@ build_node_children(tuple, root, line_num) if (ISNONTERMINAL(type)) { node* new_child = CHILD(root, i - 1); - if (new_child != build_node_children(elem, new_child, line_num)) + if (new_child != build_node_children(elem, new_child, line_num)) { + Py_XDECREF(elem); return (0); + } } - else if (type == NEWLINE) /* It's true: we increment the */ + else if (type == NEWLINE) { /* It's true: we increment the */ ++(*line_num); /* line number *after* the newline! */ + } + Py_XDECREF(elem); } return (root); @@ -669,11 +778,14 @@ build_node_children(tuple, root, line_num) static node* build_node_tree(tuple) PyObject *tuple; - { - +{ node* res = 0; - long num = PyInt_AsLong(PySequence_GetItem(tuple, 0)); + PyObject *temp = PySequence_GetItem(tuple, 0); + long num = -1; + if (temp != NULL) + num = PyInt_AsLong(temp); + Py_XDECREF(temp); if (ISTERMINAL(num)) { /* * The tuple is simple, but it doesn't start with a start symbol. @@ -737,11 +849,9 @@ staticforward int validate_terminal(); #define validate_star(ch) validate_terminal(ch, STAR, "*") #define validate_vbar(ch) validate_terminal(ch, VBAR, "|") #define validate_doublestar(ch) validate_terminal(ch, DOUBLESTAR, "**") +#define validate_dot(ch) validate_terminal(ch, DOT, ".") #define validate_name(ch, str) validate_terminal(ch, NAME, str) -#if defined(access_stmt) && defined(accesstype) -VALIDATER(access_stmt); VALIDATER(accesstype); -#endif VALIDATER(node); VALIDATER(small_stmt); VALIDATER(class); VALIDATER(node); VALIDATER(parameters); VALIDATER(suite); @@ -764,6 +874,7 @@ VALIDATER(shift_expr); VALIDATER(arith_expr); VALIDATER(term); VALIDATER(factor); VALIDATER(atom); VALIDATER(lambdef); VALIDATER(trailer); VALIDATER(subscript); +VALIDATER(subscriptlist); VALIDATER(sliceop); VALIDATER(exprlist); VALIDATER(dictmaker); VALIDATER(arglist); VALIDATER(argument); @@ -776,7 +887,7 @@ static int validate_ntype(n, t) node *n; int t; - { +{ int res = (TYPE(n) == t); if (!res) { @@ -794,7 +905,7 @@ validate_numnodes(n, num, name) node *n; int num; const char *const name; - { +{ if (NCH(n) != num) { char buff[60]; sprintf(buff, "Illegal number of children for %s node.", name); @@ -810,7 +921,7 @@ validate_terminal(terminal, type, string) node *terminal; int type; char *string; - { +{ int res = (validate_ntype(terminal, type) && ((string == 0) || (strcmp(string, STR(terminal)) == 0))); @@ -824,11 +935,42 @@ validate_terminal(terminal, type, string) } /* validate_terminal() */ +/* X (',' X) [','] + */ +static int +validate_repeating_list(tree, ntype, vfunc, name) + node *tree; + int ntype; + int (*vfunc)(); + const char *const name; +{ + int nch = NCH(tree); + int res = (nch && validate_ntype(tree, ntype) + && vfunc(CHILD(tree, 0))); + + if (!res && !PyErr_Occurred()) + validate_numnodes(tree, 1, name); + else { + if (is_even(nch)) + res = validate_comma(CHILD(tree, --nch)); + if (res && nch > 1) { + int pos = 1; + for ( ; res && pos < nch; pos += 2) + res = (validate_comma(CHILD(tree, pos)) + && vfunc(CHILD(tree, pos + 1))); + } + } + return (res); + +} /* validate_repeating_list() */ + + /* VALIDATE(class) * * classdef: * 'class' NAME ['(' testlist ')'] ':' suite */ +static int validate_class(tree) node *tree; { @@ -856,6 +998,7 @@ validate_class(tree) /* if_stmt: * 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */ +static int validate_if(tree) node *tree; { @@ -899,6 +1042,7 @@ validate_if(tree) * '(' [varargslist] ')' * */ +static int validate_parameters(tree) node *tree; { @@ -925,6 +1069,7 @@ validate_parameters(tree) * simple_stmt * | NEWLINE INDENT stmt+ DEDENT */ +static int validate_suite(tree) node *tree; { @@ -954,34 +1099,12 @@ validate_suite(tree) } /* validate_suite() */ +static int validate_testlist(tree) node *tree; { - int i; - int nch = NCH(tree); - int res = validate_ntype(tree, testlist) && (nch >= 1); - - /* If there are an even, non-zero number of children, the last one - * absolutely must be a comma. Why the trailing comma is allowed, - * I have no idea! - */ - if (res && is_even(nch)) - res = validate_comma(CHILD(tree, --nch)); - - if (res) { - /* - * If the number is odd, the last is a test, and can be - * verified. What's left, if anything, can be verified - * as a list of [test, comma] pairs. - */ - --nch; - res = validate_test(CHILD(tree, nch)); - } - for (i = 0; res && (i < nch); i += 2) - res = (validate_test(CHILD(tree, i)) - && validate_comma(CHILD(tree, i + 1))); - - return (res); + return (validate_repeating_list(tree, testlist, + validate_test, "testlist")); } /* validate_testlist() */ @@ -998,6 +1121,7 @@ validate_testlist(tree) * | fpdef ['=' test] (',' fpdef ['=' test])* [','] * */ +static int validate_varargslist(tree) node *tree; { @@ -1100,6 +1224,7 @@ validate_varargslist(tree) * NAME * | '(' fplist ')' */ +static int validate_fpdef(tree) node *tree; { @@ -1121,22 +1246,12 @@ validate_fpdef(tree) } /* validate_fpdef() */ +static int validate_fplist(tree) node *tree; { - int j; - int nch = NCH(tree); - int res = (validate_ntype(tree, fplist) - && (nch != 0) && validate_fpdef(CHILD(tree, 0))); - - if (res && is_even(nch)) - res = validate_comma(CHILD(tree, --nch)); - - for (j = 1; res && (j < nch); j += 2) - res = (validate_comma(CHILD(tree, j)) - && validate_fpdef(CHILD(tree, j + 1))); - - return (res); + return (validate_repeating_list(tree, fplist, + validate_fpdef, "fplist")); } /* validate_fplist() */ @@ -1144,6 +1259,7 @@ validate_fplist(tree) /* simple_stmt | compound_stmt * */ +static int validate_stmt(tree) node *tree; { @@ -1166,6 +1282,7 @@ validate_stmt(tree) /* small_stmt (';' small_stmt)* [';'] NEWLINE * */ +static int validate_simple_stmt(tree) node *tree; { @@ -1192,6 +1309,7 @@ validate_simple_stmt(tree) } /* validate_simple_stmt() */ +static int validate_small_stmt(tree) node *tree; { @@ -1204,9 +1322,6 @@ validate_small_stmt(tree) || (TYPE(CHILD(tree, 0)) == flow_stmt) || (TYPE(CHILD(tree, 0)) == import_stmt) || (TYPE(CHILD(tree, 0)) == global_stmt) -#if defined(access_stmt) && defined(accesstype) - || (TYPE(CHILD(tree, 0)) == access_stmt) -#endif || (TYPE(CHILD(tree, 0)) == exec_stmt))); if (res) @@ -1225,6 +1340,7 @@ validate_small_stmt(tree) /* compound_stmt: * if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef */ +static int validate_compound_stmt(tree) node *tree; { @@ -1253,6 +1369,7 @@ validate_compound_stmt(tree) } /* validate_compound_stmt() */ +static int validate_expr_stmt(tree) node *tree; { @@ -1276,6 +1393,7 @@ validate_expr_stmt(tree) * 'print' (test ',')* [test] * */ +static int validate_print_stmt(tree) node *tree; { @@ -1300,6 +1418,7 @@ validate_print_stmt(tree) } /* validate_print_stmt() */ +static int validate_del_stmt(tree) node *tree; { @@ -1310,6 +1429,7 @@ validate_del_stmt(tree) } /* validate_del_stmt() */ +static int validate_return_stmt(tree) node *tree; { @@ -1326,6 +1446,7 @@ validate_return_stmt(tree) } /* validate_return_stmt() */ +static int validate_raise_stmt(tree) node *tree; { @@ -1360,6 +1481,7 @@ validate_raise_stmt(tree) * 'import' dotted_name (',' dotted_name)* * | 'from' dotted_name 'import' ('*' | NAME (',' NAME)*) */ +static int validate_import_stmt(tree) node *tree; { @@ -1402,6 +1524,7 @@ validate_import_stmt(tree) } /* validate_import_stmt() */ +static int validate_global_stmt(tree) node *tree; { @@ -1422,67 +1545,11 @@ validate_global_stmt(tree) } /* validate_global_stmt() */ -#if defined(access_stmt) && defined(accesstype) -/* VALIDATE(accesstype) - * - * This should be removed as soon as the 'access' statement is actually - * removed from the language. The conditional compilation should help. - */ -validate_access_stmt(tree) - node *tree; -{ - int pos = 3; - int nch = NCH(tree); - int res = (validate_ntype(tree, access_stmt) - && (nch >= 4) && is_even(nch) - && validate_name(CHILD(tree, 0), "access") - && validate_accesstype(CHILD(tree, nch - 1))); - - if (res && (TYPE(CHILD(tree, 1)) != STAR)) { - int j; - - res = validate_ntype(CHILD(tree, 1), NAME); - for (j = 2; res && (j < (nch - 2)); j += 2) { - if (TYPE(CHILD(tree, j)) == COLON) - break; - res = (validate_comma(CHILD(tree, j)) - && validate_ntype(CHILD(tree, j + 1), NAME) - && (pos += 2)); - } - } - else - res = validate_star(CHILD(tree, 1)); - - res = (res && validate_colon(CHILD(tree, pos - 1))); - for (; res && (pos < (nch - 1)); pos += 2) - res = (validate_accesstype(CHILD(tree, pos)) - && validate_comma(CHILD(tree, pos + 1))); - - return (res && (pos == (nch - 1))); - -} /* validate_access_stmt() */ - - -validate_accesstype(tree) - node *tree; -{ - int nch = NCH(tree); - int res = validate_ntype(tree, accesstype) && (nch >= 1); - int i; - - for (i = 0; res && (i < nch); ++i) - res = validate_ntype(CHILD(tree, i), NAME); - - return (res); - -} /* validate_accesstype() */ -#endif - - /* exec_stmt: * * 'exec' expr ['in' test [',' test]] */ +static int validate_exec_stmt(tree) node *tree; { @@ -1506,6 +1573,7 @@ validate_exec_stmt(tree) } /* validate_exec_stmt() */ +static int validate_while(tree) node *tree; { @@ -1527,6 +1595,7 @@ validate_while(tree) } /* validate_while() */ +static int validate_for(tree) node *tree; { @@ -1555,6 +1624,7 @@ validate_for(tree) * | 'try' ':' suite 'finally' ':' suite * */ +static int validate_try(tree) node *tree; { @@ -1610,6 +1680,7 @@ validate_try(tree) } /* validate_try() */ +static int validate_except_clause(tree) node *tree; { @@ -1629,6 +1700,7 @@ validate_except_clause(tree) } /* validate_except_clause() */ +static int validate_test(tree) node *tree; { @@ -1650,6 +1722,7 @@ validate_test(tree) } /* validate_test() */ +static int validate_and_test(tree) node *tree; { @@ -1668,6 +1741,7 @@ validate_and_test(tree) } /* validate_and_test() */ +static int validate_not_test(tree) node *tree; { @@ -1686,6 +1760,7 @@ validate_not_test(tree) } /* validate_not_test() */ +static int validate_comparison(tree) node *tree; { @@ -1704,6 +1779,7 @@ validate_comparison(tree) } /* validate_comparison() */ +static int validate_comp_op(tree) node *tree; { @@ -1757,6 +1833,7 @@ validate_comp_op(tree) } /* validate_comp_op() */ +static int validate_expr(tree) node *tree; { @@ -1775,6 +1852,7 @@ validate_expr(tree) } /* validate_expr() */ +static int validate_xor_expr(tree) node *tree; { @@ -1793,6 +1871,7 @@ validate_xor_expr(tree) } /* validate_xor_expr() */ +static int validate_and_expr(tree) node *tree; { @@ -1834,6 +1913,7 @@ validate_chain_two_ops(tree, termvalid, op1, op2) } /* validate_chain_two_ops() */ +static int validate_shift_expr(tree) node *tree; { @@ -1844,6 +1924,7 @@ validate_shift_expr(tree) } /* validate_shift_expr() */ +static int validate_arith_expr(tree) node *tree; { @@ -1853,6 +1934,7 @@ validate_arith_expr(tree) } /* validate_arith_expr() */ +static int validate_term(tree) node *tree; { @@ -1877,6 +1959,7 @@ validate_term(tree) * * factor: ('+'|'-'|'~') factor | power */ +static int validate_factor(tree) node *tree; { @@ -1898,6 +1981,7 @@ validate_factor(tree) * * power: atom trailer* ('**' factor)* */ +static int validate_power(tree) node *tree; { @@ -1922,6 +2006,7 @@ validate_power(tree) } /* validate_power() */ +static int validate_atom(tree) node *tree; { @@ -1979,6 +2064,7 @@ validate_atom(tree) * 'def' NAME parameters ':' suite * */ +static int validate_funcdef(tree) node *tree; { @@ -1993,6 +2079,7 @@ validate_funcdef(tree) } /* validate_funcdef() */ +static int validate_lambdef(tree) node *tree; { @@ -2017,26 +2104,12 @@ validate_lambdef(tree) * * argument (',' argument)* [','] */ +static int validate_arglist(tree) node *tree; { - int nch = NCH(tree); - int res = (validate_ntype(tree, arglist) - && (nch > 0) - && validate_argument(CHILD(tree, 0))); - - if (res && is_even(nch)) - res = validate_comma(CHILD(tree, nch - 1)); - if (!res && !PyErr_Occurred()) - validate_numnodes(tree, 1, "arglist"); - --nch; - if (res && (nch > 1)) { - int j = 1; - for ( ; res && (j < (nch - 2)); j += 2) - res = (validate_comma(CHILD(tree, j)) - && validate_argument(CHILD(tree, j + 1))); - } - return (res); + return (validate_repeating_list(tree, arglist, + validate_argument, "arglist")); } /* validate_arglist() */ @@ -2046,6 +2119,7 @@ validate_arglist(tree) * * [test '='] test */ +static int validate_argument(tree) node *tree; { @@ -2066,8 +2140,9 @@ validate_argument(tree) /* trailer: * - * '(' [arglist] ')' | '[' subscript ']' | '.' NAME + * '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME */ +static int validate_trailer(tree) node *tree; { @@ -2083,7 +2158,7 @@ validate_trailer(tree) break; case LSQB: res = (validate_numnodes(tree, 3, "trailer") - && validate_subscript(CHILD(tree, 1)) + && validate_subscriptlist(CHILD(tree, 1)) && validate_ntype(CHILD(tree, 2), RSQB)); break; case DOT: @@ -2103,75 +2178,109 @@ validate_trailer(tree) } /* validate_trailer() */ +/* subscriptlist: + * + * subscript (',' subscript)* [','] + */ +static int +validate_subscriptlist(tree) + node *tree; +{ + return (validate_repeating_list(tree, subscriptlist, + validate_subscript, "subscriptlist")); + +} /* validate_subscriptlist() */ + + /* subscript: * - * test (',' test)* [','] | [test] ':' [test] + * '.' '.' '.' | test | [test] ':' [test] [sliceop] */ +static int validate_subscript(tree) node *tree; { + int offset = 0; int nch = NCH(tree); - int res = validate_ntype(tree, subscript) && (nch >= 1); + int res = validate_ntype(tree, subscript) && (nch >= 1) && (nch <= 4); - if (res && is_even(nch) && (nch >= 4)) - if (TYPE(CHILD(tree, nch - 1)) == COMMA) - --nch; - else - res = 0; - if (res && is_odd(nch)) { - if (TYPE(CHILD(tree, 0)) == COLON) - res = validate_numnodes(tree, 1, "subscript"); - else { - res = validate_test(CHILD(tree, 0)); - if (res && (nch == 3)) - res = ((TYPE(CHILD(tree, 1)) == COMMA) - || validate_colon(CHILD(tree, 1))) - && validate_test(CHILD(tree, 2)); - else if ((res && (nch >= 5))) { - int pos = 1; - while (res && (pos <= (nch - 2))) { - res = (validate_comma(CHILD(tree, pos)) - && validate_test(CHILD(tree, pos + 1))); - pos += 2; - } - } - } + if (!res) { + if (!PyErr_Occurred()) + err_string("invalid number of arguments for subscript node"); + return (0); } - else if (nch == 2) { - if (TYPE(CHILD(tree, 0)) == COLON) - res = validate_test(CHILD(tree, 1)); - else if (TYPE(CHILD(tree, 1)) == COLON) + if (TYPE(CHILD(tree, 0)) == DOT) + /* take care of ('.' '.' '.') possibility */ + return (validate_numnodes(tree, 3, "subscript") + && validate_dot(CHILD(tree, 0)) + && validate_dot(CHILD(tree, 1)) + && validate_dot(CHILD(tree, 2))); + if (nch == 1) { + if (TYPE(CHILD(tree, 0)) == test) res = validate_test(CHILD(tree, 0)); else - res = (validate_test(CHILD(tree, 0)) - && validate_comma(CHILD(tree, 1))); + res = validate_colon(CHILD(tree, 0)); + return (res); + } + /* Must be [test] ':' [test] [sliceop], + * but at least one of the optional components will + * be present, but we don't know which yet. + */ + if ((TYPE(CHILD(tree, 0)) != COLON) || (nch == 4)) { + res = validate_test(CHILD(tree, 0)); + offset = 1; + } + if (res) + res = validate_colon(CHILD(tree, offset)); + if (res) { + int rem = nch - ++offset; + if (rem) { + if (TYPE(CHILD(tree, offset)) == test) { + res = validate_test(CHILD(tree, offset)); + ++offset; + --rem; + } + if (res && rem) + res = validate_sliceop(CHILD(tree, offset)); + } } return (res); } /* validate_subscript() */ -validate_exprlist(tree) +static int +validate_sliceop(tree) node *tree; { int nch = NCH(tree); - int res = (validate_ntype(tree, exprlist) - && (nch >= 1) - && validate_expr(CHILD(tree, 0))); - - if (res && is_even(nch)) - res = validate_comma(CHILD(tree, --nch)); - if (res && (nch > 1)) { - int pos; - for (pos = 1; res && (pos < nch); pos += 2) - res = (validate_comma(CHILD(tree, pos)) - && validate_expr(CHILD(tree, pos + 1))); + int res = ((nch == 1) || validate_numnodes(tree, 2, "sliceop")) + && validate_ntype(tree, sliceop); + if (!res && !PyErr_Occurred()) { + validate_numnodes(tree, 1, "sliceop"); + res = 0; } + if (res) + res = validate_colon(CHILD(tree, 0)); + if (res && (nch == 2)) + res = validate_test(CHILD(tree, 1)); + return (res); +} /* validate_sliceop() */ + + +static int +validate_exprlist(tree) + node *tree; +{ + return (validate_repeating_list(tree, exprlist, + validate_expr, "exprlist")); + } /* validate_exprlist() */ +static int validate_dictmaker(tree) node *tree; { @@ -2203,6 +2312,7 @@ validate_dictmaker(tree) } /* validate_dictmaker() */ +static int validate_eval_input(tree) node *tree; { @@ -2221,6 +2331,7 @@ validate_eval_input(tree) } /* validate_eval_input() */ +static int validate_node(tree) node *tree; { @@ -2251,7 +2362,7 @@ validate_node(tree) case small_stmt: /* * expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt - * | import_stmt | global_stmt | access_stmt | exec_stmt + * | import_stmt | global_stmt | exec_stmt */ res = validate_small_stmt(tree); break; @@ -2311,11 +2422,6 @@ validate_node(tree) case global_stmt: res = validate_global_stmt(tree); break; -#if defined(access_stmt) && defined(accesstype) - case access_stmt: - res = validate_access_stmt(tree); - break; -#endif case exec_stmt: res = validate_exec_stmt(tree); break; @@ -2399,6 +2505,7 @@ validate_node(tree) } /* validate_node() */ +static int validate_expr_tree(tree) node *tree; { @@ -2415,6 +2522,7 @@ validate_expr_tree(tree) /* file_input: * (NEWLINE | stmt)* ENDMARKER */ +static int validate_file_input(tree) node *tree; { @@ -2450,6 +2558,8 @@ validate_file_input(tree) static PyMethodDef parser_functions[] = { {"ast2tuple", parser_ast2tuple, 1, "Creates a tuple-tree representation of an AST."}, + {"ast2list", parser_ast2list, 1, + "Creates a list-tree representation of an AST."}, {"compileast", parser_compileast, 1, "Compiles an AST object into a code object."}, {"expr", parser_expr, 1, @@ -2460,8 +2570,10 @@ static PyMethodDef parser_functions[] = { "Determines if an AST object was created from a suite."}, {"suite", parser_suite, 1, "Creates an AST object from a suite."}, + {"sequence2ast", parser_tuple2ast, 1, + "Creates an AST object from a tree representation."}, {"tuple2ast", parser_tuple2ast, 1, - "Creates an AST object from a tuple-tree representation."}, + "Creates an AST object from a tree representation."}, {0, 0, 0} }; |