1*796Speter /* Copyright (c) 1979 Regents of the University of California */ 2*796Speter 3*796Speter static char sccsid[] = "@(#)yytree.c 1.1 08/27/80"; 4*796Speter 5*796Speter #include "whoami.h" 6*796Speter #include "0.h" 7*796Speter #include "tree.h" 8*796Speter 9*796Speter extern int *spacep; 10*796Speter 11*796Speter /* 12*796Speter * LIST MANIPULATION ROUTINES 13*796Speter * 14*796Speter * The grammar for Pascal is written left recursively. 15*796Speter * Because of this, the portions of parse trees which are to resemble 16*796Speter * lists are in the somewhat inconvenient position of having 17*796Speter * the nodes built from left to right, while we want to eventually 18*796Speter * have as semantic value the leftmost node. 19*796Speter * We could carry the leftmost node as semantic value, but this 20*796Speter * would be inefficient as to add a new node to the list we would 21*796Speter * have to chase down to the end. Other solutions involving a head 22*796Speter * and tail pointer waste space. 23*796Speter * 24*796Speter * The simple solution to this apparent dilemma is to carry along 25*796Speter * a pointer to the leftmost node in a list in the rightmost node 26*796Speter * which is the current semantic value of the list. 27*796Speter * When we have completed building the list, we can retrieve this 28*796Speter * left end pointer very easily; neither adding new elements to the list 29*796Speter * nor finding the left end is thus expensive. As the bottommost node 30*796Speter * has an unused next pointer in it, no space is wasted either. 31*796Speter * 32*796Speter * The nodes referred to here are of the T_LISTPP type and have 33*796Speter * the form: 34*796Speter * 35*796Speter * T_LISTPP some_pointer next_element 36*796Speter * 37*796Speter * Here some_pointer points to the things of interest in the list, 38*796Speter * and next_element to the next thing in the list except for the 39*796Speter * rightmost node, in which case it points to the leftmost node. 40*796Speter * The next_element of the rightmost node is of course zapped to the 41*796Speter * NIL pointer when the list is completed. 42*796Speter * 43*796Speter * Thinking of the lists as tree we heceforth refer to the leftmost 44*796Speter * node as the "top", and the rightmost node as the "bottom" or as 45*796Speter * the "virtual root". 46*796Speter */ 47*796Speter 48*796Speter /* 49*796Speter * Make a new list 50*796Speter */ 51*796Speter newlist(new) 52*796Speter register int *new; 53*796Speter { 54*796Speter 55*796Speter if (new == NIL) 56*796Speter return (NIL); 57*796Speter return (tree3(T_LISTPP, new, spacep)); 58*796Speter } 59*796Speter 60*796Speter /* 61*796Speter * Add a new element to an existing list 62*796Speter */ 63*796Speter addlist(vroot, new) 64*796Speter register int *vroot; 65*796Speter int *new; 66*796Speter { 67*796Speter register int *top; 68*796Speter 69*796Speter if (new == NIL) 70*796Speter return (vroot); 71*796Speter if (vroot == NIL) 72*796Speter return (newlist(new)); 73*796Speter top = vroot[2]; 74*796Speter vroot[2] = spacep; 75*796Speter return (tree3(T_LISTPP, new, top)); 76*796Speter } 77*796Speter 78*796Speter /* 79*796Speter * Fix up the list which has virtual root vroot. 80*796Speter * We grab the top pointer and return it, zapping the spot 81*796Speter * where it was so that the tree is not circular. 82*796Speter */ 83*796Speter fixlist(vroot) 84*796Speter register int *vroot; 85*796Speter { 86*796Speter register int *top; 87*796Speter 88*796Speter if (vroot == NIL) 89*796Speter return (NIL); 90*796Speter top = vroot[2]; 91*796Speter vroot[2] = NIL; 92*796Speter return (top); 93*796Speter } 94*796Speter 95*796Speter 96*796Speter /* 97*796Speter * Set up a T_VAR node for a qualified variable. 98*796Speter * Init is the initial entry in the qualification, 99*796Speter * or NIL if there is none. 100*796Speter * 101*796Speter * if we are building pTrees, there has to be an extra slot for 102*796Speter * a pointer to the namelist entry of a field, if this T_VAR refers 103*796Speter * to a field name within a WITH statement. 104*796Speter * this extra field is set in lvalue, and used in VarCopy. 105*796Speter */ 106*796Speter setupvar(var, init) 107*796Speter char *var; 108*796Speter register int *init; 109*796Speter { 110*796Speter 111*796Speter if (init != NIL) 112*796Speter init = newlist(init); 113*796Speter # ifndef PTREE 114*796Speter return (tree4(T_VAR, NOCON, var, init)); 115*796Speter # else 116*796Speter return tree5( T_VAR , NOCON , var , init , NIL ); 117*796Speter # endif 118*796Speter } 119*796Speter 120*796Speter /* 121*796Speter * set up a T_TYREC node for a record 122*796Speter * 123*796Speter * if we are building pTrees, there has to be an extra slot for 124*796Speter * a pointer to the namelist entry of the record. 125*796Speter * this extra field is filled in in gtype, and used in RecTCopy. 126*796Speter */ 127*796Speter setuptyrec( line , fldlst ) 128*796Speter int line; 129*796Speter int *fldlst; 130*796Speter { 131*796Speter 132*796Speter # ifndef PTREE 133*796Speter return tree3( T_TYREC , line , fldlst ); 134*796Speter # else 135*796Speter return tree4( T_TYREC , line , fldlst , NIL ); 136*796Speter # endif 137*796Speter } 138*796Speter 139*796Speter /* 140*796Speter * set up a T_FIELD node for a field. 141*796Speter * 142*796Speter * if we are building pTrees, there has to be an extra slot for 143*796Speter * a pointer to the namelist entry of the field. 144*796Speter * this extra field is set in lvalue, and used in SelCopy. 145*796Speter */ 146*796Speter setupfield( field , other ) 147*796Speter int *field; 148*796Speter int *other; 149*796Speter { 150*796Speter 151*796Speter # ifndef PTREE 152*796Speter return tree3( T_FIELD , field , other ); 153*796Speter # else 154*796Speter return tree4( T_FIELD , field , other , NIL ); 155*796Speter # endif 156*796Speter } 157