ESLA

Embeddable Scriting LAnguage

frantz@pangea.stanford.edu

Stanford University, Rock Fracture Project research group

© 2003

fct_parser.h

Go to the documentation of this file.
00001 /*************************************************************************
00002  *              ESLA: Embeddable Scripting LAnguage
00003  *                  Copyright (C) 2003 Frantz Maerten
00004  *
00005  *   This  program  is  free  software;  you  can  redistribute it and/or
00006  *   modify  it  under  the  terms  of  the GNU General Public License as
00007  *   published  by  the Free Software Foundation; either version 2 of the
00008  *   License, or (at your option) any later version.
00009  *
00010  *   If  you modify this software, you should contact the author, include
00011  *   a  notice giving the name of the person performing the modification,
00012  *   the date of modification, and the reason for such modification.
00013  *
00014  *   Note   that   the   GNU  General  Public  License  does  not  permit
00015  *   incorporating the Software into proprietary programs.
00016  *
00017  *  Contact: Frantz Maerten
00018  *     frantz@pangea.stanford.edu
00019  *
00020  *     Dept. of Geological & Environmental Sciences
00021  *     Stanford University 
00022  *     Stanford, CA 94305-2115
00023  *     USA
00024  *************************************************************************/
00025 
00026 
00027 #ifndef FCT_PARSER__
00028 #define FCT_PARSER__
00029 #ifdef __GNUC__
00030 #pragma interface
00031 #endif
00032 
00033 
00034 //------------------------------------------------------
00035 
00036 #include <iostream>
00037 #include <cstdlib>
00038 #include <cctype>
00039 #include <cmath>
00040 #include <string>
00041 #include <vector>
00042 #include <map>
00043 #include "../esla_namespace.h"  
00044 
00045 BEGIN_LIB_NAMESPACE
00046    
00080 template <class T>
00081 class Parser {
00082 public:
00083   typedef typename std::map<std::string,T>::iterator iterator;
00084 
00085   Parser();
00086   
00095   bool set_function(const std::string& s, bool pre_test=true);
00096   
00100   std::string get_function();
00101 
00107   void  add_var(const std::string& s, T p = 0);
00113   void  set_var(const std::string& s, T p);
00114 
00120   T get_var(const std::string& s) const;
00121   
00125   T evaluate();
00126 
00130   const std::string& get_errors() const {return listERR;}
00131 
00135   void flush();
00136 
00142   iterator begin() {return vars.begin();}
00147   iterator end() {return vars.end();}
00148 
00149 private:
00150   enum types {
00151     DELIMITER=1, VARIABLE, NUMBER, FUNCTION
00152   };
00153   
00154   enum typesF { SIN=0,  COS,  TAN,
00155                 ASIN, ACOS, ATAN,
00156                 ABS,  EXP,  LOG,
00157                 LOG10,  SQRT, INT,
00158                 ROUND,  FRAC, CEIL,
00159                 FLOOR,  SQR,  SIGN,
00160                 COSH, SINH, TANH,
00161                 ASINH,  ATANH,  ACOSH
00162   };
00163 
00164   char *exp_ptr;
00165   char token[80];
00166   char tok_type;
00167   std::map<std::string,T> vars;
00168   std::map<std::string,int> functions;
00169   std::string listERR;
00170   std::string _funct;
00171 
00172   void init();
00173   void eval_exp2(T &result);
00174   void eval_exp3(T &result);
00175   void eval_exp4(T &result);
00176   void eval_exp5(T &result);
00177   void eval_exp6(T &result);
00178   void eval_exp7(T &result);
00179   void eval_exp8(T &result);
00180   void atom(T &result);
00181   void get_token(), putback();
00182   void serror(int error);
00183   T find_var(std::string s);
00184   bool isDefined(std::string s);
00185   int isdelim(char c);
00186 
00187 };
00188 
00189 
00190 
00191 //------------------------------------------------------------------------
00192 
00193 template <class T>
00194 std::string Parser<T>::get_function() {
00195   return _funct;
00196 }
00197 
00198 template <class T>
00199 inline void Parser<T>::add_var(const std::string& s, T p) { 
00200   vars.insert(std::pair<std::string,T>(s,p)); 
00201 }
00202 
00203 template <class T> 
00204 inline void Parser<T>::set_var(const std::string& s, T p) {
00205   typename std::map<std::string,T>::iterator i;
00206   i = vars.find(s);
00207   if (i!=vars.end())
00208     i->second = p;
00209 }
00210 
00211 template <class T> 
00212 inline T Parser<T>::get_var(const std::string& s) const {
00213   typename std::map<std::string,T>::iterator i;
00214   i = vars.find(s);
00215   if (i!=vars.end())
00216     return i->second;
00217   return -999.0;
00218 }
00219 
00220 
00221 template <class T>
00222 inline bool Parser<T>::set_function(const std::string& funct, bool pre_test) {
00223   _funct = funct;
00224   if (!pre_test)
00225     return true;
00226 
00227   evaluate();
00228   return (listERR.size()==0)?true:false;
00229 }
00230 
00231 template <class T> 
00232 inline T Parser<T>::evaluate() {
00233   T result;
00234   listERR = "" ;
00235 
00236   exp_ptr = const_cast<char*> (_funct.c_str());
00237   get_token();
00238   if(!*token) {
00239     serror(2);
00240     return (T) 0;
00241   }
00242   eval_exp2(result);
00243   if(*token)
00244     serror(0); // last token must be null
00245   return result;
00246 }
00247 
00248 
00249 // + - two terms
00250 template <class T>
00251 inline void Parser<T>::eval_exp2(T &result) {
00252   register char op;
00253   T temp;
00254 
00255   eval_exp3(result);
00256   while((op = *token) == '+' || op == '-') {
00257     get_token();
00258     eval_exp3(temp);
00259     switch(op) {
00260     case '-':
00261       result = result - temp;
00262       break;
00263     case '+':
00264       result = result + temp;
00265       break;
00266     }
00267   }
00268 }
00269 
00270 // boolean operations between two terms
00271 template <class T>
00272 inline void Parser<T>::eval_exp3(T &result) {
00273   std::string op;
00274   T temp;
00275 
00276   eval_exp4(result);
00277   op = std::string(token);
00278   
00279   if(op == "<" || op == ">") {
00280     if(strchr("=", *exp_ptr)) {
00281       *exp_ptr++;
00282       get_token();
00283       eval_exp4(temp);
00284       if (op==">") result = (result>=temp?1:0);
00285       else if (op=="<") result = (result<=temp?1:0);
00286       return ;
00287     }
00288     get_token();
00289     eval_exp4(temp);
00290     if (op==">") result = (result>temp?1:0);
00291     if (op=="<") result = (result<temp?1:0);
00292   }
00293   else if(op == "=") {
00294     get_token();
00295     eval_exp4(temp);
00296     result = (result==temp?1:0);
00297   }
00298 }
00299 
00300 // * / two factors.
00301 template <class T>
00302 inline void Parser<T>::eval_exp4(T &result) {
00303   register char op;
00304   T temp;
00305 
00306   eval_exp5(result);
00307   while((op = *token) == '*' || op == '/' || op == '%') {
00308     get_token();
00309     eval_exp5(temp);
00310     switch(op) {
00311     case '*':
00312       result = result * temp;
00313       break;
00314     case '/':
00315       result = result / temp;
00316       break;
00317     case '%':
00318       result = (int) result % (int) temp;
00319       break;
00320     }
00321   }
00322 }
00323 
00324 // ^
00325 template <class T>
00326 inline void Parser<T>::eval_exp5(T &result) {
00327   T temp, ex;
00328 
00329   eval_exp6(result);
00330   if(*token== '^') {
00331     get_token();
00332     eval_exp5(temp);
00333     ex = result;
00334     if(temp==0.0) {
00335       result = (T) 1;
00336       return;
00337     }
00338     result = pow(result,temp);
00339   }
00340 }
00341 
00342 // unary + or -.
00343 template <class T>
00344 inline void Parser<T>::eval_exp6(T &result) {
00345   register char  op;
00346 
00347   op = 0;
00348   if((tok_type == DELIMITER) && *token=='+' || *token == '-') {
00349     op = *token;
00350     get_token();
00351   }
00352   eval_exp7(result);
00353   if(op=='-')
00354     result = -result;
00355 }
00356 
00357 template <class T>
00358 inline void Parser<T>::eval_exp7(T &result) {
00359   char  temp_token[80];
00360   int   indexF = -1;
00361   std::string s_stoken(token);
00362 
00363   *temp_token = '\0';
00364   if((tok_type == VARIABLE)) {
00365     std::map<std::string,int>::iterator p;
00366     p = functions.find(s_stoken);
00367     if (p!=functions.end()) {
00368       strcpy(temp_token, token);
00369       indexF = p->second;
00370       get_token();
00371     }
00372   }
00373   eval_exp8(result);
00374   if(indexF!=-1) {
00375     switch(indexF){
00376     case SIN: result = sin(result);   break;
00377     case COS: result = cos(result);   break;
00378     case TAN: result = tan(result);   break;
00379     case ASIN:  result = asin(result);    break;
00380     case ACOS:  result = acos(result);    break;
00381     case ATAN:  result = atan(result);    break;
00382     case ABS: result = fabs(result);    break;
00383     case EXP: result = exp(result);   break;
00384     case LOG: result = log(result);   break;
00385     case LOG10: result = log10(result);   break;
00386     case SQRT:  result = sqrt(result);    break;
00387     case INT: result = (int)(result);   break;
00388     case ROUND: result = (int)(result+0.5); break;
00389     case CEIL:  result = ceil(result);    break;
00390     case FLOOR: result = floor(result);   break;
00391     case SQR: result = result*result;   break;
00392     case COSH:  result = cosh(result);    break;
00393     case SINH:  result = sinh(result);    break;
00394     case TANH:  result = tanh(result);    break;
00395     case ASINH: result = log(result+sqrt(result*result+1)); break;
00396     case ACOSH: result = log(result+sqrt(result*result-1)); break;
00397     case ATANH: result = log((1+result)/(1-result))/2;    break;
00398     case SIGN:
00399       if (result>0) result=1;
00400       else
00401         if (result<0) result=-1;
00402       break;
00403     }
00404   }
00405 }
00406 
00407 // ( )
00408 template <class T>
00409 inline void Parser<T>::eval_exp8(T &result) {
00410   if((*token == '(')) {
00411     get_token();
00412     eval_exp2(result);
00413     if(*token != ')')
00414       serror(1);
00415     get_token();
00416   }
00417   else
00418     atom(result);
00419 }
00420 
00421 // Return the value of a number or a variable.
00422 template <class T>
00423 inline void Parser<T>::atom(T &result) {
00424   switch(tok_type) {
00425   case VARIABLE:
00426     result = find_var(std::string(token));
00427     get_token();
00428     return;
00429   case NUMBER:
00430     result = (T) atof(token);
00431     get_token();
00432     return;
00433   default:
00434     serror(0);
00435   }
00436 }
00437 
00438 // Return a token to the input stream.
00439 template <class T>
00440 inline void Parser<T>::putback() {
00441   char *t;
00442 
00443   t = token;
00444   for(; *t; t++)
00445     exp_ptr--;
00446 }
00447 
00448 // Display a syntax error.
00449 template <class T>
00450 inline void Parser<T>::serror(int error) {
00451   static char *e[]= {
00452     "Syntax Error",
00453       "Parentheses error",
00454       "No expression"
00455       };
00456   listERR += std::string(e[error])+"\n";
00457 }
00458 
00459 // Return true if c is a delimiter.
00460 template <class T>
00461 inline int Parser<T>::isdelim(char c) {
00462   if(strchr(" +-/*%^=()<>", c) || c==9 || c=='\r' || c==0)
00463     return 1;
00464   return 0;
00465 }
00466 
00467 // Return the value of a variable.
00468 template <class T>
00469 inline T Parser<T>::find_var(std::string s) {
00470   const char *ts = s.c_str();
00471   if(!isalpha(*ts)) {
00472     serror(1);
00473     return (T) 0;
00474   }
00475   typename std::map<std::string,T>::iterator p;
00476   p = vars.find(s);
00477   if (p!=vars.end())
00478     return p->second;
00479   else {
00480         //vars.insert(std::pair<std::string,Type>(s,(T)0));
00481     vars.insert(std::pair<std::string,T>(s,(T)0));
00482   }
00483   serror(1);
00484   return (T) 0;
00485 }
00486 
00487 //------------------------------------------------------
00488 
00489 END_LIB_NAMESPACE
00490 
00491 
00492 #if defined(__GNUC__) || defined(WIN32)
00493 #include "fct_parser.cc"
00494 #elif defined(__xlC__)
00495 #pragma implementation("fct_parser.cc")
00496 #endif
00497 
00498 #endif
00499 

Generated on Wed May 14 11:42:31 2003 for Esla-lib by doxygen1.3-rc1