xref: /csrg-svn/usr.bin/pascal/src/yytree.c (revision 62227)
148116Sbostic /*-
2*62227Sbostic  * Copyright (c) 1980, 1993
3*62227Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622215Sdist  */
7796Speter 
814749Sthien #ifndef lint
9*62227Sbostic static char sccsid[] = "@(#)yytree.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11796Speter 
12796Speter #include "whoami.h"
13796Speter #include "0.h"
14796Speter #include "tree.h"
1514749Sthien #include "tree_ty.h"
16796Speter 
17796Speter extern	int *spacep;
18796Speter 
19796Speter /*
20796Speter  * LIST MANIPULATION ROUTINES
21796Speter  *
22796Speter  * The grammar for Pascal is written left recursively.
23796Speter  * Because of this, the portions of parse trees which are to resemble
24796Speter  * lists are in the somewhat inconvenient position of having
25796Speter  * the nodes built from left to right, while we want to eventually
26796Speter  * have as semantic value the leftmost node.
27796Speter  * We could carry the leftmost node as semantic value, but this
28796Speter  * would be inefficient as to add a new node to the list we would
29796Speter  * have to chase down to the end.  Other solutions involving a head
30796Speter  * and tail pointer waste space.
31796Speter  *
32796Speter  * The simple solution to this apparent dilemma is to carry along
33796Speter  * a pointer to the leftmost node in a list in the rightmost node
34796Speter  * which is the current semantic value of the list.
35796Speter  * When we have completed building the list, we can retrieve this
36796Speter  * left end pointer very easily; neither adding new elements to the list
37796Speter  * nor finding the left end is thus expensive.  As the bottommost node
38796Speter  * has an unused next pointer in it, no space is wasted either.
39796Speter  *
40796Speter  * The nodes referred to here are of the T_LISTPP type and have
41796Speter  * the form:
42796Speter  *
43796Speter  *	T_LISTPP	some_pointer		next_element
44796Speter  *
45796Speter  * Here some_pointer points to the things of interest in the list,
46796Speter  * and next_element to the next thing in the list except for the
47796Speter  * rightmost node, in which case it points to the leftmost node.
48796Speter  * The next_element of the rightmost node is of course zapped to the
49796Speter  * NIL pointer when the list is completed.
50796Speter  *
51796Speter  * Thinking of the lists as tree we heceforth refer to the leftmost
52796Speter  * node as the "top", and the rightmost node as the "bottom" or as
53796Speter  * the "virtual root".
54796Speter  */
55796Speter 
56796Speter /*
57796Speter  * Make a new list
58796Speter  */
5914749Sthien struct tnode *
newlist(new)60796Speter newlist(new)
6114749Sthien 	register struct tnode *new;
62796Speter {
63796Speter 
6414749Sthien 	if (new == TR_NIL)
6514749Sthien 		return (TR_NIL);
6614749Sthien 	return ((struct tnode *) tree3(T_LISTPP, (int) new,
6714749Sthien 					(struct tnode *) spacep));
68796Speter }
69796Speter 
70796Speter /*
71796Speter  * Add a new element to an existing list
72796Speter  */
7314749Sthien struct tnode *
addlist(vroot,new)74796Speter addlist(vroot, new)
7514749Sthien 	register struct tnode *vroot;
7614749Sthien 	struct tnode *new;
77796Speter {
7814749Sthien 	register struct tnode *top;
79796Speter 
8014749Sthien 	if (new == TR_NIL)
81796Speter 		return (vroot);
8214749Sthien 	if (vroot == TR_NIL)
83796Speter 		return (newlist(new));
8414749Sthien 	top = vroot->list_node.next;
8514749Sthien 	vroot->list_node.next = (struct tnode *) spacep;
8614749Sthien 	return ((struct tnode *) tree3(T_LISTPP, (int) new, top));
87796Speter }
88796Speter 
89796Speter /*
90796Speter  * Fix up the list which has virtual root vroot.
91796Speter  * We grab the top pointer and return it, zapping the spot
92796Speter  * where it was so that the tree is not circular.
93796Speter  */
9414749Sthien struct tnode *
fixlist(vroot)95796Speter fixlist(vroot)
9614749Sthien 	register struct tnode *vroot;
97796Speter {
9814749Sthien 	register struct tnode *top;
99796Speter 
10014749Sthien 	if (vroot == TR_NIL)
10114749Sthien 		return (TR_NIL);
10214749Sthien 	top = vroot->list_node.next;
10314749Sthien 	vroot->list_node.next = TR_NIL;
104796Speter 	return (top);
105796Speter }
106796Speter 
107796Speter 
108796Speter /*
109796Speter  * Set up a T_VAR node for a qualified variable.
110796Speter  * Init is the initial entry in the qualification,
111796Speter  * or NIL if there is none.
112796Speter  *
113796Speter  * if we are building pTrees, there has to be an extra slot for
114796Speter  * a pointer to the namelist entry of a field, if this T_VAR refers
115796Speter  * to a field name within a WITH statement.
116796Speter  * this extra field is set in lvalue, and used in VarCopy.
117796Speter  */
11814749Sthien struct tnode *
setupvar(var,init)119796Speter setupvar(var, init)
120796Speter 	char *var;
12114749Sthien 	register struct tnode *init;
122796Speter {
123796Speter 
12414749Sthien 	if (init != TR_NIL)
125796Speter 		init = newlist(init);
126796Speter #	ifndef PTREE
12714749Sthien 	    return (tree4(T_VAR, NOCON, (struct tnode *) var, init));
128796Speter #	else
12914749Sthien 	    return tree5( T_VAR, NOCON, (struct tnode *) var, init, TR_NIL );
130796Speter #	endif
131796Speter }
132796Speter 
133796Speter     /*
134796Speter      *	set up a T_TYREC node for a record
135796Speter      *
136796Speter      *	if we are building pTrees, there has to be an extra slot for
137796Speter      *	a pointer to the namelist entry of the record.
138796Speter      *	this extra field is filled in in gtype, and used in RecTCopy.
139796Speter      */
14014749Sthien struct tnode *
setuptyrec(line,fldlist)14114749Sthien setuptyrec( line , fldlist )
142796Speter     int	line;
14314749Sthien     struct tnode *fldlist;
144796Speter     {
145796Speter 
146796Speter #	ifndef PTREE
14714749Sthien 	    return tree3( T_TYREC , line , fldlist );
148796Speter #	else
14914749Sthien 	    return tree4( T_TYREC , line , fldlst , TR_NIL );
150796Speter #	endif
151796Speter     }
152796Speter 
153796Speter     /*
154796Speter      *	set up a T_FIELD node for a field.
155796Speter      *
156796Speter      *	if we are building pTrees, there has to be an extra slot for
157796Speter      *	a pointer to the namelist entry of the field.
158796Speter      *	this extra field is set in lvalue, and used in SelCopy.
159796Speter      */
16014749Sthien struct tnode *
setupfield(field,other)161796Speter setupfield( field , other )
16214749Sthien     struct tnode *field;
16314749Sthien     struct tnode *other;
164796Speter     {
165796Speter 
166796Speter #	ifndef PTREE
16714749Sthien 	    return tree3( T_FIELD , (int) field , other );
168796Speter #	else
16914749Sthien 	    return tree4( T_FIELD , (int) field , other , TR_NIL );
170796Speter #	endif
171796Speter     }
172