ESLA
Embeddable Scriting LAnguage
Stanford University, Rock Fracture Project research group
© 2003
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