1996-07-20 23:33:56 -03:00
|
|
|
/* parsermodule.c
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
1996-08-21 11:32:37 -03:00
|
|
|
* 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.
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
1996-08-21 11:32:37 -03:00
|
|
|
* 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.
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
1996-08-21 11:32:37 -03:00
|
|
|
* 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.
|
1998-04-29 11:16:32 -03:00
|
|
|
*
|
|
|
|
* I've added some annotations that help with the lint code-checking
|
|
|
|
* program, but they're not complete by a long shot. The real errors
|
|
|
|
* that lint detects are gone, but there are still warnings with
|
|
|
|
* Py_[X]DECREF() and Py_[X]INCREF() macros. The lint annotations
|
|
|
|
* look like "NOTE(...)".
|
1995-10-11 14:35:38 -03:00
|
|
|
*/
|
|
|
|
|
2000-04-19 10:54:15 -03:00
|
|
|
#include "Python.h" /* general Python API */
|
|
|
|
#include "graminit.h" /* symbols defined in the grammar */
|
|
|
|
#include "node.h" /* internal parser structure */
|
2001-12-05 18:10:44 -04:00
|
|
|
#include "errcode.h" /* error codes for PyNode_*() */
|
2000-04-19 10:54:15 -03:00
|
|
|
#include "token.h" /* token definitions */
|
|
|
|
/* ISTERMINAL() / ISNONTERMINAL() */
|
|
|
|
#include "compile.h" /* PyNode_Compile() */
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1998-04-29 11:16:32 -03:00
|
|
|
#ifdef lint
|
|
|
|
#include <note.h>
|
|
|
|
#else
|
|
|
|
#define NOTE(x)
|
|
|
|
#endif
|
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
/* String constants used to initialize module attributes.
|
|
|
|
*
|
|
|
|
*/
|
2002-06-13 17:33:02 -03:00
|
|
|
static char parser_copyright_string[] =
|
|
|
|
"Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\
|
1996-08-21 18:55:43 -03:00
|
|
|
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.";
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2002-06-13 17:33:02 -03:00
|
|
|
PyDoc_STRVAR(parser_doc_string,
|
|
|
|
"This is an interface to Python's internal parser.");
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2002-06-13 17:33:02 -03:00
|
|
|
static char parser_version_string[] = "0.5";
|
1996-08-21 11:32:37 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2006-02-15 13:27:45 -04:00
|
|
|
typedef PyObject* (*SeqMaker) (Py_ssize_t length);
|
2000-04-19 10:54:15 -03:00
|
|
|
typedef int (*SeqInserter) (PyObject* sequence,
|
2006-02-15 13:27:45 -04:00
|
|
|
Py_ssize_t index,
|
2000-04-19 10:54:15 -03:00
|
|
|
PyObject* element);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2000-07-16 09:04:32 -03:00
|
|
|
/* The function below is copyrighted by Stichting Mathematisch Centrum. The
|
1995-10-11 14:35:38 -03:00
|
|
|
* original copyright statement is included below, and continues to apply
|
|
|
|
* in full to the function immediately following. All other material is
|
|
|
|
* original, copyrighted by Fred L. Drake, Jr. and Virginia Polytechnic
|
|
|
|
* Institute and State University. Changes were made to comply with the
|
1996-08-21 18:55:43 -03:00
|
|
|
* new naming conventions. Added arguments to provide support for creating
|
|
|
|
* lists as well as tuples, and optionally including the line numbers.
|
1995-10-11 14:35:38 -03:00
|
|
|
*/
|
|
|
|
|
1993-11-10 08:53:24 -04:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
static PyObject*
|
2000-04-19 10:54:15 -03:00
|
|
|
node2tuple(node *n, /* node to convert */
|
|
|
|
SeqMaker mkseq, /* create sequence */
|
|
|
|
SeqInserter addelem, /* func. to add elem. in seq. */
|
|
|
|
int lineno) /* include line numbers? */
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1996-07-20 23:33:56 -03:00
|
|
|
if (n == NULL) {
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return (Py_None);
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
if (ISNONTERMINAL(TYPE(n))) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int i;
|
|
|
|
PyObject *v;
|
|
|
|
PyObject *w;
|
|
|
|
|
2002-12-31 14:17:44 -04:00
|
|
|
v = mkseq(1 + NCH(n) + (TYPE(n) == encoding_decl));
|
2000-04-19 10:54:15 -03:00
|
|
|
if (v == NULL)
|
|
|
|
return (v);
|
|
|
|
w = PyInt_FromLong(TYPE(n));
|
|
|
|
if (w == NULL) {
|
|
|
|
Py_DECREF(v);
|
|
|
|
return ((PyObject*) NULL);
|
|
|
|
}
|
|
|
|
(void) addelem(v, 0, w);
|
|
|
|
for (i = 0; i < NCH(n); i++) {
|
|
|
|
w = node2tuple(CHILD(n, i), mkseq, addelem, lineno);
|
|
|
|
if (w == NULL) {
|
|
|
|
Py_DECREF(v);
|
|
|
|
return ((PyObject*) NULL);
|
|
|
|
}
|
|
|
|
(void) addelem(v, i+1, w);
|
|
|
|
}
|
2003-07-21 11:25:23 -03:00
|
|
|
|
2002-12-31 14:17:44 -04:00
|
|
|
if (TYPE(n) == encoding_decl)
|
|
|
|
(void) addelem(v, i+1, PyString_FromString(STR(n)));
|
2000-04-19 10:54:15 -03:00
|
|
|
return (v);
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
else if (ISTERMINAL(TYPE(n))) {
|
2000-04-19 10:54:15 -03:00
|
|
|
PyObject *result = mkseq(2 + lineno);
|
|
|
|
if (result != NULL) {
|
|
|
|
(void) addelem(result, 0, PyInt_FromLong(TYPE(n)));
|
|
|
|
(void) addelem(result, 1, PyString_FromString(STR(n)));
|
|
|
|
if (lineno == 1)
|
|
|
|
(void) addelem(result, 2, PyInt_FromLong(n->n_lineno));
|
|
|
|
}
|
|
|
|
return (result);
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
else {
|
2000-04-19 10:54:15 -03:00
|
|
|
PyErr_SetString(PyExc_SystemError,
|
|
|
|
"unrecognized parse tree node type");
|
|
|
|
return ((PyObject*) NULL);
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
/*
|
|
|
|
* End of material copyrighted by Stichting Mathematisch Centrum.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* There are two types of intermediate objects we're interested in:
|
2001-07-17 16:32:05 -03:00
|
|
|
* 'eval' and 'exec' types. These constants can be used in the st_type
|
1995-10-11 14:35:38 -03:00
|
|
|
* field of the object type to identify which any given object represents.
|
|
|
|
* These should probably go in an external header to allow other extensions
|
|
|
|
* to use them, but then, we really should be using C++ too. ;-)
|
|
|
|
*/
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
#define PyST_EXPR 1
|
|
|
|
#define PyST_SUITE 2
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
/* These are the internal objects and definitions required to implement the
|
2001-07-17 16:32:05 -03:00
|
|
|
* ST type. Most of the internal names are more reminiscent of the 'old'
|
1995-10-11 14:35:38 -03:00
|
|
|
* naming style, but the code uses the new naming convention.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static PyObject*
|
|
|
|
parser_error = 0;
|
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
typedef struct {
|
2000-04-19 10:54:15 -03:00
|
|
|
PyObject_HEAD /* standard object header */
|
2001-07-17 16:32:05 -03:00
|
|
|
node* st_node; /* the node* returned by the parser */
|
|
|
|
int st_type; /* EXPR or SUITE ? */
|
|
|
|
} PyST_Object;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2002-07-17 13:30:39 -03:00
|
|
|
static void parser_free(PyST_Object *st);
|
|
|
|
static int parser_compare(PyST_Object *left, PyST_Object *right);
|
2006-02-27 13:01:22 -04:00
|
|
|
static PyObject *parser_getattr(PyObject *self, char *name);
|
1998-04-13 15:45:18 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1998-04-29 11:16:32 -03:00
|
|
|
static
|
2001-07-17 16:32:05 -03:00
|
|
|
PyTypeObject PyST_Type = {
|
1998-05-28 23:58:20 -03:00
|
|
|
PyObject_HEAD_INIT(NULL)
|
1995-10-11 14:35:38 -03:00
|
|
|
0,
|
2001-12-08 14:02:58 -04:00
|
|
|
"parser.st", /* tp_name */
|
2001-07-17 16:32:05 -03:00
|
|
|
(int) sizeof(PyST_Object), /* tp_basicsize */
|
2000-04-19 10:54:15 -03:00
|
|
|
0, /* tp_itemsize */
|
|
|
|
(destructor)parser_free, /* tp_dealloc */
|
|
|
|
0, /* tp_print */
|
|
|
|
parser_getattr, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
(cmpfunc)parser_compare, /* tp_compare */
|
|
|
|
0, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
0, /* tp_as_sequence */
|
|
|
|
0, /* tp_as_mapping */
|
|
|
|
0, /* tp_hash */
|
|
|
|
0, /* tp_call */
|
|
|
|
0, /* tp_str */
|
|
|
|
0, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
1997-05-23 01:04:17 -03:00
|
|
|
|
|
|
|
/* Functions to access object as input/output buffer */
|
2000-04-19 10:54:15 -03:00
|
|
|
0, /* tp_as_buffer */
|
1997-05-23 01:04:17 -03:00
|
|
|
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
1997-05-23 01:04:17 -03:00
|
|
|
|
|
|
|
/* __doc__ */
|
|
|
|
"Intermediate representation of a Python parse tree."
|
2001-07-17 16:32:05 -03:00
|
|
|
}; /* PyST_Type */
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
parser_compare_nodes(node *left, node *right)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int j;
|
|
|
|
|
|
|
|
if (TYPE(left) < TYPE(right))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (-1);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (TYPE(right) < TYPE(left))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (1);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (ISTERMINAL(TYPE(left)))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (strcmp(STR(left), STR(right)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (NCH(left) < NCH(right))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (-1);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (NCH(right) < NCH(left))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (1);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
for (j = 0; j < NCH(left); ++j) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int v = parser_compare_nodes(CHILD(left, j), CHILD(right, j));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2000-04-19 10:54:15 -03:00
|
|
|
if (v != 0)
|
|
|
|
return (v);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (0);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* int parser_compare(PyST_Object* left, PyST_Object* right)
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
* Comparison function used by the Python operators ==, !=, <, >, <=, >=
|
|
|
|
* This really just wraps a call to parser_compare_nodes() with some easy
|
|
|
|
* checks and protection code.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static int
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_compare(PyST_Object *left, PyST_Object *right)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
if (left == right)
|
2000-04-19 10:54:15 -03:00
|
|
|
return (0);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if ((left == 0) || (right == 0))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (-1);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
return (parser_compare_nodes(left->st_node, right->st_node));
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* parser_newstobject(node* st)
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
2001-07-17 16:32:05 -03:00
|
|
|
* Allocates a new Python object representing an ST. This is simply the
|
1995-10-11 14:35:38 -03:00
|
|
|
* 'wrapper' object that holds a node* and allows it to be passed around in
|
|
|
|
* Python code.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_newstobject(node *st, int type)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
2001-07-17 16:32:05 -03:00
|
|
|
PyST_Object* o = PyObject_New(PyST_Object, &PyST_Type);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (o != 0) {
|
2001-07-17 16:32:05 -03:00
|
|
|
o->st_node = st;
|
|
|
|
o->st_type = type;
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
1998-04-29 11:16:32 -03:00
|
|
|
else {
|
2001-07-17 16:32:05 -03:00
|
|
|
PyNode_Free(st);
|
1998-04-29 11:16:32 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
return ((PyObject*)o);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* void parser_free(PyST_Object* st)
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
* This is called by a del statement that reduces the reference count to 0.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_free(PyST_Object *st)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
2001-07-17 16:32:05 -03:00
|
|
|
PyNode_Free(st->st_node);
|
|
|
|
PyObject_Del(st);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* parser_st2tuple(PyObject* self, PyObject* args, PyObject* kw)
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
* This provides conversion from a node* to a tuple object that can be
|
2001-07-17 16:32:05 -03:00
|
|
|
* returned to the Python-level caller. The ST object is not modified.
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_st2tuple(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
|
|
|
PyObject *line_option = 0;
|
|
|
|
PyObject *res = 0;
|
1998-04-13 15:45:18 -03:00
|
|
|
int ok;
|
1996-08-21 11:32:37 -03:00
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"ast", "line_info", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
1998-04-29 11:16:32 -03:00
|
|
|
if (self == NULL) {
|
2001-07-17 16:32:05 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O:st2tuple", keywords,
|
|
|
|
&PyST_Type, &self, &line_option);
|
1998-04-29 11:16:32 -03:00
|
|
|
}
|
1998-04-13 15:45:18 -03:00
|
|
|
else
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "|O:totuple", &keywords[1],
|
1999-09-09 11:21:52 -03:00
|
|
|
&line_option);
|
1998-04-29 11:16:32 -03:00
|
|
|
if (ok != 0) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int lineno = 0;
|
|
|
|
if (line_option != NULL) {
|
|
|
|
lineno = (PyObject_IsTrue(line_option) != 0) ? 1 : 0;
|
|
|
|
}
|
|
|
|
/*
|
2001-07-17 16:32:05 -03:00
|
|
|
* Convert ST into a tuple representation. Use Guido's function,
|
2000-04-19 10:54:15 -03:00
|
|
|
* since it's known to work already.
|
|
|
|
*/
|
2001-07-17 16:32:05 -03:00
|
|
|
res = node2tuple(((PyST_Object*)self)->st_node,
|
2000-04-19 10:54:15 -03:00
|
|
|
PyTuple_New, PyTuple_SetItem, lineno);
|
1996-08-21 11:32:37 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* parser_st2list(PyObject* self, PyObject* args, PyObject* kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
*
|
1999-09-20 19:32:18 -03:00
|
|
|
* This provides conversion from a node* to a list object that can be
|
2001-07-17 16:32:05 -03:00
|
|
|
* returned to the Python-level caller. The ST object is not modified.
|
1996-08-21 11:32:37 -03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_st2list(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
|
|
|
PyObject *line_option = 0;
|
|
|
|
PyObject *res = 0;
|
1998-04-13 15:45:18 -03:00
|
|
|
int ok;
|
1996-08-21 11:32:37 -03:00
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"ast", "line_info", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
1998-04-13 15:45:18 -03:00
|
|
|
if (self == NULL)
|
2001-07-17 16:32:05 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O:st2list", keywords,
|
|
|
|
&PyST_Type, &self, &line_option);
|
1998-04-13 15:45:18 -03:00
|
|
|
else
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "|O:tolist", &keywords[1],
|
1999-09-09 11:21:52 -03:00
|
|
|
&line_option);
|
1998-04-13 15:45:18 -03:00
|
|
|
if (ok) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int lineno = 0;
|
|
|
|
if (line_option != 0) {
|
|
|
|
lineno = PyObject_IsTrue(line_option) ? 1 : 0;
|
|
|
|
}
|
|
|
|
/*
|
2001-07-17 16:32:05 -03:00
|
|
|
* Convert ST into a tuple representation. Use Guido's function,
|
2000-04-19 10:54:15 -03:00
|
|
|
* since it's known to work already.
|
|
|
|
*/
|
2001-07-17 16:32:05 -03:00
|
|
|
res = node2tuple(self->st_node,
|
2000-04-19 10:54:15 -03:00
|
|
|
PyList_New, PyList_SetItem, lineno);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* parser_compilest(PyObject* self, PyObject* args)
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
* This function creates code objects from the parse tree represented by
|
|
|
|
* the passed-in data object. An optional file name is passed in as well.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
PyObject* res = 0;
|
2001-07-17 16:32:05 -03:00
|
|
|
char* str = "<syntax-tree>";
|
1998-04-13 15:45:18 -03:00
|
|
|
int ok;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"ast", "filename", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
1998-04-13 15:45:18 -03:00
|
|
|
if (self == NULL)
|
2001-07-17 16:32:05 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|s:compilest", keywords,
|
|
|
|
&PyST_Type, &self, &str);
|
1998-04-13 15:45:18 -03:00
|
|
|
else
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1],
|
1999-09-09 11:21:52 -03:00
|
|
|
&str);
|
1998-04-13 15:45:18 -03:00
|
|
|
|
|
|
|
if (ok)
|
2001-07-17 16:32:05 -03:00
|
|
|
res = (PyObject *)PyNode_Compile(self->st_node, str);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
/* PyObject* parser_isexpr(PyObject* self, PyObject* args)
|
|
|
|
* PyObject* parser_issuite(PyObject* self, PyObject* args)
|
|
|
|
*
|
2001-07-17 16:32:05 -03:00
|
|
|
* Checks the passed-in ST object to determine if it is an expression or
|
1995-10-11 14:35:38 -03:00
|
|
|
* a statement suite, respectively. The return is a Python truth value.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_isexpr(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
PyObject* res = 0;
|
1998-04-13 15:45:18 -03:00
|
|
|
int ok;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"ast", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
1998-04-13 15:45:18 -03:00
|
|
|
if (self == NULL)
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:isexpr", keywords,
|
2001-07-17 16:32:05 -03:00
|
|
|
&PyST_Type, &self);
|
1998-04-13 15:45:18 -03:00
|
|
|
else
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, ":isexpr", &keywords[1]);
|
1998-04-13 15:45:18 -03:00
|
|
|
|
|
|
|
if (ok) {
|
2001-07-17 16:32:05 -03:00
|
|
|
/* Check to see if the ST represents an expression or not. */
|
|
|
|
res = (self->st_type == PyST_EXPR) ? Py_True : Py_False;
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_INCREF(res);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_issuite(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
PyObject* res = 0;
|
1998-04-13 15:45:18 -03:00
|
|
|
int ok;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"ast", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
1998-04-13 15:45:18 -03:00
|
|
|
if (self == NULL)
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:issuite", keywords,
|
2001-07-17 16:32:05 -03:00
|
|
|
&PyST_Type, &self);
|
1998-04-13 15:45:18 -03:00
|
|
|
else
|
2000-04-19 10:54:15 -03:00
|
|
|
ok = PyArg_ParseTupleAndKeywords(args, kw, ":issuite", &keywords[1]);
|
1998-04-13 15:45:18 -03:00
|
|
|
|
|
|
|
if (ok) {
|
2001-07-17 16:32:05 -03:00
|
|
|
/* Check to see if the ST represents an expression or not. */
|
|
|
|
res = (self->st_type == PyST_EXPR) ? Py_False : Py_True;
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_INCREF(res);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1999-09-09 11:21:52 -03:00
|
|
|
#define PUBLIC_METHOD_TYPE (METH_VARARGS|METH_KEYWORDS)
|
|
|
|
|
1998-04-13 15:45:18 -03:00
|
|
|
static PyMethodDef
|
|
|
|
parser_methods[] = {
|
2001-07-17 16:32:05 -03:00
|
|
|
{"compile", (PyCFunction)parser_compilest, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Compile this ST object into a code object.")},
|
2000-04-19 10:54:15 -03:00
|
|
|
{"isexpr", (PyCFunction)parser_isexpr, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Determines if this ST object was created from an expression.")},
|
2000-04-19 10:54:15 -03:00
|
|
|
{"issuite", (PyCFunction)parser_issuite, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Determines if this ST object was created from a suite.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"tolist", (PyCFunction)parser_st2list, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates a list-tree representation of this ST.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"totuple", (PyCFunction)parser_st2tuple, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates a tuple-tree representation of this ST.")},
|
1998-04-13 15:45:18 -03:00
|
|
|
|
1998-04-29 11:16:32 -03:00
|
|
|
{NULL, NULL, 0, NULL}
|
1998-04-13 15:45:18 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject*
|
2006-02-27 13:01:22 -04:00
|
|
|
parser_getattr(PyObject *self, char *name)
|
1998-04-13 15:45:18 -03:00
|
|
|
{
|
|
|
|
return (Py_FindMethod(parser_methods, self, name));
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1998-04-13 15:45:18 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* err_string(char* message)
|
|
|
|
*
|
|
|
|
* Sets the error string for an exception of type ParserError.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
2000-07-10 09:43:58 -03:00
|
|
|
err_string(char *message)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1996-07-20 23:33:56 -03:00
|
|
|
PyErr_SetString(parser_error, message);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
/* PyObject* parser_do_parse(PyObject* args, int type)
|
|
|
|
*
|
|
|
|
* Internal function to actually execute the parse and return the result if
|
2002-12-31 14:17:44 -04:00
|
|
|
* successful or set an exception if not.
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2000-04-19 10:54:15 -03:00
|
|
|
parser_do_parse(PyObject *args, PyObject *kw, char *argspec, int type)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
char* string = 0;
|
|
|
|
PyObject* res = 0;
|
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"source", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
|
|
|
if (PyArg_ParseTupleAndKeywords(args, kw, argspec, keywords, &string)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
node* n = PyParser_SimpleParseString(string,
|
2001-07-17 16:32:05 -03:00
|
|
|
(type == PyST_EXPR)
|
2000-04-19 10:54:15 -03:00
|
|
|
? eval_input : file_input);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2002-12-31 14:17:44 -04:00
|
|
|
if (n)
|
|
|
|
res = parser_newstobject(n, type);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
/* PyObject* parser_expr(PyObject* self, PyObject* args)
|
|
|
|
* PyObject* parser_suite(PyObject* self, PyObject* args)
|
|
|
|
*
|
|
|
|
* External interfaces to the parser itself. Which is called determines if
|
|
|
|
* the parser attempts to recognize an expression ('eval' form) or statement
|
|
|
|
* suite ('exec' form). The real work is done by parser_do_parse() above.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_expr(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1998-04-29 11:16:32 -03:00
|
|
|
NOTE(ARGUNUSED(self))
|
2001-07-17 16:32:05 -03:00
|
|
|
return (parser_do_parse(args, kw, "s:expr", PyST_EXPR));
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_suite(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1998-04-29 11:16:32 -03:00
|
|
|
NOTE(ARGUNUSED(self))
|
2001-07-17 16:32:05 -03:00
|
|
|
return (parser_do_parse(args, kw, "s:suite", PyST_SUITE));
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* This is the messy part of the code. Conversion from a tuple to an ST
|
1995-10-11 14:35:38 -03:00
|
|
|
* object requires that the input tuple be valid without having to rely on
|
|
|
|
* catching an exception from the compiler. This is done to allow the
|
|
|
|
* compiler itself to remain fast, since most of its input will come from
|
|
|
|
* the parser directly, and therefore be known to be syntactically correct.
|
|
|
|
* This validation is done to ensure that we don't core dump the compile
|
|
|
|
* phase, returning an exception instead.
|
|
|
|
*
|
|
|
|
* Two aspects can be broken out in this code: creating a node tree from
|
|
|
|
* the tuple passed in, and verifying that it is indeed valid. It may be
|
2001-07-17 16:32:05 -03:00
|
|
|
* advantageous to expand the number of ST types to include funcdefs and
|
|
|
|
* lambdadefs to take advantage of the optimizer, recognizing those STs
|
1995-10-11 14:35:38 -03:00
|
|
|
* here. They are not necessary, and not quite as useful in a raw form.
|
|
|
|
* For now, let's get expressions and suites working reliably.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2002-07-17 13:30:39 -03:00
|
|
|
static node* build_node_tree(PyObject *tuple);
|
|
|
|
static int validate_expr_tree(node *tree);
|
|
|
|
static int validate_file_input(node *tree);
|
2003-02-08 14:05:10 -04:00
|
|
|
static int validate_encoding_decl(node *tree);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
/* PyObject* parser_tuple2st(PyObject* self, PyObject* args)
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
* This is the public function, called from the Python code. It receives a
|
2001-07-17 16:32:05 -03:00
|
|
|
* single tuple object from the caller, and creates an ST object if the
|
1995-10-11 14:35:38 -03:00
|
|
|
* tuple can be validated. It does this by checking the first code of the
|
|
|
|
* tuple, and, if acceptable, builds the internal representation. If this
|
|
|
|
* step succeeds, the internal representation is validated as fully as
|
|
|
|
* possible with the various validate_*() routines defined below.
|
|
|
|
*
|
2001-07-17 16:32:05 -03:00
|
|
|
* This function must be changed if support is to be added for PyST_FRAGMENT
|
|
|
|
* ST objects.
|
1995-10-11 14:35:38 -03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
static PyObject*
|
2001-07-17 16:32:05 -03:00
|
|
|
parser_tuple2st(PyST_Object *self, PyObject *args, PyObject *kw)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1998-04-29 11:16:32 -03:00
|
|
|
NOTE(ARGUNUSED(self))
|
2001-07-17 16:32:05 -03:00
|
|
|
PyObject *st = 0;
|
2000-09-12 18:58:06 -03:00
|
|
|
PyObject *tuple;
|
|
|
|
node *tree;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2006-02-27 13:01:22 -04:00
|
|
|
static char *keywords[] = {"sequence", NULL};
|
1999-09-09 11:21:52 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kw, "O:sequence2st", keywords,
|
1999-09-09 11:21:52 -03:00
|
|
|
&tuple))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (0);
|
1996-08-21 11:32:37 -03:00
|
|
|
if (!PySequence_Check(tuple)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
2001-07-17 16:32:05 -03:00
|
|
|
"sequence2st() requires a single sequence argument");
|
2000-04-19 10:54:15 -03:00
|
|
|
return (0);
|
1996-08-21 11:32:37 -03:00
|
|
|
}
|
|
|
|
/*
|
2000-09-12 18:58:06 -03:00
|
|
|
* Convert the tree to the internal form before checking it.
|
1996-08-21 11:32:37 -03:00
|
|
|
*/
|
2000-09-12 18:58:06 -03:00
|
|
|
tree = build_node_tree(tuple);
|
|
|
|
if (tree != 0) {
|
|
|
|
int start_sym = TYPE(tree);
|
|
|
|
if (start_sym == eval_input) {
|
|
|
|
/* Might be an eval form. */
|
|
|
|
if (validate_expr_tree(tree))
|
2001-07-17 16:32:05 -03:00
|
|
|
st = parser_newstobject(tree, PyST_EXPR);
|
2001-12-05 18:10:44 -04:00
|
|
|
else
|
|
|
|
PyNode_Free(tree);
|
2000-09-12 18:58:06 -03:00
|
|
|
}
|
|
|
|
else if (start_sym == file_input) {
|
|
|
|
/* This looks like an exec form so far. */
|
|
|
|
if (validate_file_input(tree))
|
2001-07-17 16:32:05 -03:00
|
|
|
st = parser_newstobject(tree, PyST_SUITE);
|
2001-12-05 18:10:44 -04:00
|
|
|
else
|
|
|
|
PyNode_Free(tree);
|
2000-09-12 18:58:06 -03:00
|
|
|
}
|
2003-02-08 14:05:10 -04:00
|
|
|
else if (start_sym == encoding_decl) {
|
|
|
|
/* This looks like an encoding_decl so far. */
|
|
|
|
if (validate_encoding_decl(tree))
|
|
|
|
st = parser_newstobject(tree, PyST_SUITE);
|
|
|
|
else
|
|
|
|
PyNode_Free(tree);
|
|
|
|
}
|
2000-09-12 18:58:06 -03:00
|
|
|
else {
|
|
|
|
/* This is a fragment, at best. */
|
|
|
|
PyNode_Free(tree);
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("parse tree does not use a valid start symbol");
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
/* 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.
|
|
|
|
*/
|
2001-07-17 16:32:05 -03:00
|
|
|
if (st == NULL && !PyErr_Occurred())
|
|
|
|
err_string("unspecified ST error occurred");
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
return st;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
/* node* build_node_children()
|
|
|
|
*
|
|
|
|
* Iterate across the children of the current non-terminal node and build
|
|
|
|
* their structures. If successful, return the root of this portion of
|
|
|
|
* the tree, otherwise, 0. Any required exception will be specified already,
|
|
|
|
* and no memory will have been deallocated.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static node*
|
2000-04-19 10:54:15 -03:00
|
|
|
build_node_children(PyObject *tuple, node *root, int *line_num)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
2006-02-15 13:27:45 -04:00
|
|
|
Py_ssize_t len = PyObject_Size(tuple);
|
|
|
|
Py_ssize_t i;
|
|
|
|
int err;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
for (i = 1; i < len; ++i) {
|
2000-09-12 18:58:06 -03:00
|
|
|
/* elem must always be a sequence, however simple */
|
2000-04-19 10:54:15 -03:00
|
|
|
PyObject* elem = PySequence_GetItem(tuple, i);
|
|
|
|
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_AS_LONG(temp);
|
|
|
|
Py_DECREF(temp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ok) {
|
2006-03-20 00:08:12 -04:00
|
|
|
PyObject *err = Py_BuildValue("os", elem,
|
|
|
|
"Illegal node construct.");
|
|
|
|
PyErr_SetObject(parser_error, err);
|
|
|
|
Py_XDECREF(err);
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_XDECREF(elem);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (ISTERMINAL(type)) {
|
2006-02-15 13:27:45 -04:00
|
|
|
Py_ssize_t len = PyObject_Size(elem);
|
2000-09-12 18:58:06 -03:00
|
|
|
PyObject *temp;
|
2000-04-19 10:54:15 -03:00
|
|
|
|
2000-09-12 18:58:06 -03:00
|
|
|
if ((len != 2) && (len != 3)) {
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("terminal nodes must have 2 or 3 entries");
|
2000-09-12 18:58:06 -03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
temp = PySequence_GetItem(elem, 1);
|
|
|
|
if (temp == NULL)
|
|
|
|
return 0;
|
|
|
|
if (!PyString_Check(temp)) {
|
|
|
|
PyErr_Format(parser_error,
|
2000-10-24 16:57:45 -03:00
|
|
|
"second item in terminal node must be a string,"
|
|
|
|
" found %s",
|
2003-04-09 14:53:22 -03:00
|
|
|
temp->ob_type->tp_name);
|
2000-05-03 20:44:39 -03:00
|
|
|
Py_DECREF(temp);
|
2000-09-12 18:58:06 -03:00
|
|
|
return 0;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
2000-09-12 18:58:06 -03:00
|
|
|
if (len == 3) {
|
|
|
|
PyObject *o = PySequence_GetItem(elem, 2);
|
|
|
|
if (o != NULL) {
|
|
|
|
if (PyInt_Check(o))
|
|
|
|
*line_num = PyInt_AS_LONG(o);
|
|
|
|
else {
|
|
|
|
PyErr_Format(parser_error,
|
2000-10-24 16:57:45 -03:00
|
|
|
"third item in terminal node must be an"
|
|
|
|
" integer, found %s",
|
2003-04-09 14:53:22 -03:00
|
|
|
temp->ob_type->tp_name);
|
2000-09-12 18:58:06 -03:00
|
|
|
Py_DECREF(o);
|
|
|
|
Py_DECREF(temp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
Py_DECREF(o);
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
2000-09-12 18:58:06 -03:00
|
|
|
len = PyString_GET_SIZE(temp) + 1;
|
Years in the making.
objimpl.h, pymem.h: Stop mapping PyMem_{Del, DEL} and PyMem_{Free, FREE}
to PyObject_{Free, FREE} in a release build. They're aliases for the
system free() now.
_subprocess.c/sp_handle_dealloc(): Since the memory was originally
obtained via PyObject_NEW, it must be released via PyObject_FREE (or
_DEL).
pythonrun.c, tokenizer.c, parsermodule.c: I lost count of the number of
PyObject vs PyMem mismatches in these -- it's like the specific
function called at each site was picked at random, sometimes even with
memory obtained via PyMem getting released via PyObject. Changed most
to use PyObject uniformly, since the blobs allocated are predictably
small in most cases, and obmalloc is generally faster than system
mallocs then.
If extension modules in real life prove as sloppy as Python's front
end, we'll have to revert the objimpl.h + pymem.h part of this patch.
Note that no problems will show up in a debug build (all calls still go
thru obmalloc then). Problems will show up only in a release build, most
likely segfaults.
2006-03-26 19:27:58 -04:00
|
|
|
strn = (char *)PyObject_MALLOC(len);
|
2000-09-12 18:58:06 -03:00
|
|
|
if (strn != NULL)
|
|
|
|
(void) memcpy(strn, PyString_AS_STRING(temp), len);
|
|
|
|
Py_DECREF(temp);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
else if (!ISNONTERMINAL(type)) {
|
|
|
|
/*
|
|
|
|
* It has to be one or the other; this is an error.
|
|
|
|
* Throw an exception.
|
|
|
|
*/
|
2006-03-20 00:08:12 -04:00
|
|
|
PyObject *err = Py_BuildValue("os", elem, "unknown node type.");
|
|
|
|
PyErr_SetObject(parser_error, err);
|
|
|
|
Py_XDECREF(err);
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_XDECREF(elem);
|
|
|
|
return (0);
|
|
|
|
}
|
2006-03-01 18:49:05 -04:00
|
|
|
err = PyNode_AddChild(root, type, strn, *line_num, 0);
|
2001-12-05 18:10:44 -04:00
|
|
|
if (err == E_NOMEM) {
|
Years in the making.
objimpl.h, pymem.h: Stop mapping PyMem_{Del, DEL} and PyMem_{Free, FREE}
to PyObject_{Free, FREE} in a release build. They're aliases for the
system free() now.
_subprocess.c/sp_handle_dealloc(): Since the memory was originally
obtained via PyObject_NEW, it must be released via PyObject_FREE (or
_DEL).
pythonrun.c, tokenizer.c, parsermodule.c: I lost count of the number of
PyObject vs PyMem mismatches in these -- it's like the specific
function called at each site was picked at random, sometimes even with
memory obtained via PyMem getting released via PyObject. Changed most
to use PyObject uniformly, since the blobs allocated are predictably
small in most cases, and obmalloc is generally faster than system
mallocs then.
If extension modules in real life prove as sloppy as Python's front
end, we'll have to revert the objimpl.h + pymem.h part of this patch.
Note that no problems will show up in a debug build (all calls still go
thru obmalloc then). Problems will show up only in a release build, most
likely segfaults.
2006-03-26 19:27:58 -04:00
|
|
|
PyObject_FREE(strn);
|
2001-12-05 18:10:44 -04:00
|
|
|
return (node *) PyErr_NoMemory();
|
|
|
|
}
|
|
|
|
if (err == E_OVERFLOW) {
|
Years in the making.
objimpl.h, pymem.h: Stop mapping PyMem_{Del, DEL} and PyMem_{Free, FREE}
to PyObject_{Free, FREE} in a release build. They're aliases for the
system free() now.
_subprocess.c/sp_handle_dealloc(): Since the memory was originally
obtained via PyObject_NEW, it must be released via PyObject_FREE (or
_DEL).
pythonrun.c, tokenizer.c, parsermodule.c: I lost count of the number of
PyObject vs PyMem mismatches in these -- it's like the specific
function called at each site was picked at random, sometimes even with
memory obtained via PyMem getting released via PyObject. Changed most
to use PyObject uniformly, since the blobs allocated are predictably
small in most cases, and obmalloc is generally faster than system
mallocs then.
If extension modules in real life prove as sloppy as Python's front
end, we'll have to revert the objimpl.h + pymem.h part of this patch.
Note that no problems will show up in a debug build (all calls still go
thru obmalloc then). Problems will show up only in a release build, most
likely segfaults.
2006-03-26 19:27:58 -04:00
|
|
|
PyObject_FREE(strn);
|
2001-12-05 18:10:44 -04:00
|
|
|
PyErr_SetString(PyExc_ValueError,
|
|
|
|
"unsupported number of child nodes");
|
|
|
|
return NULL;
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
|
|
|
|
if (ISNONTERMINAL(type)) {
|
|
|
|
node* new_child = CHILD(root, i - 1);
|
|
|
|
|
|
|
|
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 */
|
|
|
|
++(*line_num); /* line number *after* the newline! */
|
|
|
|
}
|
|
|
|
Py_XDECREF(elem);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
Years in the making.
objimpl.h, pymem.h: Stop mapping PyMem_{Del, DEL} and PyMem_{Free, FREE}
to PyObject_{Free, FREE} in a release build. They're aliases for the
system free() now.
_subprocess.c/sp_handle_dealloc(): Since the memory was originally
obtained via PyObject_NEW, it must be released via PyObject_FREE (or
_DEL).
pythonrun.c, tokenizer.c, parsermodule.c: I lost count of the number of
PyObject vs PyMem mismatches in these -- it's like the specific
function called at each site was picked at random, sometimes even with
memory obtained via PyMem getting released via PyObject. Changed most
to use PyObject uniformly, since the blobs allocated are predictably
small in most cases, and obmalloc is generally faster than system
mallocs then.
If extension modules in real life prove as sloppy as Python's front
end, we'll have to revert the objimpl.h + pymem.h part of this patch.
Note that no problems will show up in a debug build (all calls still go
thru obmalloc then). Problems will show up only in a release build, most
likely segfaults.
2006-03-26 19:27:58 -04:00
|
|
|
return root;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
static node*
|
2000-04-19 10:54:15 -03:00
|
|
|
build_node_tree(PyObject *tuple)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
node* res = 0;
|
1996-08-21 11:32:37 -03:00
|
|
|
PyObject *temp = PySequence_GetItem(tuple, 0);
|
2000-09-12 18:58:06 -03:00
|
|
|
long num = -1;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
if (temp != NULL)
|
2000-04-19 10:54:15 -03:00
|
|
|
num = PyInt_AsLong(temp);
|
1996-08-21 11:32:37 -03:00
|
|
|
Py_XDECREF(temp);
|
1995-10-11 14:35:38 -03:00
|
|
|
if (ISTERMINAL(num)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
/*
|
|
|
|
* The tuple is simple, but it doesn't start with a start symbol.
|
|
|
|
* Throw an exception now and be done with it.
|
|
|
|
*/
|
2000-09-12 18:58:06 -03:00
|
|
|
tuple = Py_BuildValue("os", tuple,
|
2001-07-17 16:32:05 -03:00
|
|
|
"Illegal syntax-tree; cannot start with terminal symbol.");
|
2000-04-19 10:54:15 -03:00
|
|
|
PyErr_SetObject(parser_error, tuple);
|
2006-03-20 00:08:12 -04:00
|
|
|
Py_XDECREF(tuple);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
else if (ISNONTERMINAL(num)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
/*
|
|
|
|
* Not efficient, but that can be handled later.
|
|
|
|
*/
|
|
|
|
int line_num = 0;
|
2003-02-08 14:05:10 -04:00
|
|
|
PyObject *encoding = NULL;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2003-02-08 14:05:10 -04:00
|
|
|
if (num == encoding_decl) {
|
|
|
|
encoding = PySequence_GetItem(tuple, 2);
|
|
|
|
/* tuple isn't borrowed anymore here, need to DECREF */
|
|
|
|
tuple = PySequence_GetSlice(tuple, 0, 2);
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
res = PyNode_New(num);
|
2001-12-05 18:10:44 -04:00
|
|
|
if (res != NULL) {
|
|
|
|
if (res != build_node_children(tuple, res, &line_num)) {
|
|
|
|
PyNode_Free(res);
|
|
|
|
res = NULL;
|
|
|
|
}
|
2003-02-08 14:05:10 -04:00
|
|
|
if (res && encoding) {
|
2006-02-16 10:30:23 -04:00
|
|
|
Py_ssize_t len;
|
2003-02-08 14:05:10 -04:00
|
|
|
len = PyString_GET_SIZE(encoding) + 1;
|
Years in the making.
objimpl.h, pymem.h: Stop mapping PyMem_{Del, DEL} and PyMem_{Free, FREE}
to PyObject_{Free, FREE} in a release build. They're aliases for the
system free() now.
_subprocess.c/sp_handle_dealloc(): Since the memory was originally
obtained via PyObject_NEW, it must be released via PyObject_FREE (or
_DEL).
pythonrun.c, tokenizer.c, parsermodule.c: I lost count of the number of
PyObject vs PyMem mismatches in these -- it's like the specific
function called at each site was picked at random, sometimes even with
memory obtained via PyMem getting released via PyObject. Changed most
to use PyObject uniformly, since the blobs allocated are predictably
small in most cases, and obmalloc is generally faster than system
mallocs then.
If extension modules in real life prove as sloppy as Python's front
end, we'll have to revert the objimpl.h + pymem.h part of this patch.
Note that no problems will show up in a debug build (all calls still go
thru obmalloc then). Problems will show up only in a release build, most
likely segfaults.
2006-03-26 19:27:58 -04:00
|
|
|
res->n_str = (char *)PyObject_MALLOC(len);
|
2003-02-08 14:05:10 -04:00
|
|
|
if (res->n_str != NULL)
|
|
|
|
(void) memcpy(res->n_str, PyString_AS_STRING(encoding), len);
|
|
|
|
Py_DECREF(encoding);
|
|
|
|
Py_DECREF(tuple);
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
2006-03-20 00:08:12 -04:00
|
|
|
else {
|
2000-04-19 10:54:15 -03:00
|
|
|
/* The tuple is illegal -- if the number is neither TERMINAL nor
|
2000-09-12 18:58:06 -03:00
|
|
|
* NONTERMINAL, we can't use it. Not sure the implementation
|
|
|
|
* allows this condition, but the API doesn't preclude it.
|
2000-04-19 10:54:15 -03:00
|
|
|
*/
|
2006-03-20 00:08:12 -04:00
|
|
|
PyObject *err = Py_BuildValue("os", tuple,
|
|
|
|
"Illegal component tuple.");
|
|
|
|
PyErr_SetObject(parser_error, err);
|
|
|
|
Py_XDECREF(err);
|
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validation routines used within the validation section:
|
|
|
|
*/
|
2002-07-17 13:30:39 -03:00
|
|
|
static int validate_terminal(node *terminal, int type, char *string);
|
2000-04-19 10:54:15 -03:00
|
|
|
|
|
|
|
#define validate_ampersand(ch) validate_terminal(ch, AMPER, "&")
|
|
|
|
#define validate_circumflex(ch) validate_terminal(ch, CIRCUMFLEX, "^")
|
|
|
|
#define validate_colon(ch) validate_terminal(ch, COLON, ":")
|
|
|
|
#define validate_comma(ch) validate_terminal(ch, COMMA, ",")
|
|
|
|
#define validate_dedent(ch) validate_terminal(ch, DEDENT, "")
|
|
|
|
#define validate_equal(ch) validate_terminal(ch, EQUAL, "=")
|
|
|
|
#define validate_indent(ch) validate_terminal(ch, INDENT, (char*)NULL)
|
|
|
|
#define validate_lparen(ch) validate_terminal(ch, LPAR, "(")
|
|
|
|
#define validate_newline(ch) validate_terminal(ch, NEWLINE, (char*)NULL)
|
|
|
|
#define validate_rparen(ch) validate_terminal(ch, RPAR, ")")
|
|
|
|
#define validate_semi(ch) validate_terminal(ch, SEMI, ";")
|
|
|
|
#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, ".")
|
2004-08-02 03:10:11 -03:00
|
|
|
#define validate_at(ch) validate_terminal(ch, AT, "@")
|
2000-04-19 10:54:15 -03:00
|
|
|
#define validate_name(ch, str) validate_terminal(ch, NAME, str)
|
|
|
|
|
2000-09-12 18:58:06 -03:00
|
|
|
#define VALIDATER(n) static int validate_##n(node *tree)
|
|
|
|
|
2000-04-19 10:54:15 -03:00
|
|
|
VALIDATER(node); VALIDATER(small_stmt);
|
|
|
|
VALIDATER(class); VALIDATER(node);
|
|
|
|
VALIDATER(parameters); VALIDATER(suite);
|
|
|
|
VALIDATER(testlist); VALIDATER(varargslist);
|
|
|
|
VALIDATER(fpdef); VALIDATER(fplist);
|
|
|
|
VALIDATER(stmt); VALIDATER(simple_stmt);
|
|
|
|
VALIDATER(expr_stmt); VALIDATER(power);
|
|
|
|
VALIDATER(print_stmt); VALIDATER(del_stmt);
|
2000-08-21 19:24:43 -03:00
|
|
|
VALIDATER(return_stmt); VALIDATER(list_iter);
|
2000-04-19 10:54:15 -03:00
|
|
|
VALIDATER(raise_stmt); VALIDATER(import_stmt);
|
2004-08-31 07:07:13 -03:00
|
|
|
VALIDATER(import_name); VALIDATER(import_from);
|
2000-08-21 19:24:43 -03:00
|
|
|
VALIDATER(global_stmt); VALIDATER(list_if);
|
|
|
|
VALIDATER(assert_stmt); VALIDATER(list_for);
|
2000-04-19 10:54:15 -03:00
|
|
|
VALIDATER(exec_stmt); VALIDATER(compound_stmt);
|
|
|
|
VALIDATER(while); VALIDATER(for);
|
|
|
|
VALIDATER(try); VALIDATER(except_clause);
|
|
|
|
VALIDATER(test); VALIDATER(and_test);
|
|
|
|
VALIDATER(not_test); VALIDATER(comparison);
|
|
|
|
VALIDATER(comp_op); VALIDATER(expr);
|
|
|
|
VALIDATER(xor_expr); VALIDATER(and_expr);
|
|
|
|
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);
|
2001-07-16 23:59:15 -03:00
|
|
|
VALIDATER(listmaker); VALIDATER(yield_stmt);
|
2004-05-19 05:20:33 -03:00
|
|
|
VALIDATER(testlist1); VALIDATER(gen_for);
|
|
|
|
VALIDATER(gen_iter); VALIDATER(gen_if);
|
2005-08-01 21:46:46 -03:00
|
|
|
VALIDATER(testlist_gexp); VALIDATER(yield_expr);
|
2006-02-27 12:25:11 -04:00
|
|
|
VALIDATER(yield_or_testlist); VALIDATER(or_test);
|
|
|
|
VALIDATER(old_test); VALIDATER(old_lambdef);
|
2000-04-19 10:54:15 -03:00
|
|
|
|
2000-09-12 18:58:06 -03:00
|
|
|
#undef VALIDATER
|
2000-04-19 10:54:15 -03:00
|
|
|
|
|
|
|
#define is_even(n) (((n) & 1) == 0)
|
|
|
|
#define is_odd(n) (((n) & 1) == 1)
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_ntype(node *n, int t)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
2000-09-12 18:58:06 -03:00
|
|
|
if (TYPE(n) != t) {
|
|
|
|
PyErr_Format(parser_error, "Expected node type %d, got %d.",
|
|
|
|
t, TYPE(n));
|
|
|
|
return 0;
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
2000-09-12 18:58:06 -03:00
|
|
|
return 1;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2000-04-25 01:14:46 -03:00
|
|
|
/* Verifies that the number of child nodes is exactly 'num', raising
|
|
|
|
* an exception if it isn't. The exception message does not indicate
|
|
|
|
* the exact number of nodes, allowing this to be used to raise the
|
|
|
|
* "right" exception when the wrong number of nodes is present in a
|
|
|
|
* specific variant of a statement's syntax. This is commonly used
|
|
|
|
* in that fashion.
|
|
|
|
*/
|
1996-07-20 23:33:56 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_numnodes(node *n, int num, const char *const name)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1996-07-20 23:33:56 -03:00
|
|
|
if (NCH(n) != num) {
|
2000-09-12 18:58:06 -03:00
|
|
|
PyErr_Format(parser_error,
|
|
|
|
"Illegal number of children for %s node.", name);
|
|
|
|
return 0;
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
2000-09-12 18:58:06 -03:00
|
|
|
return 1;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_terminal(node *terminal, int type, char *string)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(terminal, type)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((string == 0) || (strcmp(string, STR(terminal)) == 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (!res && !PyErr_Occurred()) {
|
2000-09-12 18:58:06 -03:00
|
|
|
PyErr_Format(parser_error,
|
|
|
|
"Illegal terminal: expected \"%s\"", string);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
/* X (',' X) [',']
|
|
|
|
*/
|
|
|
|
static int
|
2000-07-22 20:57:55 -03:00
|
|
|
validate_repeating_list(node *tree, int ntype, int (*vfunc)(node *),
|
2000-04-19 10:54:15 -03:00
|
|
|
const char *const name)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (nch && validate_ntype(tree, ntype)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& vfunc(CHILD(tree, 0)));
|
1996-08-21 11:32:37 -03:00
|
|
|
|
|
|
|
if (!res && !PyErr_Occurred())
|
2000-04-19 10:54:15 -03:00
|
|
|
(void) validate_numnodes(tree, 1, name);
|
1996-08-21 11:32:37 -03:00
|
|
|
else {
|
2000-04-19 10:54:15 -03:00
|
|
|
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)));
|
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
/* validate_class()
|
1996-07-20 23:33:56 -03:00
|
|
|
*
|
|
|
|
* classdef:
|
2000-04-19 10:54:15 -03:00
|
|
|
* 'class' NAME ['(' testlist ')'] ':' suite
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_class(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
2005-04-08 23:30:16 -03:00
|
|
|
int res = (validate_ntype(tree, classdef) &&
|
|
|
|
((nch == 4) || (nch == 6) || (nch == 7)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, 0), "class")
|
|
|
|
&& validate_ntype(CHILD(tree, 1), NAME)
|
|
|
|
&& validate_colon(CHILD(tree, nch - 2))
|
|
|
|
&& validate_suite(CHILD(tree, nch - 1)));
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
2005-04-08 23:30:16 -03:00
|
|
|
else {
|
2000-04-19 10:54:15 -03:00
|
|
|
(void) validate_numnodes(tree, 4, "class");
|
2005-04-08 23:30:16 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
if (nch == 7) {
|
|
|
|
res = ((validate_lparen(CHILD(tree, 2)) &&
|
|
|
|
validate_testlist(CHILD(tree, 3)) &&
|
|
|
|
validate_rparen(CHILD(tree, 4))));
|
|
|
|
}
|
|
|
|
else if (nch == 6) {
|
|
|
|
res = (validate_lparen(CHILD(tree,2)) &&
|
|
|
|
validate_rparen(CHILD(tree,3)));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* if_stmt:
|
2000-04-19 10:54:15 -03:00
|
|
|
* 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_if(node *tree)
|
1995-10-11 14:35:38 -03:00
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, if_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (nch >= 4)
|
|
|
|
&& validate_name(CHILD(tree, 0), "if")
|
|
|
|
&& validate_test(CHILD(tree, 1))
|
|
|
|
&& validate_colon(CHILD(tree, 2))
|
|
|
|
&& validate_suite(CHILD(tree, 3)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (res && ((nch % 4) == 3)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
/* ... 'else' ':' suite */
|
|
|
|
res = (validate_name(CHILD(tree, nch - 3), "else")
|
|
|
|
&& validate_colon(CHILD(tree, nch - 2))
|
|
|
|
&& validate_suite(CHILD(tree, nch - 1)));
|
|
|
|
nch -= 3;
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
else if (!res && !PyErr_Occurred())
|
2000-04-19 10:54:15 -03:00
|
|
|
(void) validate_numnodes(tree, 4, "if");
|
1995-10-11 14:35:38 -03:00
|
|
|
if ((nch % 4) != 0)
|
2000-04-19 10:54:15 -03:00
|
|
|
/* Will catch the case for nch < 4 */
|
|
|
|
res = validate_numnodes(tree, 0, "if");
|
1995-10-11 14:35:38 -03:00
|
|
|
else if (res && (nch > 4)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
/* ... ('elif' test ':' suite)+ ... */
|
|
|
|
int j = 4;
|
|
|
|
while ((j < nch) && res) {
|
|
|
|
res = (validate_name(CHILD(tree, j), "elif")
|
|
|
|
&& validate_colon(CHILD(tree, j + 2))
|
|
|
|
&& validate_test(CHILD(tree, j + 1))
|
|
|
|
&& validate_suite(CHILD(tree, j + 3)));
|
|
|
|
j += 4;
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* parameters:
|
2000-04-19 10:54:15 -03:00
|
|
|
* '(' [varargslist] ')'
|
1996-07-20 23:33:56 -03:00
|
|
|
*
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_parameters(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = validate_ntype(tree, parameters) && ((nch == 2) || (nch == 3));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_lparen(CHILD(tree, 0))
|
|
|
|
&& validate_rparen(CHILD(tree, nch - 1)));
|
|
|
|
if (res && (nch == 3))
|
|
|
|
res = validate_varargslist(CHILD(tree, 1));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
(void) validate_numnodes(tree, 2, "parameters");
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
/* validate_suite()
|
1996-07-20 23:33:56 -03:00
|
|
|
*
|
|
|
|
* suite:
|
2000-04-19 10:54:15 -03:00
|
|
|
* simple_stmt
|
1996-07-20 23:33:56 -03:00
|
|
|
* | NEWLINE INDENT stmt+ DEDENT
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_suite(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, suite) && ((nch == 1) || (nch >= 4)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 1))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_simple_stmt(CHILD(tree, 0));
|
1996-07-20 23:33:56 -03:00
|
|
|
else if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
/* NEWLINE INDENT stmt+ DEDENT */
|
|
|
|
res = (validate_newline(CHILD(tree, 0))
|
|
|
|
&& validate_indent(CHILD(tree, 1))
|
|
|
|
&& validate_stmt(CHILD(tree, 2))
|
|
|
|
&& validate_dedent(CHILD(tree, nch - 1)));
|
|
|
|
|
|
|
|
if (res && (nch > 4)) {
|
|
|
|
int i = 3;
|
|
|
|
--nch; /* forget the DEDENT */
|
|
|
|
for ( ; res && (i < nch); ++i)
|
|
|
|
res = validate_stmt(CHILD(tree, i));
|
|
|
|
}
|
|
|
|
else if (nch < 4)
|
|
|
|
res = validate_numnodes(tree, 4, "suite");
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_testlist(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1996-08-21 11:32:37 -03:00
|
|
|
return (validate_repeating_list(tree, testlist,
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_test, "testlist"));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2002-05-24 12:47:06 -03:00
|
|
|
static int
|
|
|
|
validate_testlist1(node *tree)
|
|
|
|
{
|
|
|
|
return (validate_repeating_list(tree, testlist1,
|
|
|
|
validate_test, "testlist1"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-10-15 12:44:05 -03:00
|
|
|
static int
|
|
|
|
validate_testlist_safe(node *tree)
|
|
|
|
{
|
|
|
|
return (validate_repeating_list(tree, testlist_safe,
|
2006-02-27 12:25:11 -04:00
|
|
|
validate_old_test, "testlist_safe"));
|
2001-10-15 12:44:05 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
/* '*' NAME [',' '**' NAME] | '**' NAME
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_varargslist_trailer(node *tree, int start)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = 0;
|
|
|
|
int sym;
|
|
|
|
|
|
|
|
if (nch <= start) {
|
|
|
|
err_string("expected variable argument trailer for varargslist");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sym = TYPE(CHILD(tree, start));
|
|
|
|
if (sym == STAR) {
|
|
|
|
/*
|
|
|
|
* ('*' NAME [',' '**' NAME]
|
|
|
|
*/
|
|
|
|
if (nch-start == 2)
|
|
|
|
res = validate_name(CHILD(tree, start+1), NULL);
|
|
|
|
else if (nch-start == 5)
|
|
|
|
res = (validate_name(CHILD(tree, start+1), NULL)
|
|
|
|
&& validate_comma(CHILD(tree, start+2))
|
|
|
|
&& validate_doublestar(CHILD(tree, start+3))
|
|
|
|
&& validate_name(CHILD(tree, start+4), NULL));
|
|
|
|
}
|
|
|
|
else if (sym == DOUBLESTAR) {
|
|
|
|
/*
|
|
|
|
* '**' NAME
|
|
|
|
*/
|
|
|
|
if (nch-start == 2)
|
|
|
|
res = validate_name(CHILD(tree, start+1), NULL);
|
|
|
|
}
|
|
|
|
if (!res)
|
|
|
|
err_string("illegal variable argument trailer for varargslist");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* validate_varargslist()
|
1996-07-20 23:33:56 -03:00
|
|
|
*
|
|
|
|
* varargslist:
|
|
|
|
* (fpdef ['=' test] ',')*
|
2000-08-21 19:24:43 -03:00
|
|
|
* ('*' NAME [',' '**' NAME]
|
|
|
|
* | '**' NAME)
|
1996-07-20 23:33:56 -03:00
|
|
|
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
|
|
|
*
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_varargslist(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = validate_ntype(tree, varargslist) && (nch != 0);
|
2000-08-21 19:24:43 -03:00
|
|
|
int sym;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2000-12-11 18:08:27 -04:00
|
|
|
if (!res)
|
|
|
|
return 0;
|
2000-08-21 19:24:43 -03:00
|
|
|
if (nch < 1) {
|
|
|
|
err_string("varargslist missing child nodes");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sym = TYPE(CHILD(tree, 0));
|
|
|
|
if (sym == STAR || sym == DOUBLESTAR)
|
2000-12-11 18:08:27 -04:00
|
|
|
/* whole thing matches:
|
|
|
|
* '*' NAME [',' '**' NAME] | '**' NAME
|
|
|
|
*/
|
2000-08-21 19:24:43 -03:00
|
|
|
res = validate_varargslist_trailer(tree, 0);
|
|
|
|
else if (sym == fpdef) {
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
sym = TYPE(CHILD(tree, nch-1));
|
|
|
|
if (sym == NAME) {
|
|
|
|
/*
|
|
|
|
* (fpdef ['=' test] ',')+
|
|
|
|
* ('*' NAME [',' '**' NAME]
|
|
|
|
* | '**' NAME)
|
|
|
|
*/
|
|
|
|
/* skip over (fpdef ['=' test] ',')+ */
|
|
|
|
while (res && (i+2 <= nch)) {
|
|
|
|
res = validate_fpdef(CHILD(tree, i));
|
|
|
|
++i;
|
|
|
|
if (res && TYPE(CHILD(tree, i)) == EQUAL && (i+2 <= nch)) {
|
|
|
|
res = (validate_equal(CHILD(tree, i))
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
|
|
|
if (res)
|
|
|
|
i += 2;
|
|
|
|
}
|
|
|
|
if (res && i < nch) {
|
|
|
|
res = validate_comma(CHILD(tree, i));
|
2000-12-11 18:08:27 -04:00
|
|
|
++i;
|
|
|
|
if (res && i < nch
|
|
|
|
&& (TYPE(CHILD(tree, i)) == DOUBLESTAR
|
|
|
|
|| TYPE(CHILD(tree, i)) == STAR))
|
|
|
|
break;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
}
|
2000-12-11 18:08:27 -04:00
|
|
|
/* ... '*' NAME [',' '**' NAME] | '**' NAME
|
|
|
|
* i --^^^
|
|
|
|
*/
|
2000-08-21 19:24:43 -03:00
|
|
|
if (res)
|
|
|
|
res = validate_varargslist_trailer(tree, i);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
|
|
|
*/
|
2000-12-11 18:08:27 -04:00
|
|
|
/* strip trailing comma node */
|
2000-08-21 19:24:43 -03:00
|
|
|
if (sym == COMMA) {
|
|
|
|
res = validate_comma(CHILD(tree, nch-1));
|
|
|
|
if (!res)
|
|
|
|
return 0;
|
|
|
|
--nch;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
/*
|
|
|
|
* fpdef ['=' test] (',' fpdef ['=' test])*
|
|
|
|
*/
|
|
|
|
res = validate_fpdef(CHILD(tree, 0));
|
|
|
|
++i;
|
2000-12-11 18:08:27 -04:00
|
|
|
if (res && (i+2 <= nch) && TYPE(CHILD(tree, i)) == EQUAL) {
|
|
|
|
res = (validate_equal(CHILD(tree, i))
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
2000-08-21 19:24:43 -03:00
|
|
|
i += 2;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
/*
|
|
|
|
* ... (',' fpdef ['=' test])*
|
|
|
|
* i ---^^^
|
|
|
|
*/
|
|
|
|
while (res && (nch - i) >= 2) {
|
|
|
|
res = (validate_comma(CHILD(tree, i))
|
|
|
|
&& validate_fpdef(CHILD(tree, i+1)));
|
|
|
|
i += 2;
|
2000-12-11 18:08:27 -04:00
|
|
|
if (res && (nch - i) >= 2 && TYPE(CHILD(tree, i)) == EQUAL) {
|
|
|
|
res = (validate_equal(CHILD(tree, i))
|
2000-08-21 19:24:43 -03:00
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
2000-12-11 18:08:27 -04:00
|
|
|
i += 2;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
if (res && nch - i != 0) {
|
|
|
|
res = 0;
|
|
|
|
err_string("illegal formation for varargslist");
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
return res;
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
/* list_iter: list_for | list_if
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_list_iter(node *tree)
|
|
|
|
{
|
|
|
|
int res = (validate_ntype(tree, list_iter)
|
|
|
|
&& validate_numnodes(tree, 1, "list_iter"));
|
|
|
|
if (res && TYPE(CHILD(tree, 0)) == list_for)
|
|
|
|
res = validate_list_for(CHILD(tree, 0));
|
|
|
|
else
|
|
|
|
res = validate_list_if(CHILD(tree, 0));
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2004-05-19 05:20:33 -03:00
|
|
|
/* gen_iter: gen_for | gen_if
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_gen_iter(node *tree)
|
|
|
|
{
|
|
|
|
int res = (validate_ntype(tree, gen_iter)
|
|
|
|
&& validate_numnodes(tree, 1, "gen_iter"));
|
|
|
|
if (res && TYPE(CHILD(tree, 0)) == gen_for)
|
|
|
|
res = validate_gen_for(CHILD(tree, 0));
|
|
|
|
else
|
|
|
|
res = validate_gen_if(CHILD(tree, 0));
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
/* list_for: 'for' exprlist 'in' testlist [list_iter]
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_list_for(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res;
|
|
|
|
|
|
|
|
if (nch == 5)
|
|
|
|
res = validate_list_iter(CHILD(tree, 4));
|
|
|
|
else
|
|
|
|
res = validate_numnodes(tree, 4, "list_for");
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
res = (validate_name(CHILD(tree, 0), "for")
|
|
|
|
&& validate_exprlist(CHILD(tree, 1))
|
|
|
|
&& validate_name(CHILD(tree, 2), "in")
|
2001-10-15 12:44:05 -03:00
|
|
|
&& validate_testlist_safe(CHILD(tree, 3)));
|
2000-08-21 19:24:43 -03:00
|
|
|
|
|
|
|
return res;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2004-05-19 05:20:33 -03:00
|
|
|
/* gen_for: 'for' exprlist 'in' test [gen_iter]
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_gen_for(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res;
|
|
|
|
|
|
|
|
if (nch == 5)
|
|
|
|
res = validate_gen_iter(CHILD(tree, 4));
|
|
|
|
else
|
|
|
|
res = validate_numnodes(tree, 4, "gen_for");
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
res = (validate_name(CHILD(tree, 0), "for")
|
|
|
|
&& validate_exprlist(CHILD(tree, 1))
|
|
|
|
&& validate_name(CHILD(tree, 2), "in")
|
2006-02-27 12:25:11 -04:00
|
|
|
&& validate_or_test(CHILD(tree, 3)));
|
2004-05-19 05:20:33 -03:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2006-04-12 02:24:39 -03:00
|
|
|
/* list_if: 'if' old_test [list_iter]
|
2000-08-21 19:24:43 -03:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_list_if(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res;
|
|
|
|
|
|
|
|
if (nch == 3)
|
|
|
|
res = validate_list_iter(CHILD(tree, 2));
|
|
|
|
else
|
|
|
|
res = validate_numnodes(tree, 2, "list_if");
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
res = (validate_name(CHILD(tree, 0), "if")
|
2006-04-12 02:24:39 -03:00
|
|
|
&& validate_old_test(CHILD(tree, 1)));
|
2000-08-21 19:24:43 -03:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2006-04-12 02:24:39 -03:00
|
|
|
/* gen_if: 'if' old_test [gen_iter]
|
2004-05-19 05:20:33 -03:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_gen_if(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res;
|
|
|
|
|
|
|
|
if (nch == 3)
|
|
|
|
res = validate_gen_iter(CHILD(tree, 2));
|
|
|
|
else
|
|
|
|
res = validate_numnodes(tree, 2, "gen_if");
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
res = (validate_name(CHILD(tree, 0), "if")
|
2006-04-12 02:24:39 -03:00
|
|
|
&& validate_old_test(CHILD(tree, 1)));
|
2004-05-19 05:20:33 -03:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
|
|
|
|
/* validate_fpdef()
|
1996-07-20 23:33:56 -03:00
|
|
|
*
|
|
|
|
* fpdef:
|
2000-04-19 10:54:15 -03:00
|
|
|
* NAME
|
1996-07-20 23:33:56 -03:00
|
|
|
* | '(' fplist ')'
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_fpdef(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = validate_ntype(tree, fpdef);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (nch == 1)
|
|
|
|
res = validate_ntype(CHILD(tree, 0), NAME);
|
|
|
|
else if (nch == 3)
|
|
|
|
res = (validate_lparen(CHILD(tree, 0))
|
|
|
|
&& validate_fplist(CHILD(tree, 1))
|
|
|
|
&& validate_rparen(CHILD(tree, 2)));
|
|
|
|
else
|
|
|
|
res = validate_numnodes(tree, 1, "fpdef");
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_fplist(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1996-08-21 11:32:37 -03:00
|
|
|
return (validate_repeating_list(tree, fplist,
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_fpdef, "fplist"));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* simple_stmt | compound_stmt
|
|
|
|
*
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int res = (validate_ntype(tree, stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_numnodes(tree, 1, "stmt"));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
tree = CHILD(tree, 0);
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2000-04-19 10:54:15 -03:00
|
|
|
if (TYPE(tree) == simple_stmt)
|
|
|
|
res = validate_simple_stmt(tree);
|
|
|
|
else
|
|
|
|
res = validate_compound_stmt(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* small_stmt (';' small_stmt)* [';'] NEWLINE
|
|
|
|
*
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_simple_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, simple_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (nch >= 2)
|
|
|
|
&& validate_small_stmt(CHILD(tree, 0))
|
|
|
|
&& validate_newline(CHILD(tree, nch - 1)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (nch < 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_numnodes(tree, 2, "simple_stmt");
|
|
|
|
--nch; /* forget the NEWLINE */
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && is_even(nch))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_semi(CHILD(tree, --nch));
|
1995-10-11 14:35:38 -03:00
|
|
|
if (res && (nch > 2)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int i;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2000-04-19 10:54:15 -03:00
|
|
|
for (i = 1; res && (i < nch); i += 2)
|
|
|
|
res = (validate_semi(CHILD(tree, i))
|
|
|
|
&& validate_small_stmt(CHILD(tree, i + 1)));
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_small_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
2000-09-12 18:58:06 -03:00
|
|
|
int res = validate_numnodes(tree, 1, "small_stmt");
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2000-09-12 18:58:06 -03:00
|
|
|
if (res) {
|
|
|
|
int ntype = TYPE(CHILD(tree, 0));
|
|
|
|
|
|
|
|
if ( (ntype == expr_stmt)
|
|
|
|
|| (ntype == print_stmt)
|
|
|
|
|| (ntype == del_stmt)
|
|
|
|
|| (ntype == pass_stmt)
|
|
|
|
|| (ntype == flow_stmt)
|
|
|
|
|| (ntype == import_stmt)
|
|
|
|
|| (ntype == global_stmt)
|
|
|
|
|| (ntype == assert_stmt)
|
|
|
|
|| (ntype == exec_stmt))
|
|
|
|
res = validate_node(CHILD(tree, 0));
|
|
|
|
else {
|
|
|
|
res = 0;
|
|
|
|
err_string("illegal small_stmt child type");
|
|
|
|
}
|
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
else if (nch == 1) {
|
2000-09-12 18:58:06 -03:00
|
|
|
res = 0;
|
|
|
|
PyErr_Format(parser_error,
|
|
|
|
"Unrecognized child node of small_stmt: %d.",
|
|
|
|
TYPE(CHILD(tree, 0)));
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
|
|
|
|
/* compound_stmt:
|
2000-04-19 10:54:15 -03:00
|
|
|
* if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_compound_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int res = (validate_ntype(tree, compound_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_numnodes(tree, 1, "compound_stmt"));
|
2000-09-12 18:58:06 -03:00
|
|
|
int ntype;
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
if (!res)
|
2000-04-19 10:54:15 -03:00
|
|
|
return (0);
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
tree = CHILD(tree, 0);
|
2000-09-12 18:58:06 -03:00
|
|
|
ntype = TYPE(tree);
|
|
|
|
if ( (ntype == if_stmt)
|
|
|
|
|| (ntype == while_stmt)
|
|
|
|
|| (ntype == for_stmt)
|
|
|
|
|| (ntype == try_stmt)
|
|
|
|
|| (ntype == funcdef)
|
|
|
|
|| (ntype == classdef))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_node(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
else {
|
2000-09-12 18:58:06 -03:00
|
|
|
res = 0;
|
|
|
|
PyErr_Format(parser_error,
|
|
|
|
"Illegal compound statement type: %d.", TYPE(tree));
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
|
2005-08-01 21:46:46 -03:00
|
|
|
static int
|
|
|
|
validate_yield_or_testlist(node *tree)
|
|
|
|
{
|
|
|
|
if (TYPE(tree) == yield_expr)
|
|
|
|
return validate_yield_expr(tree);
|
|
|
|
else
|
|
|
|
return validate_testlist(tree);
|
|
|
|
}
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_expr_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int j;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, expr_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_testlist(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2000-08-25 19:42:40 -03:00
|
|
|
if (res && nch == 3
|
|
|
|
&& TYPE(CHILD(tree, 1)) == augassign) {
|
2005-08-01 21:46:46 -03:00
|
|
|
res = validate_numnodes(CHILD(tree, 1), 1, "augassign")
|
|
|
|
&& validate_yield_or_testlist(CHILD(tree, 2));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2000-08-25 19:42:40 -03:00
|
|
|
if (res) {
|
|
|
|
char *s = STR(CHILD(CHILD(tree, 1), 0));
|
|
|
|
|
|
|
|
res = (strcmp(s, "+=") == 0
|
|
|
|
|| strcmp(s, "-=") == 0
|
|
|
|
|| strcmp(s, "*=") == 0
|
|
|
|
|| strcmp(s, "/=") == 0
|
2003-01-29 10:20:23 -04:00
|
|
|
|| strcmp(s, "//=") == 0
|
2000-08-25 19:42:40 -03:00
|
|
|
|| strcmp(s, "%=") == 0
|
|
|
|
|| strcmp(s, "&=") == 0
|
|
|
|
|| strcmp(s, "|=") == 0
|
|
|
|
|| strcmp(s, "^=") == 0
|
|
|
|
|| strcmp(s, "<<=") == 0
|
|
|
|
|| strcmp(s, ">>=") == 0
|
|
|
|
|| strcmp(s, "**=") == 0);
|
|
|
|
if (!res)
|
|
|
|
err_string("illegal augmmented assignment operator");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (j = 1; res && (j < nch); j += 2)
|
2005-08-01 21:46:46 -03:00
|
|
|
res = validate_equal(CHILD(tree, j))
|
|
|
|
&& validate_yield_or_testlist(CHILD(tree, j + 1));
|
2000-08-25 19:42:40 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* print_stmt:
|
|
|
|
*
|
2000-08-21 19:24:43 -03:00
|
|
|
* 'print' ( [ test (',' test)* [','] ]
|
|
|
|
* | '>>' test [ (',' test)+ [','] ] )
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_print_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, print_stmt)
|
2000-08-21 19:24:43 -03:00
|
|
|
&& (nch > 0)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_name(CHILD(tree, 0), "print"));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
if (res && nch > 1) {
|
|
|
|
int sym = TYPE(CHILD(tree, 1));
|
|
|
|
int i = 1;
|
|
|
|
int allow_trailing_comma = 1;
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
if (sym == test)
|
|
|
|
res = validate_test(CHILD(tree, i++));
|
|
|
|
else {
|
|
|
|
if (nch < 3)
|
|
|
|
res = validate_numnodes(tree, 3, "print_stmt");
|
|
|
|
else {
|
|
|
|
res = (validate_ntype(CHILD(tree, i), RIGHTSHIFT)
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
|
|
|
i += 2;
|
|
|
|
allow_trailing_comma = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (res) {
|
|
|
|
/* ... (',' test)* [','] */
|
|
|
|
while (res && i+2 <= nch) {
|
|
|
|
res = (validate_comma(CHILD(tree, i))
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
|
|
|
allow_trailing_comma = 1;
|
|
|
|
i += 2;
|
|
|
|
}
|
|
|
|
if (res && !allow_trailing_comma)
|
|
|
|
res = validate_numnodes(tree, i, "print_stmt");
|
|
|
|
else if (res && i < nch)
|
|
|
|
res = validate_comma(CHILD(tree, i));
|
|
|
|
}
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_del_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
return (validate_numnodes(tree, 2, "del_stmt")
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_name(CHILD(tree, 0), "del")
|
|
|
|
&& validate_exprlist(CHILD(tree, 1)));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_return_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, return_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 1) || (nch == 2))
|
|
|
|
&& validate_name(CHILD(tree, 0), "return"));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 2))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_testlist(CHILD(tree, 1));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_raise_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, raise_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 1) || (nch == 2) || (nch == 4) || (nch == 6)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_name(CHILD(tree, 0), "raise");
|
|
|
|
if (res && (nch >= 2))
|
|
|
|
res = validate_test(CHILD(tree, 1));
|
|
|
|
if (res && nch > 2) {
|
|
|
|
res = (validate_comma(CHILD(tree, 2))
|
|
|
|
&& validate_test(CHILD(tree, 3)));
|
|
|
|
if (res && (nch > 4))
|
|
|
|
res = (validate_comma(CHILD(tree, 4))
|
|
|
|
&& validate_test(CHILD(tree, 5)));
|
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
else
|
2000-04-19 10:54:15 -03:00
|
|
|
(void) validate_numnodes(tree, 2, "raise");
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 4))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_comma(CHILD(tree, 2))
|
|
|
|
&& validate_test(CHILD(tree, 3)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2005-08-01 21:46:46 -03:00
|
|
|
/* yield_expr: 'yield' [testlist]
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_yield_expr(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (validate_ntype(tree, yield_expr)
|
|
|
|
&& ((nch == 1) || (nch == 2))
|
|
|
|
&& validate_name(CHILD(tree, 0), "yield"));
|
|
|
|
|
|
|
|
if (res && (nch == 2))
|
|
|
|
res = validate_testlist(CHILD(tree, 1));
|
|
|
|
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* yield_stmt: yield_expr
|
2001-07-16 23:59:15 -03:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_yield_stmt(node *tree)
|
|
|
|
{
|
|
|
|
return (validate_ntype(tree, yield_stmt)
|
2005-08-01 21:46:46 -03:00
|
|
|
&& validate_numnodes(tree, 1, "yield_stmt")
|
|
|
|
&& validate_yield_expr(CHILD(tree, 0)));
|
2001-07-16 23:59:15 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
static int
|
|
|
|
validate_import_as_name(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int ok = validate_ntype(tree, import_as_name);
|
|
|
|
|
|
|
|
if (ok) {
|
|
|
|
if (nch == 1)
|
|
|
|
ok = validate_name(CHILD(tree, 0), NULL);
|
|
|
|
else if (nch == 3)
|
|
|
|
ok = (validate_name(CHILD(tree, 0), NULL)
|
|
|
|
&& validate_name(CHILD(tree, 1), "as")
|
|
|
|
&& validate_name(CHILD(tree, 2), NULL));
|
|
|
|
else
|
|
|
|
ok = validate_numnodes(tree, 3, "import_as_name");
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-01-07 01:59:59 -04:00
|
|
|
/* dotted_name: NAME ("." NAME)*
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_dotted_name(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (validate_ntype(tree, dotted_name)
|
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_name(CHILD(tree, 0), NULL));
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; res && (i < nch); i += 2) {
|
|
|
|
res = (validate_dot(CHILD(tree, i))
|
|
|
|
&& validate_name(CHILD(tree, i+1), NULL));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
/* dotted_as_name: dotted_name [NAME NAME]
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_dotted_as_name(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = validate_ntype(tree, dotted_as_name);
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
if (nch == 1)
|
2001-01-07 01:59:59 -04:00
|
|
|
res = validate_dotted_name(CHILD(tree, 0));
|
2000-08-21 19:24:43 -03:00
|
|
|
else if (nch == 3)
|
2001-01-07 01:59:59 -04:00
|
|
|
res = (validate_dotted_name(CHILD(tree, 0))
|
2000-08-21 19:24:43 -03:00
|
|
|
&& validate_name(CHILD(tree, 1), "as")
|
|
|
|
&& validate_name(CHILD(tree, 2), NULL));
|
|
|
|
else {
|
|
|
|
res = 0;
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal number of children for dotted_as_name");
|
2000-08-21 19:24:43 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-31 07:07:13 -03:00
|
|
|
/* dotted_as_name (',' dotted_as_name)* */
|
|
|
|
static int
|
|
|
|
validate_dotted_as_names(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = is_odd(nch) && validate_dotted_as_name(CHILD(tree, 0));
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; res && (i < nch); i += 2)
|
|
|
|
res = (validate_comma(CHILD(tree, i))
|
|
|
|
&& validate_dotted_as_name(CHILD(tree, i + 1)));
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* import_as_name (',' import_as_name)* [','] */
|
|
|
|
static int
|
|
|
|
validate_import_as_names(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = validate_import_as_name(CHILD(tree, 0));
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; res && (i + 1 < nch); i += 2)
|
|
|
|
res = (validate_comma(CHILD(tree, i))
|
|
|
|
&& validate_import_as_name(CHILD(tree, i + 1)));
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 'import' dotted_as_names */
|
|
|
|
static int
|
|
|
|
validate_import_name(node *tree)
|
|
|
|
{
|
|
|
|
return (validate_ntype(tree, import_name)
|
|
|
|
&& validate_numnodes(tree, 2, "import_name")
|
|
|
|
&& validate_name(CHILD(tree, 0), "import")
|
|
|
|
&& validate_dotted_as_names(CHILD(tree, 1)));
|
|
|
|
}
|
|
|
|
|
2006-02-28 12:09:29 -04:00
|
|
|
/* Helper function to count the number of leading dots in
|
|
|
|
* 'from ...module import name'
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
count_from_dots(node *tree)
|
|
|
|
{
|
|
|
|
int i;
|
2008-11-03 11:19:35 -04:00
|
|
|
for (i = 1; i < NCH(tree); i++)
|
2006-02-28 12:09:29 -04:00
|
|
|
if (TYPE(CHILD(tree, i)) != DOT)
|
|
|
|
break;
|
2008-11-03 11:19:35 -04:00
|
|
|
return i-1;
|
2006-02-28 12:09:29 -04:00
|
|
|
}
|
2004-08-31 07:07:13 -03:00
|
|
|
|
2006-02-28 12:09:29 -04:00
|
|
|
/* 'from' ('.'* dotted_name | '.') 'import' ('*' | '(' import_as_names ')' |
|
2004-08-31 07:07:13 -03:00
|
|
|
* import_as_names
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2004-08-31 07:07:13 -03:00
|
|
|
validate_import_from(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
2006-02-28 12:09:29 -04:00
|
|
|
int ndots = count_from_dots(tree);
|
|
|
|
int havename = (TYPE(CHILD(tree, ndots + 1)) == dotted_name);
|
|
|
|
int offset = ndots + havename;
|
2004-08-31 07:07:13 -03:00
|
|
|
int res = validate_ntype(tree, import_from)
|
2006-02-28 12:09:29 -04:00
|
|
|
&& (nch >= 4 + ndots)
|
|
|
|
&& validate_name(CHILD(tree, 0), "from")
|
|
|
|
&& (!havename || validate_dotted_name(CHILD(tree, ndots + 1)))
|
|
|
|
&& validate_name(CHILD(tree, offset + 1), "import");
|
|
|
|
|
|
|
|
if (res && TYPE(CHILD(tree, offset + 2)) == LPAR)
|
|
|
|
res = ((nch == offset + 5)
|
|
|
|
&& validate_lparen(CHILD(tree, offset + 2))
|
|
|
|
&& validate_import_as_names(CHILD(tree, offset + 3))
|
|
|
|
&& validate_rparen(CHILD(tree, offset + 4)));
|
|
|
|
else if (res && TYPE(CHILD(tree, offset + 2)) != STAR)
|
|
|
|
res = validate_import_as_names(CHILD(tree, offset + 2));
|
2004-08-31 07:07:13 -03:00
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* import_stmt: import_name | import_from */
|
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_import_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
2004-08-31 07:07:13 -03:00
|
|
|
int res = validate_numnodes(tree, 1, "import_stmt");
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
int ntype = TYPE(CHILD(tree, 0));
|
|
|
|
|
|
|
|
if (ntype == import_name || ntype == import_from)
|
|
|
|
res = validate_node(CHILD(tree, 0));
|
2000-04-19 10:54:15 -03:00
|
|
|
else {
|
2004-08-31 07:07:13 -03:00
|
|
|
res = 0;
|
|
|
|
err_string("illegal import_stmt child type");
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
2004-08-31 07:07:13 -03:00
|
|
|
else if (nch == 1) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = 0;
|
2004-08-31 07:07:13 -03:00
|
|
|
PyErr_Format(parser_error,
|
|
|
|
"Unrecognized child node of import_stmt: %d.",
|
|
|
|
TYPE(CHILD(tree, 0)));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2004-08-31 07:07:13 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_global_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int j;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, global_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_even(nch) && (nch >= 2));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2003-02-08 14:05:10 -04:00
|
|
|
if (!res && !PyErr_Occurred())
|
|
|
|
err_string("illegal global statement");
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, 0), "global")
|
|
|
|
&& validate_ntype(CHILD(tree, 1), NAME));
|
1996-07-20 23:33:56 -03:00
|
|
|
for (j = 2; res && (j < nch); j += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_comma(CHILD(tree, j))
|
|
|
|
&& validate_ntype(CHILD(tree, j + 1), NAME));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* exec_stmt:
|
|
|
|
*
|
|
|
|
* 'exec' expr ['in' test [',' test]]
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_exec_stmt(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, exec_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 2) || (nch == 4) || (nch == 6))
|
|
|
|
&& validate_name(CHILD(tree, 0), "exec")
|
|
|
|
&& validate_expr(CHILD(tree, 1)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (!res && !PyErr_Occurred())
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal exec statement");
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch > 2))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, 2), "in")
|
|
|
|
&& validate_test(CHILD(tree, 3)));
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 6))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_comma(CHILD(tree, 4))
|
|
|
|
&& validate_test(CHILD(tree, 5)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1997-04-02 01:32:13 -04:00
|
|
|
/* assert_stmt:
|
|
|
|
*
|
|
|
|
* 'assert' test [',' test]
|
|
|
|
*/
|
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_assert_stmt(node *tree)
|
1997-04-02 01:32:13 -04:00
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (validate_ntype(tree, assert_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 2) || (nch == 4))
|
2003-02-08 14:05:10 -04:00
|
|
|
&& (validate_name(CHILD(tree, 0), "assert"))
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_test(CHILD(tree, 1)));
|
1997-04-02 01:32:13 -04:00
|
|
|
|
|
|
|
if (!res && !PyErr_Occurred())
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal assert statement");
|
1997-04-02 01:32:13 -04:00
|
|
|
if (res && (nch > 2))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_comma(CHILD(tree, 2))
|
|
|
|
&& validate_test(CHILD(tree, 3)));
|
1997-04-02 01:32:13 -04:00
|
|
|
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1997-04-02 01:32:13 -04:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_while(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, while_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 4) || (nch == 7))
|
|
|
|
&& validate_name(CHILD(tree, 0), "while")
|
|
|
|
&& validate_test(CHILD(tree, 1))
|
|
|
|
&& validate_colon(CHILD(tree, 2))
|
|
|
|
&& validate_suite(CHILD(tree, 3)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 7))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, 4), "else")
|
|
|
|
&& validate_colon(CHILD(tree, 5))
|
|
|
|
&& validate_suite(CHILD(tree, 6)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_for(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, for_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 6) || (nch == 9))
|
|
|
|
&& validate_name(CHILD(tree, 0), "for")
|
|
|
|
&& validate_exprlist(CHILD(tree, 1))
|
|
|
|
&& validate_name(CHILD(tree, 2), "in")
|
|
|
|
&& validate_testlist(CHILD(tree, 3))
|
|
|
|
&& validate_colon(CHILD(tree, 4))
|
|
|
|
&& validate_suite(CHILD(tree, 5)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 9))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, 6), "else")
|
|
|
|
&& validate_colon(CHILD(tree, 7))
|
|
|
|
&& validate_suite(CHILD(tree, 8)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* try_stmt:
|
2000-04-19 10:54:15 -03:00
|
|
|
* 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
|
1996-07-20 23:33:56 -03:00
|
|
|
* | 'try' ':' suite 'finally' ':' suite
|
|
|
|
*
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-07-10 09:43:58 -03:00
|
|
|
validate_try(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int pos = 3;
|
|
|
|
int res = (validate_ntype(tree, try_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (nch >= 6) && ((nch % 3) == 0));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
if (res)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, 0), "try")
|
|
|
|
&& validate_colon(CHILD(tree, 1))
|
|
|
|
&& validate_suite(CHILD(tree, 2))
|
|
|
|
&& validate_colon(CHILD(tree, nch - 2))
|
|
|
|
&& validate_suite(CHILD(tree, nch - 1)));
|
2000-09-12 18:58:06 -03:00
|
|
|
else if (!PyErr_Occurred()) {
|
2000-07-03 15:07:43 -03:00
|
|
|
const char* name = "except";
|
2000-04-19 10:54:15 -03:00
|
|
|
if (TYPE(CHILD(tree, nch - 3)) != except_clause)
|
|
|
|
name = STR(CHILD(tree, nch - 3));
|
2000-09-12 18:58:06 -03:00
|
|
|
|
|
|
|
PyErr_Format(parser_error,
|
|
|
|
"Illegal number of children for try/%s node.", name);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
/* Skip past except_clause sections: */
|
1996-07-20 23:33:56 -03:00
|
|
|
while (res && (TYPE(CHILD(tree, pos)) == except_clause)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_except_clause(CHILD(tree, pos))
|
|
|
|
&& validate_colon(CHILD(tree, pos + 1))
|
|
|
|
&& validate_suite(CHILD(tree, pos + 2)));
|
|
|
|
pos += 3;
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
if (res && (pos < nch)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_ntype(CHILD(tree, pos), NAME);
|
|
|
|
if (res && (strcmp(STR(CHILD(tree, pos)), "finally") == 0))
|
|
|
|
res = (validate_numnodes(tree, 6, "try/finally")
|
|
|
|
&& validate_colon(CHILD(tree, 4))
|
|
|
|
&& validate_suite(CHILD(tree, 5)));
|
|
|
|
else if (res) {
|
|
|
|
if (nch == (pos + 3)) {
|
|
|
|
res = ((strcmp(STR(CHILD(tree, pos)), "except") == 0)
|
|
|
|
|| (strcmp(STR(CHILD(tree, pos)), "else") == 0));
|
|
|
|
if (!res)
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal trailing triple in try statement");
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
else if (nch == (pos + 6)) {
|
|
|
|
res = (validate_name(CHILD(tree, pos), "except")
|
|
|
|
&& validate_colon(CHILD(tree, pos + 1))
|
|
|
|
&& validate_suite(CHILD(tree, pos + 2))
|
|
|
|
&& validate_name(CHILD(tree, pos + 3), "else"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
res = validate_numnodes(tree, pos + 3, "try/except");
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_except_clause(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, except_clause)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 1) || (nch == 2) || (nch == 4))
|
|
|
|
&& validate_name(CHILD(tree, 0), "except"));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch > 1))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_test(CHILD(tree, 1));
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (nch == 4))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_comma(CHILD(tree, 2))
|
|
|
|
&& validate_test(CHILD(tree, 3)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_test(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = validate_ntype(tree, test) && is_odd(nch);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (TYPE(CHILD(tree, 0)) == lambdef))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = ((nch == 1)
|
|
|
|
&& validate_lambdef(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
else if (res) {
|
2006-02-27 12:25:11 -04:00
|
|
|
res = validate_or_test(CHILD(tree, 0));
|
|
|
|
res = (res && (nch == 1 || (nch == 5 &&
|
|
|
|
validate_name(CHILD(tree, 1), "if") &&
|
|
|
|
validate_or_test(CHILD(tree, 2)) &&
|
|
|
|
validate_name(CHILD(tree, 3), "else") &&
|
|
|
|
validate_test(CHILD(tree, 4)))));
|
|
|
|
}
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
validate_old_test(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = validate_ntype(tree, old_test) && (nch == 1);
|
|
|
|
|
|
|
|
if (res && (TYPE(CHILD(tree, 0)) == old_lambdef))
|
|
|
|
res = (validate_old_lambdef(CHILD(tree, 0)));
|
|
|
|
else if (res) {
|
|
|
|
res = (validate_or_test(CHILD(tree, 0)));
|
|
|
|
}
|
|
|
|
return (res);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
validate_or_test(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = validate_ntype(tree, or_test) && is_odd(nch);
|
|
|
|
|
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int pos;
|
|
|
|
res = validate_and_test(CHILD(tree, 0));
|
|
|
|
for (pos = 1; res && (pos < nch); pos += 2)
|
|
|
|
res = (validate_name(CHILD(tree, pos), "or")
|
|
|
|
&& validate_and_test(CHILD(tree, pos + 1)));
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_and_test(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int pos;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, and_test)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_not_test(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for (pos = 1; res && (pos < nch); pos += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_name(CHILD(tree, pos), "and")
|
|
|
|
&& validate_not_test(CHILD(tree, 0)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_not_test(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = validate_ntype(tree, not_test) && ((nch == 1) || (nch == 2));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (nch == 2)
|
|
|
|
res = (validate_name(CHILD(tree, 0), "not")
|
|
|
|
&& validate_not_test(CHILD(tree, 1)));
|
|
|
|
else if (nch == 1)
|
|
|
|
res = validate_comparison(CHILD(tree, 0));
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_comparison(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int pos;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, comparison)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_expr(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for (pos = 1; res && (pos < nch); pos += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_comp_op(CHILD(tree, pos))
|
|
|
|
&& validate_expr(CHILD(tree, pos + 1)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_comp_op(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int res = 0;
|
|
|
|
int nch = NCH(tree);
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (!validate_ntype(tree, comp_op))
|
2000-04-19 10:54:15 -03:00
|
|
|
return (0);
|
1995-10-11 14:35:38 -03:00
|
|
|
if (nch == 1) {
|
2000-04-19 10:54:15 -03:00
|
|
|
/*
|
|
|
|
* Only child will be a terminal with a well-defined symbolic name
|
|
|
|
* or a NAME with a string of either 'is' or 'in'
|
|
|
|
*/
|
|
|
|
tree = CHILD(tree, 0);
|
|
|
|
switch (TYPE(tree)) {
|
|
|
|
case LESS:
|
|
|
|
case GREATER:
|
|
|
|
case EQEQUAL:
|
|
|
|
case EQUAL:
|
|
|
|
case LESSEQUAL:
|
|
|
|
case GREATEREQUAL:
|
|
|
|
case NOTEQUAL:
|
|
|
|
res = 1;
|
|
|
|
break;
|
|
|
|
case NAME:
|
|
|
|
res = ((strcmp(STR(tree), "in") == 0)
|
|
|
|
|| (strcmp(STR(tree), "is") == 0));
|
|
|
|
if (!res) {
|
2000-09-12 18:58:06 -03:00
|
|
|
PyErr_Format(parser_error,
|
2000-10-24 16:57:45 -03:00
|
|
|
"illegal operator '%s'", STR(tree));
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal comparison operator type");
|
2000-04-19 10:54:15 -03:00
|
|
|
break;
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
1996-12-05 19:43:35 -04:00
|
|
|
else if ((res = validate_numnodes(tree, 2, "comp_op")) != 0) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_ntype(CHILD(tree, 0), NAME)
|
|
|
|
&& validate_ntype(CHILD(tree, 1), NAME)
|
|
|
|
&& (((strcmp(STR(CHILD(tree, 0)), "is") == 0)
|
|
|
|
&& (strcmp(STR(CHILD(tree, 1)), "not") == 0))
|
|
|
|
|| ((strcmp(STR(CHILD(tree, 0)), "not") == 0)
|
|
|
|
&& (strcmp(STR(CHILD(tree, 1)), "in") == 0))));
|
|
|
|
if (!res && !PyErr_Occurred())
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("unknown comparison operator");
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_expr(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int j;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, expr)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_xor_expr(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for (j = 2; res && (j < nch); j += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_xor_expr(CHILD(tree, j))
|
|
|
|
&& validate_vbar(CHILD(tree, j - 1)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_xor_expr(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int j;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, xor_expr)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_and_expr(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for (j = 2; res && (j < nch); j += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_circumflex(CHILD(tree, j - 1))
|
|
|
|
&& validate_and_expr(CHILD(tree, j)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_and_expr(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int pos;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, and_expr)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_shift_expr(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for (pos = 1; res && (pos < nch); pos += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_ampersand(CHILD(tree, pos))
|
|
|
|
&& validate_shift_expr(CHILD(tree, pos + 1)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
2000-07-10 09:43:58 -03:00
|
|
|
validate_chain_two_ops(node *tree, int (*termvalid)(node *), int op1, int op2)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int pos = 1;
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (is_odd(nch)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (*termvalid)(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for ( ; res && (pos < nch); pos += 2) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (TYPE(CHILD(tree, pos)) != op1)
|
|
|
|
res = validate_ntype(CHILD(tree, pos), op2);
|
|
|
|
if (res)
|
|
|
|
res = (*termvalid)(CHILD(tree, pos + 1));
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_shift_expr(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
return (validate_ntype(tree, shift_expr)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_chain_two_ops(tree, validate_arith_expr,
|
|
|
|
LEFTSHIFT, RIGHTSHIFT));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_arith_expr(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
return (validate_ntype(tree, arith_expr)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_chain_two_ops(tree, validate_term, PLUS, MINUS));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_term(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int pos = 1;
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, term)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& is_odd(nch)
|
|
|
|
&& validate_factor(CHILD(tree, 0)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for ( ; res && (pos < nch); pos += 2)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (((TYPE(CHILD(tree, pos)) == STAR)
|
|
|
|
|| (TYPE(CHILD(tree, pos)) == SLASH)
|
2003-01-29 10:20:23 -04:00
|
|
|
|| (TYPE(CHILD(tree, pos)) == DOUBLESLASH)
|
2000-04-19 10:54:15 -03:00
|
|
|
|| (TYPE(CHILD(tree, pos)) == PERCENT))
|
|
|
|
&& validate_factor(CHILD(tree, pos + 1)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* factor:
|
|
|
|
*
|
|
|
|
* factor: ('+'|'-'|'~') factor | power
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_factor(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, factor)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (((nch == 2)
|
|
|
|
&& ((TYPE(CHILD(tree, 0)) == PLUS)
|
|
|
|
|| (TYPE(CHILD(tree, 0)) == MINUS)
|
|
|
|
|| (TYPE(CHILD(tree, 0)) == TILDE))
|
|
|
|
&& validate_factor(CHILD(tree, 1)))
|
|
|
|
|| ((nch == 1)
|
|
|
|
&& validate_power(CHILD(tree, 0)))));
|
1996-07-20 23:33:56 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
/* power:
|
|
|
|
*
|
|
|
|
* power: atom trailer* ('**' factor)*
|
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_power(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int pos = 1;
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (validate_ntype(tree, power) && (nch >= 1)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_atom(CHILD(tree, 0)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_trailer(CHILD(tree, pos++));
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && (pos < nch)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (!is_even(nch - pos)) {
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal number of nodes for 'power'");
|
2000-04-19 10:54:15 -03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
for ( ; res && (pos < (nch - 1)); pos += 2)
|
|
|
|
res = (validate_doublestar(CHILD(tree, pos))
|
|
|
|
&& validate_factor(CHILD(tree, pos + 1)));
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_atom(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int pos;
|
|
|
|
int nch = NCH(tree);
|
2000-08-21 19:24:43 -03:00
|
|
|
int res = validate_ntype(tree, atom);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
if (res && nch < 1)
|
|
|
|
res = validate_numnodes(tree, nch+1, "atom");
|
1995-10-11 14:35:38 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
switch (TYPE(CHILD(tree, 0))) {
|
|
|
|
case LPAR:
|
|
|
|
res = ((nch <= 3)
|
|
|
|
&& (validate_rparen(CHILD(tree, nch - 1))));
|
|
|
|
|
2005-08-01 21:46:46 -03:00
|
|
|
if (res && (nch == 3)) {
|
|
|
|
if (TYPE(CHILD(tree, 1))==yield_expr)
|
|
|
|
res = validate_yield_expr(CHILD(tree, 1));
|
|
|
|
else
|
|
|
|
res = validate_testlist_gexp(CHILD(tree, 1));
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
break;
|
|
|
|
case LSQB:
|
2000-08-21 19:24:43 -03:00
|
|
|
if (nch == 2)
|
|
|
|
res = validate_ntype(CHILD(tree, 1), RSQB);
|
|
|
|
else if (nch == 3)
|
|
|
|
res = (validate_listmaker(CHILD(tree, 1))
|
|
|
|
&& validate_ntype(CHILD(tree, 2), RSQB));
|
|
|
|
else {
|
|
|
|
res = 0;
|
|
|
|
err_string("illegal list display atom");
|
|
|
|
}
|
2000-04-19 10:54:15 -03:00
|
|
|
break;
|
|
|
|
case LBRACE:
|
|
|
|
res = ((nch <= 3)
|
|
|
|
&& validate_ntype(CHILD(tree, nch - 1), RBRACE));
|
|
|
|
|
|
|
|
if (res && (nch == 3))
|
|
|
|
res = validate_dictmaker(CHILD(tree, 1));
|
|
|
|
break;
|
|
|
|
case BACKQUOTE:
|
|
|
|
res = ((nch == 3)
|
2002-05-24 12:47:06 -03:00
|
|
|
&& validate_testlist1(CHILD(tree, 1))
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_ntype(CHILD(tree, 2), BACKQUOTE));
|
|
|
|
break;
|
|
|
|
case NAME:
|
|
|
|
case NUMBER:
|
|
|
|
res = (nch == 1);
|
|
|
|
break;
|
|
|
|
case STRING:
|
|
|
|
for (pos = 1; res && (pos < nch); ++pos)
|
|
|
|
res = validate_ntype(CHILD(tree, pos), STRING);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
2000-08-23 12:35:26 -03:00
|
|
|
/* listmaker:
|
|
|
|
* test ( list_for | (',' test)* [','] )
|
|
|
|
*/
|
2000-08-21 19:24:43 -03:00
|
|
|
static int
|
|
|
|
validate_listmaker(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int ok = nch;
|
|
|
|
|
|
|
|
if (nch == 0)
|
|
|
|
err_string("missing child nodes of listmaker");
|
|
|
|
else
|
|
|
|
ok = validate_test(CHILD(tree, 0));
|
|
|
|
|
|
|
|
/*
|
2004-05-19 05:20:33 -03:00
|
|
|
* list_for | (',' test)* [',']
|
2000-08-21 19:24:43 -03:00
|
|
|
*/
|
2000-08-23 12:35:26 -03:00
|
|
|
if (nch == 2 && TYPE(CHILD(tree, 1)) == list_for)
|
|
|
|
ok = validate_list_for(CHILD(tree, 1));
|
2000-08-21 19:24:43 -03:00
|
|
|
else {
|
|
|
|
/* (',' test)* [','] */
|
|
|
|
int i = 1;
|
|
|
|
while (ok && nch - i >= 2) {
|
|
|
|
ok = (validate_comma(CHILD(tree, i))
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
2000-08-23 12:35:26 -03:00
|
|
|
i += 2;
|
|
|
|
}
|
|
|
|
if (ok && i == nch-1)
|
|
|
|
ok = validate_comma(CHILD(tree, i));
|
|
|
|
else if (i != nch) {
|
|
|
|
ok = 0;
|
|
|
|
err_string("illegal trailing nodes for listmaker");
|
2000-08-21 19:24:43 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
2004-05-19 05:20:33 -03:00
|
|
|
/* testlist_gexp:
|
|
|
|
* test ( gen_for | (',' test)* [','] )
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_testlist_gexp(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int ok = nch;
|
|
|
|
|
|
|
|
if (nch == 0)
|
|
|
|
err_string("missing child nodes of testlist_gexp");
|
|
|
|
else {
|
|
|
|
ok = validate_test(CHILD(tree, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gen_for | (',' test)* [',']
|
|
|
|
*/
|
|
|
|
if (nch == 2 && TYPE(CHILD(tree, 1)) == gen_for)
|
|
|
|
ok = validate_gen_for(CHILD(tree, 1));
|
|
|
|
else {
|
|
|
|
/* (',' test)* [','] */
|
|
|
|
int i = 1;
|
|
|
|
while (ok && nch - i >= 2) {
|
|
|
|
ok = (validate_comma(CHILD(tree, i))
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
|
|
|
i += 2;
|
|
|
|
}
|
|
|
|
if (ok && i == nch-1)
|
|
|
|
ok = validate_comma(CHILD(tree, i));
|
|
|
|
else if (i != nch) {
|
|
|
|
ok = 0;
|
|
|
|
err_string("illegal trailing nodes for testlist_gexp");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
|
2004-08-02 03:10:11 -03:00
|
|
|
/* decorator:
|
2004-08-17 14:29:16 -03:00
|
|
|
* '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
|
2004-08-02 03:10:11 -03:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_decorator(node *tree)
|
|
|
|
{
|
|
|
|
int ok;
|
|
|
|
int nch = NCH(tree);
|
|
|
|
ok = (validate_ntype(tree, decorator) &&
|
2004-08-17 14:29:16 -03:00
|
|
|
(nch == 3 || nch == 5 || nch == 6) &&
|
2004-08-02 03:10:11 -03:00
|
|
|
validate_at(CHILD(tree, 0)) &&
|
2004-08-17 14:29:16 -03:00
|
|
|
validate_dotted_name(CHILD(tree, 1)) &&
|
|
|
|
validate_newline(RCHILD(tree, -1)));
|
2004-08-02 03:10:11 -03:00
|
|
|
|
2004-08-17 14:29:16 -03:00
|
|
|
if (ok && nch != 3) {
|
|
|
|
ok = (validate_lparen(CHILD(tree, 2)) &&
|
|
|
|
validate_rparen(RCHILD(tree, -2)));
|
2004-08-02 03:10:11 -03:00
|
|
|
|
2004-08-17 14:29:16 -03:00
|
|
|
if (ok && nch == 6)
|
|
|
|
ok = validate_arglist(CHILD(tree, 3));
|
2004-08-02 03:10:11 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
2004-08-17 14:29:16 -03:00
|
|
|
|
2004-08-02 03:10:11 -03:00
|
|
|
/* decorators:
|
2004-08-17 14:29:16 -03:00
|
|
|
* decorator+
|
2004-08-02 03:10:11 -03:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
validate_decorators(node *tree)
|
|
|
|
{
|
|
|
|
int i, nch, ok;
|
|
|
|
nch = NCH(tree);
|
2004-08-17 14:29:16 -03:00
|
|
|
ok = validate_ntype(tree, decorators) && nch >= 1;
|
2004-08-02 03:10:11 -03:00
|
|
|
|
2004-08-17 14:29:16 -03:00
|
|
|
for (i = 0; ok && i < nch; ++i)
|
2004-08-02 03:10:11 -03:00
|
|
|
ok = validate_decorator(CHILD(tree, i));
|
|
|
|
|
|
|
|
return ok;
|
2004-08-17 14:29:16 -03:00
|
|
|
}
|
2004-08-02 03:10:11 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* funcdef:
|
2004-08-02 03:10:11 -03:00
|
|
|
*
|
|
|
|
* -6 -5 -4 -3 -2 -1
|
|
|
|
* [decorators] 'def' NAME parameters ':' suite
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_funcdef(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
2004-08-02 03:10:11 -03:00
|
|
|
int nch = NCH(tree);
|
|
|
|
int ok = (validate_ntype(tree, funcdef)
|
|
|
|
&& ((nch == 5) || (nch == 6))
|
|
|
|
&& validate_name(RCHILD(tree, -5), "def")
|
|
|
|
&& validate_ntype(RCHILD(tree, -4), NAME)
|
|
|
|
&& validate_colon(RCHILD(tree, -2))
|
|
|
|
&& validate_parameters(RCHILD(tree, -3))
|
|
|
|
&& validate_suite(RCHILD(tree, -1)));
|
|
|
|
|
|
|
|
if (ok && (nch == 6))
|
|
|
|
ok = validate_decorators(CHILD(tree, 0));
|
|
|
|
|
|
|
|
return ok;
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_lambdef(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, lambdef)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& ((nch == 3) || (nch == 4))
|
|
|
|
&& validate_name(CHILD(tree, 0), "lambda")
|
|
|
|
&& validate_colon(CHILD(tree, nch - 2))
|
|
|
|
&& validate_test(CHILD(tree, nch - 1)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
if (res && (nch == 4))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_varargslist(CHILD(tree, 1));
|
1996-07-20 23:33:56 -03:00
|
|
|
else if (!res && !PyErr_Occurred())
|
2000-04-19 10:54:15 -03:00
|
|
|
(void) validate_numnodes(tree, 3, "lambdef");
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
return (res);
|
2006-02-27 12:25:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
validate_old_lambdef(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (validate_ntype(tree, old_lambdef)
|
|
|
|
&& ((nch == 3) || (nch == 4))
|
|
|
|
&& validate_name(CHILD(tree, 0), "lambda")
|
|
|
|
&& validate_colon(CHILD(tree, nch - 2))
|
|
|
|
&& validate_test(CHILD(tree, nch - 1)));
|
|
|
|
|
|
|
|
if (res && (nch == 4))
|
|
|
|
res = validate_varargslist(CHILD(tree, 1));
|
|
|
|
else if (!res && !PyErr_Occurred())
|
|
|
|
(void) validate_numnodes(tree, 3, "old_lambdef");
|
|
|
|
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* arglist:
|
|
|
|
*
|
2000-08-21 19:24:43 -03:00
|
|
|
* (argument ',')* (argument [','] | '*' test [',' '**' test] | '**' test)
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_arglist(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
2000-04-25 01:14:46 -03:00
|
|
|
int nch = NCH(tree);
|
2000-08-21 19:24:43 -03:00
|
|
|
int i = 0;
|
|
|
|
int ok = 1;
|
2000-04-25 01:14:46 -03:00
|
|
|
|
|
|
|
if (nch <= 0)
|
|
|
|
/* raise the right error from having an invalid number of children */
|
|
|
|
return validate_numnodes(tree, nch + 1, "arglist");
|
|
|
|
|
2004-05-19 05:20:33 -03:00
|
|
|
if (nch > 1) {
|
|
|
|
for (i=0; i<nch; i++) {
|
|
|
|
if (TYPE(CHILD(tree, i)) == argument) {
|
|
|
|
node *ch = CHILD(tree, i);
|
|
|
|
if (NCH(ch) == 2 && TYPE(CHILD(ch, 1)) == gen_for) {
|
|
|
|
err_string("need '(', ')' for generator expression");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-08-21 19:24:43 -03:00
|
|
|
while (ok && nch-i >= 2) {
|
|
|
|
/* skip leading (argument ',') */
|
|
|
|
ok = (validate_argument(CHILD(tree, i))
|
|
|
|
&& validate_comma(CHILD(tree, i+1)));
|
|
|
|
if (ok)
|
|
|
|
i += 2;
|
|
|
|
else
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
ok = 1;
|
|
|
|
if (nch-i > 0) {
|
|
|
|
/*
|
|
|
|
* argument | '*' test [',' '**' test] | '**' test
|
2000-04-25 01:14:46 -03:00
|
|
|
*/
|
2000-08-21 19:24:43 -03:00
|
|
|
int sym = TYPE(CHILD(tree, i));
|
|
|
|
|
|
|
|
if (sym == argument) {
|
|
|
|
ok = validate_argument(CHILD(tree, i));
|
|
|
|
if (ok && i+1 != nch) {
|
|
|
|
err_string("illegal arglist specification"
|
|
|
|
" (extra stuff on end)");
|
|
|
|
ok = 0;
|
2000-04-25 01:14:46 -03:00
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
}
|
|
|
|
else if (sym == STAR) {
|
|
|
|
ok = validate_star(CHILD(tree, i));
|
|
|
|
if (ok && (nch-i == 2))
|
|
|
|
ok = validate_test(CHILD(tree, i+1));
|
|
|
|
else if (ok && (nch-i == 5))
|
|
|
|
ok = (validate_test(CHILD(tree, i+1))
|
|
|
|
&& validate_comma(CHILD(tree, i+2))
|
|
|
|
&& validate_doublestar(CHILD(tree, i+3))
|
|
|
|
&& validate_test(CHILD(tree, i+4)));
|
2000-04-25 01:14:46 -03:00
|
|
|
else {
|
2000-08-21 19:24:43 -03:00
|
|
|
err_string("illegal use of '*' in arglist");
|
|
|
|
ok = 0;
|
2000-04-25 01:14:46 -03:00
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
}
|
|
|
|
else if (sym == DOUBLESTAR) {
|
|
|
|
if (nch-i == 2)
|
|
|
|
ok = (validate_doublestar(CHILD(tree, i))
|
|
|
|
&& validate_test(CHILD(tree, i+1)));
|
|
|
|
else {
|
|
|
|
err_string("illegal use of '**' in arglist");
|
|
|
|
ok = 0;
|
2000-04-25 01:14:46 -03:00
|
|
|
}
|
|
|
|
}
|
2000-08-21 19:24:43 -03:00
|
|
|
else {
|
|
|
|
err_string("illegal arglist specification");
|
|
|
|
ok = 0;
|
|
|
|
}
|
2000-04-25 01:14:46 -03:00
|
|
|
}
|
|
|
|
return (ok);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* argument:
|
|
|
|
*
|
2004-05-19 05:20:33 -03:00
|
|
|
* [test '='] test [gen_for]
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_argument(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = (validate_ntype(tree, argument)
|
2004-05-19 05:20:33 -03:00
|
|
|
&& ((nch == 1) || (nch == 2) || (nch == 3))
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_test(CHILD(tree, 0)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2004-05-19 05:20:33 -03:00
|
|
|
if (res && (nch == 2))
|
|
|
|
res = validate_gen_for(CHILD(tree, 1));
|
|
|
|
else if (res && (nch == 3))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = (validate_equal(CHILD(tree, 1))
|
|
|
|
&& validate_test(CHILD(tree, 2)));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* trailer:
|
|
|
|
*
|
1996-08-21 11:32:37 -03:00
|
|
|
* '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_trailer(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = validate_ntype(tree, trailer) && ((nch == 2) || (nch == 3));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
switch (TYPE(CHILD(tree, 0))) {
|
|
|
|
case LPAR:
|
|
|
|
res = validate_rparen(CHILD(tree, nch - 1));
|
|
|
|
if (res && (nch == 3))
|
|
|
|
res = validate_arglist(CHILD(tree, 1));
|
|
|
|
break;
|
|
|
|
case LSQB:
|
|
|
|
res = (validate_numnodes(tree, 3, "trailer")
|
|
|
|
&& validate_subscriptlist(CHILD(tree, 1))
|
|
|
|
&& validate_ntype(CHILD(tree, 2), RSQB));
|
|
|
|
break;
|
|
|
|
case DOT:
|
|
|
|
res = (validate_numnodes(tree, 2, "trailer")
|
|
|
|
&& validate_ntype(CHILD(tree, 1), NAME));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
(void) validate_numnodes(tree, 2, "trailer");
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
/* subscriptlist:
|
|
|
|
*
|
|
|
|
* subscript (',' subscript)* [',']
|
|
|
|
*/
|
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_subscriptlist(node *tree)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
|
|
|
return (validate_repeating_list(tree, subscriptlist,
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_subscript, "subscriptlist"));
|
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* subscript:
|
|
|
|
*
|
1996-08-21 11:32:37 -03:00
|
|
|
* '.' '.' '.' | test | [test] ':' [test] [sliceop]
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_subscript(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1996-08-21 11:32:37 -03:00
|
|
|
int offset = 0;
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-08-21 11:32:37 -03:00
|
|
|
int res = validate_ntype(tree, subscript) && (nch >= 1) && (nch <= 4);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
if (!res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (!PyErr_Occurred())
|
|
|
|
err_string("invalid number of arguments for subscript node");
|
|
|
|
return (0);
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
if (TYPE(CHILD(tree, 0)) == DOT)
|
2000-04-19 10:54:15 -03:00
|
|
|
/* 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)));
|
1996-08-21 11:32:37 -03:00
|
|
|
if (nch == 1) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (TYPE(CHILD(tree, 0)) == test)
|
|
|
|
res = validate_test(CHILD(tree, 0));
|
|
|
|
else
|
|
|
|
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.
|
1996-08-21 11:32:37 -03:00
|
|
|
*/
|
|
|
|
if ((TYPE(CHILD(tree, 0)) != COLON) || (nch == 4)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_test(CHILD(tree, 0));
|
|
|
|
offset = 1;
|
1996-08-21 11:32:37 -03:00
|
|
|
}
|
|
|
|
if (res)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_colon(CHILD(tree, offset));
|
1996-08-21 11:32:37 -03:00
|
|
|
if (res) {
|
2000-04-19 10:54:15 -03:00
|
|
|
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));
|
|
|
|
}
|
1996-07-20 23:33:56 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_sliceop(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-08-21 11:32:37 -03:00
|
|
|
int res = ((nch == 1) || validate_numnodes(tree, 2, "sliceop"))
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_ntype(tree, sliceop);
|
1996-08-21 11:32:37 -03:00
|
|
|
if (!res && !PyErr_Occurred()) {
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_numnodes(tree, 1, "sliceop");
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
if (res)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_colon(CHILD(tree, 0));
|
1996-08-21 11:32:37 -03:00
|
|
|
if (res && (nch == 2))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_test(CHILD(tree, 1));
|
1996-08-21 11:32:37 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1996-08-21 11:32:37 -03:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_exprlist(node *tree)
|
1996-08-21 11:32:37 -03:00
|
|
|
{
|
|
|
|
return (validate_repeating_list(tree, exprlist,
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_expr, "exprlist"));
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_dictmaker(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, dictmaker)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (nch >= 3)
|
|
|
|
&& validate_test(CHILD(tree, 0))
|
|
|
|
&& validate_colon(CHILD(tree, 1))
|
|
|
|
&& validate_test(CHILD(tree, 2)));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
if (res && ((nch % 4) == 0))
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_comma(CHILD(tree, --nch));
|
1996-07-20 23:33:56 -03:00
|
|
|
else if (res)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = ((nch % 4) == 3);
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
if (res && (nch > 3)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
int pos = 3;
|
|
|
|
/* ( ',' test ':' test )* */
|
|
|
|
while (res && (pos < nch)) {
|
|
|
|
res = (validate_comma(CHILD(tree, pos))
|
|
|
|
&& validate_test(CHILD(tree, pos + 1))
|
|
|
|
&& validate_colon(CHILD(tree, pos + 2))
|
|
|
|
&& validate_test(CHILD(tree, pos + 3)));
|
|
|
|
pos += 4;
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_eval_input(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
1995-10-11 14:35:38 -03:00
|
|
|
int pos;
|
|
|
|
int nch = NCH(tree);
|
1996-07-20 23:33:56 -03:00
|
|
|
int res = (validate_ntype(tree, eval_input)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& (nch >= 2)
|
|
|
|
&& validate_testlist(CHILD(tree, 0))
|
|
|
|
&& validate_ntype(CHILD(tree, nch - 1), ENDMARKER));
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
for (pos = 1; res && (pos < (nch - 1)); ++pos)
|
2000-04-19 10:54:15 -03:00
|
|
|
res = validate_ntype(CHILD(tree, pos), NEWLINE);
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_node(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
2000-04-19 10:54:15 -03:00
|
|
|
int nch = 0; /* num. children on current node */
|
|
|
|
int res = 1; /* result value */
|
|
|
|
node* next = 0; /* node to process after this one */
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2001-06-23 16:55:38 -03:00
|
|
|
while (res && (tree != 0)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
nch = NCH(tree);
|
|
|
|
next = 0;
|
|
|
|
switch (TYPE(tree)) {
|
|
|
|
/*
|
|
|
|
* Definition nodes.
|
|
|
|
*/
|
|
|
|
case funcdef:
|
|
|
|
res = validate_funcdef(tree);
|
|
|
|
break;
|
|
|
|
case classdef:
|
|
|
|
res = validate_class(tree);
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
* "Trivial" parse tree nodes.
|
|
|
|
* (Why did I call these trivial?)
|
|
|
|
*/
|
|
|
|
case stmt:
|
|
|
|
res = validate_stmt(tree);
|
|
|
|
break;
|
|
|
|
case small_stmt:
|
|
|
|
/*
|
2000-09-12 18:58:06 -03:00
|
|
|
* expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt
|
2000-04-19 10:54:15 -03:00
|
|
|
* | import_stmt | global_stmt | exec_stmt | assert_stmt
|
|
|
|
*/
|
|
|
|
res = validate_small_stmt(tree);
|
|
|
|
break;
|
|
|
|
case flow_stmt:
|
|
|
|
res = (validate_numnodes(tree, 1, "flow_stmt")
|
|
|
|
&& ((TYPE(CHILD(tree, 0)) == break_stmt)
|
|
|
|
|| (TYPE(CHILD(tree, 0)) == continue_stmt)
|
2001-07-16 23:59:15 -03:00
|
|
|
|| (TYPE(CHILD(tree, 0)) == yield_stmt)
|
2000-04-19 10:54:15 -03:00
|
|
|
|| (TYPE(CHILD(tree, 0)) == return_stmt)
|
|
|
|
|| (TYPE(CHILD(tree, 0)) == raise_stmt)));
|
|
|
|
if (res)
|
|
|
|
next = CHILD(tree, 0);
|
|
|
|
else if (nch == 1)
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("illegal flow_stmt type");
|
2000-04-19 10:54:15 -03:00
|
|
|
break;
|
2001-07-16 23:59:15 -03:00
|
|
|
case yield_stmt:
|
|
|
|
res = validate_yield_stmt(tree);
|
|
|
|
break;
|
2000-04-19 10:54:15 -03:00
|
|
|
/*
|
|
|
|
* Compound statements.
|
|
|
|
*/
|
|
|
|
case simple_stmt:
|
|
|
|
res = validate_simple_stmt(tree);
|
|
|
|
break;
|
|
|
|
case compound_stmt:
|
|
|
|
res = validate_compound_stmt(tree);
|
|
|
|
break;
|
|
|
|
/*
|
2000-07-16 09:04:32 -03:00
|
|
|
* Fundamental statements.
|
2000-04-19 10:54:15 -03:00
|
|
|
*/
|
|
|
|
case expr_stmt:
|
|
|
|
res = validate_expr_stmt(tree);
|
|
|
|
break;
|
|
|
|
case print_stmt:
|
|
|
|
res = validate_print_stmt(tree);
|
|
|
|
break;
|
|
|
|
case del_stmt:
|
|
|
|
res = validate_del_stmt(tree);
|
|
|
|
break;
|
|
|
|
case pass_stmt:
|
|
|
|
res = (validate_numnodes(tree, 1, "pass")
|
|
|
|
&& validate_name(CHILD(tree, 0), "pass"));
|
|
|
|
break;
|
|
|
|
case break_stmt:
|
|
|
|
res = (validate_numnodes(tree, 1, "break")
|
|
|
|
&& validate_name(CHILD(tree, 0), "break"));
|
|
|
|
break;
|
|
|
|
case continue_stmt:
|
|
|
|
res = (validate_numnodes(tree, 1, "continue")
|
|
|
|
&& validate_name(CHILD(tree, 0), "continue"));
|
|
|
|
break;
|
|
|
|
case return_stmt:
|
|
|
|
res = validate_return_stmt(tree);
|
|
|
|
break;
|
|
|
|
case raise_stmt:
|
|
|
|
res = validate_raise_stmt(tree);
|
|
|
|
break;
|
|
|
|
case import_stmt:
|
|
|
|
res = validate_import_stmt(tree);
|
|
|
|
break;
|
2004-08-31 07:07:13 -03:00
|
|
|
case import_name:
|
|
|
|
res = validate_import_name(tree);
|
|
|
|
break;
|
|
|
|
case import_from:
|
|
|
|
res = validate_import_from(tree);
|
|
|
|
break;
|
2000-04-19 10:54:15 -03:00
|
|
|
case global_stmt:
|
|
|
|
res = validate_global_stmt(tree);
|
|
|
|
break;
|
|
|
|
case exec_stmt:
|
|
|
|
res = validate_exec_stmt(tree);
|
|
|
|
break;
|
|
|
|
case assert_stmt:
|
|
|
|
res = validate_assert_stmt(tree);
|
|
|
|
break;
|
|
|
|
case if_stmt:
|
|
|
|
res = validate_if(tree);
|
|
|
|
break;
|
|
|
|
case while_stmt:
|
|
|
|
res = validate_while(tree);
|
|
|
|
break;
|
|
|
|
case for_stmt:
|
|
|
|
res = validate_for(tree);
|
|
|
|
break;
|
|
|
|
case try_stmt:
|
|
|
|
res = validate_try(tree);
|
|
|
|
break;
|
|
|
|
case suite:
|
|
|
|
res = validate_suite(tree);
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
* Expression nodes.
|
|
|
|
*/
|
|
|
|
case testlist:
|
|
|
|
res = validate_testlist(tree);
|
|
|
|
break;
|
2005-08-01 21:46:46 -03:00
|
|
|
case yield_expr:
|
|
|
|
res = validate_yield_expr(tree);
|
|
|
|
break;
|
2002-05-24 12:47:06 -03:00
|
|
|
case testlist1:
|
|
|
|
res = validate_testlist1(tree);
|
|
|
|
break;
|
2000-04-19 10:54:15 -03:00
|
|
|
case test:
|
|
|
|
res = validate_test(tree);
|
|
|
|
break;
|
|
|
|
case and_test:
|
|
|
|
res = validate_and_test(tree);
|
|
|
|
break;
|
|
|
|
case not_test:
|
|
|
|
res = validate_not_test(tree);
|
|
|
|
break;
|
|
|
|
case comparison:
|
|
|
|
res = validate_comparison(tree);
|
|
|
|
break;
|
|
|
|
case exprlist:
|
|
|
|
res = validate_exprlist(tree);
|
|
|
|
break;
|
|
|
|
case comp_op:
|
|
|
|
res = validate_comp_op(tree);
|
|
|
|
break;
|
|
|
|
case expr:
|
|
|
|
res = validate_expr(tree);
|
|
|
|
break;
|
|
|
|
case xor_expr:
|
|
|
|
res = validate_xor_expr(tree);
|
|
|
|
break;
|
|
|
|
case and_expr:
|
|
|
|
res = validate_and_expr(tree);
|
|
|
|
break;
|
|
|
|
case shift_expr:
|
|
|
|
res = validate_shift_expr(tree);
|
|
|
|
break;
|
|
|
|
case arith_expr:
|
|
|
|
res = validate_arith_expr(tree);
|
|
|
|
break;
|
|
|
|
case term:
|
|
|
|
res = validate_term(tree);
|
|
|
|
break;
|
|
|
|
case factor:
|
|
|
|
res = validate_factor(tree);
|
|
|
|
break;
|
|
|
|
case power:
|
|
|
|
res = validate_power(tree);
|
|
|
|
break;
|
|
|
|
case atom:
|
|
|
|
res = validate_atom(tree);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Hopefully never reached! */
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("unrecognized node type");
|
2000-04-19 10:54:15 -03:00
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tree = next;
|
1995-10-11 14:35:38 -03:00
|
|
|
}
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_expr_tree(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
|
|
|
int res = validate_eval_input(tree);
|
|
|
|
|
|
|
|
if (!res && !PyErr_Occurred())
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("could not validate expression tuple");
|
1996-07-20 23:33:56 -03:00
|
|
|
|
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
|
|
|
|
1996-07-20 23:33:56 -03:00
|
|
|
/* file_input:
|
2000-04-19 10:54:15 -03:00
|
|
|
* (NEWLINE | stmt)* ENDMARKER
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
1996-08-21 11:32:37 -03:00
|
|
|
static int
|
2000-04-19 10:54:15 -03:00
|
|
|
validate_file_input(node *tree)
|
1996-07-20 23:33:56 -03:00
|
|
|
{
|
2001-07-17 16:32:05 -03:00
|
|
|
int j;
|
1996-07-20 23:33:56 -03:00
|
|
|
int nch = NCH(tree) - 1;
|
|
|
|
int res = ((nch >= 0)
|
2000-04-19 10:54:15 -03:00
|
|
|
&& validate_ntype(CHILD(tree, nch), ENDMARKER));
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
for (j = 0; res && (j < nch); ++j) {
|
2000-04-19 10:54:15 -03:00
|
|
|
if (TYPE(CHILD(tree, j)) == stmt)
|
|
|
|
res = validate_stmt(CHILD(tree, j));
|
|
|
|
else
|
|
|
|
res = validate_newline(CHILD(tree, j));
|
|
|
|
}
|
2000-07-16 09:04:32 -03:00
|
|
|
/* This stays in to prevent any internal failures from getting to the
|
2000-04-19 10:54:15 -03:00
|
|
|
* user. Hopefully, this won't be needed. If a user reports getting
|
|
|
|
* this, we have some debugging to do.
|
1996-07-20 23:33:56 -03:00
|
|
|
*/
|
|
|
|
if (!res && !PyErr_Occurred())
|
2000-10-24 16:57:45 -03:00
|
|
|
err_string("VALIDATION FAILURE: report this to the maintainer!");
|
1996-07-20 23:33:56 -03:00
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
return (res);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2003-02-08 14:05:10 -04:00
|
|
|
static int
|
|
|
|
validate_encoding_decl(node *tree)
|
|
|
|
{
|
|
|
|
int nch = NCH(tree);
|
|
|
|
int res = ((nch == 1)
|
|
|
|
&& validate_file_input(CHILD(tree, 0)));
|
|
|
|
|
|
|
|
if (!res && !PyErr_Occurred())
|
|
|
|
err_string("Error Parsing encoding_decl");
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1998-04-13 13:25:46 -03:00
|
|
|
static PyObject*
|
|
|
|
pickle_constructor = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject*
|
2000-04-19 10:54:15 -03:00
|
|
|
parser__pickler(PyObject *self, PyObject *args)
|
1998-04-13 13:25:46 -03:00
|
|
|
{
|
1998-04-29 11:16:32 -03:00
|
|
|
NOTE(ARGUNUSED(self))
|
1998-04-13 13:25:46 -03:00
|
|
|
PyObject *result = NULL;
|
2001-07-17 16:32:05 -03:00
|
|
|
PyObject *st = NULL;
|
1999-09-20 19:32:18 -03:00
|
|
|
PyObject *empty_dict = NULL;
|
1998-04-13 13:25:46 -03:00
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
if (PyArg_ParseTuple(args, "O!:_pickler", &PyST_Type, &st)) {
|
2000-04-19 10:54:15 -03:00
|
|
|
PyObject *newargs;
|
|
|
|
PyObject *tuple;
|
1998-04-13 13:25:46 -03:00
|
|
|
|
1999-09-20 19:32:18 -03:00
|
|
|
if ((empty_dict = PyDict_New()) == NULL)
|
|
|
|
goto finally;
|
2001-07-17 16:32:05 -03:00
|
|
|
if ((newargs = Py_BuildValue("Oi", st, 1)) == NULL)
|
2000-04-19 10:54:15 -03:00
|
|
|
goto finally;
|
2001-07-17 16:32:05 -03:00
|
|
|
tuple = parser_st2tuple((PyST_Object*)NULL, newargs, empty_dict);
|
2000-04-19 10:54:15 -03:00
|
|
|
if (tuple != NULL) {
|
|
|
|
result = Py_BuildValue("O(O)", pickle_constructor, tuple);
|
|
|
|
Py_DECREF(tuple);
|
|
|
|
}
|
1999-09-20 19:32:18 -03:00
|
|
|
Py_DECREF(empty_dict);
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_DECREF(newargs);
|
1998-04-13 13:25:46 -03:00
|
|
|
}
|
|
|
|
finally:
|
1999-09-20 19:32:18 -03:00
|
|
|
Py_XDECREF(empty_dict);
|
|
|
|
|
1998-04-13 13:25:46 -03:00
|
|
|
return (result);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
1998-04-13 13:25:46 -03:00
|
|
|
|
|
|
|
|
1995-10-11 14:35:38 -03:00
|
|
|
/* Functions exported by this module. Most of this should probably
|
2001-07-17 16:32:05 -03:00
|
|
|
* be converted into an ST object with methods, but that is better
|
1995-10-11 14:35:38 -03:00
|
|
|
* done directly in Python, allowing subclasses to be created directly.
|
1996-07-20 23:33:56 -03:00
|
|
|
* We'd really have to write a wrapper around it all anyway to allow
|
|
|
|
* inheritance.
|
1995-10-11 14:35:38 -03:00
|
|
|
*/
|
|
|
|
static PyMethodDef parser_functions[] = {
|
2001-07-17 16:32:05 -03:00
|
|
|
{"ast2tuple", (PyCFunction)parser_st2tuple, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates a tuple-tree representation of an ST.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"ast2list", (PyCFunction)parser_st2list, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates a list-tree representation of an ST.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"compileast", (PyCFunction)parser_compilest, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Compiles an ST object into a code object.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"compilest", (PyCFunction)parser_compilest, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Compiles an ST object into a code object.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"expr", (PyCFunction)parser_expr, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates an ST object from an expression.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"isexpr", (PyCFunction)parser_isexpr, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Determines if an ST object was created from an expression.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"issuite", (PyCFunction)parser_issuite, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Determines if an ST object was created from a suite.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"suite", (PyCFunction)parser_suite, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates an ST object from a suite.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"sequence2ast", (PyCFunction)parser_tuple2st, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates an ST object from a tree representation.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"sequence2st", (PyCFunction)parser_tuple2st, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates an ST object from a tree representation.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"st2tuple", (PyCFunction)parser_st2tuple, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates a tuple-tree representation of an ST.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"st2list", (PyCFunction)parser_st2list, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates a list-tree representation of an ST.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"tuple2ast", (PyCFunction)parser_tuple2st, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates an ST object from a tree representation.")},
|
2001-07-17 16:32:05 -03:00
|
|
|
{"tuple2st", (PyCFunction)parser_tuple2st, PUBLIC_METHOD_TYPE,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Creates an ST object from a tree representation.")},
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1998-04-13 13:25:46 -03:00
|
|
|
/* private stuff: support pickle module */
|
2001-08-15 13:44:56 -03:00
|
|
|
{"_pickler", (PyCFunction)parser__pickler, METH_VARARGS,
|
2002-08-13 19:20:41 -03:00
|
|
|
PyDoc_STR("Returns the pickle magic to allow ST objects to be pickled.")},
|
1998-04-13 13:25:46 -03:00
|
|
|
|
1998-04-29 11:16:32 -03:00
|
|
|
{NULL, NULL, 0, NULL}
|
1995-10-11 14:35:38 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-07-23 03:31:15 -03:00
|
|
|
PyMODINIT_FUNC initparser(void); /* supply a prototype */
|
2000-08-25 19:42:40 -03:00
|
|
|
|
2002-07-23 03:31:15 -03:00
|
|
|
PyMODINIT_FUNC
|
2000-07-24 12:49:08 -03:00
|
|
|
initparser(void)
|
2000-08-25 19:42:40 -03:00
|
|
|
{
|
2001-08-15 13:44:56 -03:00
|
|
|
PyObject *module, *copyreg;
|
2001-07-17 16:32:05 -03:00
|
|
|
|
|
|
|
PyST_Type.ob_type = &PyType_Type;
|
1997-01-23 19:29:44 -04:00
|
|
|
module = Py_InitModule("parser", parser_functions);
|
2006-01-19 02:09:39 -04:00
|
|
|
if (module == NULL)
|
|
|
|
return;
|
1995-10-11 14:35:38 -03:00
|
|
|
|
1999-09-09 11:21:52 -03:00
|
|
|
if (parser_error == 0)
|
|
|
|
parser_error = PyErr_NewException("parser.ParserError", NULL, NULL);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2003-07-21 11:25:23 -03:00
|
|
|
if (parser_error == 0)
|
2001-07-17 16:32:05 -03:00
|
|
|
/* caller will check PyErr_Occurred() */
|
|
|
|
return;
|
2003-07-21 11:25:23 -03:00
|
|
|
/* CAUTION: The code next used to skip bumping the refcount on
|
|
|
|
* parser_error. That's a disaster if initparser() gets called more
|
|
|
|
* than once. By incref'ing, we ensure that each module dict that
|
|
|
|
* gets created owns its reference to the shared parser_error object,
|
|
|
|
* and the file static parser_error vrbl owns a reference too.
|
|
|
|
*/
|
|
|
|
Py_INCREF(parser_error);
|
|
|
|
if (PyModule_AddObject(module, "ParserError", parser_error) != 0)
|
|
|
|
return;
|
|
|
|
|
2001-07-17 16:32:05 -03:00
|
|
|
Py_INCREF(&PyST_Type);
|
2001-08-15 13:44:56 -03:00
|
|
|
PyModule_AddObject(module, "ASTType", (PyObject*)&PyST_Type);
|
2001-07-17 16:32:05 -03:00
|
|
|
Py_INCREF(&PyST_Type);
|
2001-08-15 13:44:56 -03:00
|
|
|
PyModule_AddObject(module, "STType", (PyObject*)&PyST_Type);
|
1996-07-20 23:33:56 -03:00
|
|
|
|
2001-08-15 13:44:56 -03:00
|
|
|
PyModule_AddStringConstant(module, "__copyright__",
|
|
|
|
parser_copyright_string);
|
|
|
|
PyModule_AddStringConstant(module, "__doc__",
|
|
|
|
parser_doc_string);
|
|
|
|
PyModule_AddStringConstant(module, "__version__",
|
|
|
|
parser_version_string);
|
1995-10-11 14:35:38 -03:00
|
|
|
|
2001-07-19 17:17:15 -03:00
|
|
|
/* Register to support pickling.
|
|
|
|
* If this fails, the import of this module will fail because an
|
|
|
|
* exception will be raised here; should we clear the exception?
|
|
|
|
*/
|
2001-08-15 13:44:56 -03:00
|
|
|
copyreg = PyImport_ImportModule("copy_reg");
|
|
|
|
if (copyreg != NULL) {
|
2000-04-19 10:54:15 -03:00
|
|
|
PyObject *func, *pickler;
|
|
|
|
|
2001-08-15 13:44:56 -03:00
|
|
|
func = PyObject_GetAttrString(copyreg, "pickle");
|
|
|
|
pickle_constructor = PyObject_GetAttrString(module, "sequence2st");
|
|
|
|
pickler = PyObject_GetAttrString(module, "_pickler");
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_XINCREF(pickle_constructor);
|
|
|
|
if ((func != NULL) && (pickle_constructor != NULL)
|
|
|
|
&& (pickler != NULL)) {
|
|
|
|
PyObject *res;
|
|
|
|
|
2006-05-25 16:15:31 -03:00
|
|
|
res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler,
|
|
|
|
pickle_constructor, NULL);
|
2000-04-19 10:54:15 -03:00
|
|
|
Py_XDECREF(res);
|
|
|
|
}
|
|
|
|
Py_XDECREF(func);
|
2001-08-15 13:44:56 -03:00
|
|
|
Py_XDECREF(pickle_constructor);
|
|
|
|
Py_XDECREF(pickler);
|
|
|
|
Py_DECREF(copyreg);
|
2000-04-19 10:54:15 -03:00
|
|
|
}
|
|
|
|
}
|