C:/Users/Dennis/src/lang/bertrand/BERTRAND/bertrand/expr.c

Go to the documentation of this file.
00001 /***********************************************************************
00002  *
00003  * Routines to manage expressions
00004  *
00005  ***********************************************************************/
00006 
00007 #include "def.h"
00008 #include <ctype.h>
00009 
00010 #define NODE_ALLOC 100          /* number of expr. tree nodes to allocate */
00011 NODE *expr_mem = NULL;          /* next free expression tree node */ 
00012 
00013 /***********************************************************************
00014  *
00015  * Allocate memory for expression tree nodes.  Such a node can
00016  * be used as a TERM_NODE, NAME_NODE, NUM_NODE, or STR_NODE.
00017  * A NODE is a generic type, and is used only for storage management.
00018  *
00019  * exit:        return pointer to a new expression-tree node
00020  *
00021  ***********************************************************************/
00022 NODE *
00023 node_new()
00024 {
00025 char *calloc();
00026 NODE *temp;
00027 register int i;
00028 
00029 if (!expr_mem) {
00030 #   ifdef DEBUG
00031     printf("allocating expression nodes\n");
00032     fflush(stdout);
00033 #   endif
00034     expr_mem = (NODE *) calloc(NODE_ALLOC, sizeof (NODE));
00035     if (!expr_mem) error("out of memory");
00036     for (i = 0; i < NODE_ALLOC - 1; i++)
00037         expr_mem[i].next = &expr_mem[i+1];
00038     expr_mem[NODE_ALLOC-1].next = NULL;
00039     }
00040 
00041 temp = expr_mem;
00042 expr_mem = expr_mem->next;
00043 return temp ;
00044 }
00045 
00046 /***********************************************************************
00047  *
00048  * Storage reclamation
00049  *
00050  ***********************************************************************/
00051 void
00052 node_free(n)
00053 NODE *n;        /* expression node to be freed */
00054 {
00055 /* Put a node back on free list */
00056 n->next = expr_mem;
00057 expr_mem = n;
00058 }
00059 
00060 void expr_free(fn)
00061 NODE *fn;
00062 {
00063 char *arity_name();             /* from ops.c */
00064 void name_free();               /* from names.c */
00065 
00066 if ((fn->op->arity == OP_STR) || (fn->op->arity == OP_NUM)) node_free(fn);
00067 else if (fn->op->arity == OP_NAME) name_free((NAME_NODE *) fn);
00068 /* if node is a nullary operator */
00069 else if (fn->op->arity == NULLARY) {
00070     if (((TERM_NODE *)fn)->label) name_free(((TERM_NODE *) fn)->label);
00071     node_free(fn);
00072     }
00073 else if ((fn->op->arity & BINARY) || (fn->op->arity & UNARY)) {
00074     if (((TERM_NODE *)fn)->label) name_free(((TERM_NODE *) fn)->label);
00075     if ((fn->op->arity & BINARY) || (fn->op->arity == POSTFIX))
00076         expr_free(((TERM_NODE *)fn)->left);
00077     if (fn->op->arity != POSTFIX) expr_free(((TERM_NODE *)fn)->right);
00078     node_free(fn);
00079     }
00080 else {
00081     fprintf(stderr, "arity: %s\n", arity_name(fn->op->arity));
00082     error("Unknown arity while printing expression tree");
00083     }
00084 }
00085 
00086 /***********************************************************************
00087  *
00088  * Traverse and print the expression tree inorder.
00089  *
00090  * entry:       root of tree (or subtree)
00091  *
00092  ***********************************************************************/
00093 void
00094 expr_print(p)
00095 NODE *p;
00096 {
00097 void name_print();      /* from names.c */
00098 char *arity_name();     /* from ops.c */
00099 
00100 /* static unsigned char *hit_newline = 0;
00101 if (_iob[2]._ptr < hit_newline || 65 < _iob[2]._ptr - hit_newline) {
00102     hit_newline = _iob[2]._ptr;
00103     fprintf(stderr,"\n   ");
00104     } */
00105 /* if node is a string */
00106 if (p->op->arity == OP_STR) fprintf(stderr, "\"%s\"", ((STR_NODE *)p)->value);
00107 /* if node is a number */
00108 else if (p->op->arity == OP_NUM) fprintf(stderr, "%g", ((NUM_NODE *)p)->value);
00109 /* if node is a name */
00110 else if (p->op->arity == OP_NAME) name_print((NAME_NODE *) p);
00111 /* if node is a nullary operator */
00112 else if (p->op->arity == NULLARY) {
00113     if (((TERM_NODE *)p)->label) {
00114         name_print(((TERM_NODE *)p)->label);
00115         fprintf(stderr, ":");
00116         }
00117     if (isalpha(p->op->pname[0])) fprintf(stderr, " %s ", p->op->pname);
00118     else fprintf(stderr, "%s", p->op->pname);
00119     }
00120 /* if node is a binary or unary operator */
00121 else if ((p->op->arity & BINARY) || (p->op->arity & UNARY)) {
00122     /* if node is labeled */
00123     if (((TERM_NODE *)p)->label) {
00124         name_print(((TERM_NODE *)p)->label);
00125         fprintf(stderr, ":");
00126         }
00127     if (p->op->arity != OUTFIX1) fprintf(stderr, "(");
00128     /* print left argument */
00129     if ((p->op->arity & BINARY) || (p->op->arity == POSTFIX))
00130         expr_print(((TERM_NODE *)p)->left);
00131     /* print operator.  If alphabetic, put spaces around it */
00132     if (isalpha(p->op->pname[0])) fprintf(stderr, " %s ", p->op->pname);
00133     else fprintf(stderr, "%s", p->op->pname);
00134     /* print right argument */
00135     if (p->op->arity != POSTFIX) expr_print(((TERM_NODE *)p)->right);
00136     /* print matching outfix operator */
00137     if (p->op->arity == OUTFIX1) fprintf(stderr, "%s", p->op->other->pname);
00138     else fprintf(stderr, ")");
00139     }
00140 else {
00141     fprintf(stderr, "arity: %s\n", arity_name(p->op->arity));
00142     error("Unknown arity while printing expression tree");
00143     }
00144 }
00145 
00146 /***********************************************************************
00147  *
00148  * Make a copy of an expression tree.
00149  *
00150  * entry:       root of tree.
00151  *
00152  * exit:        root of a copy of the tree.
00153  *
00154  ***********************************************************************/
00155 NODE *
00156 expr_copy(otree)
00157 NODE *otree;            /* old expression to copy */
00158 {
00159 NAME_NODE *name_copy(); /* from names.c */
00160 char *arity_name();     /* from ops.c */
00161 
00162 if (!otree) error("null node in expr_copy!");
00163 if (!otree->op) error("node with no operator in expr_copy!");
00164 
00165 if (otree->op->arity & OP_TERM) {               /* this is a TERM_NODE */
00166     TERM_NODE *te = (TERM_NODE *) node_new();
00167     te->op = otree->op; /* copy operator */
00168     if (((TERM_NODE *) otree)->label)
00169         te->label = name_copy(((TERM_NODE *) otree)->label);
00170     else te->label = (NAME_NODE *) NULL;
00171     if (((TERM_NODE *) otree)->right)
00172         te->right = expr_copy(((TERM_NODE *) otree)->right);
00173     else te->right = (NODE *) NULL;
00174     if (((TERM_NODE *) otree)->left)
00175         te->left = expr_copy(((TERM_NODE *) otree)->left);
00176     else te->left = (NODE *) NULL;
00177     return (NODE *) te;
00178     }
00179 if (otree->op->arity & OP_NAME) {
00180 /*    if (((NAME_NODE *) otree)->value) /* replace variable by its value *//*
00181         return expr_copy(((NAME_NODE *) otree)->value);
00182     else */ return (NODE *) name_copy((NAME_NODE *) otree);
00183     }
00184 if (otree->op->arity & OP_NUM) {
00185     NUM_NODE *ne = (NUM_NODE *) node_new();
00186     ne->op = otree->op;
00187     ne->value = ((NUM_NODE *) otree)->value;
00188     return (NODE *) ne;
00189     }
00190 if (otree->op->arity & OP_STR) {
00191     STR_NODE *se = (STR_NODE *) node_new();
00192     se->op = otree->op;
00193     /* WARNING: following leaves two pointers to the same string */
00194     se->value = ((STR_NODE *) otree)->value;
00195     return (NODE *) se;
00196     }
00197 /* if we get here, then there is an error.  Shouldn't ever happen */
00198 fprintf(stderr, "operator: %s, arity: %s\n",
00199     otree->op->pname, arity_name(otree->op->arity));
00200 error("invalid operator arity in expr_copy");
00201 }
00202 
00203 /***********************************************************************
00204  *
00205  * Walk expression tree replacing bound variables by their values.
00206  *
00207  * entry:       root of tree.
00208  *
00209  * exit:        root of updated tree.
00210  *
00211  ***********************************************************************/
00212 NODE *
00213 expr_update(tree)
00214 NODE *tree;
00215 {
00216 void name_free();               /* from names.c */
00217 
00218 if (!tree) error("null node in expr_update!");
00219 if (!tree->op) error("node with no operator in expr_update!");
00220 
00221 if (tree->op->arity & OP_NAME) {        /* a NAME_NODE */
00222     if (((NAME_NODE *)tree)->value) {   /* variable is bound */
00223         /* note recursion! */
00224         NODE *val = expr_update(((NAME_NODE *)tree)->value);
00225         ((NAME_NODE *)tree)->value = val;
00226         val = expr_copy(val);
00227         name_free((NAME_NODE *)tree);
00228         return val;
00229         }
00230     else return tree;
00231     }
00232 if (tree->op->arity & OP_TERM) {        /* a TERM_NODE */
00233     if (((TERM_NODE *)tree)->left)
00234         ((TERM_NODE *)tree)->left = expr_update(((TERM_NODE *)tree)->left);
00235     if (((TERM_NODE *)tree)->right)
00236         ((TERM_NODE *)tree)->right = expr_update(((TERM_NODE *)tree)->right);
00237     }
00238 return tree;    /* anything else */
00239 }

Generated on Fri Jan 25 09:58:42 2008 for Bertrand by  doxygen 1.5.4