parsermodule.c revision 268397f5135eec9eb01096e474ffbaf3f57c4fc0
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 "graminit.h"			/* symbols defined in the grammar */
30#include "node.h"			/* internal parser structure	  */
31#include "token.h"			/* token definitions		  */
32					/* ISTERMINAL() / ISNONTERMINAL() */
33#include "compile.h"			/* PyNode_Compile()		  */
34
35#ifdef lint
36#include <note.h>
37#else
38#define NOTE(x)
39#endif
40
41#ifdef macintosh
42char *strdup Py_PROTO((char *));
43#endif
44
45/*  String constants used to initialize module attributes.
46 *
47 */
48static char*
49parser_copyright_string
50= "Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\
51University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\
52Virginia, USA.  Portions copyright 1991-1995 by Stichting Mathematisch\n\
53Centrum, Amsterdam, The Netherlands.";
54
55
56static char*
57parser_doc_string
58= "This is an interface to Python's internal parser.";
59
60static char*
61parser_version_string = "0.4";
62
63
64typedef PyObject* (*SeqMaker) Py_PROTO((int length));
65typedef int (*SeqInserter) Py_PROTO((PyObject* sequence,
66				     int index,
67				     PyObject* element));
68
69/*  The function below is copyrigthed 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/***********************************************************
79Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
80The Netherlands.
81
82                        All Rights Reserved
83
84Permission to use, copy, modify, and distribute this software and its
85documentation for any purpose and without fee is hereby granted,
86provided that the above copyright notice appear in all copies and that
87both that copyright notice and this permission notice appear in
88supporting documentation, and that the names of Stichting Mathematisch
89Centrum or CWI or Corporation for National Research Initiatives or
90CNRI not be used in advertising or publicity pertaining to
91distribution of the software without specific, written prior
92permission.
93
94While CWI is the initial source for this software, a modified version
95is made available by the Corporation for National Research Initiatives
96(CNRI) at the Internet address ftp://ftp.python.org.
97
98STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
99REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
100MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
101CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
102DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
103PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
104TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
105PERFORMANCE OF THIS SOFTWARE.
106
107******************************************************************/
108
109static PyObject*
110node2tuple(n, mkseq, addelem, lineno)
111     node *n;				/* node to convert		 */
112     SeqMaker mkseq;			/* create sequence		 */
113     SeqInserter addelem;		/* func. to add elem. in seq.	 */
114     int lineno;			/* include line numbers?	 */
115{
116    if (n == NULL) {
117	Py_INCREF(Py_None);
118	return (Py_None);
119    }
120    if (ISNONTERMINAL(TYPE(n))) {
121	int i;
122	PyObject *v;
123	PyObject *w;
124
125	v = mkseq(1 + NCH(n));
126	if (v == NULL)
127	    return (v);
128	w = PyInt_FromLong(TYPE(n));
129	if (w == NULL) {
130	    Py_DECREF(v);
131	    return ((PyObject*) NULL);
132	}
133	(void) addelem(v, 0, w);
134	for (i = 0; i < NCH(n); i++) {
135	    w = node2tuple(CHILD(n, i), mkseq, addelem, lineno);
136	    if (w == NULL) {
137		Py_DECREF(v);
138		return ((PyObject*) NULL);
139	    }
140	    (void) addelem(v, i+1, w);
141	}
142	return (v);
143    }
144    else if (ISTERMINAL(TYPE(n))) {
145	PyObject *result = mkseq(2 + lineno);
146	if (result != NULL) {
147	    (void) addelem(result, 0, PyInt_FromLong(TYPE(n)));
148	    (void) addelem(result, 1, PyString_FromString(STR(n)));
149	    if (lineno == 1)
150		(void) addelem(result, 2, PyInt_FromLong(n->n_lineno));
151	}
152	return (result);
153    }
154    else {
155	PyErr_SetString(PyExc_SystemError,
156			"unrecognized parse tree node type");
157	return ((PyObject*) NULL);
158    }
159}   /* node2tuple() */
160/*
161 *  End of material copyrighted by Stichting Mathematisch Centrum.
162 */
163
164
165
166/*  There are two types of intermediate objects we're interested in:
167 *  'eval' and 'exec' types.  These constants can be used in the ast_type
168 *  field of the object type to identify which any given object represents.
169 *  These should probably go in an external header to allow other extensions
170 *  to use them, but then, we really should be using C++ too.  ;-)
171 *
172 *  The PyAST_FRAGMENT type is not currently supported.  Maybe not useful?
173 *  Haven't decided yet.
174 */
175
176#define PyAST_EXPR	1
177#define PyAST_SUITE	2
178#define PyAST_FRAGMENT	3
179
180
181/*  These are the internal objects and definitions required to implement the
182 *  AST type.  Most of the internal names are more reminiscent of the 'old'
183 *  naming style, but the code uses the new naming convention.
184 */
185
186static PyObject*
187parser_error = 0;
188
189
190typedef struct _PyAST_Object {
191
192    PyObject_HEAD			/* standard object header	    */
193    node* ast_node;			/* the node* returned by the parser */
194    int	  ast_type;			/* EXPR or SUITE ?		    */
195
196} PyAST_Object;
197
198
199staticforward void
200parser_free Py_PROTO((PyAST_Object *ast));
201
202staticforward int
203parser_compare Py_PROTO((PyAST_Object *left, PyAST_Object *right));
204
205staticforward PyObject *
206parser_getattr Py_PROTO((PyObject *self, char *name));
207
208
209static
210PyTypeObject PyAST_Type = {
211
212    PyObject_HEAD_INIT(&PyType_Type)
213    0,
214    "ast",				/* tp_name		*/
215    (int) sizeof(PyAST_Object),		/* tp_basicsize		*/
216    0,					/* tp_itemsize		*/
217    (destructor)parser_free,		/* tp_dealloc		*/
218    0,					/* tp_print		*/
219    parser_getattr,			/* tp_getattr		*/
220    0,					/* tp_setattr		*/
221    (cmpfunc)parser_compare,		/* tp_compare		*/
222    0,					/* tp_repr		*/
223    0,					/* tp_as_number		*/
224    0,					/* tp_as_sequence	*/
225    0,					/* tp_as_mapping	*/
226    0,					/* tp_hash		*/
227    0,					/* tp_call		*/
228    0,					/* tp_str		*/
229    0,					/* tp_getattro		*/
230    0,					/* tp_setattro		*/
231
232    /* Functions to access object as input/output buffer */
233    0,					/* tp_as_buffer		*/
234
235    /* Space for future expansion */
236    0,					/* tp_xxx4		*/
237
238    /* __doc__ */
239    "Intermediate representation of a Python parse tree."
240
241};  /* PyAST_Type */
242
243
244static int
245parser_compare_nodes(left, right)
246     node *left;
247     node *right;
248{
249    int j;
250
251    if (TYPE(left) < TYPE(right))
252	return (-1);
253
254    if (TYPE(right) < TYPE(left))
255	return (1);
256
257    if (ISTERMINAL(TYPE(left)))
258	return (strcmp(STR(left), STR(right)));
259
260    if (NCH(left) < NCH(right))
261	return (-1);
262
263    if (NCH(right) < NCH(left))
264	return (1);
265
266    for (j = 0; j < NCH(left); ++j) {
267	int v = parser_compare_nodes(CHILD(left, j), CHILD(right, j));
268
269	if (v != NULL)
270	    return (v);
271    }
272    return (0);
273
274}   /* parser_compare_nodes() */
275
276
277/*  int parser_compare(PyAST_Object* left, PyAST_Object* right)
278 *
279 *  Comparison function used by the Python operators ==, !=, <, >, <=, >=
280 *  This really just wraps a call to parser_compare_nodes() with some easy
281 *  checks and protection code.
282 *
283 */
284static int
285parser_compare(left, right)
286     PyAST_Object *left;
287     PyAST_Object *right;
288{
289    if (left == right)
290	return (0);
291
292    if ((left == 0) || (right == 0))
293	return (-1);
294
295    return (parser_compare_nodes(left->ast_node, right->ast_node));
296
297}   /* parser_compare() */
298
299
300/*  parser_newastobject(node* ast)
301 *
302 *  Allocates a new Python object representing an AST.  This is simply the
303 *  'wrapper' object that holds a node* and allows it to be passed around in
304 *  Python code.
305 *
306 */
307static PyObject*
308parser_newastobject(ast, type)
309     node *ast;
310     int type;
311{
312    PyAST_Object* o = PyObject_NEW(PyAST_Object, &PyAST_Type);
313
314    if (o != 0) {
315	o->ast_node = ast;
316	o->ast_type = type;
317    }
318    else {
319	PyNode_Free(ast);
320    }
321    return ((PyObject*)o);
322
323}   /* parser_newastobject() */
324
325
326/*  void parser_free(PyAST_Object* ast)
327 *
328 *  This is called by a del statement that reduces the reference count to 0.
329 *
330 */
331static void
332parser_free(ast)
333     PyAST_Object *ast;
334{
335    PyNode_Free(ast->ast_node);
336    PyMem_DEL(ast);
337
338}   /* parser_free() */
339
340
341/*  parser_ast2tuple(PyObject* self, PyObject* args)
342 *
343 *  This provides conversion from a node* to a tuple object that can be
344 *  returned to the Python-level caller.  The AST object is not modified.
345 *
346 */
347static PyObject*
348parser_ast2tuple(self, args)
349     PyAST_Object *self;
350     PyObject *args;
351{
352    PyObject *line_option = 0;
353    PyObject *res = 0;
354    int ok;
355
356    if (self == NULL) {
357	ok = PyArg_ParseTuple(
358		args, "O!|O:ast2tuple", &PyAST_Type, &self, &line_option);
359    }
360    else
361	ok = PyArg_ParseTuple(args, "|O:totuple", &line_option);
362    if (ok != 0) {
363	int lineno = 0;
364	if (line_option != NULL) {
365	    lineno = (PyObject_IsTrue(line_option) != 0) ? 1 : 0;
366	}
367	/*
368	 *  Convert AST into a tuple representation.  Use Guido's function,
369	 *  since it's known to work already.
370	 */
371	res = node2tuple(((PyAST_Object*)self)->ast_node,
372			 PyTuple_New, PyTuple_SetItem, lineno);
373    }
374    return (res);
375
376}   /* parser_ast2tuple() */
377
378
379/*  parser_ast2tuple(PyObject* self, PyObject* args)
380 *
381 *  This provides conversion from a node* to a tuple object that can be
382 *  returned to the Python-level caller.  The AST object is not modified.
383 *
384 */
385static PyObject*
386parser_ast2list(self, args)
387     PyAST_Object *self;
388     PyObject *args;
389{
390    PyObject *line_option = 0;
391    PyObject *res = 0;
392    int ok;
393
394    if (self == NULL)
395	ok = PyArg_ParseTuple(
396		args, "O!|O:ast2list", &PyAST_Type, &self, &line_option);
397    else
398	ok = PyArg_ParseTuple(args, "|O:tolist", &line_option);
399    if (ok) {
400	int lineno = 0;
401	if (line_option != 0) {
402	    lineno = PyObject_IsTrue(line_option) ? 1 : 0;
403	}
404	/*
405	 *  Convert AST into a tuple representation.  Use Guido's function,
406	 *  since it's known to work already.
407	 */
408	res = node2tuple(self->ast_node,
409			 PyList_New, PyList_SetItem, lineno);
410    }
411    return (res);
412
413}   /* parser_ast2list() */
414
415
416/*  parser_compileast(PyObject* self, PyObject* args)
417 *
418 *  This function creates code objects from the parse tree represented by
419 *  the passed-in data object.  An optional file name is passed in as well.
420 *
421 */
422static PyObject*
423parser_compileast(self, args)
424     PyAST_Object *self;
425     PyObject *args;
426{
427    PyObject*     res = 0;
428    char*	  str = "<ast>";
429    int ok;
430
431    if (self == NULL)
432	ok = PyArg_ParseTuple(
433		args, "O!|s:compileast", &PyAST_Type, &self, &str);
434    else
435	ok = PyArg_ParseTuple(args, "|s:compile", &str);
436
437    if (ok)
438	res = (PyObject *)PyNode_Compile(self->ast_node, str);
439
440    return (res);
441
442}   /* parser_compileast() */
443
444
445/*  PyObject* parser_isexpr(PyObject* self, PyObject* args)
446 *  PyObject* parser_issuite(PyObject* self, PyObject* args)
447 *
448 *  Checks the passed-in AST object to determine if it is an expression or
449 *  a statement suite, respectively.  The return is a Python truth value.
450 *
451 */
452static PyObject*
453parser_isexpr(self, args)
454     PyAST_Object *self;
455     PyObject *args;
456{
457    PyObject* res = 0;
458    int ok;
459
460    if (self == NULL)
461	ok = PyArg_ParseTuple(args, "O!:isexpr", &PyAST_Type, &self);
462    else
463	ok = PyArg_ParseTuple(args, ":isexpr");
464
465    if (ok) {
466	/* Check to see if the AST represents an expression or not. */
467	res = (self->ast_type == PyAST_EXPR) ? Py_True : Py_False;
468	Py_INCREF(res);
469    }
470    return (res);
471
472}   /* parser_isexpr() */
473
474
475static PyObject*
476parser_issuite(self, args)
477     PyAST_Object *self;
478     PyObject *args;
479{
480    PyObject* res = 0;
481    int ok;
482
483    if (self == NULL)
484	ok = PyArg_ParseTuple(args, "O!:issuite", &PyAST_Type, &self);
485    else
486	ok = PyArg_ParseTuple(args, ":issuite");
487
488    if (ok) {
489	/* Check to see if the AST represents an expression or not. */
490	res = (self->ast_type == PyAST_EXPR) ? Py_False : Py_True;
491	Py_INCREF(res);
492    }
493    return (res);
494
495}   /* parser_issuite() */
496
497
498static PyMethodDef
499parser_methods[] = {
500    {"compile",		(PyCFunction)parser_compileast,	METH_VARARGS,
501	"Compile this AST object into a code object."},
502    {"isexpr",		(PyCFunction)parser_isexpr,	METH_VARARGS,
503	"Determines if this AST object was created from an expression."},
504    {"issuite",		(PyCFunction)parser_issuite,	METH_VARARGS,
505	"Determines if this AST object was created from a suite."},
506    {"tolist",		(PyCFunction)parser_ast2list,	METH_VARARGS,
507	"Creates a list-tree representation of this AST."},
508    {"totuple",		(PyCFunction)parser_ast2tuple,	METH_VARARGS,
509	"Creates a tuple-tree representation of this AST."},
510
511    {NULL, NULL, 0, NULL}
512};
513
514static PyObject*
515parser_method_list = NULL;
516
517
518static PyObject*
519parser_getattr(self, name)
520     PyObject *self;
521     char *name;
522{
523    if (strcmp(name, "__methods__") == 0) {
524	Py_INCREF(parser_method_list);
525	return (parser_method_list);
526    }
527    return (Py_FindMethod(parser_methods, self, name));
528
529}   /* parser_getattr() */
530
531
532/*  err_string(char* message)
533 *
534 *  Sets the error string for an exception of type ParserError.
535 *
536 */
537static void
538err_string(message)
539     char *message;
540{
541    PyErr_SetString(parser_error, message);
542
543}  /* err_string() */
544
545
546/*  PyObject* parser_do_parse(PyObject* args, int type)
547 *
548 *  Internal function to actually execute the parse and return the result if
549 *  successful, or set an exception if not.
550 *
551 */
552static PyObject*
553parser_do_parse(args, type)
554     PyObject *args;
555     int type;
556{
557    char*     string = 0;
558    PyObject* res    = 0;
559
560    if (PyArg_ParseTuple(args, "s", &string)) {
561	node* n = PyParser_SimpleParseString(string,
562					     (type == PyAST_EXPR)
563					     ? eval_input : file_input);
564
565	if (n != 0)
566	    res = parser_newastobject(n, type);
567	else
568	    err_string("Could not parse string.");
569    }
570    return (res);
571
572}  /* parser_do_parse() */
573
574
575/*  PyObject* parser_expr(PyObject* self, PyObject* args)
576 *  PyObject* parser_suite(PyObject* self, PyObject* args)
577 *
578 *  External interfaces to the parser itself.  Which is called determines if
579 *  the parser attempts to recognize an expression ('eval' form) or statement
580 *  suite ('exec' form).  The real work is done by parser_do_parse() above.
581 *
582 */
583static PyObject*
584parser_expr(self, args)
585     PyObject *self;
586     PyObject *args;
587{
588    NOTE(ARGUNUSED(self))
589    return (parser_do_parse(args, PyAST_EXPR));
590
591}   /* parser_expr() */
592
593
594static PyObject*
595parser_suite(self, args)
596     PyObject *self;
597     PyObject *args;
598{
599    NOTE(ARGUNUSED(self))
600    return (parser_do_parse(args, PyAST_SUITE));
601
602}   /* parser_suite() */
603
604
605
606/*  This is the messy part of the code.  Conversion from a tuple to an AST
607 *  object requires that the input tuple be valid without having to rely on
608 *  catching an exception from the compiler.  This is done to allow the
609 *  compiler itself to remain fast, since most of its input will come from
610 *  the parser directly, and therefore be known to be syntactically correct.
611 *  This validation is done to ensure that we don't core dump the compile
612 *  phase, returning an exception instead.
613 *
614 *  Two aspects can be broken out in this code:  creating a node tree from
615 *  the tuple passed in, and verifying that it is indeed valid.  It may be
616 *  advantageous to expand the number of AST types to include funcdefs and
617 *  lambdadefs to take advantage of the optimizer, recognizing those ASTs
618 *  here.  They are not necessary, and not quite as useful in a raw form.
619 *  For now, let's get expressions and suites working reliably.
620 */
621
622
623staticforward node* build_node_tree Py_PROTO((PyObject *tuple));
624staticforward int   validate_expr_tree Py_PROTO((node *tree));
625staticforward int   validate_file_input Py_PROTO((node *tree));
626
627
628/*  PyObject* parser_tuple2ast(PyObject* self, PyObject* args)
629 *
630 *  This is the public function, called from the Python code.  It receives a
631 *  single tuple object from the caller, and creates an AST object if the
632 *  tuple can be validated.  It does this by checking the first code of the
633 *  tuple, and, if acceptable, builds the internal representation.  If this
634 *  step succeeds, the internal representation is validated as fully as
635 *  possible with the various validate_*() routines defined below.
636 *
637 *  This function must be changed if support is to be added for PyAST_FRAGMENT
638 *  AST objects.
639 *
640 */
641static PyObject*
642parser_tuple2ast(self, args)
643     PyObject *self;
644     PyObject *args;
645{
646    NOTE(ARGUNUSED(self))
647    PyObject *ast = 0;
648    PyObject *tuple = 0;
649    PyObject *temp = 0;
650    int ok;
651    int start_sym = 0;
652
653    if (!PyArg_ParseTuple(args, "O:tuple2ast", &tuple))
654	return (0);
655    if (!PySequence_Check(tuple)) {
656	PyErr_SetString(PyExc_ValueError,
657			"tuple2ast() requires a single sequence argument");
658	return (0);
659    }
660    /*
661     *	This mess of tests is written this way so we can use the abstract
662     *	object interface (AOI).  Unfortunately, the AOI increments reference
663     *	counts, which requires that we store a pointer to retrieved object
664     *	so we can DECREF it after the check.  But we really should accept
665     *	lists as well as tuples at the very least.
666     */
667    ok = PyObject_Length(tuple) >= 2;
668    if (ok) {
669	temp = PySequence_GetItem(tuple, 0);
670	ok = (temp != NULL) && PyInt_Check(temp);
671	if (ok)
672	    /* this is used after the initial checks: */
673	    start_sym = PyInt_AsLong(temp);
674	Py_XDECREF(temp);
675    }
676    if (ok) {
677	temp = PySequence_GetItem(tuple, 1);
678	ok = (temp != NULL) && PySequence_Check(temp);
679	Py_XDECREF(temp);
680    }
681    if (ok) {
682	temp = PySequence_GetItem(tuple, 1);
683	ok = (temp != NULL) && PyObject_Length(temp) >= 2;
684	if (ok) {
685	    PyObject *temp2 = PySequence_GetItem(temp, 0);
686	    if (temp2 != NULL) {
687		ok = PyInt_Check(temp2);
688		Py_DECREF(temp2);
689	    }
690	}
691	Py_XDECREF(temp);
692    }
693    /* If we've failed at some point, get out of here. */
694    if (!ok) {
695	err_string("malformed sequence for tuple2ast()");
696	return (0);
697    }
698    /*
699     *  This might be a valid parse tree, but let's do a quick check
700     *  before we jump the gun.
701     */
702    if (start_sym == eval_input) {
703	/*  Might be an eval form.  */
704	node* expression = build_node_tree(tuple);
705
706	if ((expression != 0) && validate_expr_tree(expression))
707	    ast = parser_newastobject(expression, PyAST_EXPR);
708    }
709    else if (start_sym == file_input) {
710	/*  This looks like an exec form so far.  */
711	node* suite_tree = build_node_tree(tuple);
712
713	if ((suite_tree != 0) && validate_file_input(suite_tree))
714	    ast = parser_newastobject(suite_tree, PyAST_SUITE);
715    }
716    else
717	/*  This is a fragment, and is not yet supported.  Maybe they
718	 *  will be if I find a use for them.
719	 */
720	err_string("Fragmentary parse trees not supported.");
721
722    /*  Make sure we throw an exception on all errors.  We should never
723     *  get this, but we'd do well to be sure something is done.
724     */
725    if ((ast == 0) && !PyErr_Occurred())
726	err_string("Unspecified ast error occurred.");
727
728    return (ast);
729
730}   /* parser_tuple2ast() */
731
732
733/*  int check_terminal_tuple()
734 *
735 *  Check a tuple to determine that it is indeed a valid terminal
736 *  node.  The node is known to be required as a terminal, so we throw
737 *  an exception if there is a failure.
738 *
739 *  The format of an acceptable terminal tuple is "(is[i])": the fact
740 *  that elem is a tuple and the integer is a valid terminal symbol
741 *  has been established before this function is called.  We must
742 *  check the length of the tuple and the type of the second element
743 *  and optional third element.  We do *NOT* check the actual text of
744 *  the string element, which we could do in many cases.  This is done
745 *  by the validate_*() functions which operate on the internal
746 *  representation.
747 */
748static int
749check_terminal_tuple(elem)
750     PyObject *elem;
751{
752    int   len = PyObject_Length(elem);
753    int   res = 1;
754    char* str = "Illegal terminal symbol; bad node length.";
755
756    if ((len == 2) || (len == 3)) {
757	PyObject *temp = PySequence_GetItem(elem, 1);
758	res = PyString_Check(temp);
759	str = "Illegal terminal symbol; expected a string.";
760	if (res && (len == 3)) {
761	    PyObject* third = PySequence_GetItem(elem, 2);
762	    res = PyInt_Check(third);
763	    str = "Invalid third element of terminal node.";
764	    Py_XDECREF(third);
765	}
766	Py_XDECREF(temp);
767    }
768    else {
769	res = 0;
770    }
771    if (!res) {
772	elem = Py_BuildValue("(os)", elem, str);
773	PyErr_SetObject(parser_error, elem);
774    }
775    return (res);
776
777}   /* check_terminal_tuple() */
778
779
780/*  node* build_node_children()
781 *
782 *  Iterate across the children of the current non-terminal node and build
783 *  their structures.  If successful, return the root of this portion of
784 *  the tree, otherwise, 0.  Any required exception will be specified already,
785 *  and no memory will have been deallocated.
786 *
787 */
788static node*
789build_node_children(tuple, root, line_num)
790     PyObject *tuple;
791     node *root;
792     int *line_num;
793{
794    int len = PyObject_Length(tuple);
795    int i;
796
797    for (i = 1; i < len; ++i) {
798	/* elem must always be a tuple, however simple */
799	PyObject* elem = PySequence_GetItem(tuple, i);
800	int ok = elem != NULL;
801	long  type = 0;
802	char *strn = 0;
803
804	if (ok)
805	    ok = PySequence_Check(elem);
806	if (ok) {
807	    PyObject *temp = PySequence_GetItem(elem, 0);
808	    if (temp == NULL)
809		ok = 0;
810	    else {
811		ok = PyInt_Check(temp);
812		if (ok)
813		    type = PyInt_AsLong(temp);
814		Py_DECREF(temp);
815	    }
816	}
817	if (!ok) {
818	    PyErr_SetObject(parser_error,
819			    Py_BuildValue("(os)", elem,
820					  "Illegal node construct."));
821	    Py_XDECREF(elem);
822	    return (0);
823	}
824	if (ISTERMINAL(type)) {
825	    if (check_terminal_tuple(elem)) {
826		PyObject *temp = PySequence_GetItem(elem, 1);
827
828		/* check_terminal_tuple() already verified it's a string */
829		strn = (char *)malloc(PyString_GET_SIZE(temp) + 1);
830		if (strn != NULL)
831		    (void) strcpy(strn, PyString_AS_STRING(temp));
832		Py_XDECREF(temp);
833
834		if (PyObject_Length(elem) == 3) {
835		    PyObject* temp = PySequence_GetItem(elem, 2);
836		    *line_num = PyInt_AsLong(temp);
837		    Py_DECREF(temp);
838		}
839	    }
840	    else {
841		Py_XDECREF(elem);
842		return (0);
843	    }
844	}
845	else if (!ISNONTERMINAL(type)) {
846	    /*
847	     *  It has to be one or the other; this is an error.
848	     *  Throw an exception.
849	     */
850	    PyErr_SetObject(parser_error,
851			    Py_BuildValue("(os)", elem,
852					  "Unknown node type."));
853	    Py_XDECREF(elem);
854	    return (0);
855	}
856	PyNode_AddChild(root, type, strn, *line_num);
857
858	if (ISNONTERMINAL(type)) {
859	    node* new_child = CHILD(root, i - 1);
860
861	    if (new_child != build_node_children(elem, new_child, line_num)) {
862		Py_XDECREF(elem);
863		return (0);
864	    }
865	}
866	else if (type == NEWLINE) {	/* It's true:  we increment the     */
867	    ++(*line_num);		/* line number *after* the newline! */
868	}
869	Py_XDECREF(elem);
870    }
871    return (root);
872
873}   /* build_node_children() */
874
875
876static node*
877build_node_tree(tuple)
878     PyObject *tuple;
879{
880    node* res = 0;
881    PyObject *temp = PySequence_GetItem(tuple, 0);
882    long  num = -1;
883
884    if (temp != NULL)
885	num = PyInt_AsLong(temp);
886    Py_XDECREF(temp);
887    if (ISTERMINAL(num)) {
888	/*
889	 *  The tuple is simple, but it doesn't start with a start symbol.
890	 *  Throw an exception now and be done with it.
891	 */
892	tuple = Py_BuildValue("(os)", tuple,
893		    "Illegal ast tuple; cannot start with terminal symbol.");
894	PyErr_SetObject(parser_error, tuple);
895    }
896    else if (ISNONTERMINAL(num)) {
897	/*
898	 *  Not efficient, but that can be handled later.
899	 */
900	int line_num = 0;
901
902	res = PyNode_New(num);
903	if (res != build_node_children(tuple, res, &line_num)) {
904	    PyNode_Free(res);
905	    res = 0;
906	}
907    }
908    else
909	/*  The tuple is illegal -- if the number is neither TERMINAL nor
910	 *  NONTERMINAL, we can't use it.
911	 */
912	PyErr_SetObject(parser_error,
913			Py_BuildValue("(os)", tuple,
914				      "Illegal component tuple."));
915
916    return (res);
917
918}   /* build_node_tree() */
919
920
921#ifdef HAVE_OLD_CPP
922#define VALIDATER(n)    static int validate_/**/n Py_PROTO((node *tree))
923#else
924#define	VALIDATER(n)	static int validate_##n Py_PROTO((node *tree))
925#endif
926
927
928/*
929 *  Validation routines used within the validation section:
930 */
931staticforward int validate_terminal Py_PROTO((node *terminal,
932					      int type, char *string));
933
934#define	validate_ampersand(ch)	validate_terminal(ch,	   AMPER, "&")
935#define	validate_circumflex(ch)	validate_terminal(ch, CIRCUMFLEX, "^")
936#define validate_colon(ch)	validate_terminal(ch,	   COLON, ":")
937#define validate_comma(ch)	validate_terminal(ch,	   COMMA, ",")
938#define validate_dedent(ch)	validate_terminal(ch,	  DEDENT, "")
939#define	validate_equal(ch)	validate_terminal(ch,	   EQUAL, "=")
940#define validate_indent(ch)	validate_terminal(ch,	  INDENT, (char*)NULL)
941#define validate_lparen(ch)	validate_terminal(ch,	    LPAR, "(")
942#define	validate_newline(ch)	validate_terminal(ch,	 NEWLINE, (char*)NULL)
943#define validate_rparen(ch)	validate_terminal(ch,	    RPAR, ")")
944#define validate_semi(ch)	validate_terminal(ch,	    SEMI, ";")
945#define	validate_star(ch)	validate_terminal(ch,	    STAR, "*")
946#define	validate_vbar(ch)	validate_terminal(ch,	    VBAR, "|")
947#define validate_doublestar(ch)	validate_terminal(ch, DOUBLESTAR, "**")
948#define validate_dot(ch)	validate_terminal(ch,	     DOT, ".")
949#define	validate_name(ch, str)	validate_terminal(ch,	    NAME, str)
950
951VALIDATER(node);		VALIDATER(small_stmt);
952VALIDATER(class);		VALIDATER(node);
953VALIDATER(parameters);		VALIDATER(suite);
954VALIDATER(testlist);		VALIDATER(varargslist);
955VALIDATER(fpdef);		VALIDATER(fplist);
956VALIDATER(stmt);		VALIDATER(simple_stmt);
957VALIDATER(expr_stmt);		VALIDATER(power);
958VALIDATER(print_stmt);		VALIDATER(del_stmt);
959VALIDATER(return_stmt);
960VALIDATER(raise_stmt);		VALIDATER(import_stmt);
961VALIDATER(global_stmt);
962VALIDATER(assert_stmt);
963VALIDATER(exec_stmt);		VALIDATER(compound_stmt);
964VALIDATER(while);		VALIDATER(for);
965VALIDATER(try);			VALIDATER(except_clause);
966VALIDATER(test);		VALIDATER(and_test);
967VALIDATER(not_test);		VALIDATER(comparison);
968VALIDATER(comp_op);		VALIDATER(expr);
969VALIDATER(xor_expr);		VALIDATER(and_expr);
970VALIDATER(shift_expr);		VALIDATER(arith_expr);
971VALIDATER(term);		VALIDATER(factor);
972VALIDATER(atom);		VALIDATER(lambdef);
973VALIDATER(trailer);		VALIDATER(subscript);
974VALIDATER(subscriptlist);	VALIDATER(sliceop);
975VALIDATER(exprlist);		VALIDATER(dictmaker);
976VALIDATER(arglist);		VALIDATER(argument);
977
978
979#define	is_even(n)	(((n) & 1) == 0)
980#define	is_odd(n)	(((n) & 1) == 1)
981
982
983static int
984validate_ntype(n, t)
985     node *n;
986     int t;
987{
988    int res = (TYPE(n) == t);
989
990    if (!res) {
991	char buffer[128];
992	(void) sprintf(buffer, "Expected node type %d, got %d.", t, TYPE(n));
993	err_string(buffer);
994    }
995    return (res);
996
997}   /* validate_ntype() */
998
999
1000static int
1001validate_numnodes(n, num, name)
1002     node *n;
1003     int num;
1004     const char *const name;
1005{
1006    if (NCH(n) != num) {
1007	char buff[60];
1008	(void) sprintf(buff, "Illegal number of children for %s node.", name);
1009	err_string(buff);
1010    }
1011    return (NCH(n) == num);
1012
1013}   /* validate_numnodes() */
1014
1015
1016static int
1017validate_terminal(terminal, type, string)
1018     node *terminal;
1019     int type;
1020     char *string;
1021{
1022    int res = (validate_ntype(terminal, type)
1023	       && ((string == 0) || (strcmp(string, STR(terminal)) == 0)));
1024
1025    if (!res && !PyErr_Occurred()) {
1026	char buffer[60];
1027	(void) sprintf(buffer, "Illegal terminal: expected \"%s\"", string);
1028	err_string(buffer);
1029    }
1030    return (res);
1031
1032}   /* validate_terminal() */
1033
1034
1035/*  X (',' X) [',']
1036 */
1037static int
1038validate_repeating_list(tree, ntype, vfunc, name)
1039    node *tree;
1040    int ntype;
1041    int (*vfunc)();
1042    const char *const name;
1043{
1044    int nch = NCH(tree);
1045    int res = (nch && validate_ntype(tree, ntype)
1046	       && vfunc(CHILD(tree, 0)));
1047
1048    if (!res && !PyErr_Occurred())
1049	(void) validate_numnodes(tree, 1, name);
1050    else {
1051	if (is_even(nch))
1052	    res = validate_comma(CHILD(tree, --nch));
1053	if (res && nch > 1) {
1054	    int pos = 1;
1055	    for ( ; res && pos < nch; pos += 2)
1056		res = (validate_comma(CHILD(tree, pos))
1057		       && vfunc(CHILD(tree, pos + 1)));
1058	}
1059    }
1060    return (res);
1061
1062}   /* validate_repeating_list() */
1063
1064
1065/*  VALIDATE(class)
1066 *
1067 *  classdef:
1068 *	'class' NAME ['(' testlist ')'] ':' suite
1069 */
1070static int
1071validate_class(tree)
1072    node *tree;
1073{
1074    int nch = NCH(tree);
1075    int res = validate_ntype(tree, classdef) && ((nch == 4) || (nch == 7));
1076
1077    if (res) {
1078	res = (validate_name(CHILD(tree, 0), "class")
1079	       && validate_ntype(CHILD(tree, 1), NAME)
1080	       && validate_colon(CHILD(tree, nch - 2))
1081	       && validate_suite(CHILD(tree, nch - 1)));
1082    }
1083    else
1084	(void) validate_numnodes(tree, 4, "class");
1085    if (res && (nch == 7)) {
1086	res = (validate_lparen(CHILD(tree, 2))
1087	       && validate_testlist(CHILD(tree, 3))
1088	       && validate_rparen(CHILD(tree, 4)));
1089    }
1090    return (res);
1091
1092}   /* validate_class() */
1093
1094
1095/*  if_stmt:
1096 *	'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
1097 */
1098static int
1099validate_if(tree)
1100    node *tree;
1101{
1102    int nch = NCH(tree);
1103    int res = (validate_ntype(tree, if_stmt)
1104	       && (nch >= 4)
1105	       && validate_name(CHILD(tree, 0), "if")
1106	       && validate_test(CHILD(tree, 1))
1107	       && validate_colon(CHILD(tree, 2))
1108	       && validate_suite(CHILD(tree, 3)));
1109
1110    if (res && ((nch % 4) == 3)) {
1111	/*  ... 'else' ':' suite  */
1112	res = (validate_name(CHILD(tree, nch - 3), "else")
1113	       && validate_colon(CHILD(tree, nch - 2))
1114	       && validate_suite(CHILD(tree, nch - 1)));
1115	nch -= 3;
1116    }
1117    else if (!res && !PyErr_Occurred())
1118	(void) validate_numnodes(tree, 4, "if");
1119    if ((nch % 4) != 0)
1120	/* Will catch the case for nch < 4 */
1121	res = validate_numnodes(tree, 0, "if");
1122    else if (res && (nch > 4)) {
1123	/*  ... ('elif' test ':' suite)+ ...  */
1124	int j = 4;
1125	while ((j < nch) && res) {
1126	    res = (validate_name(CHILD(tree, j), "elif")
1127		   && validate_colon(CHILD(tree, j + 2))
1128		   && validate_test(CHILD(tree, j + 1))
1129		   && validate_suite(CHILD(tree, j + 3)));
1130	    j += 4;
1131	}
1132    }
1133    return (res);
1134
1135}   /* validate_if() */
1136
1137
1138/*  parameters:
1139 *	'(' [varargslist] ')'
1140 *
1141 */
1142static int
1143validate_parameters(tree)
1144    node *tree;
1145{
1146    int nch = NCH(tree);
1147    int res = validate_ntype(tree, parameters) && ((nch == 2) || (nch == 3));
1148
1149    if (res) {
1150	res = (validate_lparen(CHILD(tree, 0))
1151	       && validate_rparen(CHILD(tree, nch - 1)));
1152	if (res && (nch == 3))
1153	    res = validate_varargslist(CHILD(tree, 1));
1154    }
1155    else
1156	(void) validate_numnodes(tree, 2, "parameters");
1157
1158    return (res);
1159
1160}   /* validate_parameters() */
1161
1162
1163/*  VALIDATE(suite)
1164 *
1165 *  suite:
1166 *	simple_stmt
1167 *    | NEWLINE INDENT stmt+ DEDENT
1168 */
1169static int
1170validate_suite(tree)
1171    node *tree;
1172{
1173    int nch = NCH(tree);
1174    int res = (validate_ntype(tree, suite) && ((nch == 1) || (nch >= 4)));
1175
1176    if (res && (nch == 1))
1177	res = validate_simple_stmt(CHILD(tree, 0));
1178    else if (res) {
1179	/*  NEWLINE INDENT stmt+ DEDENT  */
1180	res = (validate_newline(CHILD(tree, 0))
1181	       && validate_indent(CHILD(tree, 1))
1182	       && validate_stmt(CHILD(tree, 2))
1183	       && validate_dedent(CHILD(tree, nch - 1)));
1184
1185	if (res && (nch > 4)) {
1186	    int i = 3;
1187	    --nch;			/* forget the DEDENT	 */
1188	    for ( ; res && (i < nch); ++i)
1189		res = validate_stmt(CHILD(tree, i));
1190	}
1191	else if (nch < 4)
1192	    res = validate_numnodes(tree, 4, "suite");
1193    }
1194    return (res);
1195
1196}   /* validate_suite() */
1197
1198
1199static int
1200validate_testlist(tree)
1201    node *tree;
1202{
1203    return (validate_repeating_list(tree, testlist,
1204				    validate_test, "testlist"));
1205
1206}   /* validate_testlist() */
1207
1208
1209/*  VALIDATE(varargslist)
1210 *
1211 *  varargslist:
1212 *	(fpdef ['=' test] ',')* ('*' NAME [',' '*' '*' NAME] | '*' '*' NAME)
1213 *    | fpdef ['=' test] (',' fpdef ['=' test])* [',']
1214 *
1215 *      (fpdef ['=' test] ',')*
1216 *           ('*' NAME [',' ('**'|'*' '*') NAME]
1217 *         | ('**'|'*' '*') NAME)
1218 *    | fpdef ['=' test] (',' fpdef ['=' test])* [',']
1219 *
1220 */
1221static int
1222validate_varargslist(tree)
1223    node *tree;
1224{
1225    int nch = NCH(tree);
1226    int res = validate_ntype(tree, varargslist) && (nch != 0);
1227
1228    if (res && (nch >= 2) && (TYPE(CHILD(tree, nch - 1)) == NAME)) {
1229	/*  (fpdef ['=' test] ',')*
1230	 *  ('*' NAME [',' '*' '*' NAME] | '*' '*' NAME)
1231	 */
1232	int pos = 0;
1233	int remaining = nch;
1234
1235	while (res && (TYPE(CHILD(tree, pos)) == fpdef)) {
1236	    res = validate_fpdef(CHILD(tree, pos));
1237	    if (res) {
1238		if (TYPE(CHILD(tree, pos + 1)) == EQUAL) {
1239		    res = validate_test(CHILD(tree, pos + 2));
1240		    pos += 2;
1241		}
1242		res = res && validate_comma(CHILD(tree, pos + 1));
1243		pos += 2;
1244	    }
1245	}
1246	if (res) {
1247	    remaining = nch - pos;
1248	    res = ((remaining == 2) || (remaining == 3)
1249		   || (remaining == 5) || (remaining == 6));
1250	    if (!res)
1251		(void) validate_numnodes(tree, 2, "varargslist");
1252	    else if (TYPE(CHILD(tree, pos)) == DOUBLESTAR)
1253		return ((remaining == 2)
1254			&& validate_ntype(CHILD(tree, pos+1), NAME));
1255	    else {
1256		res = validate_star(CHILD(tree, pos++));
1257		--remaining;
1258	    }
1259	}
1260	if (res) {
1261	    if (remaining == 2) {
1262		res = (validate_star(CHILD(tree, pos))
1263		       && validate_ntype(CHILD(tree, pos + 1), NAME));
1264	    }
1265	    else {
1266		res = validate_ntype(CHILD(tree, pos++), NAME);
1267		if (res && (remaining >= 4)) {
1268		    res = validate_comma(CHILD(tree, pos));
1269		    if (--remaining == 3)
1270			res = (validate_star(CHILD(tree, pos + 1))
1271			       && validate_star(CHILD(tree, pos + 2)));
1272		    else
1273			res = validate_ntype(CHILD(tree, pos + 1), DOUBLESTAR);
1274		}
1275	    }
1276	}
1277	if (!res && !PyErr_Occurred())
1278	    err_string("Incorrect validation of variable arguments list.");
1279    }
1280    else if (res) {
1281	/*  fpdef ['=' test] (',' fpdef ['=' test])* [',']  */
1282	if (TYPE(CHILD(tree, nch - 1)) == COMMA)
1283	    --nch;
1284
1285	/*  fpdef ['=' test] (',' fpdef ['=' test])*  */
1286	res = (is_odd(nch)
1287	       && validate_fpdef(CHILD(tree, 0)));
1288
1289	if (res && (nch > 1)) {
1290	    int pos = 1;
1291	    if (TYPE(CHILD(tree, 1)) == EQUAL) {
1292		res = validate_test(CHILD(tree, 2));
1293		pos += 2;
1294	    }
1295	    /*  ... (',' fpdef ['=' test])*  */
1296	    for ( ; res && (pos < nch); pos += 2) {
1297		/* ',' fpdef */
1298		res = (validate_comma(CHILD(tree, pos))
1299		       && validate_fpdef(CHILD(tree, pos + 1)));
1300		if (res
1301		    && ((nch - pos) > 2)
1302		    && (TYPE(CHILD(tree, pos + 2)) == EQUAL)) {
1303		    /* ['=' test] */
1304		    res = validate_test(CHILD(tree, pos + 3));
1305		    pos += 2;
1306		}
1307	    }
1308	}
1309    }
1310    else
1311	err_string("Improperly formed argument list.");
1312
1313    return (res);
1314
1315}   /* validate_varargslist() */
1316
1317
1318/*  VALIDATE(fpdef)
1319 *
1320 *  fpdef:
1321 *	NAME
1322 *    | '(' fplist ')'
1323 */
1324static int
1325validate_fpdef(tree)
1326    node *tree;
1327{
1328    int nch = NCH(tree);
1329    int res = validate_ntype(tree, fpdef);
1330
1331    if (res) {
1332	if (nch == 1)
1333	    res = validate_ntype(CHILD(tree, 0), NAME);
1334	else if (nch == 3)
1335	    res = (validate_lparen(CHILD(tree, 0))
1336		   && validate_fplist(CHILD(tree, 1))
1337		   && validate_rparen(CHILD(tree, 2)));
1338	else
1339	    res = validate_numnodes(tree, 1, "fpdef");
1340    }
1341    return (res);
1342
1343} /* validate_fpdef() */
1344
1345
1346static int
1347validate_fplist(tree)
1348    node *tree;
1349{
1350    return (validate_repeating_list(tree, fplist,
1351				    validate_fpdef, "fplist"));
1352
1353}   /* validate_fplist() */
1354
1355
1356/*  simple_stmt | compound_stmt
1357 *
1358 */
1359static int
1360validate_stmt(tree)
1361    node *tree;
1362{
1363    int res = (validate_ntype(tree, stmt)
1364	       && validate_numnodes(tree, 1, "stmt"));
1365
1366    if (res) {
1367	tree = CHILD(tree, 0);
1368
1369	if (TYPE(tree) == simple_stmt)
1370	    res = validate_simple_stmt(tree);
1371	else
1372	    res = validate_compound_stmt(tree);
1373    }
1374    return (res);
1375
1376}   /* validate_stmt() */
1377
1378
1379/*  small_stmt (';' small_stmt)* [';'] NEWLINE
1380 *
1381 */
1382static int
1383validate_simple_stmt(tree)
1384    node *tree;
1385{
1386    int nch = NCH(tree);
1387    int res = (validate_ntype(tree, simple_stmt)
1388	       && (nch >= 2)
1389	       && validate_small_stmt(CHILD(tree, 0))
1390	       && validate_newline(CHILD(tree, nch - 1)));
1391
1392    if (nch < 2)
1393	res = validate_numnodes(tree, 2, "simple_stmt");
1394    --nch;				/* forget the NEWLINE	 */
1395    if (res && is_even(nch))
1396	res = validate_semi(CHILD(tree, --nch));
1397    if (res && (nch > 2)) {
1398	int i;
1399
1400	for (i = 1; res && (i < nch); i += 2)
1401	    res = (validate_semi(CHILD(tree, i))
1402		   && validate_small_stmt(CHILD(tree, i + 1)));
1403    }
1404    return (res);
1405
1406}   /* validate_simple_stmt() */
1407
1408
1409static int
1410validate_small_stmt(tree)
1411    node *tree;
1412{
1413    int nch = NCH(tree);
1414    int	res = (validate_numnodes(tree, 1, "small_stmt")
1415	       && ((TYPE(CHILD(tree, 0)) == expr_stmt)
1416		   || (TYPE(CHILD(tree, 0)) == print_stmt)
1417		   || (TYPE(CHILD(tree, 0)) == del_stmt)
1418		   || (TYPE(CHILD(tree, 0)) == pass_stmt)
1419		   || (TYPE(CHILD(tree, 0)) == flow_stmt)
1420		   || (TYPE(CHILD(tree, 0)) == import_stmt)
1421		   || (TYPE(CHILD(tree, 0)) == global_stmt)
1422		   || (TYPE(CHILD(tree, 0)) == assert_stmt)
1423		   || (TYPE(CHILD(tree, 0)) == exec_stmt)));
1424
1425    if (res)
1426	res = validate_node(CHILD(tree, 0));
1427    else if (nch == 1) {
1428	char buffer[60];
1429	(void) sprintf(buffer, "Unrecognized child node of small_stmt: %d.",
1430		       TYPE(CHILD(tree, 0)));
1431	err_string(buffer);
1432    }
1433    return (res);
1434
1435}   /* validate_small_stmt */
1436
1437
1438/*  compound_stmt:
1439 *	if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
1440 */
1441static int
1442validate_compound_stmt(tree)
1443    node *tree;
1444{
1445    int res = (validate_ntype(tree, compound_stmt)
1446	       && validate_numnodes(tree, 1, "compound_stmt"));
1447
1448    if (!res)
1449	return (0);
1450
1451    tree = CHILD(tree, 0);
1452    res = ((TYPE(tree) == if_stmt)
1453	   || (TYPE(tree) == while_stmt)
1454	   || (TYPE(tree) == for_stmt)
1455	   || (TYPE(tree) == try_stmt)
1456	   || (TYPE(tree) == funcdef)
1457	   || (TYPE(tree) == classdef));
1458    if (res)
1459	res = validate_node(tree);
1460    else {
1461	char buffer[60];
1462	(void) sprintf(buffer, "Illegal compound statement type: %d.",
1463		       TYPE(tree));
1464	err_string(buffer);
1465    }
1466    return (res);
1467
1468}   /* validate_compound_stmt() */
1469
1470
1471static int
1472validate_expr_stmt(tree)
1473    node *tree;
1474{
1475    int j;
1476    int nch = NCH(tree);
1477    int res = (validate_ntype(tree, expr_stmt)
1478	       && is_odd(nch)
1479	       && validate_testlist(CHILD(tree, 0)));
1480
1481    for (j = 1; res && (j < nch); j += 2)
1482	res = (validate_equal(CHILD(tree, j))
1483	       && validate_testlist(CHILD(tree, j + 1)));
1484
1485    return (res);
1486
1487}   /* validate_expr_stmt() */
1488
1489
1490/*  print_stmt:
1491 *
1492 *	'print' (test ',')* [test]
1493 *
1494 */
1495static int
1496validate_print_stmt(tree)
1497    node *tree;
1498{
1499    int j;
1500    int nch = NCH(tree);
1501    int res = (validate_ntype(tree, print_stmt)
1502	       && (nch != 0)
1503	       && validate_name(CHILD(tree, 0), "print"));
1504
1505    if (res && is_even(nch)) {
1506	res = validate_test(CHILD(tree, nch - 1));
1507	--nch;
1508    }
1509    else if (!res && !PyErr_Occurred())
1510	(void) validate_numnodes(tree, 1, "print_stmt");
1511    for (j = 1; res && (j < nch); j += 2)
1512	res = (validate_test(CHILD(tree, j))
1513	       && validate_ntype(CHILD(tree, j + 1), COMMA));
1514
1515    return (res);
1516
1517}   /* validate_print_stmt() */
1518
1519
1520static int
1521validate_del_stmt(tree)
1522    node *tree;
1523{
1524    return (validate_numnodes(tree, 2, "del_stmt")
1525	    && validate_name(CHILD(tree, 0), "del")
1526	    && validate_exprlist(CHILD(tree, 1)));
1527
1528}   /* validate_del_stmt() */
1529
1530
1531static int
1532validate_return_stmt(tree)
1533    node *tree;
1534{
1535    int nch = NCH(tree);
1536    int res = (validate_ntype(tree, return_stmt)
1537	       && ((nch == 1) || (nch == 2))
1538	       && validate_name(CHILD(tree, 0), "return"));
1539
1540    if (res && (nch == 2))
1541	res = validate_testlist(CHILD(tree, 1));
1542
1543    return (res);
1544
1545}   /* validate_return_stmt() */
1546
1547
1548static int
1549validate_raise_stmt(tree)
1550    node *tree;
1551{
1552    int nch = NCH(tree);
1553    int res = (validate_ntype(tree, raise_stmt)
1554	       && ((nch == 1) || (nch == 2) || (nch == 4) || (nch == 6)));
1555
1556    if (res) {
1557	res = validate_name(CHILD(tree, 0), "raise");
1558	if (res && (nch >= 2))
1559	    res = validate_test(CHILD(tree, 1));
1560	if (res && nch > 2) {
1561	    res = (validate_comma(CHILD(tree, 2))
1562		   && validate_test(CHILD(tree, 3)));
1563	    if (res && (nch > 4))
1564		res = (validate_comma(CHILD(tree, 4))
1565		       && validate_test(CHILD(tree, 5)));
1566	}
1567    }
1568    else
1569	(void) validate_numnodes(tree, 2, "raise");
1570    if (res && (nch == 4))
1571	res = (validate_comma(CHILD(tree, 2))
1572	       && validate_test(CHILD(tree, 3)));
1573
1574    return (res);
1575
1576}   /* validate_raise_stmt() */
1577
1578
1579/*  import_stmt:
1580 *
1581 *    'import' dotted_name (',' dotted_name)*
1582 *  | 'from' dotted_name 'import' ('*' | NAME (',' NAME)*)
1583 */
1584static int
1585validate_import_stmt(tree)
1586    node *tree;
1587{
1588    int nch = NCH(tree);
1589    int res = (validate_ntype(tree, import_stmt)
1590	       && (nch >= 2) && is_even(nch)
1591	       && validate_ntype(CHILD(tree, 0), NAME)
1592	       && validate_ntype(CHILD(tree, 1), dotted_name));
1593
1594    if (res && (strcmp(STR(CHILD(tree, 0)), "import") == 0)) {
1595	int j;
1596
1597	for (j = 2; res && (j < nch); j += 2)
1598	    res = (validate_comma(CHILD(tree, j))
1599		   && validate_ntype(CHILD(tree, j + 1), dotted_name));
1600    }
1601    else if (res && validate_name(CHILD(tree, 0), "from")) {
1602	res = ((nch >= 4) && is_even(nch)
1603	       && validate_name(CHILD(tree, 2), "import"));
1604	if (nch == 4) {
1605	    res = ((TYPE(CHILD(tree, 3)) == NAME)
1606		   || (TYPE(CHILD(tree, 3)) == STAR));
1607	    if (!res)
1608		err_string("Illegal import statement.");
1609	}
1610	else {
1611	    /*  'from' NAME 'import' NAME (',' NAME)+  */
1612	    int j;
1613	    res = validate_ntype(CHILD(tree, 3), NAME);
1614	    for (j = 4; res && (j < nch); j += 2)
1615		res = (validate_comma(CHILD(tree, j))
1616		       && validate_ntype(CHILD(tree, j + 1), NAME));
1617	}
1618    }
1619    else
1620	res = 0;
1621
1622    return (res);
1623
1624}   /* validate_import_stmt() */
1625
1626
1627static int
1628validate_global_stmt(tree)
1629    node *tree;
1630{
1631    int j;
1632    int nch = NCH(tree);
1633    int res = (validate_ntype(tree, global_stmt)
1634	       && is_even(nch) && (nch >= 2));
1635
1636    if (res)
1637	res = (validate_name(CHILD(tree, 0), "global")
1638	       && validate_ntype(CHILD(tree, 1), NAME));
1639    for (j = 2; res && (j < nch); j += 2)
1640	res = (validate_comma(CHILD(tree, j))
1641	       && validate_ntype(CHILD(tree, j + 1), NAME));
1642
1643    return (res);
1644
1645}   /* validate_global_stmt() */
1646
1647
1648/*  exec_stmt:
1649 *
1650 *  'exec' expr ['in' test [',' test]]
1651 */
1652static int
1653validate_exec_stmt(tree)
1654    node *tree;
1655{
1656    int nch = NCH(tree);
1657    int res = (validate_ntype(tree, exec_stmt)
1658	       && ((nch == 2) || (nch == 4) || (nch == 6))
1659	       && validate_name(CHILD(tree, 0), "exec")
1660	       && validate_expr(CHILD(tree, 1)));
1661
1662    if (!res && !PyErr_Occurred())
1663	err_string("Illegal exec statement.");
1664    if (res && (nch > 2))
1665	res = (validate_name(CHILD(tree, 2), "in")
1666	       && validate_test(CHILD(tree, 3)));
1667    if (res && (nch == 6))
1668	res = (validate_comma(CHILD(tree, 4))
1669	       && validate_test(CHILD(tree, 5)));
1670
1671    return (res);
1672
1673}   /* validate_exec_stmt() */
1674
1675
1676/*  assert_stmt:
1677 *
1678 *  'assert' test [',' test]
1679 */
1680static int
1681validate_assert_stmt(tree)
1682    node *tree;
1683{
1684    int nch = NCH(tree);
1685    int res = (validate_ntype(tree, assert_stmt)
1686	       && ((nch == 2) || (nch == 4))
1687	       && (validate_name(CHILD(tree, 0), "__assert__") ||
1688		   validate_name(CHILD(tree, 0), "assert"))
1689	       && validate_test(CHILD(tree, 1)));
1690
1691    if (!res && !PyErr_Occurred())
1692	err_string("Illegal assert statement.");
1693    if (res && (nch > 2))
1694	res = (validate_comma(CHILD(tree, 2))
1695	       && validate_test(CHILD(tree, 3)));
1696
1697    return (res);
1698
1699}   /* validate_assert_stmt() */
1700
1701
1702static int
1703validate_while(tree)
1704    node *tree;
1705{
1706    int nch = NCH(tree);
1707    int res = (validate_ntype(tree, while_stmt)
1708	       && ((nch == 4) || (nch == 7))
1709	       && validate_name(CHILD(tree, 0), "while")
1710	       && validate_test(CHILD(tree, 1))
1711	       && validate_colon(CHILD(tree, 2))
1712	       && validate_suite(CHILD(tree, 3)));
1713
1714    if (res && (nch == 7))
1715	res = (validate_name(CHILD(tree, 4), "else")
1716	       && validate_colon(CHILD(tree, 5))
1717	       && validate_suite(CHILD(tree, 6)));
1718
1719    return (res);
1720
1721}   /* validate_while() */
1722
1723
1724static int
1725validate_for(tree)
1726    node *tree;
1727{
1728    int nch = NCH(tree);
1729    int res = (validate_ntype(tree, for_stmt)
1730	       && ((nch == 6) || (nch == 9))
1731	       && validate_name(CHILD(tree, 0), "for")
1732	       && validate_exprlist(CHILD(tree, 1))
1733	       && validate_name(CHILD(tree, 2), "in")
1734	       && validate_testlist(CHILD(tree, 3))
1735	       && validate_colon(CHILD(tree, 4))
1736	       && validate_suite(CHILD(tree, 5)));
1737
1738    if (res && (nch == 9))
1739	res = (validate_name(CHILD(tree, 6), "else")
1740	       && validate_colon(CHILD(tree, 7))
1741	       && validate_suite(CHILD(tree, 8)));
1742
1743    return (res);
1744
1745}   /* validate_for() */
1746
1747
1748/*  try_stmt:
1749 *	'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
1750 *    | 'try' ':' suite 'finally' ':' suite
1751 *
1752 */
1753static int
1754validate_try(tree)
1755    node *tree;
1756{
1757    int nch = NCH(tree);
1758    int pos = 3;
1759    int res = (validate_ntype(tree, try_stmt)
1760	       && (nch >= 6) && ((nch % 3) == 0));
1761
1762    if (res)
1763	res = (validate_name(CHILD(tree, 0), "try")
1764	       && validate_colon(CHILD(tree, 1))
1765	       && validate_suite(CHILD(tree, 2))
1766	       && validate_colon(CHILD(tree, nch - 2))
1767	       && validate_suite(CHILD(tree, nch - 1)));
1768    else {
1769	const char* name = "execpt";
1770	char buffer[60];
1771	if (TYPE(CHILD(tree, nch - 3)) != except_clause)
1772	    name = STR(CHILD(tree, nch - 3));
1773	(void) sprintf(buffer,
1774		       "Illegal number of children for try/%s node.", name);
1775	err_string(buffer);
1776    }
1777    /*	Skip past except_clause sections:  */
1778    while (res && (TYPE(CHILD(tree, pos)) == except_clause)) {
1779	res = (validate_except_clause(CHILD(tree, pos))
1780	       && validate_colon(CHILD(tree, pos + 1))
1781	       && validate_suite(CHILD(tree, pos + 2)));
1782	pos += 3;
1783    }
1784    if (res && (pos < nch)) {
1785	res = validate_ntype(CHILD(tree, pos), NAME);
1786	if (res && (strcmp(STR(CHILD(tree, pos)), "finally") == 0))
1787	    res = (validate_numnodes(tree, 6, "try/finally")
1788		   && validate_colon(CHILD(tree, 4))
1789		   && validate_suite(CHILD(tree, 5)));
1790	else if (res) {
1791	    if (nch == (pos + 3)) {
1792		res = ((strcmp(STR(CHILD(tree, pos)), "except") == 0)
1793		       || (strcmp(STR(CHILD(tree, pos)), "else") == 0));
1794		if (!res)
1795		    err_string("Illegal trailing triple in try statement.");
1796	    }
1797	    else if (nch == (pos + 6)) {
1798		res = (validate_name(CHILD(tree, pos), "except")
1799		       && validate_colon(CHILD(tree, pos + 1))
1800		       && validate_suite(CHILD(tree, pos + 2))
1801		       && validate_name(CHILD(tree, pos + 3), "else"));
1802	    }
1803	    else
1804		res = validate_numnodes(tree, pos + 3, "try/except");
1805	}
1806    }
1807    return (res);
1808
1809}   /* validate_try() */
1810
1811
1812static int
1813validate_except_clause(tree)
1814    node *tree;
1815{
1816    int nch = NCH(tree);
1817    int res = (validate_ntype(tree, except_clause)
1818	       && ((nch == 1) || (nch == 2) || (nch == 4))
1819	       && validate_name(CHILD(tree, 0), "except"));
1820
1821    if (res && (nch > 1))
1822	res = validate_test(CHILD(tree, 1));
1823    if (res && (nch == 4))
1824	res = (validate_comma(CHILD(tree, 2))
1825	       && validate_test(CHILD(tree, 3)));
1826
1827    return (res);
1828
1829}   /* validate_except_clause() */
1830
1831
1832static int
1833validate_test(tree)
1834    node *tree;
1835{
1836    int nch = NCH(tree);
1837    int res = validate_ntype(tree, test) && is_odd(nch);
1838
1839    if (res && (TYPE(CHILD(tree, 0)) == lambdef))
1840	res = ((nch == 1)
1841	       && validate_lambdef(CHILD(tree, 0)));
1842    else if (res) {
1843	int pos;
1844	res = validate_and_test(CHILD(tree, 0));
1845	for (pos = 1; res && (pos < nch); pos += 2)
1846	    res = (validate_name(CHILD(tree, pos), "or")
1847		   && validate_and_test(CHILD(tree, pos + 1)));
1848    }
1849    return (res);
1850
1851}   /* validate_test() */
1852
1853
1854static int
1855validate_and_test(tree)
1856    node *tree;
1857{
1858    int pos;
1859    int nch = NCH(tree);
1860    int res = (validate_ntype(tree, and_test)
1861	       && is_odd(nch)
1862	       && validate_not_test(CHILD(tree, 0)));
1863
1864    for (pos = 1; res && (pos < nch); pos += 2)
1865	res = (validate_name(CHILD(tree, pos), "and")
1866	       && validate_not_test(CHILD(tree, 0)));
1867
1868    return (res);
1869
1870}   /* validate_and_test() */
1871
1872
1873static int
1874validate_not_test(tree)
1875    node *tree;
1876{
1877    int nch = NCH(tree);
1878    int res = validate_ntype(tree, not_test) && ((nch == 1) || (nch == 2));
1879
1880    if (res) {
1881	if (nch == 2)
1882	    res = (validate_name(CHILD(tree, 0), "not")
1883		   && validate_not_test(CHILD(tree, 1)));
1884	else if (nch == 1)
1885	    res = validate_comparison(CHILD(tree, 0));
1886    }
1887    return (res);
1888
1889}   /* validate_not_test() */
1890
1891
1892static int
1893validate_comparison(tree)
1894    node *tree;
1895{
1896    int pos;
1897    int nch = NCH(tree);
1898    int res = (validate_ntype(tree, comparison)
1899	       && is_odd(nch)
1900	       && validate_expr(CHILD(tree, 0)));
1901
1902    for (pos = 1; res && (pos < nch); pos += 2)
1903	res = (validate_comp_op(CHILD(tree, pos))
1904	       && validate_expr(CHILD(tree, pos + 1)));
1905
1906    return (res);
1907
1908}   /* validate_comparison() */
1909
1910
1911static int
1912validate_comp_op(tree)
1913    node *tree;
1914{
1915    int res = 0;
1916    int nch = NCH(tree);
1917
1918    if (!validate_ntype(tree, comp_op))
1919	return (0);
1920    if (nch == 1) {
1921	/*
1922	 *  Only child will be a terminal with a well-defined symbolic name
1923	 *  or a NAME with a string of either 'is' or 'in'
1924	 */
1925	tree = CHILD(tree, 0);
1926	switch (TYPE(tree)) {
1927	    case LESS:
1928	    case GREATER:
1929	    case EQEQUAL:
1930	    case EQUAL:
1931	    case LESSEQUAL:
1932	    case GREATEREQUAL:
1933	    case NOTEQUAL:
1934	      res = 1;
1935	      break;
1936	    case NAME:
1937	      res = ((strcmp(STR(tree), "in") == 0)
1938		     || (strcmp(STR(tree), "is") == 0));
1939	      if (!res) {
1940		  char buff[128];
1941		  (void) sprintf(buff, "Illegal operator: '%s'.", STR(tree));
1942		  err_string(buff);
1943	      }
1944	      break;
1945	  default:
1946	      err_string("Illegal comparison operator type.");
1947	      break;
1948	}
1949    }
1950    else if ((res = validate_numnodes(tree, 2, "comp_op")) != 0) {
1951	res = (validate_ntype(CHILD(tree, 0), NAME)
1952	       && validate_ntype(CHILD(tree, 1), NAME)
1953	       && (((strcmp(STR(CHILD(tree, 0)), "is") == 0)
1954		    && (strcmp(STR(CHILD(tree, 1)), "not") == 0))
1955		   || ((strcmp(STR(CHILD(tree, 0)), "not") == 0)
1956		       && (strcmp(STR(CHILD(tree, 1)), "in") == 0))));
1957	if (!res && !PyErr_Occurred())
1958	    err_string("Unknown comparison operator.");
1959    }
1960    return (res);
1961
1962}   /* validate_comp_op() */
1963
1964
1965static int
1966validate_expr(tree)
1967    node *tree;
1968{
1969    int j;
1970    int nch = NCH(tree);
1971    int res = (validate_ntype(tree, expr)
1972	       && is_odd(nch)
1973	       && validate_xor_expr(CHILD(tree, 0)));
1974
1975    for (j = 2; res && (j < nch); j += 2)
1976	res = (validate_xor_expr(CHILD(tree, j))
1977	       && validate_vbar(CHILD(tree, j - 1)));
1978
1979    return (res);
1980
1981}   /* validate_expr() */
1982
1983
1984static int
1985validate_xor_expr(tree)
1986    node *tree;
1987{
1988    int j;
1989    int nch = NCH(tree);
1990    int res = (validate_ntype(tree, xor_expr)
1991	       && is_odd(nch)
1992	       && validate_and_expr(CHILD(tree, 0)));
1993
1994    for (j = 2; res && (j < nch); j += 2)
1995	res = (validate_circumflex(CHILD(tree, j - 1))
1996	       && validate_and_expr(CHILD(tree, j)));
1997
1998    return (res);
1999
2000}   /* validate_xor_expr() */
2001
2002
2003static int
2004validate_and_expr(tree)
2005    node *tree;
2006{
2007    int pos;
2008    int nch = NCH(tree);
2009    int res = (validate_ntype(tree, and_expr)
2010	       && is_odd(nch)
2011	       && validate_shift_expr(CHILD(tree, 0)));
2012
2013    for (pos = 1; res && (pos < nch); pos += 2)
2014	res = (validate_ampersand(CHILD(tree, pos))
2015	       && validate_shift_expr(CHILD(tree, pos + 1)));
2016
2017    return (res);
2018
2019}   /* validate_and_expr() */
2020
2021
2022static int
2023validate_chain_two_ops(tree, termvalid, op1, op2)
2024     node *tree;
2025     int (*termvalid)();
2026     int op1;
2027     int op2;
2028 {
2029    int pos = 1;
2030    int nch = NCH(tree);
2031    int res = (is_odd(nch)
2032	       && (*termvalid)(CHILD(tree, 0)));
2033
2034    for ( ; res && (pos < nch); pos += 2) {
2035	if (TYPE(CHILD(tree, pos)) != op1)
2036	    res = validate_ntype(CHILD(tree, pos), op2);
2037	if (res)
2038	    res = (*termvalid)(CHILD(tree, pos + 1));
2039    }
2040    return (res);
2041
2042}   /* validate_chain_two_ops() */
2043
2044
2045static int
2046validate_shift_expr(tree)
2047    node *tree;
2048{
2049    return (validate_ntype(tree, shift_expr)
2050	    && validate_chain_two_ops(tree, validate_arith_expr,
2051				      LEFTSHIFT, RIGHTSHIFT));
2052
2053}   /* validate_shift_expr() */
2054
2055
2056static int
2057validate_arith_expr(tree)
2058    node *tree;
2059{
2060    return (validate_ntype(tree, arith_expr)
2061	    && validate_chain_two_ops(tree, validate_term, PLUS, MINUS));
2062
2063}   /* validate_arith_expr() */
2064
2065
2066static int
2067validate_term(tree)
2068    node *tree;
2069{
2070    int pos = 1;
2071    int nch = NCH(tree);
2072    int res = (validate_ntype(tree, term)
2073	       && is_odd(nch)
2074	       && validate_factor(CHILD(tree, 0)));
2075
2076    for ( ; res && (pos < nch); pos += 2)
2077	res = (((TYPE(CHILD(tree, pos)) == STAR)
2078	       || (TYPE(CHILD(tree, pos)) == SLASH)
2079	       || (TYPE(CHILD(tree, pos)) == PERCENT))
2080	       && validate_factor(CHILD(tree, pos + 1)));
2081
2082    return (res);
2083
2084}   /* validate_term() */
2085
2086
2087/*  factor:
2088 *
2089 *  factor: ('+'|'-'|'~') factor | power
2090 */
2091static int
2092validate_factor(tree)
2093    node *tree;
2094{
2095    int nch = NCH(tree);
2096    int res = (validate_ntype(tree, factor)
2097	       && (((nch == 2)
2098		    && ((TYPE(CHILD(tree, 0)) == PLUS)
2099		        || (TYPE(CHILD(tree, 0)) == MINUS)
2100		        || (TYPE(CHILD(tree, 0)) == TILDE))
2101		    && validate_factor(CHILD(tree, 1)))
2102		   || ((nch == 1)
2103		       && validate_power(CHILD(tree, 0)))));
2104    return (res);
2105
2106}   /* validate_factor() */
2107
2108
2109/*  power:
2110 *
2111 *  power: atom trailer* ('**' factor)*
2112 */
2113static int
2114validate_power(tree)
2115    node *tree;
2116{
2117    int pos = 1;
2118    int nch = NCH(tree);
2119    int res = (validate_ntype(tree, power) && (nch >= 1)
2120	       && validate_atom(CHILD(tree, 0)));
2121
2122    while (res && (pos < nch) && (TYPE(CHILD(tree, pos)) == trailer))
2123	res = validate_trailer(CHILD(tree, pos++));
2124    if (res && (pos < nch)) {
2125	if (!is_even(nch - pos)) {
2126	    err_string("Illegal number of nodes for 'power'.");
2127	    return (0);
2128	}
2129	for ( ; res && (pos < (nch - 1)); pos += 2)
2130	    res = (validate_doublestar(CHILD(tree, pos))
2131		   && validate_factor(CHILD(tree, pos + 1)));
2132    }
2133    return (res);
2134
2135}   /* validate_power() */
2136
2137
2138static int
2139validate_atom(tree)
2140    node *tree;
2141{
2142    int pos;
2143    int nch = NCH(tree);
2144    int res = validate_ntype(tree, atom) && (nch >= 1);
2145
2146    if (res) {
2147	switch (TYPE(CHILD(tree, 0))) {
2148	  case LPAR:
2149	    res = ((nch <= 3)
2150		   && (validate_rparen(CHILD(tree, nch - 1))));
2151
2152	    if (res && (nch == 3))
2153		res = validate_testlist(CHILD(tree, 1));
2154	    break;
2155	  case LSQB:
2156	    res = ((nch <= 3)
2157		   && validate_ntype(CHILD(tree, nch - 1), RSQB));
2158
2159	    if (res && (nch == 3))
2160		res = validate_testlist(CHILD(tree, 1));
2161	    break;
2162	  case LBRACE:
2163	    res = ((nch <= 3)
2164		   && validate_ntype(CHILD(tree, nch - 1), RBRACE));
2165
2166	    if (res && (nch == 3))
2167		res = validate_dictmaker(CHILD(tree, 1));
2168	    break;
2169	  case BACKQUOTE:
2170	    res = ((nch == 3)
2171		   && validate_testlist(CHILD(tree, 1))
2172		   && validate_ntype(CHILD(tree, 2), BACKQUOTE));
2173	    break;
2174	  case NAME:
2175	  case NUMBER:
2176	    res = (nch == 1);
2177	    break;
2178	  case STRING:
2179	    for (pos = 1; res && (pos < nch); ++pos)
2180		res = validate_ntype(CHILD(tree, pos), STRING);
2181	    break;
2182	  default:
2183	    res = 0;
2184	    break;
2185	}
2186    }
2187    return (res);
2188
2189}   /* validate_atom() */
2190
2191
2192/*  funcdef:
2193 *	'def' NAME parameters ':' suite
2194 *
2195 */
2196static int
2197validate_funcdef(tree)
2198    node *tree;
2199{
2200    return (validate_ntype(tree, funcdef)
2201	    && validate_numnodes(tree, 5, "funcdef")
2202	    && validate_name(CHILD(tree, 0), "def")
2203	    && validate_ntype(CHILD(tree, 1), NAME)
2204	    && validate_colon(CHILD(tree, 3))
2205	    && validate_parameters(CHILD(tree, 2))
2206	    && validate_suite(CHILD(tree, 4)));
2207
2208}   /* validate_funcdef() */
2209
2210
2211static int
2212validate_lambdef(tree)
2213    node *tree;
2214{
2215    int nch = NCH(tree);
2216    int res = (validate_ntype(tree, lambdef)
2217	       && ((nch == 3) || (nch == 4))
2218	       && validate_name(CHILD(tree, 0), "lambda")
2219	       && validate_colon(CHILD(tree, nch - 2))
2220	       && validate_test(CHILD(tree, nch - 1)));
2221
2222    if (res && (nch == 4))
2223	res = validate_varargslist(CHILD(tree, 1));
2224    else if (!res && !PyErr_Occurred())
2225	(void) validate_numnodes(tree, 3, "lambdef");
2226
2227    return (res);
2228
2229}   /* validate_lambdef() */
2230
2231
2232/*  arglist:
2233 *
2234 *  argument (',' argument)* [',']
2235 */
2236static int
2237validate_arglist(tree)
2238    node *tree;
2239{
2240    return (validate_repeating_list(tree, arglist,
2241				    validate_argument, "arglist"));
2242
2243}   /* validate_arglist() */
2244
2245
2246
2247/*  argument:
2248 *
2249 *  [test '='] test
2250 */
2251static int
2252validate_argument(tree)
2253    node *tree;
2254{
2255    int nch = NCH(tree);
2256    int res = (validate_ntype(tree, argument)
2257	       && ((nch == 1) || (nch == 3))
2258	       && validate_test(CHILD(tree, 0)));
2259
2260    if (res && (nch == 3))
2261	res = (validate_equal(CHILD(tree, 1))
2262	       && validate_test(CHILD(tree, 2)));
2263
2264    return (res);
2265
2266}   /* validate_argument() */
2267
2268
2269
2270/*  trailer:
2271 *
2272 *  '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
2273 */
2274static int
2275validate_trailer(tree)
2276    node *tree;
2277{
2278    int nch = NCH(tree);
2279    int res = validate_ntype(tree, trailer) && ((nch == 2) || (nch == 3));
2280
2281    if (res) {
2282	switch (TYPE(CHILD(tree, 0))) {
2283	  case LPAR:
2284	    res = validate_rparen(CHILD(tree, nch - 1));
2285	    if (res && (nch == 3))
2286		res = validate_arglist(CHILD(tree, 1));
2287	    break;
2288	  case LSQB:
2289	    res = (validate_numnodes(tree, 3, "trailer")
2290		   && validate_subscriptlist(CHILD(tree, 1))
2291		   && validate_ntype(CHILD(tree, 2), RSQB));
2292	    break;
2293	  case DOT:
2294	    res = (validate_numnodes(tree, 2, "trailer")
2295		   && validate_ntype(CHILD(tree, 1), NAME));
2296	    break;
2297	  default:
2298	    res = 0;
2299	    break;
2300	}
2301    }
2302    else
2303	(void) validate_numnodes(tree, 2, "trailer");
2304
2305    return (res);
2306
2307}   /* validate_trailer() */
2308
2309
2310/*  subscriptlist:
2311 *
2312 *  subscript (',' subscript)* [',']
2313 */
2314static int
2315validate_subscriptlist(tree)
2316    node *tree;
2317{
2318    return (validate_repeating_list(tree, subscriptlist,
2319				    validate_subscript, "subscriptlist"));
2320
2321}   /* validate_subscriptlist() */
2322
2323
2324/*  subscript:
2325 *
2326 *  '.' '.' '.' | test | [test] ':' [test] [sliceop]
2327 */
2328static int
2329validate_subscript(tree)
2330    node *tree;
2331{
2332    int offset = 0;
2333    int nch = NCH(tree);
2334    int res = validate_ntype(tree, subscript) && (nch >= 1) && (nch <= 4);
2335
2336    if (!res) {
2337	if (!PyErr_Occurred())
2338	    err_string("invalid number of arguments for subscript node");
2339	return (0);
2340    }
2341    if (TYPE(CHILD(tree, 0)) == DOT)
2342	/* take care of ('.' '.' '.') possibility */
2343	return (validate_numnodes(tree, 3, "subscript")
2344		&& validate_dot(CHILD(tree, 0))
2345		&& validate_dot(CHILD(tree, 1))
2346		&& validate_dot(CHILD(tree, 2)));
2347    if (nch == 1) {
2348	if (TYPE(CHILD(tree, 0)) == test)
2349	    res = validate_test(CHILD(tree, 0));
2350	else
2351	    res = validate_colon(CHILD(tree, 0));
2352	return (res);
2353    }
2354    /*	Must be [test] ':' [test] [sliceop],
2355     *	but at least one of the optional components will
2356     *	be present, but we don't know which yet.
2357     */
2358    if ((TYPE(CHILD(tree, 0)) != COLON) || (nch == 4)) {
2359	res = validate_test(CHILD(tree, 0));
2360	offset = 1;
2361    }
2362    if (res)
2363	res = validate_colon(CHILD(tree, offset));
2364    if (res) {
2365	int rem = nch - ++offset;
2366	if (rem) {
2367	    if (TYPE(CHILD(tree, offset)) == test) {
2368		res = validate_test(CHILD(tree, offset));
2369		++offset;
2370		--rem;
2371	    }
2372	    if (res && rem)
2373		res = validate_sliceop(CHILD(tree, offset));
2374	}
2375    }
2376    return (res);
2377
2378}   /* validate_subscript() */
2379
2380
2381static int
2382validate_sliceop(tree)
2383    node *tree;
2384{
2385    int nch = NCH(tree);
2386    int res = ((nch == 1) || validate_numnodes(tree, 2, "sliceop"))
2387	      && validate_ntype(tree, sliceop);
2388    if (!res && !PyErr_Occurred()) {
2389	res = validate_numnodes(tree, 1, "sliceop");
2390    }
2391    if (res)
2392	res = validate_colon(CHILD(tree, 0));
2393    if (res && (nch == 2))
2394	res = validate_test(CHILD(tree, 1));
2395
2396    return (res);
2397
2398}   /* validate_sliceop() */
2399
2400
2401static int
2402validate_exprlist(tree)
2403    node *tree;
2404{
2405    return (validate_repeating_list(tree, exprlist,
2406				    validate_expr, "exprlist"));
2407
2408}   /* validate_exprlist() */
2409
2410
2411static int
2412validate_dictmaker(tree)
2413    node *tree;
2414{
2415    int nch = NCH(tree);
2416    int res = (validate_ntype(tree, dictmaker)
2417	       && (nch >= 3)
2418	       && validate_test(CHILD(tree, 0))
2419	       && validate_colon(CHILD(tree, 1))
2420	       && validate_test(CHILD(tree, 2)));
2421
2422    if (res && ((nch % 4) == 0))
2423	res = validate_comma(CHILD(tree, --nch));
2424    else if (res)
2425	res = ((nch % 4) == 3);
2426
2427    if (res && (nch > 3)) {
2428	int pos = 3;
2429	/*  ( ',' test ':' test )*  */
2430	while (res && (pos < nch)) {
2431	    res = (validate_comma(CHILD(tree, pos))
2432		   && validate_test(CHILD(tree, pos + 1))
2433		   && validate_colon(CHILD(tree, pos + 2))
2434		   && validate_test(CHILD(tree, pos + 3)));
2435	    pos += 4;
2436	}
2437    }
2438    return (res);
2439
2440}   /* validate_dictmaker() */
2441
2442
2443static int
2444validate_eval_input(tree)
2445    node *tree;
2446{
2447    int pos;
2448    int nch = NCH(tree);
2449    int res = (validate_ntype(tree, eval_input)
2450	       && (nch >= 2)
2451	       && validate_testlist(CHILD(tree, 0))
2452	       && validate_ntype(CHILD(tree, nch - 1), ENDMARKER));
2453
2454    for (pos = 1; res && (pos < (nch - 1)); ++pos)
2455	res = validate_ntype(CHILD(tree, pos), NEWLINE);
2456
2457    return (res);
2458
2459}   /* validate_eval_input() */
2460
2461
2462static int
2463validate_node(tree)
2464    node *tree;
2465{
2466    int   nch  = 0;			/* num. children on current node  */
2467    int   res  = 1;			/* result value			  */
2468    node* next = 0;			/* node to process after this one */
2469
2470    while (res & (tree != 0)) {
2471	nch  = NCH(tree);
2472	next = 0;
2473	switch (TYPE(tree)) {
2474	    /*
2475	     *  Definition nodes.
2476	     */
2477	  case funcdef:
2478	    res = validate_funcdef(tree);
2479	    break;
2480	  case classdef:
2481	    res = validate_class(tree);
2482	    break;
2483	    /*
2484	     *  "Trivial" parse tree nodes.
2485	     *  (Why did I call these trivial?)
2486	     */
2487	  case stmt:
2488	    res = validate_stmt(tree);
2489	    break;
2490	  case small_stmt:
2491	    /*
2492	     *  expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt
2493	     *  | import_stmt | global_stmt | exec_stmt | assert_stmt
2494	     */
2495	    res = validate_small_stmt(tree);
2496	    break;
2497	  case flow_stmt:
2498	    res  = (validate_numnodes(tree, 1, "flow_stmt")
2499		    && ((TYPE(CHILD(tree, 0)) == break_stmt)
2500			|| (TYPE(CHILD(tree, 0)) == continue_stmt)
2501			|| (TYPE(CHILD(tree, 0)) == return_stmt)
2502			|| (TYPE(CHILD(tree, 0)) == raise_stmt)));
2503	    if (res)
2504		next = CHILD(tree, 0);
2505	    else if (nch == 1)
2506		err_string("Illegal flow_stmt type.");
2507	    break;
2508	    /*
2509	     *  Compound statements.
2510	     */
2511	  case simple_stmt:
2512	    res = validate_simple_stmt(tree);
2513	    break;
2514	  case compound_stmt:
2515	    res = validate_compound_stmt(tree);
2516	    break;
2517	    /*
2518	     *  Fundemental statements.
2519	     */
2520	  case expr_stmt:
2521	    res = validate_expr_stmt(tree);
2522	    break;
2523	  case print_stmt:
2524	    res = validate_print_stmt(tree);
2525	    break;
2526	  case del_stmt:
2527	    res = validate_del_stmt(tree);
2528	    break;
2529	  case pass_stmt:
2530	    res = (validate_numnodes(tree, 1, "pass")
2531		   && validate_name(CHILD(tree, 0), "pass"));
2532	    break;
2533	  case break_stmt:
2534	    res = (validate_numnodes(tree, 1, "break")
2535		   && validate_name(CHILD(tree, 0), "break"));
2536	    break;
2537	  case continue_stmt:
2538	    res = (validate_numnodes(tree, 1, "continue")
2539		   && validate_name(CHILD(tree, 0), "continue"));
2540	    break;
2541	  case return_stmt:
2542	    res = validate_return_stmt(tree);
2543	    break;
2544	  case raise_stmt:
2545	    res = validate_raise_stmt(tree);
2546	    break;
2547	  case import_stmt:
2548	    res = validate_import_stmt(tree);
2549	    break;
2550	  case global_stmt:
2551	    res = validate_global_stmt(tree);
2552	    break;
2553	  case exec_stmt:
2554	    res = validate_exec_stmt(tree);
2555	    break;
2556	  case assert_stmt:
2557	    res = validate_assert_stmt(tree);
2558	    break;
2559	  case if_stmt:
2560	    res = validate_if(tree);
2561	    break;
2562	  case while_stmt:
2563	    res = validate_while(tree);
2564	    break;
2565	  case for_stmt:
2566	    res = validate_for(tree);
2567	    break;
2568	  case try_stmt:
2569	    res = validate_try(tree);
2570	    break;
2571	  case suite:
2572	    res = validate_suite(tree);
2573	    break;
2574	    /*
2575	     *  Expression nodes.
2576	     */
2577	  case testlist:
2578	    res = validate_testlist(tree);
2579	    break;
2580	  case test:
2581	    res = validate_test(tree);
2582	    break;
2583	  case and_test:
2584	    res = validate_and_test(tree);
2585	    break;
2586	  case not_test:
2587	    res = validate_not_test(tree);
2588	    break;
2589	  case comparison:
2590	    res = validate_comparison(tree);
2591	    break;
2592	  case exprlist:
2593	    res = validate_exprlist(tree);
2594	    break;
2595	  case comp_op:
2596	    res = validate_comp_op(tree);
2597	    break;
2598	  case expr:
2599	    res = validate_expr(tree);
2600	    break;
2601	  case xor_expr:
2602	    res = validate_xor_expr(tree);
2603	    break;
2604	  case and_expr:
2605	    res = validate_and_expr(tree);
2606	    break;
2607	  case shift_expr:
2608	    res = validate_shift_expr(tree);
2609	    break;
2610	  case arith_expr:
2611	    res = validate_arith_expr(tree);
2612	    break;
2613	  case term:
2614	    res = validate_term(tree);
2615	    break;
2616	  case factor:
2617	    res = validate_factor(tree);
2618	    break;
2619	  case power:
2620	    res = validate_power(tree);
2621	    break;
2622	  case atom:
2623	    res = validate_atom(tree);
2624	    break;
2625
2626	  default:
2627	    /* Hopefully never reached! */
2628	    err_string("Unrecogniged node type.");
2629	    res = 0;
2630	    break;
2631	}
2632	tree = next;
2633    }
2634    return (res);
2635
2636}   /* validate_node() */
2637
2638
2639static int
2640validate_expr_tree(tree)
2641    node *tree;
2642{
2643    int res = validate_eval_input(tree);
2644
2645    if (!res && !PyErr_Occurred())
2646	err_string("Could not validate expression tuple.");
2647
2648    return (res);
2649
2650}   /* validate_expr_tree() */
2651
2652
2653/*  file_input:
2654 *	(NEWLINE | stmt)* ENDMARKER
2655 */
2656static int
2657validate_file_input(tree)
2658    node *tree;
2659{
2660    int j   = 0;
2661    int nch = NCH(tree) - 1;
2662    int res = ((nch >= 0)
2663	       && validate_ntype(CHILD(tree, nch), ENDMARKER));
2664
2665    for ( ; res && (j < nch); ++j) {
2666	if (TYPE(CHILD(tree, j)) == stmt)
2667	    res = validate_stmt(CHILD(tree, j));
2668	else
2669	    res = validate_newline(CHILD(tree, j));
2670    }
2671    /*	This stays in to prevent any internal failues from getting to the
2672     *	user.  Hopefully, this won't be needed.  If a user reports getting
2673     *	this, we have some debugging to do.
2674     */
2675    if (!res && !PyErr_Occurred())
2676	err_string("VALIDATION FAILURE: report this to the maintainer!.");
2677
2678    return (res);
2679
2680}   /* validate_file_input() */
2681
2682
2683static PyObject*
2684pickle_constructor = NULL;
2685
2686
2687static PyObject*
2688parser__pickler(self, args)
2689    PyObject *self;
2690    PyObject *args;
2691{
2692    NOTE(ARGUNUSED(self))
2693    PyObject *result = NULL;
2694    PyObject *ast = NULL;
2695
2696    if (PyArg_ParseTuple(args, "O!:_pickler", &PyAST_Type, &ast)) {
2697	PyObject *newargs;
2698	PyObject *tuple;
2699
2700	if ((newargs = Py_BuildValue("Oi", ast, 1)) == NULL)
2701	    goto finally;
2702	tuple = parser_ast2tuple((PyAST_Object*)NULL, newargs);
2703	if (tuple != NULL) {
2704	    result = Py_BuildValue("O(O)", pickle_constructor, tuple);
2705	    Py_DECREF(tuple);
2706	}
2707	Py_XDECREF(newargs);
2708    }
2709  finally:
2710    return (result);
2711
2712}   /* parser__pickler() */
2713
2714
2715/*  Functions exported by this module.  Most of this should probably
2716 *  be converted into an AST object with methods, but that is better
2717 *  done directly in Python, allowing subclasses to be created directly.
2718 *  We'd really have to write a wrapper around it all anyway to allow
2719 *  inheritance.
2720 */
2721static PyMethodDef parser_functions[] =  {
2722    {"ast2tuple",	(PyCFunction)parser_ast2tuple,	METH_VARARGS,
2723	"Creates a tuple-tree representation of an AST."},
2724    {"ast2list",	(PyCFunction)parser_ast2list,	METH_VARARGS,
2725	"Creates a list-tree representation of an AST."},
2726    {"compileast",	(PyCFunction)parser_compileast,	METH_VARARGS,
2727	"Compiles an AST object into a code object."},
2728    {"expr",		(PyCFunction)parser_expr,	METH_VARARGS,
2729	"Creates an AST object from an expression."},
2730    {"isexpr",		(PyCFunction)parser_isexpr,	METH_VARARGS,
2731	"Determines if an AST object was created from an expression."},
2732    {"issuite",		(PyCFunction)parser_issuite,	METH_VARARGS,
2733	"Determines if an AST object was created from a suite."},
2734    {"suite",		(PyCFunction)parser_suite,	METH_VARARGS,
2735	"Creates an AST object from a suite."},
2736    {"sequence2ast",	(PyCFunction)parser_tuple2ast,	METH_VARARGS,
2737	"Creates an AST object from a tree representation."},
2738    {"tuple2ast",	(PyCFunction)parser_tuple2ast,	METH_VARARGS,
2739	"Creates an AST object from a tree representation."},
2740
2741    /* private stuff: support pickle module */
2742    {"_pickler",	(PyCFunction)parser__pickler,	METH_VARARGS,
2743        "Returns the pickle magic to allow ast objects to be pickled."},
2744
2745    {NULL, NULL, 0, NULL}
2746    };
2747
2748
2749void
2750initparser()
2751 {
2752    PyObject* module;
2753    PyObject* dict;
2754
2755    PyAST_Type.ob_type = &PyType_Type;
2756    module = Py_InitModule("parser", parser_functions);
2757    dict = PyModule_GetDict(module);
2758
2759    parser_error = PyErr_NewException("parser.ParserError", NULL, NULL);
2760
2761    if ((parser_error == 0)
2762	|| (PyDict_SetItemString(dict, "ParserError", parser_error) != 0)) {
2763	/*
2764	 *  This is serious.
2765	 */
2766	Py_FatalError("can't define parser.ParserError");
2767    }
2768    /*
2769     *  Nice to have, but don't cry if we fail.
2770     */
2771    Py_INCREF(&PyAST_Type);
2772    PyDict_SetItemString(dict, "ASTType", (PyObject*)&PyAST_Type);
2773
2774    PyDict_SetItemString(dict, "__copyright__",
2775			 PyString_FromString(parser_copyright_string));
2776    PyDict_SetItemString(dict, "__doc__",
2777			 PyString_FromString(parser_doc_string));
2778    PyDict_SetItemString(dict, "__version__",
2779			 PyString_FromString(parser_version_string));
2780
2781    parser_method_list = PyList_New(0);
2782    if (parser_method_list != NULL) {
2783	PyMethodDef *mdef = parser_methods;
2784
2785	while (mdef->ml_name != NULL) {
2786	    PyObject *temp = PyString_FromString(mdef->ml_name);
2787	    if (temp != NULL) {
2788		PyList_Append(parser_method_list, temp);
2789		Py_DECREF(temp);
2790	    }
2791	    ++mdef;
2792	}
2793    }
2794
2795    /* register to support pickling */
2796    module = PyImport_ImportModule("copy_reg");
2797    if (module != NULL) {
2798	PyObject *func, *pickler;
2799
2800	func = PyObject_GetAttrString(module, "pickle");
2801	pickle_constructor = PyDict_GetItemString(dict, "sequence2ast");
2802	pickler = PyDict_GetItemString(dict, "_pickler");
2803	Py_XINCREF(pickle_constructor);
2804	if ((func != NULL) && (pickle_constructor != NULL)
2805	    && (pickler != NULL)) {
2806	    PyObject *res;
2807
2808	    res = PyObject_CallFunction(
2809		    func, "OOO", &PyAST_Type, pickler, pickle_constructor);
2810	    Py_XDECREF(res);
2811	}
2812	Py_XDECREF(func);
2813	Py_DECREF(module);
2814    }
2815}   /* initparser() */
2816