Home | History | Annotate | Download | only in h
      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