xref: /csrg-svn/usr.bin/pascal/src/yytree.c (revision 22215)
1*22215Sdist /*
2*22215Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22215Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22215Sdist  * specifies the terms and conditions for redistribution.
5*22215Sdist  */
6796Speter 
714749Sthien #ifndef lint
8*22215Sdist static char sccsid[] = "@(#)yytree.c	5.1 (Berkeley) 06/05/85";
9*22215Sdist #endif not lint
10796Speter 
11796Speter #include "whoami.h"
12796Speter #include "0.h"
13796Speter #include "tree.h"
1414749Sthien #include "tree_ty.h"
15796Speter 
16796Speter extern	int *spacep;
17796Speter 
18796Speter /*
19796Speter  * LIST MANIPULATION ROUTINES
20796Speter  *
21796Speter  * The grammar for Pascal is written left recursively.
22796Speter  * Because of this, the portions of parse trees which are to resemble
23796Speter  * lists are in the somewhat inconvenient position of having
24796Speter  * the nodes built from left to right, while we want to eventually
25796Speter  * have as semantic value the leftmost node.
26796Speter  * We could carry the leftmost node as semantic value, but this
27796Speter  * would be inefficient as to add a new node to the list we would
28796Speter  * have to chase down to the end.  Other solutions involving a head
29796Speter  * and tail pointer waste space.
30796Speter  *
31796Speter  * The simple solution to this apparent dilemma is to carry along
32796Speter  * a pointer to the leftmost node in a list in the rightmost node
33796Speter  * which is the current semantic value of the list.
34796Speter  * When we have completed building the list, we can retrieve this
35796Speter  * left end pointer very easily; neither adding new elements to the list
36796Speter  * nor finding the left end is thus expensive.  As the bottommost node
37796Speter  * has an unused next pointer in it, no space is wasted either.
38796Speter  *
39796Speter  * The nodes referred to here are of the T_LISTPP type and have
40796Speter  * the form:
41796Speter  *
42796Speter  *	T_LISTPP	some_pointer		next_element
43796Speter  *
44796Speter  * Here some_pointer points to the things of interest in the list,
45796Speter  * and next_element to the next thing in the list except for the
46796Speter  * rightmost node, in which case it points to the leftmost node.
47796Speter  * The next_element of the rightmost node is of course zapped to the
48796Speter  * NIL pointer when the list is completed.
49796Speter  *
50796Speter  * Thinking of the lists as tree we heceforth refer to the leftmost
51796Speter  * node as the "top", and the rightmost node as the "bottom" or as
52796Speter  * the "virtual root".
53796Speter  */
54796Speter 
55796Speter /*
56796Speter  * Make a new list
57796Speter  */
5814749Sthien struct tnode *
59796Speter newlist(new)
6014749Sthien 	register struct tnode *new;
61796Speter {
62796Speter 
6314749Sthien 	if (new == TR_NIL)
6414749Sthien 		return (TR_NIL);
6514749Sthien 	return ((struct tnode *) tree3(T_LISTPP, (int) new,
6614749Sthien 					(struct tnode *) spacep));
67796Speter }
68796Speter 
69796Speter /*
70796Speter  * Add a new element to an existing list
71796Speter  */
7214749Sthien struct tnode *
73796Speter addlist(vroot, new)
7414749Sthien 	register struct tnode *vroot;
7514749Sthien 	struct tnode *new;
76796Speter {
7714749Sthien 	register struct tnode *top;
78796Speter 
7914749Sthien 	if (new == TR_NIL)
80796Speter 		return (vroot);
8114749Sthien 	if (vroot == TR_NIL)
82796Speter 		return (newlist(new));
8314749Sthien 	top = vroot->list_node.next;
8414749Sthien 	vroot->list_node.next = (struct tnode *) spacep;
8514749Sthien 	return ((struct tnode *) tree3(T_LISTPP, (int) new, top));
86796Speter }
87796Speter 
88796Speter /*
89796Speter  * Fix up the list which has virtual root vroot.
90796Speter  * We grab the top pointer and return it, zapping the spot
91796Speter  * where it was so that the tree is not circular.
92796Speter  */
9314749Sthien struct tnode *
94796Speter fixlist(vroot)
9514749Sthien 	register struct tnode *vroot;
96796Speter {
9714749Sthien 	register struct tnode *top;
98796Speter 
9914749Sthien 	if (vroot == TR_NIL)
10014749Sthien 		return (TR_NIL);
10114749Sthien 	top = vroot->list_node.next;
10214749Sthien 	vroot->list_node.next = TR_NIL;
103796Speter 	return (top);
104796Speter }
105796Speter 
106796Speter 
107796Speter /*
108796Speter  * Set up a T_VAR node for a qualified variable.
109796Speter  * Init is the initial entry in the qualification,
110796Speter  * or NIL if there is none.
111796Speter  *
112796Speter  * if we are building pTrees, there has to be an extra slot for
113796Speter  * a pointer to the namelist entry of a field, if this T_VAR refers
114796Speter  * to a field name within a WITH statement.
115796Speter  * this extra field is set in lvalue, and used in VarCopy.
116796Speter  */
11714749Sthien struct tnode *
118796Speter setupvar(var, init)
119796Speter 	char *var;
12014749Sthien 	register struct tnode *init;
121796Speter {
122796Speter 
12314749Sthien 	if (init != TR_NIL)
124796Speter 		init = newlist(init);
125796Speter #	ifndef PTREE
12614749Sthien 	    return (tree4(T_VAR, NOCON, (struct tnode *) var, init));
127796Speter #	else
12814749Sthien 	    return tree5( T_VAR, NOCON, (struct tnode *) var, init, TR_NIL );
129796Speter #	endif
130796Speter }
131796Speter 
132796Speter     /*
133796Speter      *	set up a T_TYREC node for a record
134796Speter      *
135796Speter      *	if we are building pTrees, there has to be an extra slot for
136796Speter      *	a pointer to the namelist entry of the record.
137796Speter      *	this extra field is filled in in gtype, and used in RecTCopy.
138796Speter      */
13914749Sthien struct tnode *
14014749Sthien setuptyrec( line , fldlist )
141796Speter     int	line;
14214749Sthien     struct tnode *fldlist;
143796Speter     {
144796Speter 
145796Speter #	ifndef PTREE
14614749Sthien 	    return tree3( T_TYREC , line , fldlist );
147796Speter #	else
14814749Sthien 	    return tree4( T_TYREC , line , fldlst , TR_NIL );
149796Speter #	endif
150796Speter     }
151796Speter 
152796Speter     /*
153796Speter      *	set up a T_FIELD node for a field.
154796Speter      *
155796Speter      *	if we are building pTrees, there has to be an extra slot for
156796Speter      *	a pointer to the namelist entry of the field.
157796Speter      *	this extra field is set in lvalue, and used in SelCopy.
158796Speter      */
15914749Sthien struct tnode *
160796Speter setupfield( field , other )
16114749Sthien     struct tnode *field;
16214749Sthien     struct tnode *other;
163796Speter     {
164796Speter 
165796Speter #	ifndef PTREE
16614749Sthien 	    return tree3( T_FIELD , (int) field , other );
167796Speter #	else
16814749Sthien 	    return tree4( T_FIELD , (int) field , other , TR_NIL );
169796Speter #	endif
170796Speter     }
171