1 /* Abstract syntax tree manipulation functions 2 * 3 * SOFTWARE RIGHTS 4 * 5 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool 6 * Set (PCCTS) -- PCCTS is in the public domain. An individual or 7 * company may do whatever they wish with source code distributed with 8 * PCCTS or the code generated by PCCTS, including the incorporation of 9 * PCCTS, or its output, into commerical software. 10 * 11 * We encourage users to develop software with PCCTS. However, we do ask 12 * that credit is given to us for developing PCCTS. By "credit", 13 * we mean that if you incorporate our source code into one of your 14 * programs (commercial product, research project, or otherwise) that you 15 * acknowledge this fact somewhere in the documentation, research report, 16 * etc... If you like PCCTS and have developed a nice tool with the 17 * output, please mention that you developed it using PCCTS. In 18 * addition, we ask that this header remain intact in our source code. 19 * As long as these guidelines are kept, we expect to continue enhancing 20 * this system and expect to make other tools available as they are 21 * completed. 22 * 23 * ANTLR 1.33 24 * Terence Parr 25 * Parr Research Corporation 26 * with Purdue University and AHPCRC, University of Minnesota 27 * 1989-2000 28 */ 29 30 #include "pcctscfg.h" 31 32 #include "pccts_stdio.h" 33 #include "pccts_stdarg.h" 34 35 PCCTS_NAMESPACE_STD 36 37 #define ANTLR_SUPPORT_CODE 38 39 #include "ASTBase.h" 40 41 /* ensure that tree manipulation variables are current after a rule 42 * reference 43 */ 44 void 45 ASTBase::link(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) 46 { 47 if ( *_sibling == NULL ) return; 48 if ( *_root == NULL ) *_root = *_sibling; 49 else if ( *_root != *_sibling ) (*_root)->_down = *_sibling; 50 if ( *_tail==NULL ) *_tail = *_sibling; 51 while ( (*_tail)->_right != NULL ) *_tail = (*_tail)->_right; 52 } 53 54 /* add a child node to the current sibling list */ 55 void 56 ASTBase::subchild(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) 57 { 58 if ( *_tail != NULL ) (*_tail)->_right = this; 59 else { 60 *_sibling = this; 61 if ( *_root != NULL ) (*_root)->_down = *_sibling; 62 } 63 *_tail = this; 64 if ( *_root == NULL ) *_root = *_sibling; 65 } 66 67 /* make a new AST node. Make the newly-created 68 * node the root for the current sibling list. If a root node already 69 * exists, make the newly-created node the root of the current root. 70 */ 71 void 72 ASTBase::subroot(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) 73 { 74 if ( *_root != NULL ) 75 if ( (*_root)->_down == *_sibling ) *_sibling = *_tail = *_root; 76 *_root = this; 77 (*_root)->_down = *_sibling; 78 } 79 80 /* Apply preorder_action(), etc.. to root then each sibling */ 81 // 82 // 7-Apr-97 133MR1 83 // Fix suggested by Ron House (house (at) helios.usq.edu.au) 84 // 85 void 86 ASTBase::preorder(void* pData /*= NULL*/ /* MR23 */) 87 { 88 ASTBase *tree = this; 89 90 while ( tree!= NULL ) 91 { 92 if ( tree->_down != NULL ) { 93 tree->preorder_before_action(pData); // MR1 94 }; 95 tree->preorder_action(pData); 96 if ( tree->_down!=NULL ) 97 { 98 tree->_down->preorder(pData); 99 tree->preorder_after_action(pData); // MR1 100 } 101 tree = tree->_right; 102 } 103 } 104 105 /* free all AST nodes in tree; apply func to each before freeing */ 106 void 107 ASTBase::destroy() 108 { 109 ASTBase* tree = this; 110 while (tree) { 111 if (tree->_down) tree->_down->destroy(); 112 113 ASTBase* cur = tree; 114 tree = tree->_right; 115 delete cur; 116 } 117 } 118 119 /* build a tree (root child1 child2 ... NULL) 120 * If root is NULL, simply make the children siblings and return ptr 121 * to 1st sibling (child1). If root is not single node, return NULL. 122 * 123 * Siblings that are actually siblins lists themselves are handled 124 * correctly. For example #( NULL, #( NULL, A, B, C), D) results 125 * in the tree ( NULL A B C D ). 126 * 127 * Requires at least two parameters with the last one being NULL. If 128 * both are NULL, return NULL. 129 */ 130 ASTBase * 131 ASTBase::tmake(ASTBase *root, ...) 132 { 133 va_list ap; 134 register ASTBase *child, *sibling=NULL, *tail=NULL /*MR23*/, *w; 135 136 va_start(ap, root); 137 138 if ( root != NULL ) 139 if ( root->_down != NULL ) { 140 root->reportOverwriteOfDownPointer(); /* MR21 Report problem which almost always an error */ 141 return NULL; 142 } 143 child = va_arg(ap, ASTBase *); 144 while ( child != NULL ) 145 { 146 for (w=child; w->_right!=NULL; w=w->_right) {;} /* find end of child */ 147 if ( sibling == NULL ) {sibling = child; tail = w;} 148 else {tail->_right = child; tail = w;} 149 child = va_arg(ap, ASTBase *); 150 } 151 if ( root==NULL ) root = sibling; 152 else root->_down = sibling; 153 va_end(ap); 154 return root; 155 } 156 157 #ifndef PCCTS_NOT_USING_SOR 158 159 /* tree duplicate */ 160 // forgot to check for NULL this (TJP July 23,1995) 161 ASTBase * 162 ASTBase::dup() 163 { 164 ASTBase *u, *t=this; 165 166 if ( t == NULL ) return NULL; 167 /* 168 u = new ASTBase; 169 *u = *t; 170 */ 171 u = (ASTBase *)this->shallowCopy(); 172 if ( t->_right!=NULL ) u->_right = t->_right->dup(); 173 else u->_right = NULL; 174 if ( t->_down!=NULL ) u->_down = t->_down->dup(); 175 else u->_down = NULL; 176 return u; 177 } 178 #endif 179 180 // 181 // 7-Apr-97 133MR1 182 // Fix suggested by Asgeir Olafsson (olafsson (at) cstar.ac.com) 183 // 184 /* tree duplicate */ 185 186 #ifndef PCCTS_NOT_USING_SOR 187 188 ASTBase * 189 ASTDoublyLinkedBase::dup() 190 { 191 ASTDoublyLinkedBase *u, *t=this; 192 193 if ( t == NULL ) return NULL; 194 u = (ASTDoublyLinkedBase *)this->shallowCopy(); 195 u->_up = NULL; /* set by calling invocation */ 196 u->_left = NULL; 197 if (t->_right!=NULL) { // MR1 198 u->_right=t->_right->dup(); // MR1 199 ((ASTDoublyLinkedBase *)u->_right)->_left = u; // MR1 200 } else { // MR1 201 u->_right = NULL; // MR1 202 }; // MR1 203 if (t->_down!=NULL) { // MR1 204 u->_down = t->_down->dup(); // MR1 205 ((ASTDoublyLinkedBase *)u->_down)->_up = u; // MR1 206 } else { // MR1 207 u->_down = NULL; // MR1 208 }; // MR1 209 return u; 210 } 211 212 #endif 213 214 /* 215 * Set the 'up', and 'left' pointers of all nodes in 't'. 216 * Initial call is double_link(your_tree, NULL, NULL). 217 */ 218 void 219 ASTDoublyLinkedBase::double_link(ASTBase *left, ASTBase *up) 220 { 221 ASTDoublyLinkedBase *t = this; 222 223 t->_left = (ASTDoublyLinkedBase *) left; 224 t->_up = (ASTDoublyLinkedBase *) up; 225 if (t->_down != NULL) 226 ((ASTDoublyLinkedBase *)t->_down)->double_link(NULL, t); 227 if (t->_right != NULL) 228 ((ASTDoublyLinkedBase *)t->_right)->double_link(t, up); 229 } 230 231 // MR21 ASTBase::reportOverwriteOfDownPointer 232 233 void ASTBase::reportOverwriteOfDownPointer() 234 { 235 panic("Attempt to overwrite down pointer in ASTBase::tmake"); 236 } 237 238 // MR21 ASTBase::panic 239 240 void ASTBase::panic(const char *msg) 241 { 242 /* MR23 */ printMessage(stderr,"ASTBase panic: %s\n", msg); 243 exit(PCCTS_EXIT_FAILURE); 244 } 245 246 #ifdef PCCTS_NOT_USING_SOR 247 //MR23 248 int ASTBase::printMessage(FILE* pFile, const char* pFormat, ...) 249 { 250 va_list marker; 251 va_start( marker, pFormat ); 252 int iRet = vfprintf(pFile, pFormat, marker); 253 va_end( marker ); 254 return iRet; 255 } 256 #endif 257