--- capa/capa51/pProj/capaFormula.y 1999/09/28 21:26:21 1.1 +++ capa/capa51/pProj/capaFormula.y 2000/10/23 16:22:57 1.9 @@ -1,7 +1,29 @@ +/* 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 */ -/* copyrighted by Isaac Tsai 1999 */ /* TODO: checking user inputs 2/27/99 IT */ /* ====================================================== */ %{ @@ -12,6 +34,10 @@ #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 @@ -36,16 +62,12 @@ #define IDIV_op 5 #define NOT_DEFINED_op 9 -#ifdef YYSTYPE -#undef YYSTYPE -#endif -#define YYSTYPE Symbol_p /* =============================================================== */ extern int Func_idx; extern Symbol FuncStack[MAX_FUNC_NEST]; - +void fml_error(char *msg); double FormulaVal; int FormulaParseOK=1; @@ -55,7 +77,8 @@ 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 F_LPAR F_RPAR F_COMMA +%token F_POW +%token F_LPAR F_RPAR F_COMMA %start f_expr @@ -83,19 +106,25 @@ f_expr : block 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_DIV basic_constr { $$ = symbols_op($1, $3, DIV_op); } - | term F_MOD basic_constr { $$ = symbols_op($1, $3, IDIV_op); } +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; } ; @@ -126,25 +155,12 @@ basic_item : F_ID F_LPAR F_RPAR $$ = 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_MINUS basic_item { $$ = $2; - switch($2->s_type) { - case I_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1); - $$->s_type = I_CONSTANT; - case I_CONSTANT: $$->s_int = - $2->s_int; break; - case R_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1); - $$->s_type = R_CONSTANT; - case R_CONSTANT: $$->s_real = (-1.0)*($2->s_real); - break; - case S_VAR: - case S_CONSTANT: break; - default: break; - } - } | F_PLUS basic_item { $$ = $2; } | F_NUMBER { FMLDBUG_PR2("[F %.16g] ",$1->s_real); $$ = $1; @@ -160,6 +176,24 @@ fml_error(char *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; { @@ -194,6 +228,9 @@ f_symbol_pow(ap,bp) Symbol *ap; Symbol * 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;