File indexing completed on 2025-01-26 04:43:58
0001 /* Abstract syntax tree manipulation functions 0002 * 0003 * SOFTWARE RIGHTS 0004 * 0005 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool 0006 * Set (PCCTS) -- PCCTS is in the public domain. An individual or 0007 * company may do whatever they wish with source code distributed with 0008 * PCCTS or the code generated by PCCTS, including the incorporation of 0009 * PCCTS, or its output, into commercial software. 0010 * 0011 * We encourage users to develop software with PCCTS. However, we do ask 0012 * that credit is given to us for developing PCCTS. By "credit", 0013 * we mean that if you incorporate our source code into one of your 0014 * programs (commercial product, research project, or otherwise) that you 0015 * acknowledge this fact somewhere in the documentation, research report, 0016 * etc... If you like PCCTS and have developed a nice tool with the 0017 * output, please mention that you developed it using PCCTS. In 0018 * addition, we ask that this header remain intact in our source code. 0019 * As long as these guidelines are kept, we expect to continue enhancing 0020 * this system and expect to make other tools available as they are 0021 * completed. 0022 * 0023 * ANTLR 1.33 0024 * Terence Parr 0025 * Parr Research Corporation 0026 * with Purdue University and AHPCRC, University of Minnesota 0027 * 1989-1995 0028 */ 0029 #include <stdarg.h> 0030 #include <stdio.h> 0031 0032 #include "ast.h" 0033 #include "attrib.h" 0034 #include "antlr.h" 0035 0036 /* ensure that tree manipulation variables are current after a rule 0037 * reference 0038 */ 0039 void 0040 zzlink(AST **_root, AST **_sibling, AST **_tail) 0041 { 0042 if ( *_sibling == NULL ) return; 0043 if ( *_root == NULL ) *_root = *_sibling; 0044 else if ( *_root != *_sibling ) (*_root)->down = *_sibling; 0045 if ( *_tail==NULL ) *_tail = *_sibling; 0046 while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right; 0047 } 0048 0049 AST * 0050 zzastnew(void) 0051 { 0052 AST *p = (AST *) calloc(1, sizeof(AST)); 0053 if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__); 0054 return p; 0055 } 0056 0057 /* add a child node to the current sibling list */ 0058 void 0059 zzsubchild(AST **_root, AST **_sibling, AST **_tail) 0060 { 0061 AST *n; 0062 zzNON_GUESS_MODE { 0063 n = zzastnew(); 0064 #ifdef DEMAND_LOOK 0065 zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); 0066 #else 0067 zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); 0068 #endif 0069 zzastPush( n ); 0070 if ( *_tail != NULL ) (*_tail)->right = n; 0071 else { 0072 *_sibling = n; 0073 if ( *_root != NULL ) (*_root)->down = *_sibling; 0074 } 0075 *_tail = n; 0076 if ( *_root == NULL ) *_root = *_sibling; 0077 } 0078 } 0079 0080 /* make a new AST node. Make the newly-created 0081 * node the root for the current sibling list. If a root node already 0082 * exists, make the newly-created node the root of the current root. 0083 */ 0084 void 0085 zzsubroot(AST **_root, AST **_sibling, AST **_tail) 0086 { 0087 AST *n; 0088 zzNON_GUESS_MODE { 0089 n = zzastnew(); 0090 #ifdef DEMAND_LOOK 0091 zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); 0092 #else 0093 zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); 0094 #endif 0095 zzastPush( n ); 0096 if ( *_root != NULL ) 0097 if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root; 0098 *_root = n; 0099 (*_root)->down = *_sibling; 0100 } 0101 } 0102 0103 /* Apply function to root then each sibling 0104 * example: print tree in child-sibling LISP-format (AST has token field) 0105 * 0106 * void show(tree) 0107 * AST *tree; 0108 * { 0109 * if ( tree == NULL ) return; 0110 * printf(" %s", zztokens[tree->token]); 0111 * } 0112 * 0113 * void before() { printf(" ("); } 0114 * void after() { printf(" )"); } 0115 * 0116 * LISPdump() { zzpre_ast(tree, show, before, after); } 0117 * 0118 */ 0119 void 0120 zzpre_ast( 0121 AST *tree, 0122 void (*func)(AST *), /* apply this to each tree node */ 0123 void (*before)(AST *), /* apply this to root of subtree before preordering it */ 0124 void (*after)(AST *)) /* apply this to root of subtree after preordering it */ 0125 { 0126 while ( tree!= NULL ) 0127 { 0128 if ( tree->down != NULL ) (*before)(tree); 0129 (*func)(tree); 0130 zzpre_ast(tree->down, func, before, after); 0131 if ( tree->down != NULL ) (*after)(tree); 0132 tree = tree->right; 0133 } 0134 } 0135 0136 /* free all AST nodes in tree; apply func to each before freeing */ 0137 void 0138 zzfree_ast(AST *tree) 0139 { 0140 if ( tree == NULL ) return; 0141 zzfree_ast( tree->down ); 0142 zzfree_ast( tree->right ); 0143 zztfree( tree ); 0144 } 0145 0146 /* build a tree (root child1 child2 ... NULL) 0147 * If root is NULL, simply make the children siblings and return ptr 0148 * to 1st sibling (child1). If root is not single node, return NULL. 0149 * 0150 * Siblings that are actually siblins lists themselves are handled 0151 * correctly. For example #( NULL, #( NULL, A, B, C), D) results 0152 * in the tree ( NULL A B C D ). 0153 * 0154 * Requires at least two parameters with the last one being NULL. If 0155 * both are NULL, return NULL. 0156 */ 0157 AST *zztmake(AST *rt, ...) 0158 { 0159 va_list ap; 0160 register AST *child, *sibling=NULL, *tail, *w; 0161 AST *root; 0162 0163 va_start(ap, rt); 0164 root = rt; 0165 0166 if ( root != NULL ) 0167 if ( root->down != NULL ) return NULL; 0168 child = va_arg(ap, AST *); 0169 while ( child != NULL ) 0170 { 0171 for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */ 0172 if ( sibling == NULL ) {sibling = child; tail = w;} 0173 else {tail->right = child; tail = w;} 0174 child = va_arg(ap, AST *); 0175 } 0176 if ( root==NULL ) root = sibling; 0177 else root->down = sibling; 0178 va_end(ap); 0179 return root; 0180 } 0181 0182 /* tree duplicate */ 0183 AST * 0184 zzdup_ast(AST *t) 0185 { 0186 AST *u; 0187 0188 if ( t == NULL ) return NULL; 0189 u = zzastnew(); 0190 *u = *t; 0191 #ifdef zzAST_DOUBLE 0192 u->up = NULL; /* set by calling invocation */ 0193 u->left = NULL; 0194 #endif 0195 u->right = zzdup_ast(t->right); 0196 u->down = zzdup_ast(t->down); 0197 #ifdef zzAST_DOUBLE 0198 if ( u->right!=NULL ) u->right->left = u; 0199 if ( u->down!=NULL ) u->down->up = u; 0200 #endif 0201 return u; 0202 } 0203 0204 void 0205 zztfree(AST *t) 0206 { 0207 #ifdef zzd_ast 0208 zzd_ast( t ); 0209 #endif 0210 free( t ); 0211 } 0212 0213 #ifdef zzAST_DOUBLE 0214 /* 0215 * Set the 'up', and 'left' pointers of all nodes in 't'. 0216 * Initial call is double_link(your_tree, NULL, NULL). 0217 */ 0218 void 0219 zzdouble_link(AST *t, AST *left, AST *up) 0220 { 0221 if ( t==NULL ) return; 0222 t->left = left; 0223 t->up = up; 0224 zzdouble_link(t->down, NULL, t); 0225 zzdouble_link(t->right, t, up); 0226 } 0227 #endif