xref: /csrg-svn/usr.bin/pascal/src/yytree.c (revision 14749)
1796Speter /* Copyright (c) 1979 Regents of the University of California */
2796Speter 
3*14749Sthien #ifndef lint
4*14749Sthien static	char sccsid[] = "@(#)yytree.c 1.2 08/19/83";
5*14749Sthien #endif
6796Speter 
7796Speter #include "whoami.h"
8796Speter #include "0.h"
9796Speter #include "tree.h"
10*14749Sthien #include "tree_ty.h"
11796Speter 
12796Speter extern	int *spacep;
13796Speter 
14796Speter /*
15796Speter  * LIST MANIPULATION ROUTINES
16796Speter  *
17796Speter  * The grammar for Pascal is written left recursively.
18796Speter  * Because of this, the portions of parse trees which are to resemble
19796Speter  * lists are in the somewhat inconvenient position of having
20796Speter  * the nodes built from left to right, while we want to eventually
21796Speter  * have as semantic value the leftmost node.
22796Speter  * We could carry the leftmost node as semantic value, but this
23796Speter  * would be inefficient as to add a new node to the list we would
24796Speter  * have to chase down to the end.  Other solutions involving a head
25796Speter  * and tail pointer waste space.
26796Speter  *
27796Speter  * The simple solution to this apparent dilemma is to carry along
28796Speter  * a pointer to the leftmost node in a list in the rightmost node
29796Speter  * which is the current semantic value of the list.
30796Speter  * When we have completed building the list, we can retrieve this
31796Speter  * left end pointer very easily; neither adding new elements to the list
32796Speter  * nor finding the left end is thus expensive.  As the bottommost node
33796Speter  * has an unused next pointer in it, no space is wasted either.
34796Speter  *
35796Speter  * The nodes referred to here are of the T_LISTPP type and have
36796Speter  * the form:
37796Speter  *
38796Speter  *	T_LISTPP	some_pointer		next_element
39796Speter  *
40796Speter  * Here some_pointer points to the things of interest in the list,
41796Speter  * and next_element to the next thing in the list except for the
42796Speter  * rightmost node, in which case it points to the leftmost node.
43796Speter  * The next_element of the rightmost node is of course zapped to the
44796Speter  * NIL pointer when the list is completed.
45796Speter  *
46796Speter  * Thinking of the lists as tree we heceforth refer to the leftmost
47796Speter  * node as the "top", and the rightmost node as the "bottom" or as
48796Speter  * the "virtual root".
49796Speter  */
50796Speter 
51796Speter /*
52796Speter  * Make a new list
53796Speter  */
54*14749Sthien struct tnode *
55796Speter newlist(new)
56*14749Sthien 	register struct tnode *new;
57796Speter {
58796Speter 
59*14749Sthien 	if (new == TR_NIL)
60*14749Sthien 		return (TR_NIL);
61*14749Sthien 	return ((struct tnode *) tree3(T_LISTPP, (int) new,
62*14749Sthien 					(struct tnode *) spacep));
63796Speter }
64796Speter 
65796Speter /*
66796Speter  * Add a new element to an existing list
67796Speter  */
68*14749Sthien struct tnode *
69796Speter addlist(vroot, new)
70*14749Sthien 	register struct tnode *vroot;
71*14749Sthien 	struct tnode *new;
72796Speter {
73*14749Sthien 	register struct tnode *top;
74796Speter 
75*14749Sthien 	if (new == TR_NIL)
76796Speter 		return (vroot);
77*14749Sthien 	if (vroot == TR_NIL)
78796Speter 		return (newlist(new));
79*14749Sthien 	top = vroot->list_node.next;
80*14749Sthien 	vroot->list_node.next = (struct tnode *) spacep;
81*14749Sthien 	return ((struct tnode *) tree3(T_LISTPP, (int) new, top));
82796Speter }
83796Speter 
84796Speter /*
85796Speter  * Fix up the list which has virtual root vroot.
86796Speter  * We grab the top pointer and return it, zapping the spot
87796Speter  * where it was so that the tree is not circular.
88796Speter  */
89*14749Sthien struct tnode *
90796Speter fixlist(vroot)
91*14749Sthien 	register struct tnode *vroot;
92796Speter {
93*14749Sthien 	register struct tnode *top;
94796Speter 
95*14749Sthien 	if (vroot == TR_NIL)
96*14749Sthien 		return (TR_NIL);
97*14749Sthien 	top = vroot->list_node.next;
98*14749Sthien 	vroot->list_node.next = TR_NIL;
99796Speter 	return (top);
100796Speter }
101796Speter 
102796Speter 
103796Speter /*
104796Speter  * Set up a T_VAR node for a qualified variable.
105796Speter  * Init is the initial entry in the qualification,
106796Speter  * or NIL if there is none.
107796Speter  *
108796Speter  * if we are building pTrees, there has to be an extra slot for
109796Speter  * a pointer to the namelist entry of a field, if this T_VAR refers
110796Speter  * to a field name within a WITH statement.
111796Speter  * this extra field is set in lvalue, and used in VarCopy.
112796Speter  */
113*14749Sthien struct tnode *
114796Speter setupvar(var, init)
115796Speter 	char *var;
116*14749Sthien 	register struct tnode *init;
117796Speter {
118796Speter 
119*14749Sthien 	if (init != TR_NIL)
120796Speter 		init = newlist(init);
121796Speter #	ifndef PTREE
122*14749Sthien 	    return (tree4(T_VAR, NOCON, (struct tnode *) var, init));
123796Speter #	else
124*14749Sthien 	    return tree5( T_VAR, NOCON, (struct tnode *) var, init, TR_NIL );
125796Speter #	endif
126796Speter }
127796Speter 
128796Speter     /*
129796Speter      *	set up a T_TYREC node for a record
130796Speter      *
131796Speter      *	if we are building pTrees, there has to be an extra slot for
132796Speter      *	a pointer to the namelist entry of the record.
133796Speter      *	this extra field is filled in in gtype, and used in RecTCopy.
134796Speter      */
135*14749Sthien struct tnode *
136*14749Sthien setuptyrec( line , fldlist )
137796Speter     int	line;
138*14749Sthien     struct tnode *fldlist;
139796Speter     {
140796Speter 
141796Speter #	ifndef PTREE
142*14749Sthien 	    return tree3( T_TYREC , line , fldlist );
143796Speter #	else
144*14749Sthien 	    return tree4( T_TYREC , line , fldlst , TR_NIL );
145796Speter #	endif
146796Speter     }
147796Speter 
148796Speter     /*
149796Speter      *	set up a T_FIELD node for a field.
150796Speter      *
151796Speter      *	if we are building pTrees, there has to be an extra slot for
152796Speter      *	a pointer to the namelist entry of the field.
153796Speter      *	this extra field is set in lvalue, and used in SelCopy.
154796Speter      */
155*14749Sthien struct tnode *
156796Speter setupfield( field , other )
157*14749Sthien     struct tnode *field;
158*14749Sthien     struct tnode *other;
159796Speter     {
160796Speter 
161796Speter #	ifndef PTREE
162*14749Sthien 	    return tree3( T_FIELD , (int) field , other );
163796Speter #	else
164*14749Sthien 	    return tree4( T_FIELD , (int) field , other , TR_NIL );
165796Speter #	endif
166796Speter     }
167