/* formula parser Copyright (C) 1992-2000 Michigan State University The CAPA system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The CAPA system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the CAPA system; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, you have permission to link this program with the TtH/TtM library and distribute executables, as long as you follow the requirements of the GNU GPL in regard to all of the software in the executable aside from TtH/TtM. */ /* ====================================================== */ /* capaFormula.y created by Isaac Tsai @ Feb 1999 */ /* TODO: checking user inputs 2/27/99 IT */ /* ====================================================== */ %{ #include #include #include #include #include "capaParser.h" /* _symbol structure def */ #include "capaCommon.h" #include "capaFunction.h" #ifdef YYSTYPE #undef YYSTYPE #endif #define YYSTYPE Symbol_p #include "capaToken.h" #ifdef __hpux #include #include #endif #ifdef FML_DBUG #define FMLDBUG_PR1(xx) { printf(xx); fflush(stdout); } #define FMLDBUG_PR2(xx,yy) { printf(xx,yy); fflush(stdout); } #define FMLDBUG_PR3(xx,yy,zz) { printf(xx,yy,zz); fflush(stdout); } #else #define FMLDBUG_PR1(xx) { } #define FMLDBUG_PR2(xx,yy) { } #define FMLDBUG_PR3(xx,yy,zz) { } #endif #define ADD_op 1 #define SUB_op 2 #define MUL_op 3 #define DIV_op 4 #define IDIV_op 5 #define NOT_DEFINED_op 9 /* =============================================================== */ extern int Func_idx; extern Symbol FuncStack[MAX_FUNC_NEST]; void fml_error(char *msg); double FormulaVal; int FormulaParseOK=1; %} %token F_NUMBER V_ID F_ID EoI F_ERROR %left F_PLUS F_MINUS %left F_MULT F_DIV F_MOD %token F_POW %token F_LPAR F_RPAR F_COMMA %start f_expr %% f_expr : block { switch($1->s_type) { case I_VAR: case I_CONSTANT: FormulaVal = (double)($1->s_int); break; case R_VAR: case R_CONSTANT: FormulaVal = $1->s_real; break; case S_VAR: case S_CONSTANT: FormulaParseOK = 0; break; default: FormulaParseOK = 0; break; } capa_mfree((char *)$1); FMLDBUG_PR1("[f_expr <= block ]\n"); } ; block : block F_PLUS term { $$ = symbols_op($1, $3, ADD_op); } | block F_MINUS term { $$ = symbols_op($1, $3, SUB_op); } | F_MINUS block { $$ = negate($2); } | term { $$ = $1; } | F_ERROR { FormulaParseOK = 0; FMLDBUG_PR1("[F_ERROR]\n"); return 0;} | error { FormulaParseOK = 0; FMLDBUG_PR1("[ERROR]\n"); return 0; } ; term : term F_MULT basic_constr { $$ = symbols_op($1, $3, MUL_op); } | term F_MULT F_MINUS basic_constr { $$ = symbols_op($1, negate($4), MUL_op); } | term F_DIV basic_constr { $$ = symbols_op($1, $3, DIV_op); } | term F_DIV F_MINUS basic_constr { $$ = symbols_op($1, negate($4), DIV_op); } | term F_MOD basic_constr { $$ = symbols_op($1, $3, IDIV_op); } | term F_MOD F_MINUS basic_constr { $$ = symbols_op($1, negate($4), IDIV_op); } | basic_constr { $$ = $1; } ; basic_constr : basic_constr F_POW basic_item { $$ = f_symbol_pow($1,$3); FMLDBUG_PR3("[%.16g ^ %.16g] ",$1->s_real,$3->s_real); } | basic_constr F_POW F_MINUS basic_item { $$ = f_symbol_pow($1,negate($4)); FMLDBUG_PR3("[%.16g ^ %.16g] ",$1->s_real,$4->s_real); } | basic_item { $$ = $1; } ; arg_list : arg_list F_COMMA block { $$ = $1; $$->s_argc++; $$->s_argp = addto_arglist($1->s_argp, $3); } | block { $$ = $1; $$->s_argc = 1; $$->s_argp = new_arglist($1); } ; basic_item : F_ID F_LPAR F_RPAR { int tmp; Func_idx--; if(Func_idx >= 0 ) { tmp = match_function(FuncStack[Func_idx].s_name,0); $$ = do_function(tmp, 0, NULL ); capa_mfree(FuncStack[Func_idx].s_name); } } | F_ID F_LPAR arg_list F_RPAR { int tmp; Func_idx--; if(Func_idx >= 0 ) { tmp = match_function(FuncStack[Func_idx].s_name,$3->s_argc); $$ = do_function(tmp, $3->s_argc, $3->s_argp); capa_mfree(FuncStack[Func_idx].s_name); free_arglist($3->s_argp); $3->s_argp=NULL; } } | V_ID { FMLDBUG_PR3("[V %s = %.16g] ",$1->s_name, $1->s_real); $$ = $1; } | F_PLUS basic_item { $$ = $2; } | F_NUMBER { FMLDBUG_PR2("[F %.16g] ",$1->s_real); $$ = $1; } | F_LPAR block F_RPAR { $$ = $2; } ; %% void fml_error(char *msg) { FormulaParseOK=0; printf("Error Parsing: %s\n",msg); } /* ---------------------------------------------------- */ Symbol* negate(Symbol* symb) { Symbol* temp=symb; switch(symb->s_type) { case I_VAR: temp = (Symbol *)capa_malloc(sizeof(Symbol),1); temp->s_type = I_CONSTANT; case I_CONSTANT: temp->s_int = - symb->s_int; break; case R_VAR: temp = (Symbol *)capa_malloc(sizeof(Symbol),1); temp->s_type = R_CONSTANT; case R_CONSTANT: temp->s_real = (-1.0)*(symb->s_real); break; case S_VAR: case S_CONSTANT: break; default: break; } return temp; } Symbol * f_symbol_pow(ap,bp) Symbol *ap; Symbol *bp; { Symbol *cp; double a, b; int error = 0; /*Even if we can't do it we need to return something*/ cp = (Symbol *)capa_malloc(sizeof(Symbol),1); cp->s_type = R_CONSTANT; cp->s_real = 0.0; switch(ap->s_type) { case I_VAR: a = (double)(ap->s_int); break; case I_CONSTANT: a = (double)(ap->s_int); capa_mfree((char *)ap); break; case R_VAR: a = ap->s_real; break; case R_CONSTANT: a = ap->s_real; capa_mfree((char *)ap); break; case S_VAR: case S_CONSTANT: default: error = 1; break; } switch(bp->s_type) { case I_VAR: b = (double)(bp->s_int); break; case I_CONSTANT: b = (double)(bp->s_int); capa_mfree((char *)bp); break; case R_VAR: b = bp->s_real; break; case R_CONSTANT: b = bp->s_real; capa_mfree((char *)bp); break; case S_VAR: case S_CONSTANT: default: error = 1; break; } if ((!(((double)((int)b)) == b)) && (a < 0.0)) { error = 1; } if (!error) { cp = (Symbol *)capa_malloc(sizeof(Symbol),1); cp->s_type = R_CONSTANT; cp->s_real = pow(a,b); } else { FormulaParseOK=0; } return (cp); } /* ============================================================================= */