File:  [LON-CAPA] / capa / capa51 / pProj / capaFormula.y
Revision 1.4: download - view: text, annotated - select for diffs
Fri Jul 7 18:30:57 2000 UTC (24 years, 1 month ago) by albertel
Branches: MAIN
CVS tags: HEAD
- need to check if taking a negative number to a fractional power

    1: /* formula parser
    2:    Copyright (C) 1992-2000 Michigan State University
    3: 
    4:    The CAPA system is free software; you can redistribute it and/or
    5:    modify it under the terms of the GNU Library General Public License as
    6:    published by the Free Software Foundation; either version 2 of the
    7:    License, or (at your option) any later version.
    8: 
    9:    The CAPA system is distributed in the hope that it will be useful,
   10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12:    Library General Public License for more details.
   13: 
   14:    You should have received a copy of the GNU Library General Public
   15:    License along with the CAPA system; see the file COPYING.  If not,
   16:    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   17:    Boston, MA 02111-1307, USA.  */
   18: 
   19: /* ====================================================== */
   20: /*      capaFormula.y  created by Isaac Tsai @ Feb 1999   */
   21: /*      copyrighted by Isaac Tsai    1999                 */
   22: /*  TODO: checking user inputs   2/27/99      IT          */
   23: /* ====================================================== */
   24: %{
   25: #include <stdio.h>
   26: #include <ctype.h>
   27: #include <string.h>
   28: #include <math.h>
   29: #include "capaParser.h"   /* _symbol structure def */
   30: #include "capaCommon.h"
   31: #include "capaFunction.h"
   32: #ifdef  YYSTYPE
   33: #undef  YYSTYPE
   34: #endif
   35: #define YYSTYPE  Symbol_p
   36: #include "capaToken.h"
   37: 
   38: #ifdef __hpux
   39: #include <stdlib.h>
   40: #include <alloca.h>
   41: #endif
   42: 
   43: #ifdef   FML_DBUG
   44: #define  FMLDBUG_PR1(xx)        { printf(xx);    fflush(stdout); }
   45: #define  FMLDBUG_PR2(xx,yy)     { printf(xx,yy); fflush(stdout); }
   46: #define  FMLDBUG_PR3(xx,yy,zz)  { printf(xx,yy,zz); fflush(stdout); }
   47: #else
   48: #define  FMLDBUG_PR1(xx)        { }
   49: #define  FMLDBUG_PR2(xx,yy)     { }
   50: #define  FMLDBUG_PR3(xx,yy,zz)  { }
   51: #endif
   52: 
   53: #define ADD_op          1
   54: #define SUB_op          2
   55: #define MUL_op          3
   56: #define DIV_op          4
   57: #define IDIV_op         5
   58: #define NOT_DEFINED_op  9
   59: 
   60: 
   61: /* =============================================================== */
   62: 
   63: extern      int         Func_idx;
   64: extern      Symbol      FuncStack[MAX_FUNC_NEST];
   65: void   fml_error(char *msg);
   66: double      FormulaVal;
   67: int         FormulaParseOK=1;
   68: 
   69: %}
   70: 
   71: 
   72: %token    F_NUMBER    V_ID      F_ID     EoI      F_ERROR 
   73: %left     F_PLUS      F_MINUS   
   74: %left     F_MULT      F_DIV     F_MOD
   75: %token    F_POW       F_LPAR    F_RPAR   F_COMMA 
   76: 
   77: 
   78: %start    f_expr
   79: 
   80: 
   81: %%
   82: 
   83: f_expr       : block                             { switch($1->s_type) {
   84:                                                       case I_VAR:
   85:                                                       case I_CONSTANT: FormulaVal = (double)($1->s_int);
   86:                                                           break;
   87:                                                       case R_VAR: 
   88:                                                       case R_CONSTANT: FormulaVal = $1->s_real;
   89:                                                           break;
   90:                                                       case S_VAR:
   91:                                                       case S_CONSTANT: FormulaParseOK = 0;
   92:                                                           break;
   93:                                                       default:         FormulaParseOK = 0;
   94:                                                           break;
   95:                                                     }
   96:                                                     capa_mfree((char *)$1);
   97:                                                     FMLDBUG_PR1("[f_expr <= block ]\n");
   98:                                                   }
   99:              ;
  100: 
  101: block        : block F_PLUS   term                { $$ = symbols_op($1, $3, ADD_op);  }
  102:              | block F_MINUS  term                { $$ = symbols_op($1, $3, SUB_op);  }
  103:              | term                               { $$ = $1; }
  104:              | F_ERROR                            { FormulaParseOK = 0; FMLDBUG_PR1("[F_ERROR]\n"); return 0;}
  105:              | error                              { FormulaParseOK = 0; FMLDBUG_PR1("[ERROR]\n"); return 0;  }
  106:              ;
  107: 
  108: term         : term    F_MULT  basic_constr       { $$ = symbols_op($1, $3, MUL_op);  }
  109:              | term    F_DIV   basic_constr       { $$ = symbols_op($1, $3, DIV_op);  }
  110:              | term    F_MOD   basic_constr       { $$ = symbols_op($1, $3, IDIV_op); }
  111:              | basic_constr                       { $$ = $1; }
  112:              ;
  113: 
  114: basic_constr : basic_constr  F_POW   basic_item   { $$ = f_symbol_pow($1,$3);
  115:                                                     FMLDBUG_PR3("[%.16g ^ %.16g] ",$1->s_real,$3->s_real);       }
  116:              | basic_item                         { $$ = $1; }
  117:              ;
  118: 
  119: arg_list     : arg_list F_COMMA  block            { $$ = $1;
  120:                                                     $$->s_argc++;
  121:                                                     $$->s_argp = addto_arglist($1->s_argp, $3);
  122:                                                   }
  123:              | block                              { $$ = $1;
  124:                                                     $$->s_argc = 1;
  125:                                                     $$->s_argp = new_arglist($1);
  126:                                                   }
  127:              ;
  128: 
  129: basic_item   : F_ID F_LPAR F_RPAR                 {  int tmp;
  130:                                          
  131:                                                      Func_idx--;
  132:                                                      if(Func_idx >= 0 ) {
  133:                                                        tmp = match_function(FuncStack[Func_idx].s_name,0);
  134:                                                        $$ = do_function(tmp, 0, NULL );
  135:                                                        capa_mfree(FuncStack[Func_idx].s_name);
  136:                                                      }
  137:                                                   }
  138:              | F_ID F_LPAR arg_list  F_RPAR       {  int  tmp;
  139:                                          
  140:                                                      Func_idx--;
  141:                                                      if(Func_idx >= 0 ) {
  142:                                                         tmp = match_function(FuncStack[Func_idx].s_name,$3->s_argc);
  143: 					                $$ = do_function(tmp, $3->s_argc, $3->s_argp);
  144: 					                capa_mfree(FuncStack[Func_idx].s_name);
  145: 					                free_arglist($3->s_argp);
  146:                                                       }
  147:                                                   }
  148:              | V_ID                               { FMLDBUG_PR3("[V %s = %.16g] ",$1->s_name, $1->s_real);
  149:                                                     $$ = $1;
  150:                                                   }
  151:              | F_MINUS  basic_item                { $$ = $2;
  152:                                                     switch($2->s_type) {
  153:                                                       case I_VAR:      $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
  154:                                                              $$->s_type = I_CONSTANT;
  155:                                                       case I_CONSTANT: $$->s_int =    - $2->s_int; break;
  156:                                                       case R_VAR: $$ = (Symbol *)capa_malloc(sizeof(Symbol),1);
  157:                                                              $$->s_type = R_CONSTANT;
  158:                                                       case R_CONSTANT: $$->s_real =   (-1.0)*($2->s_real); 
  159:                                                              break;
  160:                                                       case S_VAR:
  161:                                                       case S_CONSTANT: break;
  162:                                                       default:         break;
  163:                                                     }
  164:                                                   }
  165:              | F_PLUS  basic_item                 { $$ = $2; }
  166:              | F_NUMBER                           { FMLDBUG_PR2("[F %.16g] ",$1->s_real);
  167:                                                     $$ = $1;
  168:                                                   }
  169:              | F_LPAR   block  F_RPAR             { $$ = $2; }
  170:              ;
  171: %%
  172: void
  173: fml_error(char *msg)
  174: {
  175:   FormulaParseOK=0;
  176:   printf("Error Parsing: %s\n",msg);
  177:   
  178: }
  179: /* ---------------------------------------------------- */
  180: Symbol *
  181: f_symbol_pow(ap,bp) Symbol *ap; Symbol *bp;
  182: {
  183:   Symbol *cp;
  184:   double  a, b;
  185:   int     error = 0;
  186:   
  187:   cp = NULL;
  188:   switch(ap->s_type) {
  189:      case I_VAR:      a = (double)(ap->s_int);
  190:          break;
  191:      case I_CONSTANT: a = (double)(ap->s_int); capa_mfree((char *)ap);
  192:          break;
  193:      case R_VAR:      a = ap->s_real;
  194:          break;
  195:      case R_CONSTANT: a = ap->s_real;   capa_mfree((char *)ap);
  196:          break;
  197:      case S_VAR:
  198:      case S_CONSTANT: 
  199:      default:         error = 1;  break;
  200:   }
  201:   switch(bp->s_type) {
  202:      case I_VAR:      b = (double)(bp->s_int);
  203:          break;
  204:      case I_CONSTANT: b = (double)(bp->s_int);  capa_mfree((char *)bp);
  205:          break;
  206:      case R_VAR:      b = bp->s_real;
  207:          break;
  208:      case R_CONSTANT: b = bp->s_real;   capa_mfree((char *)bp);
  209:          break;
  210:      case S_VAR:
  211:      case S_CONSTANT: 
  212:      default:         error = 1; break;
  213:   }
  214:   if ((!(((double)((int)b)) == b)) && (a < 0.0)) {
  215:     error = 1;
  216:   }
  217:   if (!error) {
  218:     cp = (Symbol *)capa_malloc(sizeof(Symbol),1);
  219:     cp->s_type = R_CONSTANT;
  220:     cp->s_real = pow(a,b);
  221:     
  222:   }
  223:   return (cp);
  224: }
  225: 
  226: /* ============================================================================= */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>