LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules - parsermodule.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1593 0.0 %
Date: 2012-12-17 Functions: 0 106 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*  parsermodule.c
       2             :  *
       3             :  *  Copyright 1995-1996 by Fred L. Drake, Jr. and Virginia Polytechnic
       4             :  *  Institute and State University, Blacksburg, Virginia, USA.
       5             :  *  Portions copyright 1991-1995 by Stichting Mathematisch Centrum,
       6             :  *  Amsterdam, The Netherlands.  Copying is permitted under the terms
       7             :  *  associated with the main Python distribution, with the additional
       8             :  *  restriction that this additional notice be included and maintained
       9             :  *  on all distributed copies.
      10             :  *
      11             :  *  This module serves to replace the original parser module written
      12             :  *  by Guido.  The functionality is not matched precisely, but the
      13             :  *  original may be implemented on top of this.  This is desirable
      14             :  *  since the source of the text to be parsed is now divorced from
      15             :  *  this interface.
      16             :  *
      17             :  *  Unlike the prior interface, the ability to give a parse tree
      18             :  *  produced by Python code as a tuple to the compiler is enabled by
      19             :  *  this module.  See the documentation for more details.
      20             :  *
      21             :  *  I've added some annotations that help with the lint code-checking
      22             :  *  program, but they're not complete by a long shot.  The real errors
      23             :  *  that lint detects are gone, but there are still warnings with
      24             :  *  Py_[X]DECREF() and Py_[X]INCREF() macros.  The lint annotations
      25             :  *  look like "NOTE(...)".
      26             :  */
      27             : 
      28             : #include "Python.h"                     /* general Python API             */
      29             : #include "Python-ast.h"                 /* mod_ty */
      30             : #include "graminit.h"                   /* symbols defined in the grammar */
      31             : #include "node.h"                       /* internal parser structure      */
      32             : #include "errcode.h"                    /* error codes for PyNode_*()     */
      33             : #include "token.h"                      /* token definitions              */
      34             : #include "grammar.h"
      35             : #include "parsetok.h"
      36             :                                         /* ISTERMINAL() / ISNONTERMINAL() */
      37             : #undef Yield
      38             : #include "ast.h"
      39             : 
      40             : extern grammar _PyParser_Grammar; /* From graminit.c */
      41             : 
      42             : #ifdef lint
      43             : #include <note.h>
      44             : #else
      45             : #define NOTE(x)
      46             : #endif
      47             : 
      48             : /*  String constants used to initialize module attributes.
      49             :  *
      50             :  */
      51             : static char parser_copyright_string[] =
      52             : "Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\
      53             : University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\
      54             : Virginia, USA.  Portions copyright 1991-1995 by Stichting Mathematisch\n\
      55             : Centrum, Amsterdam, The Netherlands.";
      56             : 
      57             : 
      58             : PyDoc_STRVAR(parser_doc_string,
      59             : "This is an interface to Python's internal parser.");
      60             : 
      61             : static char parser_version_string[] = "0.5";
      62             : 
      63             : 
      64             : typedef PyObject* (*SeqMaker) (Py_ssize_t length);
      65             : typedef int (*SeqInserter) (PyObject* sequence,
      66             :                             Py_ssize_t index,
      67             :                             PyObject* element);
      68             : 
      69             : /*  The function below is copyrighted by Stichting Mathematisch Centrum.  The
      70             :  *  original copyright statement is included below, and continues to apply
      71             :  *  in full to the function immediately following.  All other material is
      72             :  *  original, copyrighted by Fred L. Drake, Jr. and Virginia Polytechnic
      73             :  *  Institute and State University.  Changes were made to comply with the
      74             :  *  new naming conventions.  Added arguments to provide support for creating
      75             :  *  lists as well as tuples, and optionally including the line numbers.
      76             :  */
      77             : 
      78             : 
      79             : static PyObject*
      80           0 : node2tuple(node *n,                     /* node to convert               */
      81             :            SeqMaker mkseq,              /* create sequence               */
      82             :            SeqInserter addelem,         /* func. to add elem. in seq.    */
      83             :            int lineno,                  /* include line numbers?         */
      84             :            int col_offset)              /* include column offsets?       */
      85             : {
      86           0 :     if (n == NULL) {
      87           0 :         Py_INCREF(Py_None);
      88           0 :         return (Py_None);
      89             :     }
      90           0 :     if (ISNONTERMINAL(TYPE(n))) {
      91             :         int i;
      92             :         PyObject *v;
      93             :         PyObject *w;
      94             : 
      95           0 :         v = mkseq(1 + NCH(n) + (TYPE(n) == encoding_decl));
      96           0 :         if (v == NULL)
      97           0 :             return (v);
      98           0 :         w = PyLong_FromLong(TYPE(n));
      99           0 :         if (w == NULL) {
     100           0 :             Py_DECREF(v);
     101           0 :             return ((PyObject*) NULL);
     102             :         }
     103           0 :         (void) addelem(v, 0, w);
     104           0 :         for (i = 0; i < NCH(n); i++) {
     105           0 :             w = node2tuple(CHILD(n, i), mkseq, addelem, lineno, col_offset);
     106           0 :             if (w == NULL) {
     107           0 :                 Py_DECREF(v);
     108           0 :                 return ((PyObject*) NULL);
     109             :             }
     110           0 :             (void) addelem(v, i+1, w);
     111             :         }
     112             : 
     113           0 :         if (TYPE(n) == encoding_decl)
     114           0 :             (void) addelem(v, i+1, PyUnicode_FromString(STR(n)));
     115           0 :         return (v);
     116             :     }
     117           0 :     else if (ISTERMINAL(TYPE(n))) {
     118           0 :         PyObject *result = mkseq(2 + lineno + col_offset);
     119           0 :         if (result != NULL) {
     120           0 :             (void) addelem(result, 0, PyLong_FromLong(TYPE(n)));
     121           0 :             (void) addelem(result, 1, PyUnicode_FromString(STR(n)));
     122           0 :             if (lineno == 1)
     123           0 :                 (void) addelem(result, 2, PyLong_FromLong(n->n_lineno));
     124           0 :             if (col_offset == 1)
     125           0 :                 (void) addelem(result, 3, PyLong_FromLong(n->n_col_offset));
     126             :         }
     127           0 :         return (result);
     128             :     }
     129             :     else {
     130           0 :         PyErr_SetString(PyExc_SystemError,
     131             :                         "unrecognized parse tree node type");
     132           0 :         return ((PyObject*) NULL);
     133             :     }
     134             : }
     135             : /*
     136             :  *  End of material copyrighted by Stichting Mathematisch Centrum.
     137             :  */
     138             : 
     139             : 
     140             : 
     141             : /*  There are two types of intermediate objects we're interested in:
     142             :  *  'eval' and 'exec' types.  These constants can be used in the st_type
     143             :  *  field of the object type to identify which any given object represents.
     144             :  *  These should probably go in an external header to allow other extensions
     145             :  *  to use them, but then, we really should be using C++ too.  ;-)
     146             :  */
     147             : 
     148             : #define PyST_EXPR  1
     149             : #define PyST_SUITE 2
     150             : 
     151             : 
     152             : /*  These are the internal objects and definitions required to implement the
     153             :  *  ST type.  Most of the internal names are more reminiscent of the 'old'
     154             :  *  naming style, but the code uses the new naming convention.
     155             :  */
     156             : 
     157             : static PyObject*
     158             : parser_error = 0;
     159             : 
     160             : 
     161             : typedef struct {
     162             :     PyObject_HEAD                       /* standard object header           */
     163             :     node* st_node;                      /* the node* returned by the parser */
     164             :     int   st_type;                      /* EXPR or SUITE ?                  */
     165             :     PyCompilerFlags st_flags;           /* Parser and compiler flags        */
     166             : } PyST_Object;
     167             : 
     168             : 
     169             : static void parser_free(PyST_Object *st);
     170             : static PyObject* parser_sizeof(PyST_Object *, void *);
     171             : static PyObject* parser_richcompare(PyObject *left, PyObject *right, int op);
     172             : static PyObject* parser_compilest(PyST_Object *, PyObject *, PyObject *);
     173             : static PyObject* parser_isexpr(PyST_Object *, PyObject *, PyObject *);
     174             : static PyObject* parser_issuite(PyST_Object *, PyObject *, PyObject *);
     175             : static PyObject* parser_st2list(PyST_Object *, PyObject *, PyObject *);
     176             : static PyObject* parser_st2tuple(PyST_Object *, PyObject *, PyObject *);
     177             : 
     178             : #define PUBLIC_METHOD_TYPE (METH_VARARGS|METH_KEYWORDS)
     179             : 
     180             : static PyMethodDef parser_methods[] = {
     181             :     {"compile",         (PyCFunction)parser_compilest,  PUBLIC_METHOD_TYPE,
     182             :         PyDoc_STR("Compile this ST object into a code object.")},
     183             :     {"isexpr",          (PyCFunction)parser_isexpr,     PUBLIC_METHOD_TYPE,
     184             :         PyDoc_STR("Determines if this ST object was created from an expression.")},
     185             :     {"issuite",         (PyCFunction)parser_issuite,    PUBLIC_METHOD_TYPE,
     186             :         PyDoc_STR("Determines if this ST object was created from a suite.")},
     187             :     {"tolist",          (PyCFunction)parser_st2list,    PUBLIC_METHOD_TYPE,
     188             :         PyDoc_STR("Creates a list-tree representation of this ST.")},
     189             :     {"totuple",         (PyCFunction)parser_st2tuple,   PUBLIC_METHOD_TYPE,
     190             :         PyDoc_STR("Creates a tuple-tree representation of this ST.")},
     191             :     {"__sizeof__",      (PyCFunction)parser_sizeof,     METH_NOARGS,
     192             :         PyDoc_STR("Returns size in memory, in bytes.")},
     193             :     {NULL, NULL, 0, NULL}
     194             : };
     195             : 
     196             : static
     197             : PyTypeObject PyST_Type = {
     198             :     PyVarObject_HEAD_INIT(NULL, 0)
     199             :     "parser.st",                        /* tp_name              */
     200             :     (int) sizeof(PyST_Object),          /* tp_basicsize         */
     201             :     0,                                  /* tp_itemsize          */
     202             :     (destructor)parser_free,            /* tp_dealloc           */
     203             :     0,                                  /* tp_print             */
     204             :     0,                                  /* tp_getattr           */
     205             :     0,                                  /* tp_setattr           */
     206             :     0,                                  /* tp_reserved          */
     207             :     0,                                  /* tp_repr              */
     208             :     0,                                  /* tp_as_number         */
     209             :     0,                                  /* tp_as_sequence       */
     210             :     0,                                  /* tp_as_mapping        */
     211             :     0,                                  /* tp_hash              */
     212             :     0,                                  /* tp_call              */
     213             :     0,                                  /* tp_str               */
     214             :     0,                                  /* tp_getattro          */
     215             :     0,                                  /* tp_setattro          */
     216             : 
     217             :     /* Functions to access object as input/output buffer */
     218             :     0,                                  /* tp_as_buffer         */
     219             : 
     220             :     Py_TPFLAGS_DEFAULT,                 /* tp_flags             */
     221             : 
     222             :     /* __doc__ */
     223             :     "Intermediate representation of a Python parse tree.",
     224             :     0,                                  /* tp_traverse */
     225             :     0,                                  /* tp_clear */
     226             :     parser_richcompare,                 /* tp_richcompare */
     227             :     0,                                  /* tp_weaklistoffset */
     228             :     0,                                  /* tp_iter */
     229             :     0,                                  /* tp_iternext */
     230             :     parser_methods,                     /* tp_methods */
     231             : };  /* PyST_Type */
     232             : 
     233             : 
     234             : /* PyST_Type isn't subclassable, so just check ob_type */
     235             : #define PyST_Object_Check(v) ((v)->ob_type == &PyST_Type)
     236             : 
     237             : static int
     238           0 : parser_compare_nodes(node *left, node *right)
     239             : {
     240             :     int j;
     241             : 
     242           0 :     if (TYPE(left) < TYPE(right))
     243           0 :         return (-1);
     244             : 
     245           0 :     if (TYPE(right) < TYPE(left))
     246           0 :         return (1);
     247             : 
     248           0 :     if (ISTERMINAL(TYPE(left)))
     249           0 :         return (strcmp(STR(left), STR(right)));
     250             : 
     251           0 :     if (NCH(left) < NCH(right))
     252           0 :         return (-1);
     253             : 
     254           0 :     if (NCH(right) < NCH(left))
     255           0 :         return (1);
     256             : 
     257           0 :     for (j = 0; j < NCH(left); ++j) {
     258           0 :         int v = parser_compare_nodes(CHILD(left, j), CHILD(right, j));
     259             : 
     260           0 :         if (v != 0)
     261           0 :             return (v);
     262             :     }
     263           0 :     return (0);
     264             : }
     265             : 
     266             : /*  parser_richcompare(PyObject* left, PyObject* right, int op)
     267             :  *
     268             :  *  Comparison function used by the Python operators ==, !=, <, >, <=, >=
     269             :  *  This really just wraps a call to parser_compare_nodes() with some easy
     270             :  *  checks and protection code.
     271             :  *
     272             :  */
     273             : 
     274             : #define TEST_COND(cond) ((cond) ? Py_True : Py_False)
     275             : 
     276             : static PyObject *
     277           0 : parser_richcompare(PyObject *left, PyObject *right, int op)
     278             : {
     279             :     int result;
     280             :     PyObject *v;
     281             : 
     282             :     /* neither argument should be NULL, unless something's gone wrong */
     283           0 :     if (left == NULL || right == NULL) {
     284           0 :         PyErr_BadInternalCall();
     285           0 :         return NULL;
     286             :     }
     287             : 
     288             :     /* both arguments should be instances of PyST_Object */
     289           0 :     if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) {
     290           0 :         v = Py_NotImplemented;
     291           0 :         goto finished;
     292             :     }
     293             : 
     294           0 :     if (left == right)
     295             :         /* if arguments are identical, they're equal */
     296           0 :         result = 0;
     297             :     else
     298           0 :         result = parser_compare_nodes(((PyST_Object *)left)->st_node,
     299             :                                       ((PyST_Object *)right)->st_node);
     300             : 
     301             :     /* Convert return value to a Boolean */
     302           0 :     switch (op) {
     303             :       case Py_EQ:
     304           0 :         v = TEST_COND(result == 0);
     305           0 :         break;
     306             :       case Py_NE:
     307           0 :         v = TEST_COND(result != 0);
     308           0 :         break;
     309             :       case Py_LE:
     310           0 :         v = TEST_COND(result <= 0);
     311           0 :         break;
     312             :       case Py_GE:
     313           0 :         v = TEST_COND(result >= 0);
     314           0 :         break;
     315             :       case Py_LT:
     316           0 :         v = TEST_COND(result < 0);
     317           0 :         break;
     318             :       case Py_GT:
     319           0 :         v = TEST_COND(result > 0);
     320           0 :         break;
     321             :       default:
     322           0 :         PyErr_BadArgument();
     323           0 :         return NULL;
     324             :     }
     325             :   finished:
     326           0 :     Py_INCREF(v);
     327           0 :     return v;
     328             : }
     329             : 
     330             : /*  parser_newstobject(node* st)
     331             :  *
     332             :  *  Allocates a new Python object representing an ST.  This is simply the
     333             :  *  'wrapper' object that holds a node* and allows it to be passed around in
     334             :  *  Python code.
     335             :  *
     336             :  */
     337             : static PyObject*
     338           0 : parser_newstobject(node *st, int type)
     339             : {
     340           0 :     PyST_Object* o = PyObject_New(PyST_Object, &PyST_Type);
     341             : 
     342           0 :     if (o != 0) {
     343           0 :         o->st_node = st;
     344           0 :         o->st_type = type;
     345           0 :         o->st_flags.cf_flags = 0;
     346             :     }
     347             :     else {
     348           0 :         PyNode_Free(st);
     349             :     }
     350           0 :     return ((PyObject*)o);
     351             : }
     352             : 
     353             : 
     354             : /*  void parser_free(PyST_Object* st)
     355             :  *
     356             :  *  This is called by a del statement that reduces the reference count to 0.
     357             :  *
     358             :  */
     359             : static void
     360           0 : parser_free(PyST_Object *st)
     361             : {
     362           0 :     PyNode_Free(st->st_node);
     363           0 :     PyObject_Del(st);
     364           0 : }
     365             : 
     366             : static PyObject *
     367           0 : parser_sizeof(PyST_Object *st, void *unused)
     368             : {
     369             :     Py_ssize_t res;
     370             : 
     371           0 :     res = sizeof(PyST_Object) + _PyNode_SizeOf(st->st_node);
     372           0 :     return PyLong_FromSsize_t(res);
     373             : }
     374             : 
     375             : 
     376             : /*  parser_st2tuple(PyObject* self, PyObject* args, PyObject* kw)
     377             :  *
     378             :  *  This provides conversion from a node* to a tuple object that can be
     379             :  *  returned to the Python-level caller.  The ST object is not modified.
     380             :  *
     381             :  */
     382             : static PyObject*
     383           0 : parser_st2tuple(PyST_Object *self, PyObject *args, PyObject *kw)
     384             : {
     385           0 :     int line_info = 0;
     386           0 :     int col_info = 0;
     387           0 :     PyObject *res = 0;
     388             :     int ok;
     389             : 
     390             :     static char *keywords[] = {"st", "line_info", "col_info", NULL};
     391             : 
     392           0 :     if (self == NULL || PyModule_Check(self)) {
     393           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2tuple", keywords,
     394             :                                          &PyST_Type, &self, &line_info,
     395             :                                          &col_info);
     396             :     }
     397             :     else
     398           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:totuple", &keywords[1],
     399             :                                          &line_info, &col_info);
     400           0 :     if (ok != 0) {
     401             :         /*
     402             :          *  Convert ST into a tuple representation.  Use Guido's function,
     403             :          *  since it's known to work already.
     404             :          */
     405           0 :         res = node2tuple(((PyST_Object*)self)->st_node,
     406             :                          PyTuple_New, PyTuple_SetItem, line_info, col_info);
     407             :     }
     408           0 :     return (res);
     409             : }
     410             : 
     411             : 
     412             : /*  parser_st2list(PyObject* self, PyObject* args, PyObject* kw)
     413             :  *
     414             :  *  This provides conversion from a node* to a list object that can be
     415             :  *  returned to the Python-level caller.  The ST object is not modified.
     416             :  *
     417             :  */
     418             : static PyObject*
     419           0 : parser_st2list(PyST_Object *self, PyObject *args, PyObject *kw)
     420             : {
     421           0 :     int line_info = 0;
     422           0 :     int col_info = 0;
     423           0 :     PyObject *res = 0;
     424             :     int ok;
     425             : 
     426             :     static char *keywords[] = {"st", "line_info", "col_info", NULL};
     427             : 
     428           0 :     if (self == NULL || PyModule_Check(self))
     429           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|pp:st2list", keywords,
     430             :                                          &PyST_Type, &self, &line_info,
     431             :                                          &col_info);
     432             :     else
     433           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "|pp:tolist", &keywords[1],
     434             :                                          &line_info, &col_info);
     435           0 :     if (ok) {
     436             :         /*
     437             :          *  Convert ST into a tuple representation.  Use Guido's function,
     438             :          *  since it's known to work already.
     439             :          */
     440           0 :         res = node2tuple(self->st_node,
     441             :                          PyList_New, PyList_SetItem, line_info, col_info);
     442             :     }
     443           0 :     return (res);
     444             : }
     445             : 
     446             : 
     447             : /*  parser_compilest(PyObject* self, PyObject* args)
     448             :  *
     449             :  *  This function creates code objects from the parse tree represented by
     450             :  *  the passed-in data object.  An optional file name is passed in as well.
     451             :  *
     452             :  */
     453             : static PyObject*
     454           0 : parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw)
     455             : {
     456           0 :     PyObject*     res = 0;
     457             :     PyArena*      arena;
     458             :     mod_ty        mod;
     459           0 :     char*         str = "<syntax-tree>";
     460             :     int ok;
     461             : 
     462             :     static char *keywords[] = {"st", "filename", NULL};
     463             : 
     464           0 :     if (self == NULL || PyModule_Check(self))
     465           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|s:compilest", keywords,
     466             :                                          &PyST_Type, &self, &str);
     467             :     else
     468           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1],
     469             :                                          &str);
     470             : 
     471           0 :     if (ok) {
     472           0 :         arena = PyArena_New();
     473           0 :         if (arena) {
     474           0 :            mod = PyAST_FromNode(self->st_node, &(self->st_flags), str, arena);
     475           0 :            if (mod) {
     476           0 :                res = (PyObject *)PyAST_Compile(mod, str, &(self->st_flags), arena);
     477             :            }
     478           0 :            PyArena_Free(arena);
     479             :         }
     480             :     }
     481             : 
     482           0 :     return (res);
     483             : }
     484             : 
     485             : 
     486             : /*  PyObject* parser_isexpr(PyObject* self, PyObject* args)
     487             :  *  PyObject* parser_issuite(PyObject* self, PyObject* args)
     488             :  *
     489             :  *  Checks the passed-in ST object to determine if it is an expression or
     490             :  *  a statement suite, respectively.  The return is a Python truth value.
     491             :  *
     492             :  */
     493             : static PyObject*
     494           0 : parser_isexpr(PyST_Object *self, PyObject *args, PyObject *kw)
     495             : {
     496           0 :     PyObject* res = 0;
     497             :     int ok;
     498             : 
     499             :     static char *keywords[] = {"st", NULL};
     500             : 
     501           0 :     if (self == NULL || PyModule_Check(self))
     502           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:isexpr", keywords,
     503             :                                          &PyST_Type, &self);
     504             :     else
     505           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, ":isexpr", &keywords[1]);
     506             : 
     507           0 :     if (ok) {
     508             :         /* Check to see if the ST represents an expression or not. */
     509           0 :         res = (self->st_type == PyST_EXPR) ? Py_True : Py_False;
     510           0 :         Py_INCREF(res);
     511             :     }
     512           0 :     return (res);
     513             : }
     514             : 
     515             : 
     516             : static PyObject*
     517           0 : parser_issuite(PyST_Object *self, PyObject *args, PyObject *kw)
     518             : {
     519           0 :     PyObject* res = 0;
     520             :     int ok;
     521             : 
     522             :     static char *keywords[] = {"st", NULL};
     523             : 
     524           0 :     if (self == NULL || PyModule_Check(self))
     525           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:issuite", keywords,
     526             :                                          &PyST_Type, &self);
     527             :     else
     528           0 :         ok = PyArg_ParseTupleAndKeywords(args, kw, ":issuite", &keywords[1]);
     529             : 
     530           0 :     if (ok) {
     531             :         /* Check to see if the ST represents an expression or not. */
     532           0 :         res = (self->st_type == PyST_EXPR) ? Py_False : Py_True;
     533           0 :         Py_INCREF(res);
     534             :     }
     535           0 :     return (res);
     536             : }
     537             : 
     538             : 
     539             : /*  err_string(char* message)
     540             :  *
     541             :  *  Sets the error string for an exception of type ParserError.
     542             :  *
     543             :  */
     544             : static void
     545           0 : err_string(char *message)
     546             : {
     547           0 :     PyErr_SetString(parser_error, message);
     548           0 : }
     549             : 
     550             : 
     551             : /*  PyObject* parser_do_parse(PyObject* args, int type)
     552             :  *
     553             :  *  Internal function to actually execute the parse and return the result if
     554             :  *  successful or set an exception if not.
     555             :  *
     556             :  */
     557             : static PyObject*
     558           0 : parser_do_parse(PyObject *args, PyObject *kw, char *argspec, int type)
     559             : {
     560           0 :     char*     string = 0;
     561           0 :     PyObject* res    = 0;
     562           0 :     int flags        = 0;
     563             :     perrdetail err;
     564             : 
     565             :     static char *keywords[] = {"source", NULL};
     566             : 
     567           0 :     if (PyArg_ParseTupleAndKeywords(args, kw, argspec, keywords, &string)) {
     568           0 :         node* n = PyParser_ParseStringFlagsFilenameEx(string, NULL,
     569             :                                                        &_PyParser_Grammar,
     570             :                                                       (type == PyST_EXPR)
     571             :                                                       ? eval_input : file_input,
     572             :                                                       &err, &flags);
     573             : 
     574           0 :         if (n) {
     575           0 :             res = parser_newstobject(n, type);
     576           0 :             if (res)
     577           0 :                 ((PyST_Object *)res)->st_flags.cf_flags = flags & PyCF_MASK;
     578             :         }
     579             :         else {
     580           0 :             PyParser_SetError(&err);
     581             :         }
     582           0 :         PyParser_ClearError(&err);
     583             :     }
     584           0 :     return (res);
     585             : }
     586             : 
     587             : 
     588             : /*  PyObject* parser_expr(PyObject* self, PyObject* args)
     589             :  *  PyObject* parser_suite(PyObject* self, PyObject* args)
     590             :  *
     591             :  *  External interfaces to the parser itself.  Which is called determines if
     592             :  *  the parser attempts to recognize an expression ('eval' form) or statement
     593             :  *  suite ('exec' form).  The real work is done by parser_do_parse() above.
     594             :  *
     595             :  */
     596             : static PyObject*
     597           0 : parser_expr(PyST_Object *self, PyObject *args, PyObject *kw)
     598             : {
     599             :     NOTE(ARGUNUSED(self))
     600           0 :     return (parser_do_parse(args, kw, "s:expr", PyST_EXPR));
     601             : }
     602             : 
     603             : 
     604             : static PyObject*
     605           0 : parser_suite(PyST_Object *self, PyObject *args, PyObject *kw)
     606             : {
     607             :     NOTE(ARGUNUSED(self))
     608           0 :     return (parser_do_parse(args, kw, "s:suite", PyST_SUITE));
     609             : }
     610             : 
     611             : 
     612             : 
     613             : /*  This is the messy part of the code.  Conversion from a tuple to an ST
     614             :  *  object requires that the input tuple be valid without having to rely on
     615             :  *  catching an exception from the compiler.  This is done to allow the
     616             :  *  compiler itself to remain fast, since most of its input will come from
     617             :  *  the parser directly, and therefore be known to be syntactically correct.
     618             :  *  This validation is done to ensure that we don't core dump the compile
     619             :  *  phase, returning an exception instead.
     620             :  *
     621             :  *  Two aspects can be broken out in this code:  creating a node tree from
     622             :  *  the tuple passed in, and verifying that it is indeed valid.  It may be
     623             :  *  advantageous to expand the number of ST types to include funcdefs and
     624             :  *  lambdadefs to take advantage of the optimizer, recognizing those STs
     625             :  *  here.  They are not necessary, and not quite as useful in a raw form.
     626             :  *  For now, let's get expressions and suites working reliably.
     627             :  */
     628             : 
     629             : 
     630             : static node* build_node_tree(PyObject *tuple);
     631             : static int   validate_expr_tree(node *tree);
     632             : static int   validate_file_input(node *tree);
     633             : static int   validate_encoding_decl(node *tree);
     634             : 
     635             : /*  PyObject* parser_tuple2st(PyObject* self, PyObject* args)
     636             :  *
     637             :  *  This is the public function, called from the Python code.  It receives a
     638             :  *  single tuple object from the caller, and creates an ST object if the
     639             :  *  tuple can be validated.  It does this by checking the first code of the
     640             :  *  tuple, and, if acceptable, builds the internal representation.  If this
     641             :  *  step succeeds, the internal representation is validated as fully as
     642             :  *  possible with the various validate_*() routines defined below.
     643             :  *
     644             :  *  This function must be changed if support is to be added for PyST_FRAGMENT
     645             :  *  ST objects.
     646             :  *
     647             :  */
     648             : static PyObject*
     649           0 : parser_tuple2st(PyST_Object *self, PyObject *args, PyObject *kw)
     650             : {
     651             :     NOTE(ARGUNUSED(self))
     652           0 :     PyObject *st = 0;
     653             :     PyObject *tuple;
     654             :     node *tree;
     655             : 
     656             :     static char *keywords[] = {"sequence", NULL};
     657             : 
     658           0 :     if (!PyArg_ParseTupleAndKeywords(args, kw, "O:sequence2st", keywords,
     659             :                                      &tuple))
     660           0 :         return (0);
     661           0 :     if (!PySequence_Check(tuple)) {
     662           0 :         PyErr_SetString(PyExc_ValueError,
     663             :                         "sequence2st() requires a single sequence argument");
     664           0 :         return (0);
     665             :     }
     666             :     /*
     667             :      *  Convert the tree to the internal form before checking it.
     668             :      */
     669           0 :     tree = build_node_tree(tuple);
     670           0 :     if (tree != 0) {
     671           0 :         int start_sym = TYPE(tree);
     672           0 :         if (start_sym == eval_input) {
     673             :             /*  Might be an eval form.  */
     674           0 :             if (validate_expr_tree(tree))
     675           0 :                 st = parser_newstobject(tree, PyST_EXPR);
     676             :             else
     677           0 :                 PyNode_Free(tree);
     678             :         }
     679           0 :         else if (start_sym == file_input) {
     680             :             /*  This looks like an exec form so far.  */
     681           0 :             if (validate_file_input(tree))
     682           0 :                 st = parser_newstobject(tree, PyST_SUITE);
     683             :             else
     684           0 :                 PyNode_Free(tree);
     685             :         }
     686           0 :         else if (start_sym == encoding_decl) {
     687             :             /* This looks like an encoding_decl so far. */
     688           0 :             if (validate_encoding_decl(tree))
     689           0 :                 st = parser_newstobject(tree, PyST_SUITE);
     690             :             else
     691           0 :                 PyNode_Free(tree);
     692             :         }
     693             :         else {
     694             :             /*  This is a fragment, at best. */
     695           0 :             PyNode_Free(tree);
     696           0 :             err_string("parse tree does not use a valid start symbol");
     697             :         }
     698             :     }
     699             :     /*  Make sure we throw an exception on all errors.  We should never
     700             :      *  get this, but we'd do well to be sure something is done.
     701             :      */
     702           0 :     if (st == NULL && !PyErr_Occurred())
     703           0 :         err_string("unspecified ST error occurred");
     704             : 
     705           0 :     return st;
     706             : }
     707             : 
     708             : 
     709             : /*  node* build_node_children()
     710             :  *
     711             :  *  Iterate across the children of the current non-terminal node and build
     712             :  *  their structures.  If successful, return the root of this portion of
     713             :  *  the tree, otherwise, 0.  Any required exception will be specified already,
     714             :  *  and no memory will have been deallocated.
     715             :  *
     716             :  */
     717             : static node*
     718           0 : build_node_children(PyObject *tuple, node *root, int *line_num)
     719             : {
     720           0 :     Py_ssize_t len = PyObject_Size(tuple);
     721             :     Py_ssize_t i;
     722             :     int  err;
     723             : 
     724           0 :     for (i = 1; i < len; ++i) {
     725             :         /* elem must always be a sequence, however simple */
     726           0 :         PyObject* elem = PySequence_GetItem(tuple, i);
     727           0 :         int ok = elem != NULL;
     728           0 :         long  type = 0;
     729           0 :         char *strn = 0;
     730             : 
     731           0 :         if (ok)
     732           0 :             ok = PySequence_Check(elem);
     733           0 :         if (ok) {
     734           0 :             PyObject *temp = PySequence_GetItem(elem, 0);
     735           0 :             if (temp == NULL)
     736           0 :                 ok = 0;
     737             :             else {
     738           0 :                 ok = PyLong_Check(temp);
     739           0 :                 if (ok)
     740           0 :                     type = PyLong_AS_LONG(temp);
     741           0 :                 Py_DECREF(temp);
     742             :             }
     743             :         }
     744           0 :         if (!ok) {
     745           0 :             PyObject *err = Py_BuildValue("os", elem,
     746             :                                           "Illegal node construct.");
     747           0 :             PyErr_SetObject(parser_error, err);
     748           0 :             Py_XDECREF(err);
     749           0 :             Py_XDECREF(elem);
     750           0 :             return (0);
     751             :         }
     752           0 :         if (ISTERMINAL(type)) {
     753           0 :             Py_ssize_t len = PyObject_Size(elem);
     754             :             PyObject *temp;
     755             :             const char *temp_str;
     756             : 
     757           0 :             if ((len != 2) && (len != 3)) {
     758           0 :                 err_string("terminal nodes must have 2 or 3 entries");
     759           0 :                 return 0;
     760             :             }
     761           0 :             temp = PySequence_GetItem(elem, 1);
     762           0 :             if (temp == NULL)
     763           0 :                 return 0;
     764           0 :             if (!PyUnicode_Check(temp)) {
     765           0 :                 PyErr_Format(parser_error,
     766             :                              "second item in terminal node must be a string,"
     767             :                              " found %s",
     768           0 :                              Py_TYPE(temp)->tp_name);
     769           0 :                 Py_DECREF(temp);
     770           0 :                 Py_DECREF(elem);
     771           0 :                 return 0;
     772             :             }
     773           0 :             if (len == 3) {
     774           0 :                 PyObject *o = PySequence_GetItem(elem, 2);
     775           0 :                 if (o != NULL) {
     776           0 :                     if (PyLong_Check(o))
     777           0 :                         *line_num = PyLong_AS_LONG(o);
     778             :                     else {
     779           0 :                         PyErr_Format(parser_error,
     780             :                                      "third item in terminal node must be an"
     781             :                                      " integer, found %s",
     782           0 :                                      Py_TYPE(temp)->tp_name);
     783           0 :                         Py_DECREF(o);
     784           0 :                         Py_DECREF(temp);
     785           0 :                         Py_DECREF(elem);
     786           0 :                         return 0;
     787             :                     }
     788           0 :                     Py_DECREF(o);
     789             :                 }
     790             :             }
     791           0 :             temp_str = _PyUnicode_AsStringAndSize(temp, &len);
     792           0 :             if (temp_str == NULL) {
     793           0 :                 Py_DECREF(temp);
     794           0 :                 Py_XDECREF(elem);
     795           0 :                 return 0;
     796             :             }
     797           0 :             strn = (char *)PyObject_MALLOC(len + 1);
     798           0 :             if (strn != NULL)
     799           0 :                 (void) memcpy(strn, temp_str, len + 1);
     800           0 :             Py_DECREF(temp);
     801             :         }
     802           0 :         else if (!ISNONTERMINAL(type)) {
     803             :             /*
     804             :              *  It has to be one or the other; this is an error.
     805             :              *  Throw an exception.
     806             :              */
     807           0 :             PyObject *err = Py_BuildValue("os", elem, "unknown node type.");
     808           0 :             PyErr_SetObject(parser_error, err);
     809           0 :             Py_XDECREF(err);
     810           0 :             Py_XDECREF(elem);
     811           0 :             return (0);
     812             :         }
     813           0 :         err = PyNode_AddChild(root, type, strn, *line_num, 0);
     814           0 :         if (err == E_NOMEM) {
     815           0 :             Py_XDECREF(elem);
     816           0 :             PyObject_FREE(strn);
     817           0 :             return (node *) PyErr_NoMemory();
     818             :         }
     819           0 :         if (err == E_OVERFLOW) {
     820           0 :             Py_XDECREF(elem);
     821           0 :             PyObject_FREE(strn);
     822           0 :             PyErr_SetString(PyExc_ValueError,
     823             :                             "unsupported number of child nodes");
     824           0 :             return NULL;
     825             :         }
     826             : 
     827           0 :         if (ISNONTERMINAL(type)) {
     828           0 :             node* new_child = CHILD(root, i - 1);
     829             : 
     830           0 :             if (new_child != build_node_children(elem, new_child, line_num)) {
     831           0 :                 Py_XDECREF(elem);
     832           0 :                 return (0);
     833             :             }
     834             :         }
     835           0 :         else if (type == NEWLINE) {     /* It's true:  we increment the     */
     836           0 :             ++(*line_num);              /* line number *after* the newline! */
     837             :         }
     838           0 :         Py_XDECREF(elem);
     839             :     }
     840           0 :     return root;
     841             : }
     842             : 
     843             : 
     844             : static node*
     845           0 : build_node_tree(PyObject *tuple)
     846             : {
     847           0 :     node* res = 0;
     848           0 :     PyObject *temp = PySequence_GetItem(tuple, 0);
     849           0 :     long num = -1;
     850             : 
     851           0 :     if (temp != NULL)
     852           0 :         num = PyLong_AsLong(temp);
     853           0 :     Py_XDECREF(temp);
     854           0 :     if (ISTERMINAL(num)) {
     855             :         /*
     856             :          *  The tuple is simple, but it doesn't start with a start symbol.
     857             :          *  Throw an exception now and be done with it.
     858             :          */
     859           0 :         tuple = Py_BuildValue("os", tuple,
     860             :                     "Illegal syntax-tree; cannot start with terminal symbol.");
     861           0 :         PyErr_SetObject(parser_error, tuple);
     862           0 :         Py_XDECREF(tuple);
     863             :     }
     864           0 :     else if (ISNONTERMINAL(num)) {
     865             :         /*
     866             :          *  Not efficient, but that can be handled later.
     867             :          */
     868           0 :         int line_num = 0;
     869           0 :         PyObject *encoding = NULL;
     870             : 
     871           0 :         if (num == encoding_decl) {
     872           0 :             encoding = PySequence_GetItem(tuple, 2);
     873             :             /* tuple isn't borrowed anymore here, need to DECREF */
     874           0 :             tuple = PySequence_GetSlice(tuple, 0, 2);
     875           0 :             if (tuple == NULL)
     876           0 :                 return NULL;
     877             :         }
     878           0 :         res = PyNode_New(num);
     879           0 :         if (res != NULL) {
     880           0 :             if (res != build_node_children(tuple, res, &line_num)) {
     881           0 :                 PyNode_Free(res);
     882           0 :                 res = NULL;
     883             :             }
     884           0 :             if (res && encoding) {
     885             :                 Py_ssize_t len;
     886             :                 const char *temp;
     887           0 :                 temp = _PyUnicode_AsStringAndSize(encoding, &len);
     888           0 :                 if (temp == NULL) {
     889           0 :                     Py_DECREF(res);
     890           0 :                     Py_DECREF(encoding);
     891           0 :                     Py_DECREF(tuple);
     892           0 :                     return NULL;
     893             :                 }
     894           0 :                 res->n_str = (char *)PyObject_MALLOC(len + 1);
     895           0 :                 if (res->n_str != NULL && temp != NULL)
     896           0 :                     (void) memcpy(res->n_str, temp, len + 1);
     897           0 :                 Py_DECREF(encoding);
     898           0 :                 Py_DECREF(tuple);
     899             :             }
     900             :         }
     901             :     }
     902             :     else {
     903             :         /*  The tuple is illegal -- if the number is neither TERMINAL nor
     904             :          *  NONTERMINAL, we can't use it.  Not sure the implementation
     905             :          *  allows this condition, but the API doesn't preclude it.
     906             :          */
     907           0 :         PyObject *err = Py_BuildValue("os", tuple,
     908             :                                       "Illegal component tuple.");
     909           0 :         PyErr_SetObject(parser_error, err);
     910           0 :         Py_XDECREF(err);
     911             :     }
     912             : 
     913           0 :     return (res);
     914             : }
     915             : 
     916             : 
     917             : /*
     918             :  *  Validation routines used within the validation section:
     919             :  */
     920             : static int validate_terminal(node *terminal, int type, char *string);
     921             : 
     922             : #define validate_ampersand(ch)  validate_terminal(ch,      AMPER, "&")
     923             : #define validate_circumflex(ch) validate_terminal(ch, CIRCUMFLEX, "^")
     924             : #define validate_colon(ch)      validate_terminal(ch,      COLON, ":")
     925             : #define validate_comma(ch)      validate_terminal(ch,      COMMA, ",")
     926             : #define validate_dedent(ch)     validate_terminal(ch,     DEDENT, "")
     927             : #define validate_equal(ch)      validate_terminal(ch,      EQUAL, "=")
     928             : #define validate_indent(ch)     validate_terminal(ch,     INDENT, (char*)NULL)
     929             : #define validate_lparen(ch)     validate_terminal(ch,       LPAR, "(")
     930             : #define validate_newline(ch)    validate_terminal(ch,    NEWLINE, (char*)NULL)
     931             : #define validate_rparen(ch)     validate_terminal(ch,       RPAR, ")")
     932             : #define validate_semi(ch)       validate_terminal(ch,       SEMI, ";")
     933             : #define validate_star(ch)       validate_terminal(ch,       STAR, "*")
     934             : #define validate_vbar(ch)       validate_terminal(ch,       VBAR, "|")
     935             : #define validate_doublestar(ch) validate_terminal(ch, DOUBLESTAR, "**")
     936             : #define validate_dot(ch)        validate_terminal(ch,        DOT, ".")
     937             : #define validate_at(ch)         validate_terminal(ch,         AT, "@")
     938             : #define validate_rarrow(ch)     validate_terminal(ch,     RARROW, "->")
     939             : #define validate_name(ch, str)  validate_terminal(ch,       NAME, str)
     940             : 
     941             : #define VALIDATER(n)    static int validate_##n(node *tree)
     942             : 
     943             : VALIDATER(node);                VALIDATER(small_stmt);
     944             : VALIDATER(class);               VALIDATER(node);
     945             : VALIDATER(parameters);          VALIDATER(suite);
     946             : VALIDATER(testlist);            VALIDATER(varargslist);
     947             : VALIDATER(vfpdef);
     948             : VALIDATER(stmt);                VALIDATER(simple_stmt);
     949             : VALIDATER(expr_stmt);           VALIDATER(power);
     950             : VALIDATER(del_stmt);
     951             : VALIDATER(return_stmt);         VALIDATER(raise_stmt);
     952             : VALIDATER(import_stmt);         VALIDATER(import_stmt);
     953             : VALIDATER(import_name);         VALIDATER(yield_stmt);
     954             : VALIDATER(global_stmt);         VALIDATER(nonlocal_stmt);
     955             : VALIDATER(assert_stmt);
     956             : VALIDATER(compound_stmt);       VALIDATER(test_or_star_expr);
     957             : VALIDATER(while);               VALIDATER(for);
     958             : VALIDATER(try);                 VALIDATER(except_clause);
     959             : VALIDATER(test);                VALIDATER(and_test);
     960             : VALIDATER(not_test);            VALIDATER(comparison);
     961             : VALIDATER(comp_op);
     962             : VALIDATER(star_expr);           VALIDATER(expr);
     963             : VALIDATER(xor_expr);            VALIDATER(and_expr);
     964             : VALIDATER(shift_expr);          VALIDATER(arith_expr);
     965             : VALIDATER(term);                VALIDATER(factor);
     966             : VALIDATER(atom);                VALIDATER(lambdef);
     967             : VALIDATER(trailer);             VALIDATER(subscript);
     968             : VALIDATER(subscriptlist);       VALIDATER(sliceop);
     969             : VALIDATER(exprlist);            VALIDATER(dictorsetmaker);
     970             : VALIDATER(arglist);             VALIDATER(argument);
     971             : VALIDATER(comp_for);
     972             : VALIDATER(comp_iter);           VALIDATER(comp_if);
     973             : VALIDATER(testlist_comp);       VALIDATER(yield_expr);
     974             : VALIDATER(or_test);
     975             : VALIDATER(test_nocond);         VALIDATER(lambdef_nocond);
     976             : VALIDATER(yield_arg);
     977             : 
     978             : #undef VALIDATER
     979             : 
     980             : #define is_even(n)      (((n) & 1) == 0)
     981             : #define is_odd(n)       (((n) & 1) == 1)
     982             : 
     983             : 
     984             : static int
     985           0 : validate_ntype(node *n, int t)
     986             : {
     987           0 :     if (TYPE(n) != t) {
     988           0 :         PyErr_Format(parser_error, "Expected node type %d, got %d.",
     989           0 :                      t, TYPE(n));
     990           0 :         return 0;
     991             :     }
     992           0 :     return 1;
     993             : }
     994             : 
     995             : 
     996             : /*  Verifies that the number of child nodes is exactly 'num', raising
     997             :  *  an exception if it isn't.  The exception message does not indicate
     998             :  *  the exact number of nodes, allowing this to be used to raise the
     999             :  *  "right" exception when the wrong number of nodes is present in a
    1000             :  *  specific variant of a statement's syntax.  This is commonly used
    1001             :  *  in that fashion.
    1002             :  */
    1003             : static int
    1004           0 : validate_numnodes(node *n, int num, const char *const name)
    1005             : {
    1006           0 :     if (NCH(n) != num) {
    1007           0 :         PyErr_Format(parser_error,
    1008             :                      "Illegal number of children for %s node.", name);
    1009           0 :         return 0;
    1010             :     }
    1011           0 :     return 1;
    1012             : }
    1013             : 
    1014             : 
    1015             : static int
    1016           0 : validate_terminal(node *terminal, int type, char *string)
    1017             : {
    1018           0 :     int res = (validate_ntype(terminal, type)
    1019           0 :                && ((string == 0) || (strcmp(string, STR(terminal)) == 0)));
    1020             : 
    1021           0 :     if (!res && !PyErr_Occurred()) {
    1022           0 :         PyErr_Format(parser_error,
    1023             :                      "Illegal terminal: expected \"%s\"", string);
    1024             :     }
    1025           0 :     return (res);
    1026             : }
    1027             : 
    1028             : 
    1029             : /*  X (',' X) [',']
    1030             :  */
    1031             : static int
    1032           0 : validate_repeating_list(node *tree, int ntype, int (*vfunc)(node *),
    1033             :                         const char *const name)
    1034             : {
    1035           0 :     int nch = NCH(tree);
    1036           0 :     int res = (nch && validate_ntype(tree, ntype)
    1037           0 :                && vfunc(CHILD(tree, 0)));
    1038             : 
    1039           0 :     if (!res && !PyErr_Occurred())
    1040           0 :         (void) validate_numnodes(tree, 1, name);
    1041             :     else {
    1042           0 :         if (is_even(nch))
    1043           0 :             res = validate_comma(CHILD(tree, --nch));
    1044           0 :         if (res && nch > 1) {
    1045           0 :             int pos = 1;
    1046           0 :             for ( ; res && pos < nch; pos += 2)
    1047           0 :                 res = (validate_comma(CHILD(tree, pos))
    1048           0 :                        && vfunc(CHILD(tree, pos + 1)));
    1049             :         }
    1050             :     }
    1051           0 :     return (res);
    1052             : }
    1053             : 
    1054             : 
    1055             : /*  validate_class()
    1056             :  *
    1057             :  *  classdef:
    1058             :  *      'class' NAME ['(' testlist ')'] ':' suite
    1059             :  */
    1060             : static int
    1061           0 : validate_class(node *tree)
    1062             : {
    1063           0 :     int nch = NCH(tree);
    1064           0 :     int res = (validate_ntype(tree, classdef) &&
    1065           0 :                 ((nch == 4) || (nch == 6) || (nch == 7)));
    1066             : 
    1067           0 :     if (res) {
    1068           0 :         res = (validate_name(CHILD(tree, 0), "class")
    1069           0 :                && validate_ntype(CHILD(tree, 1), NAME)
    1070           0 :                && validate_colon(CHILD(tree, nch - 2))
    1071           0 :                && validate_suite(CHILD(tree, nch - 1)));
    1072             :     }
    1073             :     else {
    1074           0 :         (void) validate_numnodes(tree, 4, "class");
    1075             :     }
    1076             : 
    1077           0 :     if (res) {
    1078           0 :         if (nch == 7) {
    1079           0 :                 res = ((validate_lparen(CHILD(tree, 2)) &&
    1080           0 :                         validate_arglist(CHILD(tree, 3)) &&
    1081           0 :                         validate_rparen(CHILD(tree, 4))));
    1082             :         }
    1083           0 :         else if (nch == 6) {
    1084           0 :                 res = (validate_lparen(CHILD(tree,2)) &&
    1085           0 :                         validate_rparen(CHILD(tree,3)));
    1086             :         }
    1087             :     }
    1088           0 :     return (res);
    1089             : }
    1090             : 
    1091             : 
    1092             : /*  if_stmt:
    1093             :  *      'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
    1094             :  */
    1095             : static int
    1096           0 : validate_if(node *tree)
    1097             : {
    1098           0 :     int nch = NCH(tree);
    1099           0 :     int res = (validate_ntype(tree, if_stmt)
    1100           0 :                && (nch >= 4)
    1101           0 :                && validate_name(CHILD(tree, 0), "if")
    1102           0 :                && validate_test(CHILD(tree, 1))
    1103           0 :                && validate_colon(CHILD(tree, 2))
    1104           0 :                && validate_suite(CHILD(tree, 3)));
    1105             : 
    1106           0 :     if (res && ((nch % 4) == 3)) {
    1107             :         /*  ... 'else' ':' suite  */
    1108           0 :         res = (validate_name(CHILD(tree, nch - 3), "else")
    1109           0 :                && validate_colon(CHILD(tree, nch - 2))
    1110           0 :                && validate_suite(CHILD(tree, nch - 1)));
    1111           0 :         nch -= 3;
    1112             :     }
    1113           0 :     else if (!res && !PyErr_Occurred())
    1114           0 :         (void) validate_numnodes(tree, 4, "if");
    1115           0 :     if ((nch % 4) != 0)
    1116             :         /* Will catch the case for nch < 4 */
    1117           0 :         res = validate_numnodes(tree, 0, "if");
    1118           0 :     else if (res && (nch > 4)) {
    1119             :         /*  ... ('elif' test ':' suite)+ ...  */
    1120           0 :         int j = 4;
    1121           0 :         while ((j < nch) && res) {
    1122           0 :             res = (validate_name(CHILD(tree, j), "elif")
    1123           0 :                    && validate_colon(CHILD(tree, j + 2))
    1124           0 :                    && validate_test(CHILD(tree, j + 1))
    1125           0 :                    && validate_suite(CHILD(tree, j + 3)));
    1126           0 :             j += 4;
    1127             :         }
    1128             :     }
    1129           0 :     return (res);
    1130             : }
    1131             : 
    1132             : 
    1133             : /*  parameters:
    1134             :  *      '(' [varargslist] ')'
    1135             :  *
    1136             :  */
    1137             : static int
    1138           0 : validate_parameters(node *tree)
    1139             : {
    1140           0 :     int nch = NCH(tree);
    1141           0 :     int res = validate_ntype(tree, parameters) && ((nch == 2) || (nch == 3));
    1142             : 
    1143           0 :     if (res) {
    1144           0 :         res = (validate_lparen(CHILD(tree, 0))
    1145           0 :                && validate_rparen(CHILD(tree, nch - 1)));
    1146           0 :         if (res && (nch == 3))
    1147           0 :             res = validate_varargslist(CHILD(tree, 1));
    1148             :     }
    1149             :     else {
    1150           0 :         (void) validate_numnodes(tree, 2, "parameters");
    1151             :     }
    1152           0 :     return (res);
    1153             : }
    1154             : 
    1155             : 
    1156             : /*  validate_suite()
    1157             :  *
    1158             :  *  suite:
    1159             :  *      simple_stmt
    1160             :  *    | NEWLINE INDENT stmt+ DEDENT
    1161             :  */
    1162             : static int
    1163           0 : validate_suite(node *tree)
    1164             : {
    1165           0 :     int nch = NCH(tree);
    1166           0 :     int res = (validate_ntype(tree, suite) && ((nch == 1) || (nch >= 4)));
    1167             : 
    1168           0 :     if (res && (nch == 1))
    1169           0 :         res = validate_simple_stmt(CHILD(tree, 0));
    1170           0 :     else if (res) {
    1171             :         /*  NEWLINE INDENT stmt+ DEDENT  */
    1172           0 :         res = (validate_newline(CHILD(tree, 0))
    1173           0 :                && validate_indent(CHILD(tree, 1))
    1174           0 :                && validate_stmt(CHILD(tree, 2))
    1175           0 :                && validate_dedent(CHILD(tree, nch - 1)));
    1176             : 
    1177           0 :         if (res && (nch > 4)) {
    1178           0 :             int i = 3;
    1179           0 :             --nch;                      /* forget the DEDENT     */
    1180           0 :             for ( ; res && (i < nch); ++i)
    1181           0 :                 res = validate_stmt(CHILD(tree, i));
    1182             :         }
    1183           0 :         else if (nch < 4)
    1184           0 :             res = validate_numnodes(tree, 4, "suite");
    1185             :     }
    1186           0 :     return (res);
    1187             : }
    1188             : 
    1189             : 
    1190             : static int
    1191           0 : validate_testlist(node *tree)
    1192             : {
    1193           0 :     return (validate_repeating_list(tree, testlist,
    1194             :                                     validate_test, "testlist"));
    1195             : }
    1196             : 
    1197             : static int
    1198           0 : validate_testlist_star_expr(node *tl)
    1199             : {
    1200           0 :     return (validate_repeating_list(tl, testlist_star_expr, validate_test_or_star_expr,
    1201             :                                     "testlist"));
    1202             : }
    1203             : 
    1204             : 
    1205             : /* validate either vfpdef or tfpdef.
    1206             :  * vfpdef: NAME
    1207             :  * tfpdef: NAME [':' test]
    1208             :  */
    1209             : static int
    1210           0 : validate_vfpdef(node *tree)
    1211             : {
    1212           0 :     int nch = NCH(tree);
    1213           0 :     if (TYPE(tree) == vfpdef) {
    1214           0 :         return nch == 1 && validate_name(CHILD(tree, 0), NULL);
    1215             :     }
    1216           0 :     else if (TYPE(tree) == tfpdef) {
    1217           0 :         if (nch == 1) {
    1218           0 :             return validate_name(CHILD(tree, 0), NULL);
    1219             :         }
    1220           0 :         else if (nch == 3) {
    1221           0 :             return validate_name(CHILD(tree, 0), NULL) &&
    1222           0 :                    validate_colon(CHILD(tree, 1)) &&
    1223           0 :                    validate_test(CHILD(tree, 2));
    1224             :         }
    1225             :     }
    1226           0 :     return 0;
    1227             : }
    1228             : 
    1229             : /* '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef
    1230             :  * ..or tfpdef in place of vfpdef. vfpdef: NAME; tfpdef: NAME [':' test]
    1231             :  */
    1232             : static int
    1233           0 : validate_varargslist_trailer(node *tree, int start)
    1234             : {
    1235           0 :     int nch = NCH(tree);
    1236           0 :     int res = 0;
    1237             : 
    1238           0 :     if (nch <= start) {
    1239           0 :         err_string("expected variable argument trailer for varargslist");
    1240           0 :         return 0;
    1241             :     }
    1242           0 :     if (TYPE(CHILD(tree, start)) == STAR) {
    1243             :         /*
    1244             :          * '*' [vfpdef]
    1245             :          */
    1246           0 :         res = validate_star(CHILD(tree, start++));
    1247           0 :         if (res && start < nch && (TYPE(CHILD(tree, start)) == vfpdef ||
    1248           0 :                                    TYPE(CHILD(tree, start)) == tfpdef))
    1249           0 :             res = validate_vfpdef(CHILD(tree, start++));
    1250             :         /*
    1251             :          * (',' vfpdef ['=' test])*
    1252             :          */
    1253           0 :         while (res && start + 1 < nch && (
    1254           0 :                    TYPE(CHILD(tree, start + 1)) == vfpdef ||
    1255           0 :                    TYPE(CHILD(tree, start + 1)) == tfpdef)) {
    1256           0 :             res = (validate_comma(CHILD(tree, start++))
    1257           0 :                    && validate_vfpdef(CHILD(tree, start++)));
    1258           0 :             if (res && start + 1 < nch && TYPE(CHILD(tree, start)) == EQUAL)
    1259           0 :                 res = (validate_equal(CHILD(tree, start++))
    1260           0 :                        && validate_test(CHILD(tree, start++)));
    1261             :         }
    1262             :         /*
    1263             :          * [',' '**' vfpdef]
    1264             :          */
    1265           0 :         if (res && start + 2 < nch && TYPE(CHILD(tree, start+1)) == DOUBLESTAR)
    1266           0 :             res = (validate_comma(CHILD(tree, start++))
    1267           0 :                    && validate_doublestar(CHILD(tree, start++))
    1268           0 :                    && validate_vfpdef(CHILD(tree, start++)));
    1269             :     }
    1270           0 :     else if (TYPE(CHILD(tree, start)) == DOUBLESTAR) {
    1271             :         /*
    1272             :          * '**' vfpdef
    1273             :          */
    1274           0 :         if (start + 1 < nch)
    1275           0 :             res = (validate_doublestar(CHILD(tree, start++))
    1276           0 :                    && validate_vfpdef(CHILD(tree, start++)));
    1277             :         else {
    1278           0 :             res = 0;
    1279           0 :             err_string("expected vfpdef after ** in varargslist trailer");
    1280             :         }
    1281             :     }
    1282             :     else {
    1283           0 :         res = 0;
    1284           0 :         err_string("expected * or ** in varargslist trailer");
    1285             :     }
    1286             : 
    1287           0 :     if (res && start != nch) {
    1288           0 :         res = 0;
    1289           0 :         err_string("unexpected extra children in varargslist trailer");
    1290             :     }
    1291           0 :     return res;
    1292             : }
    1293             : 
    1294             : 
    1295             : /* validate_varargslist()
    1296             :  *
    1297             :  * Validate typedargslist or varargslist.
    1298             :  *
    1299             :  * typedargslist: ((tfpdef ['=' test] ',')*
    1300             :  *                 ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] |
    1301             :  *                  '**' tfpdef)
    1302             :  *                 | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
    1303             :  * tfpdef: NAME [':' test]
    1304             :  * varargslist: ((vfpdef ['=' test] ',')*
    1305             :  *               ('*' [vfpdef] (',' vfpdef ['=' test])*  [',' '**' vfpdef] |
    1306             :  *                '**' vfpdef)
    1307             :  *               | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
    1308             :  * vfpdef: NAME
    1309             :  *
    1310             :  */
    1311             : static int
    1312           0 : validate_varargslist(node *tree)
    1313             : {
    1314           0 :     int nch = NCH(tree);
    1315           0 :     int res = (TYPE(tree) == varargslist ||
    1316           0 :                TYPE(tree) == typedargslist) &&
    1317             :               (nch != 0);
    1318             :     int sym;
    1319             :     node *ch;
    1320           0 :     int i = 0;
    1321             : 
    1322           0 :     if (!res)
    1323           0 :         return 0;
    1324           0 :     if (nch < 1) {
    1325           0 :         err_string("varargslist missing child nodes");
    1326           0 :         return 0;
    1327             :     }
    1328           0 :     while (i < nch) {
    1329           0 :         ch = CHILD(tree, i);
    1330           0 :         sym = TYPE(ch);
    1331           0 :         if (sym == vfpdef || sym == tfpdef) {
    1332             :             /* validate (vfpdef ['=' test] ',')+ */
    1333           0 :             res = validate_vfpdef(ch);
    1334           0 :             ++i;
    1335           0 :             if (res && (i+2 <= nch) && TYPE(CHILD(tree, i)) == EQUAL) {
    1336           0 :                 res = (validate_equal(CHILD(tree, i))
    1337           0 :                        && validate_test(CHILD(tree, i+1)));
    1338           0 :                 if (res)
    1339           0 :                   i += 2;
    1340             :             }
    1341           0 :             if (res && i < nch) {
    1342           0 :                 res = validate_comma(CHILD(tree, i));
    1343           0 :                 ++i;
    1344             :             }
    1345           0 :         } else if (sym == DOUBLESTAR || sym == STAR) {
    1346           0 :             res = validate_varargslist_trailer(tree, i);
    1347           0 :             break;
    1348             :         } else {
    1349           0 :             res = 0;
    1350           0 :             err_string("illegal formation for varargslist");
    1351             :         }
    1352             :     }
    1353           0 :     return res;
    1354             : }
    1355             : 
    1356             : 
    1357             : /*  comp_iter:  comp_for | comp_if
    1358             :  */
    1359             : static int
    1360           0 : validate_comp_iter(node *tree)
    1361             : {
    1362           0 :     int res = (validate_ntype(tree, comp_iter)
    1363           0 :                && validate_numnodes(tree, 1, "comp_iter"));
    1364           0 :     if (res && TYPE(CHILD(tree, 0)) == comp_for)
    1365           0 :         res = validate_comp_for(CHILD(tree, 0));
    1366             :     else
    1367           0 :         res = validate_comp_if(CHILD(tree, 0));
    1368             : 
    1369           0 :     return res;
    1370             : }
    1371             : 
    1372             : /*  comp_for:  'for' exprlist 'in' test [comp_iter]
    1373             :  */
    1374             : static int
    1375           0 : validate_comp_for(node *tree)
    1376             : {
    1377           0 :     int nch = NCH(tree);
    1378             :     int res;
    1379             : 
    1380           0 :     if (nch == 5)
    1381           0 :         res = validate_comp_iter(CHILD(tree, 4));
    1382             :     else
    1383           0 :         res = validate_numnodes(tree, 4, "comp_for");
    1384             : 
    1385           0 :     if (res)
    1386           0 :         res = (validate_name(CHILD(tree, 0), "for")
    1387           0 :                && validate_exprlist(CHILD(tree, 1))
    1388           0 :                && validate_name(CHILD(tree, 2), "in")
    1389           0 :                && validate_or_test(CHILD(tree, 3)));
    1390             : 
    1391           0 :     return res;
    1392             : }
    1393             : 
    1394             : /*  comp_if:  'if' test_nocond [comp_iter]
    1395             :  */
    1396             : static int
    1397           0 : validate_comp_if(node *tree)
    1398             : {
    1399           0 :     int nch = NCH(tree);
    1400             :     int res;
    1401             : 
    1402           0 :     if (nch == 3)
    1403           0 :         res = validate_comp_iter(CHILD(tree, 2));
    1404             :     else
    1405           0 :         res = validate_numnodes(tree, 2, "comp_if");
    1406             : 
    1407           0 :     if (res)
    1408           0 :         res = (validate_name(CHILD(tree, 0), "if")
    1409           0 :                && validate_test_nocond(CHILD(tree, 1)));
    1410             : 
    1411           0 :     return res;
    1412             : }
    1413             : 
    1414             : 
    1415             : /*  simple_stmt | compound_stmt
    1416             :  *
    1417             :  */
    1418             : static int
    1419           0 : validate_stmt(node *tree)
    1420             : {
    1421           0 :     int res = (validate_ntype(tree, stmt)
    1422           0 :                && validate_numnodes(tree, 1, "stmt"));
    1423             : 
    1424           0 :     if (res) {
    1425           0 :         tree = CHILD(tree, 0);
    1426             : 
    1427           0 :         if (TYPE(tree) == simple_stmt)
    1428           0 :             res = validate_simple_stmt(tree);
    1429             :         else
    1430           0 :             res = validate_compound_stmt(tree);
    1431             :     }
    1432           0 :     return (res);
    1433             : }
    1434             : 
    1435             : 
    1436             : /*  small_stmt (';' small_stmt)* [';'] NEWLINE
    1437             :  *
    1438             :  */
    1439             : static int
    1440           0 : validate_simple_stmt(node *tree)
    1441             : {
    1442           0 :     int nch = NCH(tree);
    1443           0 :     int res = (validate_ntype(tree, simple_stmt)
    1444           0 :                && (nch >= 2)
    1445           0 :                && validate_small_stmt(CHILD(tree, 0))
    1446           0 :                && validate_newline(CHILD(tree, nch - 1)));
    1447             : 
    1448           0 :     if (nch < 2)
    1449           0 :         res = validate_numnodes(tree, 2, "simple_stmt");
    1450           0 :     --nch;                              /* forget the NEWLINE    */
    1451           0 :     if (res && is_even(nch))
    1452           0 :         res = validate_semi(CHILD(tree, --nch));
    1453           0 :     if (res && (nch > 2)) {
    1454             :         int i;
    1455             : 
    1456           0 :         for (i = 1; res && (i < nch); i += 2)
    1457           0 :             res = (validate_semi(CHILD(tree, i))
    1458           0 :                    && validate_small_stmt(CHILD(tree, i + 1)));
    1459             :     }
    1460           0 :     return (res);
    1461             : }
    1462             : 
    1463             : 
    1464             : static int
    1465           0 : validate_small_stmt(node *tree)
    1466             : {
    1467           0 :     int nch = NCH(tree);
    1468           0 :     int res = validate_numnodes(tree, 1, "small_stmt");
    1469             : 
    1470           0 :     if (res) {
    1471           0 :         int ntype = TYPE(CHILD(tree, 0));
    1472             : 
    1473           0 :         if (  (ntype == expr_stmt)
    1474           0 :               || (ntype == del_stmt)
    1475           0 :               || (ntype == pass_stmt)
    1476           0 :               || (ntype == flow_stmt)
    1477           0 :               || (ntype == import_stmt)
    1478           0 :               || (ntype == global_stmt)
    1479           0 :               || (ntype == nonlocal_stmt)
    1480           0 :               || (ntype == assert_stmt))
    1481           0 :             res = validate_node(CHILD(tree, 0));
    1482             :         else {
    1483           0 :             res = 0;
    1484           0 :             err_string("illegal small_stmt child type");
    1485             :         }
    1486             :     }
    1487           0 :     else if (nch == 1) {
    1488           0 :         res = 0;
    1489           0 :         PyErr_Format(parser_error,
    1490             :                      "Unrecognized child node of small_stmt: %d.",
    1491           0 :                      TYPE(CHILD(tree, 0)));
    1492             :     }
    1493           0 :     return (res);
    1494             : }
    1495             : 
    1496             : 
    1497             : /*  compound_stmt:
    1498             :  *      if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
    1499             :  */
    1500             : static int
    1501           0 : validate_compound_stmt(node *tree)
    1502             : {
    1503           0 :     int res = (validate_ntype(tree, compound_stmt)
    1504           0 :                && validate_numnodes(tree, 1, "compound_stmt"));
    1505             :     int ntype;
    1506             : 
    1507           0 :     if (!res)
    1508           0 :         return (0);
    1509             : 
    1510           0 :     tree = CHILD(tree, 0);
    1511           0 :     ntype = TYPE(tree);
    1512           0 :     if (  (ntype == if_stmt)
    1513           0 :           || (ntype == while_stmt)
    1514           0 :           || (ntype == for_stmt)
    1515           0 :           || (ntype == try_stmt)
    1516           0 :           || (ntype == with_stmt)
    1517           0 :           || (ntype == funcdef)
    1518           0 :           || (ntype == classdef)
    1519           0 :           || (ntype == decorated))
    1520           0 :         res = validate_node(tree);
    1521             :     else {
    1522           0 :         res = 0;
    1523           0 :         PyErr_Format(parser_error,
    1524           0 :                      "Illegal compound statement type: %d.", TYPE(tree));
    1525             :     }
    1526           0 :     return (res);
    1527             : }
    1528             : 
    1529             : static int
    1530           0 : validate_yield_or_testlist(node *tree, int tse)
    1531             : {
    1532           0 :     if (TYPE(tree) == yield_expr) {
    1533           0 :         return validate_yield_expr(tree);
    1534             :     }
    1535             :     else {
    1536           0 :         if (tse)
    1537           0 :             return validate_testlist_star_expr(tree);
    1538             :         else
    1539           0 :             return validate_testlist(tree);
    1540             :     }
    1541             : }
    1542             : 
    1543             : static int
    1544           0 : validate_expr_stmt(node *tree)
    1545             : {
    1546             :     int j;
    1547           0 :     int nch = NCH(tree);
    1548           0 :     int res = (validate_ntype(tree, expr_stmt)
    1549           0 :                && is_odd(nch)
    1550           0 :                && validate_testlist_star_expr(CHILD(tree, 0)));
    1551             : 
    1552           0 :     if (res && nch == 3
    1553           0 :         && TYPE(CHILD(tree, 1)) == augassign) {
    1554           0 :         res = validate_numnodes(CHILD(tree, 1), 1, "augassign")
    1555           0 :             && validate_yield_or_testlist(CHILD(tree, 2), 0);
    1556             : 
    1557           0 :         if (res) {
    1558           0 :             char *s = STR(CHILD(CHILD(tree, 1), 0));
    1559             : 
    1560           0 :             res = (strcmp(s, "+=") == 0
    1561           0 :                    || strcmp(s, "-=") == 0
    1562           0 :                    || strcmp(s, "*=") == 0
    1563           0 :                    || strcmp(s, "/=") == 0
    1564           0 :                    || strcmp(s, "//=") == 0
    1565           0 :                    || strcmp(s, "%=") == 0
    1566           0 :                    || strcmp(s, "&=") == 0
    1567           0 :                    || strcmp(s, "|=") == 0
    1568           0 :                    || strcmp(s, "^=") == 0
    1569           0 :                    || strcmp(s, "<<=") == 0
    1570           0 :                    || strcmp(s, ">>=") == 0
    1571           0 :                    || strcmp(s, "**=") == 0);
    1572           0 :             if (!res)
    1573           0 :                 err_string("illegal augmented assignment operator");
    1574             :         }
    1575             :     }
    1576             :     else {
    1577           0 :         for (j = 1; res && (j < nch); j += 2)
    1578           0 :             res = validate_equal(CHILD(tree, j))
    1579           0 :                 && validate_yield_or_testlist(CHILD(tree, j + 1), 1);
    1580             :     }
    1581           0 :     return (res);
    1582             : }
    1583             : 
    1584             : 
    1585             : static int
    1586           0 : validate_del_stmt(node *tree)
    1587             : {
    1588           0 :     return (validate_numnodes(tree, 2, "del_stmt")
    1589           0 :             && validate_name(CHILD(tree, 0), "del")
    1590           0 :             && validate_exprlist(CHILD(tree, 1)));
    1591             : }
    1592             : 
    1593             : 
    1594             : static int
    1595           0 : validate_return_stmt(node *tree)
    1596             : {
    1597           0 :     int nch = NCH(tree);
    1598           0 :     int res = (validate_ntype(tree, return_stmt)
    1599           0 :                && ((nch == 1) || (nch == 2))
    1600           0 :                && validate_name(CHILD(tree, 0), "return"));
    1601             : 
    1602           0 :     if (res && (nch == 2))
    1603           0 :         res = validate_testlist(CHILD(tree, 1));
    1604             : 
    1605           0 :     return (res);
    1606             : }
    1607             : 
    1608             : 
    1609             : /*
    1610             :  *  raise_stmt:
    1611             :  *
    1612             :  *  'raise' [test ['from' test]]
    1613             :  */
    1614             : static int
    1615           0 : validate_raise_stmt(node *tree)
    1616             : {
    1617           0 :     int nch = NCH(tree);
    1618           0 :     int res = (validate_ntype(tree, raise_stmt)
    1619           0 :                && ((nch == 1) || (nch == 2) || (nch == 4)));
    1620             : 
    1621           0 :     if (!res && !PyErr_Occurred())
    1622           0 :         (void) validate_numnodes(tree, 2, "raise");
    1623             : 
    1624           0 :     if (res) {
    1625           0 :         res = validate_name(CHILD(tree, 0), "raise");
    1626           0 :         if (res && (nch >= 2))
    1627           0 :             res = validate_test(CHILD(tree, 1));
    1628           0 :         if (res && (nch == 4)) {
    1629           0 :             res = (validate_name(CHILD(tree, 2), "from")
    1630           0 :                    && validate_test(CHILD(tree, 3)));
    1631             :         }
    1632             :     }
    1633           0 :     return (res);
    1634             : }
    1635             : 
    1636             : 
    1637             : /* yield_expr: 'yield' [yield_arg]
    1638             :  */
    1639             : static int
    1640           0 : validate_yield_expr(node *tree)
    1641             : {
    1642           0 :     int nch = NCH(tree);
    1643           0 :     if (nch < 1 || nch > 2)
    1644           0 :         return 0;
    1645           0 :     if (!validate_ntype(tree, yield_expr))
    1646           0 :         return 0;
    1647           0 :     if (!validate_name(CHILD(tree, 0), "yield"))
    1648           0 :         return 0;
    1649           0 :     if (nch == 2) {
    1650           0 :         if (!validate_yield_arg(CHILD(tree, 1)))
    1651           0 :             return 0;
    1652             :     }
    1653           0 :     return 1;
    1654             : }
    1655             : 
    1656             : /* yield_arg: 'from' test | testlist
    1657             :  */
    1658             : static int
    1659           0 : validate_yield_arg(node *tree)
    1660             : {
    1661           0 :     int nch = NCH(tree);
    1662           0 :     if (!validate_ntype(tree, yield_arg))
    1663           0 :         return 0;
    1664           0 :     switch (nch) {
    1665             :       case 1:
    1666           0 :         if (!validate_testlist(CHILD(tree, nch - 1)))
    1667           0 :             return 0;
    1668           0 :         break;
    1669             :       case 2:
    1670           0 :         if (!validate_name(CHILD(tree, 0), "from"))
    1671           0 :             return 0;
    1672           0 :         if (!validate_test(CHILD(tree, 1)))
    1673           0 :             return 0;
    1674           0 :         break;
    1675             :       default:
    1676           0 :         return 0;
    1677             :     }
    1678           0 :     return 1;
    1679             : }
    1680             : 
    1681             : /* yield_stmt: yield_expr
    1682             :  */
    1683             : static int
    1684           0 : validate_yield_stmt(node *tree)
    1685             : {
    1686           0 :     return (validate_ntype(tree, yield_stmt)
    1687           0 :             && validate_numnodes(tree, 1, "yield_stmt")
    1688           0 :             && validate_yield_expr(CHILD(tree, 0)));
    1689             : }
    1690             : 
    1691             : 
    1692             : static int
    1693           0 : validate_import_as_name(node *tree)
    1694             : {
    1695           0 :     int nch = NCH(tree);
    1696           0 :     int ok = validate_ntype(tree, import_as_name);
    1697             : 
    1698           0 :     if (ok) {
    1699           0 :         if (nch == 1)
    1700           0 :             ok = validate_name(CHILD(tree, 0), NULL);
    1701           0 :         else if (nch == 3)
    1702           0 :             ok = (validate_name(CHILD(tree, 0), NULL)
    1703           0 :                   && validate_name(CHILD(tree, 1), "as")
    1704           0 :                   && validate_name(CHILD(tree, 2), NULL));
    1705             :         else
    1706           0 :             ok = validate_numnodes(tree, 3, "import_as_name");
    1707             :     }
    1708           0 :     return ok;
    1709             : }
    1710             : 
    1711             : 
    1712             : /* dotted_name:  NAME ("." NAME)*
    1713             :  */
    1714             : static int
    1715           0 : validate_dotted_name(node *tree)
    1716             : {
    1717           0 :     int nch = NCH(tree);
    1718           0 :     int res = (validate_ntype(tree, dotted_name)
    1719           0 :                && is_odd(nch)
    1720           0 :                && validate_name(CHILD(tree, 0), NULL));
    1721             :     int i;
    1722             : 
    1723           0 :     for (i = 1; res && (i < nch); i += 2) {
    1724           0 :         res = (validate_dot(CHILD(tree, i))
    1725           0 :                && validate_name(CHILD(tree, i+1), NULL));
    1726             :     }
    1727           0 :     return res;
    1728             : }
    1729             : 
    1730             : 
    1731             : /* dotted_as_name:  dotted_name [NAME NAME]
    1732             :  */
    1733             : static int
    1734           0 : validate_dotted_as_name(node *tree)
    1735             : {
    1736           0 :     int nch = NCH(tree);
    1737           0 :     int res = validate_ntype(tree, dotted_as_name);
    1738             : 
    1739           0 :     if (res) {
    1740           0 :         if (nch == 1)
    1741           0 :             res = validate_dotted_name(CHILD(tree, 0));
    1742           0 :         else if (nch == 3)
    1743           0 :             res = (validate_dotted_name(CHILD(tree, 0))
    1744           0 :                    && validate_name(CHILD(tree, 1), "as")
    1745           0 :                    && validate_name(CHILD(tree, 2), NULL));
    1746             :         else {
    1747           0 :             res = 0;
    1748           0 :             err_string("illegal number of children for dotted_as_name");
    1749             :         }
    1750             :     }
    1751           0 :     return res;
    1752             : }
    1753             : 
    1754             : 
    1755             : /* dotted_as_name (',' dotted_as_name)* */
    1756             : static int
    1757           0 : validate_dotted_as_names(node *tree)
    1758             : {
    1759           0 :         int nch = NCH(tree);
    1760           0 :         int res = is_odd(nch) && validate_dotted_as_name(CHILD(tree, 0));
    1761             :         int i;
    1762             : 
    1763           0 :         for (i = 1; res && (i < nch); i += 2)
    1764           0 :             res = (validate_comma(CHILD(tree, i))
    1765           0 :                    && validate_dotted_as_name(CHILD(tree, i + 1)));
    1766           0 :         return (res);
    1767             : }
    1768             : 
    1769             : 
    1770             : /* import_as_name (',' import_as_name)* [','] */
    1771             : static int
    1772           0 : validate_import_as_names(node *tree)
    1773             : {
    1774           0 :     int nch = NCH(tree);
    1775           0 :     int res = validate_import_as_name(CHILD(tree, 0));
    1776             :     int i;
    1777             : 
    1778           0 :     for (i = 1; res && (i + 1 < nch); i += 2)
    1779           0 :         res = (validate_comma(CHILD(tree, i))
    1780           0 :                && validate_import_as_name(CHILD(tree, i + 1)));
    1781           0 :     return (res);
    1782             : }
    1783             : 
    1784             : 
    1785             : /* 'import' dotted_as_names */
    1786             : static int
    1787           0 : validate_import_name(node *tree)
    1788             : {
    1789           0 :         return (validate_ntype(tree, import_name)
    1790           0 :                 && validate_numnodes(tree, 2, "import_name")
    1791           0 :                 && validate_name(CHILD(tree, 0), "import")
    1792           0 :                 && validate_dotted_as_names(CHILD(tree, 1)));
    1793             : }
    1794             : 
    1795             : /* Helper function to count the number of leading dots (or ellipsis tokens) in
    1796             :  * 'from ...module import name'
    1797             :  */
    1798             : static int
    1799           0 : count_from_dots(node *tree)
    1800             : {
    1801             :     int i;
    1802           0 :     for (i = 1; i < NCH(tree); i++)
    1803           0 :         if (TYPE(CHILD(tree, i)) != DOT && TYPE(CHILD(tree, i)) != ELLIPSIS)
    1804           0 :             break;
    1805           0 :     return i - 1;
    1806             : }
    1807             : 
    1808             : /* import_from: ('from' ('.'* dotted_name | '.'+)
    1809             :  *               'import' ('*' | '(' import_as_names ')' | import_as_names))
    1810             :  */
    1811             : static int
    1812           0 : validate_import_from(node *tree)
    1813             : {
    1814           0 :         int nch = NCH(tree);
    1815           0 :         int ndots = count_from_dots(tree);
    1816           0 :         int havename = (TYPE(CHILD(tree, ndots + 1)) == dotted_name);
    1817           0 :         int offset = ndots + havename;
    1818           0 :         int res = validate_ntype(tree, import_from)
    1819           0 :                 && (offset >= 1)
    1820           0 :                 && (nch >= 3 + offset)
    1821           0 :                 && validate_name(CHILD(tree, 0), "from")
    1822           0 :                 && (!havename || validate_dotted_name(CHILD(tree, ndots + 1)))
    1823           0 :                 && validate_name(CHILD(tree, offset + 1), "import");
    1824             : 
    1825           0 :         if (res && TYPE(CHILD(tree, offset + 2)) == LPAR)
    1826           0 :             res = ((nch == offset + 5)
    1827           0 :                    && validate_lparen(CHILD(tree, offset + 2))
    1828           0 :                    && validate_import_as_names(CHILD(tree, offset + 3))
    1829           0 :                    && validate_rparen(CHILD(tree, offset + 4)));
    1830           0 :         else if (res && TYPE(CHILD(tree, offset + 2)) != STAR)
    1831           0 :             res = validate_import_as_names(CHILD(tree, offset + 2));
    1832           0 :         return (res);
    1833             : }
    1834             : 
    1835             : 
    1836             : /* import_stmt: import_name | import_from */
    1837             : static int
    1838           0 : validate_import_stmt(node *tree)
    1839             : {
    1840           0 :     int nch = NCH(tree);
    1841           0 :     int res = validate_numnodes(tree, 1, "import_stmt");
    1842             : 
    1843           0 :     if (res) {
    1844           0 :         int ntype = TYPE(CHILD(tree, 0));
    1845             : 
    1846           0 :         if (ntype == import_name || ntype == import_from)
    1847           0 :             res = validate_node(CHILD(tree, 0));
    1848             :         else {
    1849           0 :             res = 0;
    1850           0 :             err_string("illegal import_stmt child type");
    1851             :         }
    1852             :     }
    1853           0 :     else if (nch == 1) {
    1854           0 :         res = 0;
    1855           0 :         PyErr_Format(parser_error,
    1856             :                      "Unrecognized child node of import_stmt: %d.",
    1857           0 :                      TYPE(CHILD(tree, 0)));
    1858             :     }
    1859           0 :     return (res);
    1860             : }
    1861             : 
    1862             : 
    1863             : /*  global_stmt:
    1864             :  *
    1865             :  *  'global' NAME (',' NAME)*
    1866             :  */
    1867             : static int
    1868           0 : validate_global_stmt(node *tree)
    1869             : {
    1870             :     int j;
    1871           0 :     int nch = NCH(tree);
    1872           0 :     int res = (validate_ntype(tree, global_stmt)
    1873           0 :                && is_even(nch) && (nch >= 2));
    1874             : 
    1875           0 :     if (!res && !PyErr_Occurred())
    1876           0 :         err_string("illegal global statement");
    1877             : 
    1878           0 :     if (res)
    1879           0 :         res = (validate_name(CHILD(tree, 0), "global")
    1880           0 :                && validate_ntype(CHILD(tree, 1), NAME));
    1881           0 :     for (j = 2; res && (j < nch); j += 2)
    1882           0 :         res = (validate_comma(CHILD(tree, j))
    1883           0 :                && validate_ntype(CHILD(tree, j + 1), NAME));
    1884             : 
    1885           0 :     return (res);
    1886             : }
    1887             : 
    1888             : /*  nonlocal_stmt:
    1889             :  *
    1890             :  *  'nonlocal' NAME (',' NAME)*
    1891             :  */
    1892             : static int
    1893           0 : validate_nonlocal_stmt(node *tree)
    1894             : {
    1895             :     int j;
    1896           0 :     int nch = NCH(tree);
    1897           0 :     int res = (validate_ntype(tree, nonlocal_stmt)
    1898           0 :                && is_even(nch) && (nch >= 2));
    1899             : 
    1900           0 :     if (!res && !PyErr_Occurred())
    1901           0 :         err_string("illegal nonlocal statement");
    1902             : 
    1903           0 :     if (res)
    1904           0 :         res = (validate_name(CHILD(tree, 0), "nonlocal")
    1905           0 :                && validate_ntype(CHILD(tree, 1), NAME));
    1906           0 :     for (j = 2; res && (j < nch); j += 2)
    1907           0 :         res = (validate_comma(CHILD(tree, j))
    1908           0 :                && validate_ntype(CHILD(tree, j + 1), NAME));
    1909             : 
    1910           0 :     return res;
    1911             : }
    1912             : 
    1913             : /*  assert_stmt:
    1914             :  *
    1915             :  *  'assert' test [',' test]
    1916             :  */
    1917             : static int
    1918           0 : validate_assert_stmt(node *tree)
    1919             : {
    1920           0 :     int nch = NCH(tree);
    1921           0 :     int res = (validate_ntype(tree, assert_stmt)
    1922           0 :                && ((nch == 2) || (nch == 4))
    1923           0 :                && (validate_name(CHILD(tree, 0), "assert"))
    1924           0 :                && validate_test(CHILD(tree, 1)));
    1925             : 
    1926           0 :     if (!res && !PyErr_Occurred())
    1927           0 :         err_string("illegal assert statement");
    1928           0 :     if (res && (nch > 2))
    1929           0 :         res = (validate_comma(CHILD(tree, 2))
    1930           0 :                && validate_test(CHILD(tree, 3)));
    1931             : 
    1932           0 :     return (res);
    1933             : }
    1934             : 
    1935             : 
    1936             : static int
    1937           0 : validate_while(node *tree)
    1938             : {
    1939           0 :     int nch = NCH(tree);
    1940           0 :     int res = (validate_ntype(tree, while_stmt)
    1941           0 :                && ((nch == 4) || (nch == 7))
    1942           0 :                && validate_name(CHILD(tree, 0), "while")
    1943           0 :                && validate_test(CHILD(tree, 1))
    1944           0 :                && validate_colon(CHILD(tree, 2))
    1945           0 :                && validate_suite(CHILD(tree, 3)));
    1946             : 
    1947           0 :     if (res && (nch == 7))
    1948           0 :         res = (validate_name(CHILD(tree, 4), "else")
    1949           0 :                && validate_colon(CHILD(tree, 5))
    1950           0 :                && validate_suite(CHILD(tree, 6)));
    1951             : 
    1952           0 :     return (res);
    1953             : }
    1954             : 
    1955             : 
    1956             : static int
    1957           0 : validate_for(node *tree)
    1958             : {
    1959           0 :     int nch = NCH(tree);
    1960           0 :     int res = (validate_ntype(tree, for_stmt)
    1961           0 :                && ((nch == 6) || (nch == 9))
    1962           0 :                && validate_name(CHILD(tree, 0), "for")
    1963           0 :                && validate_exprlist(CHILD(tree, 1))
    1964           0 :                && validate_name(CHILD(tree, 2), "in")
    1965           0 :                && validate_testlist(CHILD(tree, 3))
    1966           0 :                && validate_colon(CHILD(tree, 4))
    1967           0 :                && validate_suite(CHILD(tree, 5)));
    1968             : 
    1969           0 :     if (res && (nch == 9))
    1970           0 :         res = (validate_name(CHILD(tree, 6), "else")
    1971           0 :                && validate_colon(CHILD(tree, 7))
    1972           0 :                && validate_suite(CHILD(tree, 8)));
    1973             : 
    1974           0 :     return (res);
    1975             : }
    1976             : 
    1977             : 
    1978             : /*  try_stmt:
    1979             :  *      'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
    1980             :                                                    ['finally' ':' suite]
    1981             :  *    | 'try' ':' suite 'finally' ':' suite
    1982             :  *
    1983             :  */
    1984             : static int
    1985           0 : validate_try(node *tree)
    1986             : {
    1987           0 :     int nch = NCH(tree);
    1988           0 :     int pos = 3;
    1989           0 :     int res = (validate_ntype(tree, try_stmt)
    1990           0 :                && (nch >= 6) && ((nch % 3) == 0));
    1991             : 
    1992           0 :     if (res)
    1993           0 :         res = (validate_name(CHILD(tree, 0), "try")
    1994           0 :                && validate_colon(CHILD(tree, 1))
    1995           0 :                && validate_suite(CHILD(tree, 2))
    1996           0 :                && validate_colon(CHILD(tree, nch - 2))
    1997           0 :                && validate_suite(CHILD(tree, nch - 1)));
    1998           0 :     else if (!PyErr_Occurred()) {
    1999           0 :         const char* name = "except";
    2000           0 :         if (TYPE(CHILD(tree, nch - 3)) != except_clause)
    2001           0 :             name = STR(CHILD(tree, nch - 3));
    2002             : 
    2003           0 :         PyErr_Format(parser_error,
    2004             :                      "Illegal number of children for try/%s node.", name);
    2005             :     }
    2006             :     /* Handle try/finally statement */
    2007           0 :     if (res && (TYPE(CHILD(tree, pos)) == NAME) &&
    2008           0 :         (strcmp(STR(CHILD(tree, pos)), "finally") == 0)) {
    2009           0 :         res = (validate_numnodes(tree, 6, "try/finally")
    2010           0 :                && validate_colon(CHILD(tree, 4))
    2011           0 :                && validate_suite(CHILD(tree, 5)));
    2012           0 :         return (res);
    2013             :     }
    2014             :     /* try/except statement: skip past except_clause sections */
    2015           0 :     while (res && pos < nch && (TYPE(CHILD(tree, pos)) == except_clause)) {
    2016           0 :         res = (validate_except_clause(CHILD(tree, pos))
    2017           0 :                && validate_colon(CHILD(tree, pos + 1))
    2018           0 :                && validate_suite(CHILD(tree, pos + 2)));
    2019           0 :         pos += 3;
    2020             :     }
    2021             :     /* skip else clause */
    2022           0 :     if (res && pos < nch && (TYPE(CHILD(tree, pos)) == NAME) &&
    2023           0 :         (strcmp(STR(CHILD(tree, pos)), "else") == 0)) {
    2024           0 :         res = (validate_colon(CHILD(tree, pos + 1))
    2025           0 :                && validate_suite(CHILD(tree, pos + 2)));
    2026           0 :         pos += 3;
    2027             :     }
    2028           0 :     if (res && pos < nch) {
    2029             :         /* last clause must be a finally */
    2030           0 :         res = (validate_name(CHILD(tree, pos), "finally")
    2031           0 :                && validate_numnodes(tree, pos + 3, "try/except/finally")
    2032           0 :                && validate_colon(CHILD(tree, pos + 1))
    2033           0 :                && validate_suite(CHILD(tree, pos + 2)));
    2034             :     }
    2035           0 :     return (res);
    2036             : }
    2037             : 
    2038             : 
    2039             : static int
    2040           0 : validate_except_clause(node *tree)
    2041             : {
    2042           0 :     int nch = NCH(tree);
    2043           0 :     int res = (validate_ntype(tree, except_clause)
    2044           0 :                && ((nch == 1) || (nch == 2) || (nch == 4))
    2045           0 :                && validate_name(CHILD(tree, 0), "except"));
    2046             : 
    2047           0 :     if (res && (nch > 1))
    2048           0 :         res = validate_test(CHILD(tree, 1));
    2049           0 :     if (res && (nch == 4))
    2050           0 :         res = (validate_name(CHILD(tree, 2), "as")
    2051           0 :                && validate_ntype(CHILD(tree, 3), NAME));
    2052             : 
    2053           0 :     return (res);
    2054             : }
    2055             : 
    2056             : 
    2057             : static int
    2058           0 : validate_test(node *tree)
    2059             : {
    2060           0 :     int nch = NCH(tree);
    2061           0 :     int res = validate_ntype(tree, test) && is_odd(nch);
    2062             : 
    2063           0 :     if (res && (TYPE(CHILD(tree, 0)) == lambdef))
    2064           0 :         res = ((nch == 1)
    2065           0 :                && validate_lambdef(CHILD(tree, 0)));
    2066           0 :     else if (res) {
    2067           0 :         res = validate_or_test(CHILD(tree, 0));
    2068           0 :         res = (res && (nch == 1 || (nch == 5 &&
    2069           0 :             validate_name(CHILD(tree, 1), "if") &&
    2070           0 :             validate_or_test(CHILD(tree, 2)) &&
    2071           0 :             validate_name(CHILD(tree, 3), "else") &&
    2072           0 :             validate_test(CHILD(tree, 4)))));
    2073             :     }
    2074           0 :     return (res);
    2075             : }
    2076             : 
    2077             : static int
    2078           0 : validate_test_nocond(node *tree)
    2079             : {
    2080           0 :     int nch = NCH(tree);
    2081           0 :     int res = validate_ntype(tree, test_nocond) && (nch == 1);
    2082             : 
    2083           0 :     if (res && (TYPE(CHILD(tree, 0)) == lambdef_nocond))
    2084           0 :         res = (validate_lambdef_nocond(CHILD(tree, 0)));
    2085           0 :     else if (res) {
    2086           0 :         res = (validate_or_test(CHILD(tree, 0)));
    2087             :     }
    2088           0 :     return (res);
    2089             : }
    2090             : 
    2091             : static int
    2092           0 : validate_or_test(node *tree)
    2093             : {
    2094           0 :     int nch = NCH(tree);
    2095           0 :     int res = validate_ntype(tree, or_test) && is_odd(nch);
    2096             : 
    2097           0 :     if (res) {
    2098             :         int pos;
    2099           0 :         res = validate_and_test(CHILD(tree, 0));
    2100           0 :         for (pos = 1; res && (pos < nch); pos += 2)
    2101           0 :             res = (validate_name(CHILD(tree, pos), "or")
    2102           0 :                    && validate_and_test(CHILD(tree, pos + 1)));
    2103             :     }
    2104           0 :     return (res);
    2105             : }
    2106             : 
    2107             : 
    2108             : static int
    2109           0 : validate_and_test(node *tree)
    2110             : {
    2111             :     int pos;
    2112           0 :     int nch = NCH(tree);
    2113           0 :     int res = (validate_ntype(tree, and_test)
    2114           0 :                && is_odd(nch)
    2115           0 :                && validate_not_test(CHILD(tree, 0)));
    2116             : 
    2117           0 :     for (pos = 1; res && (pos < nch); pos += 2)
    2118           0 :         res = (validate_name(CHILD(tree, pos), "and")
    2119           0 :                && validate_not_test(CHILD(tree, 0)));
    2120             : 
    2121           0 :     return (res);
    2122             : }
    2123             : 
    2124             : 
    2125             : static int
    2126           0 : validate_not_test(node *tree)
    2127             : {
    2128           0 :     int nch = NCH(tree);
    2129           0 :     int res = validate_ntype(tree, not_test) && ((nch == 1) || (nch == 2));
    2130             : 
    2131           0 :     if (res) {
    2132           0 :         if (nch == 2)
    2133           0 :             res = (validate_name(CHILD(tree, 0), "not")
    2134           0 :                    && validate_not_test(CHILD(tree, 1)));
    2135           0 :         else if (nch == 1)
    2136           0 :             res = validate_comparison(CHILD(tree, 0));
    2137             :     }
    2138           0 :     return (res);
    2139             : }
    2140             : 
    2141             : 
    2142             : static int
    2143           0 : validate_comparison(node *tree)
    2144             : {
    2145             :     int pos;
    2146           0 :     int nch = NCH(tree);
    2147           0 :     int res = (validate_ntype(tree, comparison)
    2148           0 :                && is_odd(nch)
    2149           0 :                && validate_expr(CHILD(tree, 0)));
    2150             : 
    2151           0 :     for (pos = 1; res && (pos < nch); pos += 2)
    2152           0 :         res = (validate_comp_op(CHILD(tree, pos))
    2153           0 :                && validate_expr(CHILD(tree, pos + 1)));
    2154             : 
    2155           0 :     return (res);
    2156             : }
    2157             : 
    2158             : 
    2159             : static int
    2160           0 : validate_comp_op(node *tree)
    2161             : {
    2162           0 :     int res = 0;
    2163           0 :     int nch = NCH(tree);
    2164             : 
    2165           0 :     if (!validate_ntype(tree, comp_op))
    2166           0 :         return (0);
    2167           0 :     if (nch == 1) {
    2168             :         /*
    2169             :          *  Only child will be a terminal with a well-defined symbolic name
    2170             :          *  or a NAME with a string of either 'is' or 'in'
    2171             :          */
    2172           0 :         tree = CHILD(tree, 0);
    2173           0 :         switch (TYPE(tree)) {
    2174             :           case LESS:
    2175             :           case GREATER:
    2176             :           case EQEQUAL:
    2177             :           case EQUAL:
    2178             :           case LESSEQUAL:
    2179             :           case GREATEREQUAL:
    2180             :           case NOTEQUAL:
    2181           0 :               res = 1;
    2182           0 :               break;
    2183             :           case NAME:
    2184           0 :               res = ((strcmp(STR(tree), "in") == 0)
    2185           0 :                      || (strcmp(STR(tree), "is") == 0));
    2186           0 :               if (!res) {
    2187           0 :                   PyErr_Format(parser_error,
    2188             :                                "illegal operator '%s'", STR(tree));
    2189             :               }
    2190           0 :               break;
    2191             :           default:
    2192           0 :               err_string("illegal comparison operator type");
    2193           0 :               break;
    2194             :         }
    2195             :     }
    2196           0 :     else if ((res = validate_numnodes(tree, 2, "comp_op")) != 0) {
    2197           0 :         res = (validate_ntype(CHILD(tree, 0), NAME)
    2198           0 :                && validate_ntype(CHILD(tree, 1), NAME)
    2199           0 :                && (((strcmp(STR(CHILD(tree, 0)), "is") == 0)
    2200           0 :                     && (strcmp(STR(CHILD(tree, 1)), "not") == 0))
    2201           0 :                    || ((strcmp(STR(CHILD(tree, 0)), "not") == 0)
    2202           0 :                        && (strcmp(STR(CHILD(tree, 1)), "in") == 0))));
    2203           0 :         if (!res && !PyErr_Occurred())
    2204           0 :             err_string("unknown comparison operator");
    2205             :     }
    2206           0 :     return (res);
    2207             : }
    2208             : 
    2209             : 
    2210             : static int
    2211           0 : validate_star_expr(node *tree)
    2212             : {
    2213           0 :     int res = validate_ntype(tree, star_expr);
    2214           0 :     if (!res) return res;
    2215           0 :     if (!validate_numnodes(tree, 2, "star_expr"))
    2216           0 :         return 0;
    2217           0 :     return validate_ntype(CHILD(tree, 0), STAR) &&      \
    2218           0 :         validate_expr(CHILD(tree, 1));
    2219             : }
    2220             : 
    2221             : 
    2222             : static int
    2223           0 : validate_expr(node *tree)
    2224             : {
    2225             :     int j;
    2226           0 :     int nch = NCH(tree);
    2227           0 :     int res = (validate_ntype(tree, expr)
    2228           0 :                && is_odd(nch)
    2229           0 :                && validate_xor_expr(CHILD(tree, 0)));
    2230             : 
    2231           0 :     for (j = 2; res && (j < nch); j += 2)
    2232           0 :         res = (validate_xor_expr(CHILD(tree, j))
    2233           0 :                && validate_vbar(CHILD(tree, j - 1)));
    2234             : 
    2235           0 :     return (res);
    2236             : }
    2237             : 
    2238             : 
    2239             : static int
    2240           0 : validate_xor_expr(node *tree)
    2241             : {
    2242             :     int j;
    2243           0 :     int nch = NCH(tree);
    2244           0 :     int res = (validate_ntype(tree, xor_expr)
    2245           0 :                && is_odd(nch)
    2246           0 :                && validate_and_expr(CHILD(tree, 0)));
    2247             : 
    2248           0 :     for (j = 2; res && (j < nch); j += 2)
    2249           0 :         res = (validate_circumflex(CHILD(tree, j - 1))
    2250           0 :                && validate_and_expr(CHILD(tree, j)));
    2251             : 
    2252           0 :     return (res);
    2253             : }
    2254             : 
    2255             : 
    2256             : static int
    2257           0 : validate_and_expr(node *tree)
    2258             : {
    2259             :     int pos;
    2260           0 :     int nch = NCH(tree);
    2261           0 :     int res = (validate_ntype(tree, and_expr)
    2262           0 :                && is_odd(nch)
    2263           0 :                && validate_shift_expr(CHILD(tree, 0)));
    2264             : 
    2265           0 :     for (pos = 1; res && (pos < nch); pos += 2)
    2266           0 :         res = (validate_ampersand(CHILD(tree, pos))
    2267           0 :                && validate_shift_expr(CHILD(tree, pos + 1)));
    2268             : 
    2269           0 :     return (res);
    2270             : }
    2271             : 
    2272             : 
    2273             : static int
    2274           0 : validate_chain_two_ops(node *tree, int (*termvalid)(node *), int op1, int op2)
    2275             :  {
    2276           0 :     int pos = 1;
    2277           0 :     int nch = NCH(tree);
    2278           0 :     int res = (is_odd(nch)
    2279           0 :                && (*termvalid)(CHILD(tree, 0)));
    2280             : 
    2281           0 :     for ( ; res && (pos < nch); pos += 2) {
    2282           0 :         if (TYPE(CHILD(tree, pos)) != op1)
    2283           0 :             res = validate_ntype(CHILD(tree, pos), op2);
    2284           0 :         if (res)
    2285           0 :             res = (*termvalid)(CHILD(tree, pos + 1));
    2286             :     }
    2287           0 :     return (res);
    2288             : }
    2289             : 
    2290             : 
    2291             : static int
    2292           0 : validate_shift_expr(node *tree)
    2293             : {
    2294           0 :     return (validate_ntype(tree, shift_expr)
    2295           0 :             && validate_chain_two_ops(tree, validate_arith_expr,
    2296             :                                       LEFTSHIFT, RIGHTSHIFT));
    2297             : }
    2298             : 
    2299             : 
    2300             : static int
    2301           0 : validate_arith_expr(node *tree)
    2302             : {
    2303           0 :     return (validate_ntype(tree, arith_expr)
    2304           0 :             && validate_chain_two_ops(tree, validate_term, PLUS, MINUS));
    2305             : }
    2306             : 
    2307             : 
    2308             : static int
    2309           0 : validate_term(node *tree)
    2310             : {
    2311           0 :     int pos = 1;
    2312           0 :     int nch = NCH(tree);
    2313           0 :     int res = (validate_ntype(tree, term)
    2314           0 :                && is_odd(nch)
    2315           0 :                && validate_factor(CHILD(tree, 0)));
    2316             : 
    2317           0 :     for ( ; res && (pos < nch); pos += 2)
    2318           0 :         res = (((TYPE(CHILD(tree, pos)) == STAR)
    2319           0 :                || (TYPE(CHILD(tree, pos)) == SLASH)
    2320           0 :                || (TYPE(CHILD(tree, pos)) == DOUBLESLASH)
    2321           0 :                || (TYPE(CHILD(tree, pos)) == PERCENT))
    2322           0 :                && validate_factor(CHILD(tree, pos + 1)));
    2323             : 
    2324           0 :     return (res);
    2325             : }
    2326             : 
    2327             : 
    2328             : /*  factor:
    2329             :  *
    2330             :  *  factor: ('+'|'-'|'~') factor | power
    2331             :  */
    2332             : static int
    2333           0 : validate_factor(node *tree)
    2334             : {
    2335           0 :     int nch = NCH(tree);
    2336           0 :     int res = (validate_ntype(tree, factor)
    2337           0 :                && (((nch == 2)
    2338           0 :                     && ((TYPE(CHILD(tree, 0)) == PLUS)
    2339           0 :                         || (TYPE(CHILD(tree, 0)) == MINUS)
    2340           0 :                         || (TYPE(CHILD(tree, 0)) == TILDE))
    2341           0 :                     && validate_factor(CHILD(tree, 1)))
    2342           0 :                    || ((nch == 1)
    2343           0 :                        && validate_power(CHILD(tree, 0)))));
    2344           0 :     return (res);
    2345             : }
    2346             : 
    2347             : 
    2348             : /*  power:
    2349             :  *
    2350             :  *  power: atom trailer* ('**' factor)*
    2351             :  */
    2352             : static int
    2353           0 : validate_power(node *tree)
    2354             : {
    2355           0 :     int pos = 1;
    2356           0 :     int nch = NCH(tree);
    2357           0 :     int res = (validate_ntype(tree, power) && (nch >= 1)
    2358           0 :                && validate_atom(CHILD(tree, 0)));
    2359             : 
    2360           0 :     while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer))
    2361           0 :         res = validate_trailer(CHILD(tree, pos++));
    2362           0 :     if (res && (pos < nch)) {
    2363           0 :         if (!is_even(nch - pos)) {
    2364           0 :             err_string("illegal number of nodes for 'power'");
    2365           0 :             return (0);
    2366             :         }
    2367           0 :         for ( ; res && (pos < (nch - 1)); pos += 2)
    2368           0 :             res = (validate_doublestar(CHILD(tree, pos))
    2369           0 :                    && validate_factor(CHILD(tree, pos + 1)));
    2370             :     }
    2371           0 :     return (res);
    2372             : }
    2373             : 
    2374             : 
    2375             : static int
    2376           0 : validate_atom(node *tree)
    2377             : {
    2378             :     int pos;
    2379           0 :     int nch = NCH(tree);
    2380           0 :     int res = validate_ntype(tree, atom);
    2381             : 
    2382           0 :     if (res && nch < 1)
    2383           0 :         res = validate_numnodes(tree, nch+1, "atom");
    2384           0 :     if (res) {
    2385           0 :         switch (TYPE(CHILD(tree, 0))) {
    2386             :           case LPAR:
    2387           0 :             res = ((nch <= 3)
    2388           0 :                    && (validate_rparen(CHILD(tree, nch - 1))));
    2389             : 
    2390           0 :             if (res && (nch == 3)) {
    2391           0 :                 if (TYPE(CHILD(tree, 1))==yield_expr)
    2392           0 :                         res = validate_yield_expr(CHILD(tree, 1));
    2393             :                 else
    2394           0 :                         res = validate_testlist_comp(CHILD(tree, 1));
    2395             :             }
    2396           0 :             break;
    2397             :           case LSQB:
    2398           0 :             if (nch == 2)
    2399           0 :                 res = validate_ntype(CHILD(tree, 1), RSQB);
    2400           0 :             else if (nch == 3)
    2401           0 :                 res = (validate_testlist_comp(CHILD(tree, 1))
    2402           0 :                        && validate_ntype(CHILD(tree, 2), RSQB));
    2403             :             else {
    2404           0 :                 res = 0;
    2405           0 :                 err_string("illegal list display atom");
    2406             :             }
    2407           0 :             break;
    2408             :           case LBRACE:
    2409           0 :             res = ((nch <= 3)
    2410           0 :                    && validate_ntype(CHILD(tree, nch - 1), RBRACE));
    2411             : 
    2412           0 :             if (res && (nch == 3))
    2413           0 :                 res = validate_dictorsetmaker(CHILD(tree, 1));
    2414           0 :             break;
    2415             :           case NAME:
    2416             :           case NUMBER:
    2417             :           case ELLIPSIS:
    2418           0 :             res = (nch == 1);
    2419           0 :             break;
    2420             :           case STRING:
    2421           0 :             for (pos = 1; res && (pos < nch); ++pos)
    2422           0 :                 res = validate_ntype(CHILD(tree, pos), STRING);
    2423           0 :             break;
    2424             :           default:
    2425           0 :             res = 0;
    2426           0 :             break;
    2427             :         }
    2428             :     }
    2429           0 :     return (res);
    2430             : }
    2431             : 
    2432             : 
    2433             : /*  testlist_comp:
    2434             :  *    test ( comp_for | (',' test)* [','] )
    2435             :  */
    2436             : static int
    2437           0 : validate_testlist_comp(node *tree)
    2438             : {
    2439           0 :     int nch = NCH(tree);
    2440           0 :     int ok = nch;
    2441             : 
    2442           0 :     if (nch == 0)
    2443           0 :         err_string("missing child nodes of testlist_comp");
    2444             :     else {
    2445           0 :         ok = validate_test_or_star_expr(CHILD(tree, 0));
    2446             :     }
    2447             : 
    2448             :     /*
    2449             :      *  comp_for | (',' test)* [',']
    2450             :      */
    2451           0 :     if (nch == 2 && TYPE(CHILD(tree, 1)) == comp_for)
    2452           0 :         ok = validate_comp_for(CHILD(tree, 1));
    2453             :     else {
    2454             :         /*  (',' test)* [',']  */
    2455           0 :         int i = 1;
    2456           0 :         while (ok && nch - i >= 2) {
    2457           0 :             ok = (validate_comma(CHILD(tree, i))
    2458           0 :                   && validate_test_or_star_expr(CHILD(tree, i+1)));
    2459           0 :             i += 2;
    2460             :         }
    2461           0 :         if (ok && i == nch-1)
    2462           0 :             ok = validate_comma(CHILD(tree, i));
    2463           0 :         else if (i != nch) {
    2464           0 :             ok = 0;
    2465           0 :             err_string("illegal trailing nodes for testlist_comp");
    2466             :         }
    2467             :     }
    2468           0 :     return ok;
    2469             : }
    2470             : 
    2471             : /*  decorator:
    2472             :  *    '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
    2473             :  */
    2474             : static int
    2475           0 : validate_decorator(node *tree)
    2476             : {
    2477             :     int ok;
    2478           0 :     int nch = NCH(tree);
    2479           0 :     ok = (validate_ntype(tree, decorator) &&
    2480           0 :           (nch == 3 || nch == 5 || nch == 6) &&
    2481           0 :           validate_at(CHILD(tree, 0)) &&
    2482           0 :           validate_dotted_name(CHILD(tree, 1)) &&
    2483           0 :           validate_newline(RCHILD(tree, -1)));
    2484             : 
    2485           0 :     if (ok && nch != 3) {
    2486           0 :         ok = (validate_lparen(CHILD(tree, 2)) &&
    2487           0 :               validate_rparen(RCHILD(tree, -2)));
    2488             : 
    2489           0 :         if (ok && nch == 6)
    2490           0 :             ok = validate_arglist(CHILD(tree, 3));
    2491             :     }
    2492             : 
    2493           0 :     return ok;
    2494             : }
    2495             : 
    2496             : /*  decorators:
    2497             :  *    decorator+
    2498             :  */
    2499             : static int
    2500           0 : validate_decorators(node *tree)
    2501             : {
    2502             :     int i, nch, ok;
    2503           0 :     nch = NCH(tree);
    2504           0 :     ok = validate_ntype(tree, decorators) && nch >= 1;
    2505             : 
    2506           0 :     for (i = 0; ok && i < nch; ++i)
    2507           0 :         ok = validate_decorator(CHILD(tree, i));
    2508             : 
    2509           0 :     return ok;
    2510             : }
    2511             : 
    2512             : /*  with_item:
    2513             :  *   test ['as' expr]
    2514             :  */
    2515             : static int
    2516           0 : validate_with_item(node *tree)
    2517             : {
    2518           0 :     int nch = NCH(tree);
    2519           0 :     int ok = (validate_ntype(tree, with_item)
    2520           0 :               && (nch == 1 || nch == 3)
    2521           0 :               && validate_test(CHILD(tree, 0)));
    2522           0 :     if (ok && nch == 3)
    2523           0 :         ok = (validate_name(CHILD(tree, 1), "as")
    2524           0 :               && validate_expr(CHILD(tree, 2)));
    2525           0 :     return ok;
    2526             : }
    2527             : 
    2528             : /*  with_stmt:
    2529             :  *    0      1          ...             -2   -1
    2530             :  *   'with' with_item (',' with_item)* ':' suite
    2531             :  */
    2532             : static int
    2533           0 : validate_with_stmt(node *tree)
    2534             : {
    2535             :     int i;
    2536           0 :     int nch = NCH(tree);
    2537           0 :     int ok = (validate_ntype(tree, with_stmt)
    2538           0 :         && (nch % 2 == 0)
    2539           0 :         && validate_name(CHILD(tree, 0), "with")
    2540           0 :         && validate_colon(RCHILD(tree, -2))
    2541           0 :         && validate_suite(RCHILD(tree, -1)));
    2542           0 :     for (i = 1; ok && i < nch - 2; i += 2)
    2543           0 :         ok = validate_with_item(CHILD(tree, i));
    2544           0 :     return ok;
    2545             : }
    2546             : 
    2547             : /* funcdef: 'def' NAME parameters ['->' test] ':' suite */
    2548             : 
    2549             : static int
    2550           0 : validate_funcdef(node *tree)
    2551             : {
    2552           0 :     int nch = NCH(tree);
    2553           0 :     int res = validate_ntype(tree, funcdef);
    2554           0 :     if (res) {
    2555           0 :         if (nch == 5) {
    2556           0 :             res = (validate_name(CHILD(tree, 0), "def")
    2557           0 :                    && validate_ntype(CHILD(tree, 1), NAME)
    2558           0 :                    && validate_parameters(CHILD(tree, 2))
    2559           0 :                    && validate_colon(CHILD(tree, 3))
    2560           0 :                    && validate_suite(CHILD(tree, 4)));
    2561             :         }
    2562           0 :         else if (nch == 7) {
    2563           0 :             res = (validate_name(CHILD(tree, 0), "def")
    2564           0 :                    && validate_ntype(CHILD(tree, 1), NAME)
    2565           0 :                    && validate_parameters(CHILD(tree, 2))
    2566           0 :                    && validate_rarrow(CHILD(tree, 3))
    2567           0 :                    && validate_test(CHILD(tree, 4))
    2568           0 :                    && validate_colon(CHILD(tree, 5))
    2569           0 :                    && validate_suite(CHILD(tree, 6)));
    2570             :         }
    2571             :         else {
    2572           0 :             res = 0;
    2573           0 :             err_string("illegal number of children for funcdef");
    2574             :         }
    2575             :     }
    2576           0 :     return res;
    2577             : }
    2578             : 
    2579             : 
    2580             : /* decorated
    2581             :  *   decorators (classdef | funcdef)
    2582             :  */
    2583             : static int
    2584           0 : validate_decorated(node *tree)
    2585             : {
    2586           0 :     int nch = NCH(tree);
    2587           0 :     int ok = (validate_ntype(tree, decorated)
    2588           0 :               && (nch == 2)
    2589           0 :               && validate_decorators(RCHILD(tree, -2)));
    2590           0 :     if (TYPE(RCHILD(tree, -1)) == funcdef)
    2591           0 :         ok = ok && validate_funcdef(RCHILD(tree, -1));
    2592             :     else
    2593           0 :         ok = ok && validate_class(RCHILD(tree, -1));
    2594           0 :     return ok;
    2595             : }
    2596             : 
    2597             : static int
    2598           0 : validate_lambdef(node *tree)
    2599             : {
    2600           0 :     int nch = NCH(tree);
    2601           0 :     int res = (validate_ntype(tree, lambdef)
    2602           0 :                && ((nch == 3) || (nch == 4))
    2603           0 :                && validate_name(CHILD(tree, 0), "lambda")
    2604           0 :                && validate_colon(CHILD(tree, nch - 2))
    2605           0 :                && validate_test(CHILD(tree, nch - 1)));
    2606             : 
    2607           0 :     if (res && (nch == 4))
    2608           0 :         res = validate_varargslist(CHILD(tree, 1));
    2609           0 :     else if (!res && !PyErr_Occurred())
    2610           0 :         (void) validate_numnodes(tree, 3, "lambdef");
    2611             : 
    2612           0 :     return (res);
    2613             : }
    2614             : 
    2615             : 
    2616             : static int
    2617           0 : validate_lambdef_nocond(node *tree)
    2618             : {
    2619           0 :     int nch = NCH(tree);
    2620           0 :     int res = (validate_ntype(tree, lambdef_nocond)
    2621           0 :                && ((nch == 3) || (nch == 4))
    2622           0 :                && validate_name(CHILD(tree, 0), "lambda")
    2623           0 :                && validate_colon(CHILD(tree, nch - 2))
    2624           0 :                && validate_test(CHILD(tree, nch - 1)));
    2625             : 
    2626           0 :     if (res && (nch == 4))
    2627           0 :         res = validate_varargslist(CHILD(tree, 1));
    2628           0 :     else if (!res && !PyErr_Occurred())
    2629           0 :         (void) validate_numnodes(tree, 3, "lambdef_nocond");
    2630             : 
    2631           0 :     return (res);
    2632             : }
    2633             : 
    2634             : 
    2635             : /*  arglist:
    2636             :  *
    2637             :  *  (argument ',')* (argument [','] | '*' test [',' '**' test] | '**' test)
    2638             :  */
    2639             : static int
    2640           0 : validate_arglist(node *tree)
    2641             : {
    2642           0 :     int nch = NCH(tree);
    2643           0 :     int i = 0;
    2644           0 :     int ok = 1;
    2645             : 
    2646           0 :     if (nch <= 0)
    2647             :         /* raise the right error from having an invalid number of children */
    2648           0 :         return validate_numnodes(tree, nch + 1, "arglist");
    2649             : 
    2650           0 :     if (nch > 1) {
    2651           0 :         for (i=0; i<nch; i++) {
    2652           0 :             if (TYPE(CHILD(tree, i)) == argument) {
    2653           0 :                 node *ch = CHILD(tree, i);
    2654           0 :                 if (NCH(ch) == 2 && TYPE(CHILD(ch, 1)) == comp_for) {
    2655           0 :                     err_string("need '(', ')' for generator expression");
    2656           0 :                     return 0;
    2657             :                 }
    2658             :             }
    2659             :         }
    2660             :     }
    2661             : 
    2662           0 :     while (ok && nch-i >= 2) {
    2663             :         /* skip leading (argument ',') */
    2664           0 :         ok = (validate_argument(CHILD(tree, i))
    2665           0 :               && validate_comma(CHILD(tree, i+1)));
    2666           0 :         if (ok)
    2667           0 :             i += 2;
    2668             :         else
    2669           0 :             PyErr_Clear();
    2670             :     }
    2671           0 :     ok = 1;
    2672           0 :     if (nch-i > 0) {
    2673             :         /*
    2674             :          * argument | '*' test [',' '**' test] | '**' test
    2675             :          */
    2676           0 :         int sym = TYPE(CHILD(tree, i));
    2677             : 
    2678           0 :         if (sym == argument) {
    2679           0 :             ok = validate_argument(CHILD(tree, i));
    2680           0 :             if (ok && i+1 != nch) {
    2681           0 :                 err_string("illegal arglist specification"
    2682             :                            " (extra stuff on end)");
    2683           0 :                 ok = 0;
    2684             :             }
    2685             :         }
    2686           0 :         else if (sym == STAR) {
    2687           0 :             ok = validate_star(CHILD(tree, i));
    2688           0 :             if (ok && (nch-i == 2))
    2689           0 :                 ok = validate_test(CHILD(tree, i+1));
    2690           0 :             else if (ok && (nch-i == 5))
    2691           0 :                 ok = (validate_test(CHILD(tree, i+1))
    2692           0 :                       && validate_comma(CHILD(tree, i+2))
    2693           0 :                       && validate_doublestar(CHILD(tree, i+3))
    2694           0 :                       && validate_test(CHILD(tree, i+4)));
    2695             :             else {
    2696           0 :                 err_string("illegal use of '*' in arglist");
    2697           0 :                 ok = 0;
    2698             :             }
    2699             :         }
    2700           0 :         else if (sym == DOUBLESTAR) {
    2701           0 :             if (nch-i == 2)
    2702           0 :                 ok = (validate_doublestar(CHILD(tree, i))
    2703           0 :                       && validate_test(CHILD(tree, i+1)));
    2704             :             else {
    2705           0 :                 err_string("illegal use of '**' in arglist");
    2706           0 :                 ok = 0;
    2707             :             }
    2708             :         }
    2709             :         else {
    2710           0 :             err_string("illegal arglist specification");
    2711           0 :             ok = 0;
    2712             :         }
    2713             :     }
    2714           0 :     return (ok);
    2715             : }
    2716             : 
    2717             : 
    2718             : 
    2719             : /*  argument:
    2720             :  *
    2721             :  *  [test '='] test [comp_for]
    2722             :  */
    2723             : static int
    2724           0 : validate_argument(node *tree)
    2725             : {
    2726           0 :     int nch = NCH(tree);
    2727           0 :     int res = (validate_ntype(tree, argument)
    2728           0 :                && ((nch == 1) || (nch == 2) || (nch == 3)));
    2729           0 :     if (res) 
    2730           0 :         res = validate_test(CHILD(tree, 0));
    2731           0 :     if (res && (nch == 2))
    2732           0 :         res = validate_comp_for(CHILD(tree, 1));
    2733           0 :     else if (res && (nch == 3))
    2734           0 :         res = (validate_equal(CHILD(tree, 1))
    2735           0 :                && validate_test(CHILD(tree, 2)));
    2736             : 
    2737           0 :     return (res);
    2738             : }
    2739             : 
    2740             : 
    2741             : 
    2742             : /*  trailer:
    2743             :  *
    2744             :  *  '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
    2745             :  */
    2746             : static int
    2747           0 : validate_trailer(node *tree)
    2748             : {
    2749           0 :     int nch = NCH(tree);
    2750           0 :     int res = validate_ntype(tree, trailer) && ((nch == 2) || (nch == 3));
    2751             : 
    2752           0 :     if (res) {
    2753           0 :         switch (TYPE(CHILD(tree, 0))) {
    2754             :           case LPAR:
    2755           0 :             res = validate_rparen(CHILD(tree, nch - 1));
    2756           0 :             if (res && (nch == 3))
    2757           0 :                 res = validate_arglist(CHILD(tree, 1));
    2758           0 :             break;
    2759             :           case LSQB:
    2760           0 :             res = (validate_numnodes(tree, 3, "trailer")
    2761           0 :                    && validate_subscriptlist(CHILD(tree, 1))
    2762           0 :                    && validate_ntype(CHILD(tree, 2), RSQB));
    2763           0 :             break;
    2764             :           case DOT:
    2765           0 :             res = (validate_numnodes(tree, 2, "trailer")
    2766           0 :                    && validate_ntype(CHILD(tree, 1), NAME));
    2767           0 :             break;
    2768             :           default:
    2769           0 :             res = 0;
    2770           0 :             break;
    2771             :         }
    2772             :     }
    2773             :     else {
    2774           0 :         (void) validate_numnodes(tree, 2, "trailer");
    2775             :     }
    2776           0 :     return (res);
    2777             : }
    2778             : 
    2779             : 
    2780             : /*  subscriptlist:
    2781             :  *
    2782             :  *  subscript (',' subscript)* [',']
    2783             :  */
    2784             : static int
    2785           0 : validate_subscriptlist(node *tree)
    2786             : {
    2787           0 :     return (validate_repeating_list(tree, subscriptlist,
    2788             :                                     validate_subscript, "subscriptlist"));
    2789             : }
    2790             : 
    2791             : 
    2792             : /*  subscript:
    2793             :  *
    2794             :  *  '.' '.' '.' | test | [test] ':' [test] [sliceop]
    2795             :  */
    2796             : static int
    2797           0 : validate_subscript(node *tree)
    2798             : {
    2799           0 :     int offset = 0;
    2800           0 :     int nch = NCH(tree);
    2801           0 :     int res = validate_ntype(tree, subscript) && (nch >= 1) && (nch <= 4);
    2802             : 
    2803           0 :     if (!res) {
    2804           0 :         if (!PyErr_Occurred())
    2805           0 :             err_string("invalid number of arguments for subscript node");
    2806           0 :         return (0);
    2807             :     }
    2808           0 :     if (TYPE(CHILD(tree, 0)) == DOT)
    2809             :         /* take care of ('.' '.' '.') possibility */
    2810           0 :         return (validate_numnodes(tree, 3, "subscript")
    2811           0 :                 && validate_dot(CHILD(tree, 0))
    2812           0 :                 && validate_dot(CHILD(tree, 1))
    2813           0 :                 && validate_dot(CHILD(tree, 2)));
    2814           0 :     if (nch == 1) {
    2815           0 :         if (TYPE(CHILD(tree, 0)) == test)
    2816           0 :             res = validate_test(CHILD(tree, 0));
    2817             :         else
    2818           0 :             res = validate_colon(CHILD(tree, 0));
    2819           0 :         return (res);
    2820             :     }
    2821             :     /*  Must be [test] ':' [test] [sliceop],
    2822             :      *  but at least one of the optional components will
    2823             :      *  be present, but we don't know which yet.
    2824             :      */
    2825           0 :     if ((TYPE(CHILD(tree, 0)) != COLON) || (nch == 4)) {
    2826           0 :         res = validate_test(CHILD(tree, 0));
    2827           0 :         offset = 1;
    2828             :     }
    2829           0 :     if (res)
    2830           0 :         res = validate_colon(CHILD(tree, offset));
    2831           0 :     if (res) {
    2832           0 :         int rem = nch - ++offset;
    2833           0 :         if (rem) {
    2834           0 :             if (TYPE(CHILD(tree, offset)) == test) {
    2835           0 :                 res = validate_test(CHILD(tree, offset));
    2836           0 :                 ++offset;
    2837           0 :                 --rem;
    2838             :             }
    2839           0 :             if (res && rem)
    2840           0 :                 res = validate_sliceop(CHILD(tree, offset));
    2841             :         }
    2842             :     }
    2843           0 :     return (res);
    2844             : }
    2845             : 
    2846             : 
    2847             : static int
    2848           0 : validate_sliceop(node *tree)
    2849             : {
    2850           0 :     int nch = NCH(tree);
    2851           0 :     int res = ((nch == 1) || validate_numnodes(tree, 2, "sliceop"))
    2852           0 :               && validate_ntype(tree, sliceop);
    2853           0 :     if (!res && !PyErr_Occurred()) {
    2854           0 :         res = validate_numnodes(tree, 1, "sliceop");
    2855             :     }
    2856           0 :     if (res)
    2857           0 :         res = validate_colon(CHILD(tree, 0));
    2858           0 :     if (res && (nch == 2))
    2859           0 :         res = validate_test(CHILD(tree, 1));
    2860             : 
    2861           0 :     return (res);
    2862             : }
    2863             : 
    2864             : 
    2865             : static int
    2866           0 : validate_test_or_star_expr(node *n)
    2867             : {
    2868           0 :     if (TYPE(n) == test)
    2869           0 :         return validate_test(n);
    2870           0 :     return validate_star_expr(n);
    2871             : }
    2872             : 
    2873             : static int
    2874           0 : validate_expr_or_star_expr(node *n)
    2875             : {
    2876           0 :     if (TYPE(n) == expr)
    2877           0 :         return validate_expr(n);
    2878           0 :     return validate_star_expr(n);
    2879             : }
    2880             : 
    2881             : 
    2882             : static int
    2883           0 : validate_exprlist(node *tree)
    2884             : {
    2885           0 :     return (validate_repeating_list(tree, exprlist,
    2886             :                                     validate_expr_or_star_expr, "exprlist"));
    2887             : }
    2888             : 
    2889             : /*
    2890             :  *  dictorsetmaker:
    2891             :  *
    2892             :  *  (test ':' test (comp_for | (',' test ':' test)* [','])) |
    2893             :  *  (test (comp_for | (',' test)* [',']))
    2894             :  */
    2895             : static int
    2896           0 : validate_dictorsetmaker(node *tree)
    2897             : {
    2898           0 :     int nch = NCH(tree);
    2899             :     int res;
    2900           0 :     int i = 0;
    2901             : 
    2902           0 :     res = validate_ntype(tree, dictorsetmaker);
    2903           0 :     if (!res)
    2904           0 :         return 0;
    2905             : 
    2906           0 :     if (nch - i < 1) {
    2907           0 :         (void) validate_numnodes(tree, 1, "dictorsetmaker");
    2908           0 :         return 0;
    2909             :     }
    2910             : 
    2911           0 :     res = validate_test(CHILD(tree, i++));
    2912           0 :     if (!res)
    2913           0 :         return 0;
    2914             : 
    2915           0 :     if (nch - i >= 2 && TYPE(CHILD(tree, i)) == COLON) {
    2916             :         /* Dictionary display or dictionary comprehension. */
    2917           0 :         res = (validate_colon(CHILD(tree, i++))
    2918           0 :                && validate_test(CHILD(tree, i++)));
    2919           0 :         if (!res)
    2920           0 :             return 0;
    2921             : 
    2922           0 :         if (nch - i >= 1 && TYPE(CHILD(tree, i)) == comp_for) {
    2923             :             /* Dictionary comprehension. */
    2924           0 :             res = validate_comp_for(CHILD(tree, i++));
    2925           0 :             if (!res)
    2926           0 :                 return 0;
    2927             :         }
    2928             :         else {
    2929             :             /* Dictionary display. */
    2930           0 :             while (nch - i >= 4) {
    2931           0 :                 res = (validate_comma(CHILD(tree, i++))
    2932           0 :                        && validate_test(CHILD(tree, i++))
    2933           0 :                        && validate_colon(CHILD(tree, i++))
    2934           0 :                        && validate_test(CHILD(tree, i++)));
    2935           0 :                 if (!res)
    2936           0 :                     return 0;
    2937             :             }
    2938           0 :             if (nch - i == 1) {
    2939           0 :                 res = validate_comma(CHILD(tree, i++));
    2940           0 :                 if (!res)
    2941           0 :                     return 0;
    2942             :             }
    2943             :         }
    2944             :     }
    2945             :     else {
    2946             :         /* Set display or set comprehension. */
    2947           0 :         if (nch - i >= 1 && TYPE(CHILD(tree, i)) == comp_for) {
    2948             :             /* Set comprehension. */
    2949           0 :             res = validate_comp_for(CHILD(tree, i++));
    2950           0 :             if (!res)
    2951           0 :                 return 0;
    2952             :         }
    2953             :         else {
    2954             :             /* Set display. */
    2955           0 :             while (nch - i >= 2) {
    2956           0 :                 res = (validate_comma(CHILD(tree, i++))
    2957           0 :                        && validate_test(CHILD(tree, i++)));
    2958           0 :                 if (!res)
    2959           0 :                     return 0;
    2960             :             }
    2961           0 :             if (nch - i == 1) {
    2962           0 :                 res = validate_comma(CHILD(tree, i++));
    2963           0 :                 if (!res)
    2964           0 :                     return 0;
    2965             :             }
    2966             :         }
    2967             :     }
    2968             : 
    2969           0 :     if (nch - i > 0) {
    2970           0 :         err_string("Illegal trailing nodes for dictorsetmaker.");
    2971           0 :         return 0;
    2972             :     }
    2973             : 
    2974           0 :     return 1;
    2975             : }
    2976             : 
    2977             : 
    2978             : static int
    2979           0 : validate_eval_input(node *tree)
    2980             : {
    2981             :     int pos;
    2982           0 :     int nch = NCH(tree);
    2983           0 :     int res = (validate_ntype(tree, eval_input)
    2984           0 :                && (nch >= 2)
    2985           0 :                && validate_testlist(CHILD(tree, 0))
    2986           0 :                && validate_ntype(CHILD(tree, nch - 1), ENDMARKER));
    2987             : 
    2988           0 :     for (pos = 1; res && (pos < (nch - 1)); ++pos)
    2989           0 :         res = validate_ntype(CHILD(tree, pos), NEWLINE);
    2990             : 
    2991           0 :     return (res);
    2992             : }
    2993             : 
    2994             : 
    2995             : static int
    2996           0 : validate_node(node *tree)
    2997             : {
    2998           0 :     int   nch  = 0;                     /* num. children on current node  */
    2999           0 :     int   res  = 1;                     /* result value                   */
    3000           0 :     node* next = 0;                     /* node to process after this one */
    3001             : 
    3002           0 :     while (res && (tree != 0)) {
    3003           0 :         nch  = NCH(tree);
    3004           0 :         next = 0;
    3005           0 :         switch (TYPE(tree)) {
    3006             :             /*
    3007             :              *  Definition nodes.
    3008             :              */
    3009             :           case funcdef:
    3010           0 :             res = validate_funcdef(tree);
    3011           0 :             break;
    3012             :           case with_stmt:
    3013           0 :             res = validate_with_stmt(tree);
    3014           0 :             break;
    3015             :           case classdef:
    3016           0 :             res = validate_class(tree);
    3017           0 :             break;
    3018             :           case decorated:
    3019           0 :             res = validate_decorated(tree);
    3020           0 :             break;
    3021             :             /*
    3022             :              *  "Trivial" parse tree nodes.
    3023             :              *  (Why did I call these trivial?)
    3024             :              */
    3025             :           case stmt:
    3026           0 :             res = validate_stmt(tree);
    3027           0 :             break;
    3028             :           case small_stmt:
    3029             :             /*
    3030             :              *  expr_stmt | del_stmt | pass_stmt | flow_stmt |
    3031             :              *  import_stmt | global_stmt | nonlocal_stmt | assert_stmt
    3032             :              */
    3033           0 :             res = validate_small_stmt(tree);
    3034           0 :             break;
    3035             :           case flow_stmt:
    3036           0 :             res  = (validate_numnodes(tree, 1, "flow_stmt")
    3037           0 :                     && ((TYPE(CHILD(tree, 0)) == break_stmt)
    3038           0 :                         || (TYPE(CHILD(tree, 0)) == continue_stmt)
    3039           0 :                         || (TYPE(CHILD(tree, 0)) == yield_stmt)
    3040           0 :                         || (TYPE(CHILD(tree, 0)) == return_stmt)
    3041           0 :                         || (TYPE(CHILD(tree, 0)) == raise_stmt)));
    3042           0 :             if (res)
    3043           0 :                 next = CHILD(tree, 0);
    3044           0 :             else if (nch == 1)
    3045           0 :                 err_string("illegal flow_stmt type");
    3046           0 :             break;
    3047             :           case yield_stmt:
    3048           0 :             res = validate_yield_stmt(tree);
    3049           0 :             break;
    3050             :             /*
    3051             :              *  Compound statements.
    3052             :              */
    3053             :           case simple_stmt:
    3054           0 :             res = validate_simple_stmt(tree);
    3055           0 :             break;
    3056             :           case compound_stmt:
    3057           0 :             res = validate_compound_stmt(tree);
    3058           0 :             break;
    3059             :             /*
    3060             :              *  Fundamental statements.
    3061             :              */
    3062             :           case expr_stmt:
    3063           0 :             res = validate_expr_stmt(tree);
    3064           0 :             break;
    3065             :           case del_stmt:
    3066           0 :             res = validate_del_stmt(tree);
    3067           0 :             break;
    3068             :           case pass_stmt:
    3069           0 :             res = (validate_numnodes(tree, 1, "pass")
    3070           0 :                    && validate_name(CHILD(tree, 0), "pass"));
    3071           0 :             break;
    3072             :           case break_stmt:
    3073           0 :             res = (validate_numnodes(tree, 1, "break")
    3074           0 :                    && validate_name(CHILD(tree, 0), "break"));
    3075           0 :             break;
    3076             :           case continue_stmt:
    3077           0 :             res = (validate_numnodes(tree, 1, "continue")
    3078           0 :                    && validate_name(CHILD(tree, 0), "continue"));
    3079           0 :             break;
    3080             :           case return_stmt:
    3081           0 :             res = validate_return_stmt(tree);
    3082           0 :             break;
    3083             :           case raise_stmt:
    3084           0 :             res = validate_raise_stmt(tree);
    3085           0 :             break;
    3086             :           case import_stmt:
    3087           0 :             res = validate_import_stmt(tree);
    3088           0 :             break;
    3089             :           case import_name:
    3090           0 :             res = validate_import_name(tree);
    3091           0 :             break;
    3092             :           case import_from:
    3093           0 :             res = validate_import_from(tree);
    3094           0 :             break;
    3095             :           case global_stmt:
    3096           0 :             res = validate_global_stmt(tree);
    3097           0 :             break;
    3098             :           case nonlocal_stmt:
    3099           0 :             res = validate_nonlocal_stmt(tree);
    3100           0 :             break;
    3101             :           case assert_stmt:
    3102           0 :             res = validate_assert_stmt(tree);
    3103           0 :             break;
    3104             :           case if_stmt:
    3105           0 :             res = validate_if(tree);
    3106           0 :             break;
    3107             :           case while_stmt:
    3108           0 :             res = validate_while(tree);
    3109           0 :             break;
    3110             :           case for_stmt:
    3111           0 :             res = validate_for(tree);
    3112           0 :             break;
    3113             :           case try_stmt:
    3114           0 :             res = validate_try(tree);
    3115           0 :             break;
    3116             :           case suite:
    3117           0 :             res = validate_suite(tree);
    3118           0 :             break;
    3119             :             /*
    3120             :              *  Expression nodes.
    3121             :              */
    3122             :           case testlist:
    3123           0 :             res = validate_testlist(tree);
    3124           0 :             break;
    3125             :           case yield_expr:
    3126           0 :             res = validate_yield_expr(tree);
    3127           0 :             break;
    3128             :           case test:
    3129           0 :             res = validate_test(tree);
    3130           0 :             break;
    3131             :           case and_test:
    3132           0 :             res = validate_and_test(tree);
    3133           0 :             break;
    3134             :           case not_test:
    3135           0 :             res = validate_not_test(tree);
    3136           0 :             break;
    3137             :           case comparison:
    3138           0 :             res = validate_comparison(tree);
    3139           0 :             break;
    3140             :           case exprlist:
    3141           0 :             res = validate_exprlist(tree);
    3142           0 :             break;
    3143             :           case comp_op:
    3144           0 :             res = validate_comp_op(tree);
    3145           0 :             break;
    3146             :           case expr:
    3147           0 :             res = validate_expr(tree);
    3148           0 :             break;
    3149             :           case xor_expr:
    3150           0 :             res = validate_xor_expr(tree);
    3151           0 :             break;
    3152             :           case and_expr:
    3153           0 :             res = validate_and_expr(tree);
    3154           0 :             break;
    3155             :           case shift_expr:
    3156           0 :             res = validate_shift_expr(tree);
    3157           0 :             break;
    3158             :           case arith_expr:
    3159           0 :             res = validate_arith_expr(tree);
    3160           0 :             break;
    3161             :           case term:
    3162           0 :             res = validate_term(tree);
    3163           0 :             break;
    3164             :           case factor:
    3165           0 :             res = validate_factor(tree);
    3166           0 :             break;
    3167             :           case power:
    3168           0 :             res = validate_power(tree);
    3169           0 :             break;
    3170             :           case atom:
    3171           0 :             res = validate_atom(tree);
    3172           0 :             break;
    3173             : 
    3174             :           default:
    3175             :             /* Hopefully never reached! */
    3176           0 :             err_string("unrecognized node type");
    3177           0 :             res = 0;
    3178           0 :             break;
    3179             :         }
    3180           0 :         tree = next;
    3181             :     }
    3182           0 :     return (res);
    3183             : }
    3184             : 
    3185             : 
    3186             : static int
    3187           0 : validate_expr_tree(node *tree)
    3188             : {
    3189           0 :     int res = validate_eval_input(tree);
    3190             : 
    3191           0 :     if (!res && !PyErr_Occurred())
    3192           0 :         err_string("could not validate expression tuple");
    3193             : 
    3194           0 :     return (res);
    3195             : }
    3196             : 
    3197             : 
    3198             : /*  file_input:
    3199             :  *      (NEWLINE | stmt)* ENDMARKER
    3200             :  */
    3201             : static int
    3202           0 : validate_file_input(node *tree)
    3203             : {
    3204             :     int j;
    3205           0 :     int nch = NCH(tree) - 1;
    3206           0 :     int res = ((nch >= 0)
    3207           0 :                && validate_ntype(CHILD(tree, nch), ENDMARKER));
    3208             : 
    3209           0 :     for (j = 0; res && (j < nch); ++j) {
    3210           0 :         if (TYPE(CHILD(tree, j)) == stmt)
    3211           0 :             res = validate_stmt(CHILD(tree, j));
    3212             :         else
    3213           0 :             res = validate_newline(CHILD(tree, j));
    3214             :     }
    3215             :     /*  This stays in to prevent any internal failures from getting to the
    3216             :      *  user.  Hopefully, this won't be needed.  If a user reports getting
    3217             :      *  this, we have some debugging to do.
    3218             :      */
    3219           0 :     if (!res && !PyErr_Occurred())
    3220           0 :         err_string("VALIDATION FAILURE: report this to the maintainer!");
    3221             : 
    3222           0 :     return (res);
    3223             : }
    3224             : 
    3225             : static int
    3226           0 : validate_encoding_decl(node *tree)
    3227             : {
    3228           0 :     int nch = NCH(tree);
    3229           0 :     int res = ((nch == 1)
    3230           0 :         && validate_file_input(CHILD(tree, 0)));
    3231             : 
    3232           0 :     if (!res && !PyErr_Occurred())
    3233           0 :         err_string("Error Parsing encoding_decl");
    3234             : 
    3235           0 :     return res;
    3236             : }
    3237             : 
    3238             : static PyObject*
    3239             : pickle_constructor = NULL;
    3240             : 
    3241             : 
    3242             : static PyObject*
    3243           0 : parser__pickler(PyObject *self, PyObject *args)
    3244             : {
    3245             :     NOTE(ARGUNUSED(self))
    3246           0 :     PyObject *result = NULL;
    3247           0 :     PyObject *st = NULL;
    3248           0 :     PyObject *empty_dict = NULL;
    3249             : 
    3250           0 :     if (PyArg_ParseTuple(args, "O!:_pickler", &PyST_Type, &st)) {
    3251             :         PyObject *newargs;
    3252             :         PyObject *tuple;
    3253             : 
    3254           0 :         if ((empty_dict = PyDict_New()) == NULL)
    3255           0 :             goto finally;
    3256           0 :         if ((newargs = Py_BuildValue("Oi", st, 1)) == NULL)
    3257           0 :             goto finally;
    3258           0 :         tuple = parser_st2tuple((PyST_Object*)NULL, newargs, empty_dict);
    3259           0 :         if (tuple != NULL) {
    3260           0 :             result = Py_BuildValue("O(O)", pickle_constructor, tuple);
    3261           0 :             Py_DECREF(tuple);
    3262             :         }
    3263           0 :         Py_DECREF(empty_dict);
    3264           0 :         Py_DECREF(newargs);
    3265             :     }
    3266             :   finally:
    3267           0 :     Py_XDECREF(empty_dict);
    3268             : 
    3269           0 :     return (result);
    3270             : }
    3271             : 
    3272             : 
    3273             : /*  Functions exported by this module.  Most of this should probably
    3274             :  *  be converted into an ST object with methods, but that is better
    3275             :  *  done directly in Python, allowing subclasses to be created directly.
    3276             :  *  We'd really have to write a wrapper around it all anyway to allow
    3277             :  *  inheritance.
    3278             :  */
    3279             : static PyMethodDef parser_functions[] =  {
    3280             :     {"compilest",      (PyCFunction)parser_compilest,  PUBLIC_METHOD_TYPE,
    3281             :         PyDoc_STR("Compiles an ST object into a code object.")},
    3282             :     {"expr",            (PyCFunction)parser_expr,      PUBLIC_METHOD_TYPE,
    3283             :         PyDoc_STR("Creates an ST object from an expression.")},
    3284             :     {"isexpr",          (PyCFunction)parser_isexpr,    PUBLIC_METHOD_TYPE,
    3285             :         PyDoc_STR("Determines if an ST object was created from an expression.")},
    3286             :     {"issuite",         (PyCFunction)parser_issuite,   PUBLIC_METHOD_TYPE,
    3287             :         PyDoc_STR("Determines if an ST object was created from a suite.")},
    3288             :     {"suite",           (PyCFunction)parser_suite,     PUBLIC_METHOD_TYPE,
    3289             :         PyDoc_STR("Creates an ST object from a suite.")},
    3290             :     {"sequence2st",     (PyCFunction)parser_tuple2st,  PUBLIC_METHOD_TYPE,
    3291             :         PyDoc_STR("Creates an ST object from a tree representation.")},
    3292             :     {"st2tuple",        (PyCFunction)parser_st2tuple,  PUBLIC_METHOD_TYPE,
    3293             :         PyDoc_STR("Creates a tuple-tree representation of an ST.")},
    3294             :     {"st2list",         (PyCFunction)parser_st2list,   PUBLIC_METHOD_TYPE,
    3295             :         PyDoc_STR("Creates a list-tree representation of an ST.")},
    3296             :     {"tuple2st",        (PyCFunction)parser_tuple2st,  PUBLIC_METHOD_TYPE,
    3297             :         PyDoc_STR("Creates an ST object from a tree representation.")},
    3298             : 
    3299             :     /* private stuff: support pickle module */
    3300             :     {"_pickler",        (PyCFunction)parser__pickler,  METH_VARARGS,
    3301             :         PyDoc_STR("Returns the pickle magic to allow ST objects to be pickled.")},
    3302             : 
    3303             :     {NULL, NULL, 0, NULL}
    3304             :     };
    3305             : 
    3306             : 
    3307             : 
    3308             : static struct PyModuleDef parsermodule = {
    3309             :         PyModuleDef_HEAD_INIT,
    3310             :         "parser",
    3311             :         NULL,
    3312             :         -1,
    3313             :         parser_functions,
    3314             :         NULL,
    3315             :         NULL,
    3316             :         NULL,
    3317             :         NULL
    3318             : };
    3319             : 
    3320             : PyMODINIT_FUNC PyInit_parser(void);  /* supply a prototype */
    3321             : 
    3322             : PyMODINIT_FUNC
    3323           0 : PyInit_parser(void)
    3324             : {
    3325             :     PyObject *module, *copyreg;
    3326             : 
    3327           0 :     if (PyType_Ready(&PyST_Type) < 0)
    3328           0 :         return NULL;
    3329           0 :     module = PyModule_Create(&parsermodule);
    3330           0 :     if (module == NULL)
    3331           0 :         return NULL;
    3332             : 
    3333           0 :     if (parser_error == 0)
    3334           0 :         parser_error = PyErr_NewException("parser.ParserError", NULL, NULL);
    3335             : 
    3336           0 :     if (parser_error == 0)
    3337           0 :         return NULL;
    3338             :     /* CAUTION:  The code next used to skip bumping the refcount on
    3339             :      * parser_error.  That's a disaster if PyInit_parser() gets called more
    3340             :      * than once.  By incref'ing, we ensure that each module dict that
    3341             :      * gets created owns its reference to the shared parser_error object,
    3342             :      * and the file static parser_error vrbl owns a reference too.
    3343             :      */
    3344           0 :     Py_INCREF(parser_error);
    3345           0 :     if (PyModule_AddObject(module, "ParserError", parser_error) != 0)
    3346           0 :         return NULL;
    3347             : 
    3348           0 :     Py_INCREF(&PyST_Type);
    3349           0 :     PyModule_AddObject(module, "STType", (PyObject*)&PyST_Type);
    3350             : 
    3351           0 :     PyModule_AddStringConstant(module, "__copyright__",
    3352             :                                parser_copyright_string);
    3353           0 :     PyModule_AddStringConstant(module, "__doc__",
    3354             :                                parser_doc_string);
    3355           0 :     PyModule_AddStringConstant(module, "__version__",
    3356             :                                parser_version_string);
    3357             : 
    3358             :     /* Register to support pickling.
    3359             :      * If this fails, the import of this module will fail because an
    3360             :      * exception will be raised here; should we clear the exception?
    3361             :      */
    3362           0 :     copyreg = PyImport_ImportModuleNoBlock("copyreg");
    3363           0 :     if (copyreg != NULL) {
    3364             :         PyObject *func, *pickler;
    3365             :         _Py_IDENTIFIER(pickle);
    3366             :         _Py_IDENTIFIER(sequence2st);
    3367             :         _Py_IDENTIFIER(_pickler);
    3368             : 
    3369           0 :         func = _PyObject_GetAttrId(copyreg, &PyId_pickle);
    3370           0 :         pickle_constructor = _PyObject_GetAttrId(module, &PyId_sequence2st);
    3371           0 :         pickler = _PyObject_GetAttrId(module, &PyId__pickler);
    3372           0 :         Py_XINCREF(pickle_constructor);
    3373           0 :         if ((func != NULL) && (pickle_constructor != NULL)
    3374           0 :             && (pickler != NULL)) {
    3375             :             PyObject *res;
    3376             : 
    3377           0 :             res = PyObject_CallFunctionObjArgs(func, &PyST_Type, pickler,
    3378             :                                                pickle_constructor, NULL);
    3379           0 :             Py_XDECREF(res);
    3380             :         }
    3381           0 :         Py_XDECREF(func);
    3382           0 :         Py_XDECREF(pickle_constructor);
    3383           0 :         Py_XDECREF(pickler);
    3384           0 :         Py_DECREF(copyreg);
    3385             :     }
    3386           0 :     return module;
    3387             : }

Generated by: LCOV version 1.10