home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************
- *
- * Copyright (c) 1993 Ke Jin
- *
- * Permission to use, copy, modify, and distribute
- * this software and its documentation without fee
- * is granted, provided that the author's name and
- * this copyright notice are retained.
- *
- * -----------------------------------------------------
- *
- * dfctree.c -- defunc low level module
- *
- * public function : exparse();
- * evaluate();
- * reduce();
- *
- *********************************************************/
-
- #include <stdio.h>
- #include "dfctree.h"
-
- #ifdef __cplusplus
- extern "C" { /* for c++ */
- #endif
-
- #if NeedFunctionPrototypes
- extern yyinit(char* expression);
- extern int yyparse(void);
- #else
- extern yyinit();
- extern int yyparse();
- #endif
-
- #define ltree reduce(tree+tree->left-i, tree->left)
- #define rtree reduce(tree+tree->right-i, tree->right)
- #define trval tree->content.value
- #define ltrval ltree->content.value
- #define rtrval rtree->content.value
-
- #if NeedFunctionPrototypes
- Node* reduce(Node* tree, int i)
- #else
- Node* reduce(tree, i)
- Node* tree;
- int i;
- #endif
- /* constant folding. i is the shift relative to root
- * reduce tree still in original memory address. the
- * root of the tree be returned */
- {
- if(tree == 0) return 0;
-
- switch(tree->type)
- {
- case const_node:
- case arg_node:
- break;
-
- case simplex_fnct_node:
- if(rtree->type==const_node)
- {
- tree->type = const_node;
- trval = (tree->content.fnctptr)(rtrval);
- }
- break;
-
- case duplex_fnct_node:
- if((ltree->type==const_node)&&(rtree->type==const_node))
- {
- tree->type = const_node;
- trval = (tree->content.fnctptr)(ltrval, rtrval);
- }
- break;
-
- case unary_op_node:
- if(rtree->type==const_node)
- {
- tree->type = const_node;
- switch(tree->content.op)
- {
- case op_neg: trval = -rtrval; break;
-
- default: break;
- }
- }
- break;
-
- case binary_op_node:
- if(rtree->type==const_node&&tree->content.op==op_div)
- {
- tree->content.op=op_mul;
- rtree->content.value = 1.0/(rtree->content.value);
- }
-
- if(ltree->type==const_node&&rtree->type==const_node)
- {
- tree->type = const_node;
- switch(tree->content.op)
- {
- case op_sum: trval = ltrval+rtrval; break;
- case op_sub: trval = ltrval-rtrval; break;
- case op_mul: trval = ltrval*rtrval; break;
- case op_div: trval = ltrval/rtrval; break;
-
- default: break;
- }
- }
- break;
-
- default: break;
- }
-
- return tree;
- };
-
- #if NeedFunctionPrototype
- int exparse(char* expression)
- #else
- int exparse(expression)
- char* expression;
- #endif
- {
- yyinit(expression); /* initial the parser */
-
- return yyparse(); /* on success, return 0 or tree size
- * on error , return -1 */
- };
-
- #define lval evaluate(tree+tree->left-i, tree->left , x, y)
- #define rval evaluate(tree+tree->right-i, tree->right, x, y)
-
- #if NeedFunctionPrototype
- double evaluate(Node* tree, int i, double x, double y)
- #else
- double evaluate(tree, i, x, y)
- Node* tree;
- int i;
- double x, y;
- #endif
- /* evaluate a parse tree. i is the shift relative to root */
- {
- if(tree == 0)
- {
- fprintf(stderr, "Null parse tree\n");
- exit(1) ;
- }
-
- switch (tree->type)
- {
- case const_node:
- return tree->content.value;
-
- case arg_node:
- switch(tree->content.argidx)
- {
- case 1: return x;
- case 2: return y;
- default: exit(1);
- }
- break;
-
- case simplex_fnct_node:
- return (tree->content.fnctptr)(rval);
-
- case duplex_fnct_node:
- return (tree->content.fnctptr)(lval, rval);
-
- case unary_op_node:
- switch(tree->content.op)
- {
- case op_neg: return -rval;
-
- default: break;
- }
- break;
-
- case binary_op_node:
- switch(tree->content.op)
- {
- case op_sum: return lval + rval;
- case op_sub: return lval - rval;
- case op_mul: return lval * rval;
- case op_div: return lval / rval;
-
- default: break;
- }
- break;
-
- default:
- exit(1) ; /* something wrong */
- }
-
- return 0; /* turn off the warning of lint */
- };
-
- #ifdef __cplusplus
- } /* end for c++ */
- #endif
-