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