1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbutil/mathp.h,v 1.53 2017/01/12 14:44:04 masarati Exp $ */ 2 /* 3 * MBDyn (C) is a multibody analysis code. 4 * http://www.mbdyn.org 5 * 6 * Copyright (C) 1996-2017 7 * 8 * Pierangelo Masarati <masarati@aero.polimi.it> 9 * Paolo Mantegazza <mantegazza@aero.polimi.it> 10 * 11 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano 12 * via La Masa, 34 - 20156 Milano, Italy 13 * http://www.aero.polimi.it 14 * 15 * Changing this copyright notice is forbidden. 16 * 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU General Public License as published by 19 * the Free Software Foundation (version 2 of the License). 20 * 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30 */ 31 32 /* 33 * With the contribution of Ankit Aggarwal <ankit.ankit.aggarwal@gmail.com> 34 * during Google Summer of Code 2015 35 */ 36 37 #ifndef MATHP_H 38 #define MATHP_H 39 40 #include <stdlib.h> 41 #include <ctype.h> 42 #include <string.h> 43 #include <cmath> 44 #include <time.h> 45 #include <iostream> 46 #include <vector> 47 #include <map> 48 #include <stack> 49 #include <string> 50 51 #include "myassert.h" 52 #include "mynewmem.h" 53 #include "except.h" 54 55 #include "mathtyp.h" 56 #include "table.h" 57 #include "input.h" 58 59 #ifdef USE_EE 60 #include "evaluator.h" 61 #endif // USE_EE 62 63 class MathParser { 64 public: 65 enum ArgType { 66 /* AT_PRIVATE means only who created that type 67 * is supposed to deal with it (the default); 68 * the MathParser only knows how to deal with 69 * the remaining types */ 70 AT_PRIVATE, 71 72 AT_TYPE, 73 AT_ANY, 74 AT_VOID, 75 AT_BOOL, 76 AT_INT, 77 AT_REAL, 78 AT_STRING 79 }; 80 81 enum ArgFlag { 82 AF_NONE = 0x0U, 83 AF_OPTIONAL = 0x1U, 84 AF_OPTIONAL_NON_PRESENT = 0x2U, 85 AF_CONST = 0x10U 86 }; 87 88 class MathArg_t { 89 private: 90 unsigned m_flags; 91 92 public: m_flags(f)93 MathArg_t(unsigned f = AF_NONE) : m_flags(f) {}; ~MathArg_t(void)94 virtual ~MathArg_t(void) { NO_OP; }; 95 SetFlag(const MathParser::ArgFlag & f)96 void SetFlag(const MathParser::ArgFlag& f) { m_flags |= unsigned(f); }; ClearFlag(const MathParser::ArgFlag & f)97 void ClearFlag(const MathParser::ArgFlag& f) { m_flags &= ~unsigned(f); }; IsFlag(const MathParser::ArgFlag f)98 bool IsFlag(const MathParser::ArgFlag f) const { return (m_flags & unsigned(f)) == unsigned(f); }; GetFlags(void)99 unsigned GetFlags(void) const { return m_flags; }; 100 virtual ArgType Type(void) const = 0; 101 #ifdef USE_EE SetExpr(const ExpressionElement * ee)102 virtual void SetExpr(const ExpressionElement *ee) { throw ErrGeneric(MBDYN_EXCEPT_ARGS); }; GetExpr(void)103 virtual const ExpressionElement *GetExpr(void) const { return 0; }; Eval(void)104 virtual void Eval(void) { NO_OP; }; 105 #endif // USE_EE 106 virtual MathArg_t *Copy(void) const = 0; 107 }; 108 109 class MathArgVoid_t : public MathArg_t { 110 public: ~MathArgVoid_t(void)111 virtual ~MathArgVoid_t(void) { NO_OP; }; Type(void)112 virtual ArgType Type(void) const { return AT_VOID; }; Copy(void)113 virtual MathArg_t *Copy(void) const { return new MathArgVoid_t; }; 114 }; 115 116 template <class T, ArgType TT = AT_PRIVATE> 117 class MathArgPriv_t : public MathArg_t { 118 protected: 119 T m_val; 120 #ifdef USE_EE 121 const ExpressionElement *m_ee; // NOTE: memory owned by someone else 122 #endif // USE_EE 123 124 public: 125 #ifdef USE_EE MathArg_t(f)126 MathArgPriv_t(const T& val, unsigned f = AF_NONE) : MathArg_t(f), m_val(val), m_ee(0) { NO_OP; }; MathArg_t(f)127 MathArgPriv_t(const T& val, const ExpressionElement *ee, unsigned f = AF_NONE) : MathArg_t(f), m_val(val), m_ee(ee) { NO_OP; }; MathArgPriv_t(void)128 MathArgPriv_t(void) : MathArg_t(AF_NONE), m_ee(0) { NO_OP; }; 129 #else // ! USE_EE 130 MathArgPriv_t(const T& val, unsigned f = AF_NONE) : MathArg_t(f), m_val(val) { NO_OP; }; 131 MathArgPriv_t(void) : MathArg_t(AF_NONE) { NO_OP; }; 132 #endif // ! USE_EE 133 ~MathArgPriv_t(void)134 virtual ~MathArgPriv_t(void) { NO_OP; }; Type(void)135 virtual ArgType Type(void) const { return TT; }; 136 #ifdef USE_EE SetExpr(const ExpressionElement * ee)137 virtual void SetExpr(const ExpressionElement *ee) { m_ee = ee; }; GetExpr(void)138 virtual const ExpressionElement *GetExpr(void) const { return m_ee; }; Eval(void)139 virtual void Eval(void) { if (m_ee) { EE_Eval(m_val, m_ee); } }; Copy(void)140 virtual MathArg_t *Copy(void) const { return new MathArgPriv_t<T, TT>(m_val, m_ee, GetFlags()); }; 141 #else // ! USE_EE Copy(void)142 virtual MathArg_t *Copy(void) const { return new MathArgPriv_t<T, TT>(m_val, GetFlags()); }; 143 #endif // ! USE_EE 144 operator()145 const T& operator()(void) const { return m_val; }; operator()146 T& operator()(void) { return m_val; }; 147 }; 148 149 // not used right now; could be used for casting and so 150 typedef MathArgPriv_t<ArgType, AT_TYPE> MathArgType_t; 151 152 typedef MathArgPriv_t<TypedValue, AT_ANY> MathArgAny_t; 153 typedef MathArgPriv_t<bool, AT_BOOL> MathArgBool_t; 154 typedef MathArgPriv_t<Int, AT_INT> MathArgInt_t; 155 typedef MathArgPriv_t<Real, AT_REAL> MathArgReal_t; 156 typedef MathArgPriv_t<std::string, AT_STRING> MathArgString_t; 157 158 typedef std::vector<MathArg_t*> MathArgs; 159 typedef int (*MathFunc_f)(const MathArgs& args); 160 typedef int (*MathFuncTest_f)(const MathArgs& args); 161 162 // forward declaration 163 class NameSpace; 164 165 /* struttura delle funzioni built-in */ 166 struct MathFunc_t { 167 std::string fname; /* function name */ 168 NameSpace *ns; /* puntatore a namespace */ 169 MathArgs args; /* argomenti (0: out; 1->n: in) */ 170 MathFunc_f f; /* puntatore a funzione */ 171 MathFuncTest_f t; /* puntatore a funzione di test */ 172 std::string errmsg; /* messaggio di errore */ 173 MathFunc_tMathFunc_t174 MathFunc_t(void) : ns(0), f(0), t(0) {}; MathFunc_tMathFunc_t175 MathFunc_t(const MathFunc_t& in) : fname(in.fname), ns(in.ns), args(in.args.size()), f(in.f), t(in.t), errmsg(in.errmsg) { 176 for (unsigned i = 0; i < args.size(); ++i) { 177 args[i] = in.args[i]->Copy(); 178 } 179 }; ~MathFunc_tMathFunc_t180 ~MathFunc_t(void) { 181 for (unsigned i = 0; i < args.size(); ++i) { 182 delete args[i]; 183 } 184 }; 185 }; 186 187 /* carattere di inizio commento */ 188 static const char ONE_LINE_REMARK = '#'; 189 190 /* Namespace */ 191 class NameSpace { 192 std::string name; 193 194 public: 195 NameSpace(const std::string& name); 196 virtual ~NameSpace(void); 197 virtual const std::string& sGetName(void) const; 198 virtual bool IsFunc(const std::string& fname) const = 0; 199 virtual MathParser::MathFunc_t* GetFunc(const std::string& fname) const = 0; 200 virtual TypedValue EvalFunc(MathParser::MathFunc_t *f) const = 0; 201 virtual Table* GetTable(void) = 0; 202 }; 203 204 /* Static namespace */ 205 class StaticNameSpace : public MathParser::NameSpace { 206 private: 207 typedef std::map<std::string, MathParser::MathFunc_t *> funcType; 208 funcType func; 209 Table *m_pTable; 210 211 public: 212 StaticNameSpace(Table *pTable = 0); 213 ~StaticNameSpace(void); 214 215 bool IsFunc(const std::string& fname) const; 216 MathParser::MathFunc_t* GetFunc(const std::string& fname) const; 217 virtual TypedValue EvalFunc(MathParser::MathFunc_t *f) const; 218 virtual Table* GetTable(void); 219 }; 220 221 /* Prototipo dei plugin */ 222 class PlugIn { 223 protected: 224 MathParser& mp; 225 226 /* 227 * Idea base: 228 * un plugin e' un qualcosa che viene collegato al parser 229 * dopo la sua costruzione. Il plugin e' dotato di 'tipo' 230 * (sName). Quando il parser incontra una parentesi quadra 231 * che si apre ('['), si comporta come segue: 232 * - esegue il parsing dello stream fino alla chiusura 233 * della parentesi (']'), 234 * - separando i token in base alle virgole (','), 235 * - quindi legge il primo token che contiene il nome del 236 * plugin 237 * - legge il secondo token con il quale definisce una 238 * metavariabile a cui il risultato della creazione 239 * del plugin viene assegnato. 240 * Il risultato e' una metavariabile, a cui e' associata una 241 * certa operazione. Ogni qualvolta la variabile viene usata, 242 * questo provoca l'esecuzione del plugin. 243 */ 244 public: PlugIn(MathParser & mp)245 PlugIn(MathParser& mp) : mp(mp) {}; ~PlugIn()246 virtual ~PlugIn() {}; 247 virtual const char *sName(void) const = 0; 248 virtual int Read(int argc, char *argv[]) = 0; 249 virtual TypedValue::Type GetType(void) const = 0; 250 virtual TypedValue GetVal(void) const = 0; 251 }; 252 253 protected: 254 class PlugInVar : public NamedValue { 255 private: 256 MathParser::PlugIn *pgin; 257 258 public: 259 PlugInVar(const char *const s, MathParser::PlugIn *p); 260 ~PlugInVar(void); 261 262 TypedValue::Type GetType(void) const; 263 bool Const(void) const; 264 bool MayChange(void) const; 265 TypedValue GetVal(void) const; 266 }; 267 268 struct PlugInRegister { 269 const char *name; 270 MathParser::PlugIn * (*constructor)(MathParser&, void *); 271 void *arg; 272 struct PlugInRegister *next; 273 PlugInRegisterPlugInRegister274 PlugInRegister(void) 275 : name(NULL), constructor(0), arg(0), next(0) {}; 276 } *PlugIns; 277 278 public: 279 280 /* Gestione degli errori */ 281 class ErrGeneric : public MBDynErrBase { 282 public: 283 ErrGeneric(MBDYN_EXCEPT_ARGS_DECL); 284 ErrGeneric(MathParser* p, MBDYN_EXCEPT_ARGS_DECL); 285 }; 286 287 Table& table; /* symbol table */ 288 bool bRedefineVars; /* redefine_vars flag */ 289 290 public: 291 /* gioca con table e stream di ingresso */ 292 Table& GetSymbolTable(void) const; 293 void PutSymbolTable(Table& T); 294 295 InputStream* in; /* stream in ingresso */ 296 int GetLineNumber(void) const; 297 298 public: 299 300 /* i token che il lex riconosce */ 301 enum Token { 302 ENDOFFILE = -2, 303 UNKNOWNTOKEN = -1, 304 305 MP_INT = TypedValue::VAR_INT, 306 MP_REAL = TypedValue::VAR_REAL, 307 MP_STRING = TypedValue::VAR_STRING, 308 309 NUM, /* Numero */ 310 NAME, /* Nome */ 311 EXP, /* '^' : Elevamento a potenza */ 312 MULT, /* '*' : Moltiplicazione */ 313 DIV, /* '/' : Divisione */ 314 MOD, /* '%' : Divisione */ 315 MINUS, /* '-' : Meno */ 316 PLUS, /* '+' : Piu' */ 317 GT, /* '>' : Maggiore di */ 318 GE, /* '>=' : Maggiore o uguale */ 319 EQ, /* '==' : Uguale */ 320 LE, /* '<=' : Minore o uguale */ 321 LT, /* '<' : Minore di */ 322 NE, /* '!=' : Diverso da */ 323 NOT, /* '!' : Negazione (operatore logico) */ 324 AND, /* '&&' : AND (operatore logico) */ 325 OR, /* '||' : OR (operatore logico) */ 326 XOR, /* '~|' : XOR, o OR esclusivo (op. logico) */ 327 328 OBR, /* '(' : Parentesi aperta */ 329 CBR, /* ')' : Parentesi chiusa */ 330 OPGIN, /* '[' : Apertura di plugin statement */ 331 CPGIN, /* ']' : Chiusura di plugin statement */ 332 STMTSEP, /* ';' : Separatore di statements */ 333 ARGSEP, /* ',' : Separatore di argomenti */ 334 NAMESPACESEP, /* '::' : Separatore di namespace */ 335 ASSIGN, /* '=' : Assegnazione */ 336 337 LASTTOKEN 338 }; 339 340 enum DeclarationModifier { 341 DMOD_UNKNOWN = -1, 342 DMOD_IFNDEF, 343 DMOD_LAST 344 }; 345 346 protected: 347 348 StaticNameSpace* defaultNameSpace; 349 350 public: 351 typedef std::map<std::string, NameSpace *> NameSpaceMap; 352 const NameSpaceMap& GetNameSpaceMap(void) const; 353 354 protected: 355 NameSpaceMap nameSpaceMap; 356 357 /* buffer statico reallocabile per leggere nomi */ 358 std::string namebuf; 359 360 /* valore numerico dotato di tipo */ 361 TypedValue value; 362 363 /* token corrente */ 364 enum Token currtoken; 365 366 struct TokenVal { 367 Token m_t; 368 TypedValue m_v; 369 }; 370 std::stack<TokenVal> TokenStack; 371 372 /* operazioni sulla stack */ 373 void TokenPush(enum Token t); 374 int TokenPop(void); 375 376 TypedValue::Type GetType(const char* const s) const; 377 TypedValue::TypeModifier GetTypeModifier(const char* const s) const; 378 MathParser::DeclarationModifier GetDeclarationModifier(const char* const s) const; 379 380 bool IsType(const char* const s) const; 381 bool IsTypeModifier(const char* const s) const; 382 bool IsDeclarationModifier(const char* const s) const; 383 bool IsKeyWord(NameSpace *ns, const char* const s) const; 384 385 /* lexer */ 386 enum Token GetToken(void); 387 388 void trim_arg(char *const s); 389 390 /* 391 * functions whose recursive invocation expresses 392 * operators' precedence 393 * 394 * NOTE: 395 * - the *_int(d) version does the actual job 396 * - the *(void) version first parses the first operand, 397 * then calls *_int(d) 398 * - the *(d) version calls *_int(d) with the argument 399 */ 400 401 #ifdef USE_EE 402 ExpressionElement* logical(void); 403 ExpressionElement* logical(ExpressionElement* d); 404 ExpressionElement* logical_int(ExpressionElement* d); 405 ExpressionElement* relational(void); 406 ExpressionElement* relational(ExpressionElement* d); 407 ExpressionElement* relational_int(ExpressionElement* d); 408 ExpressionElement* binary(void); 409 ExpressionElement* binary(ExpressionElement* d); 410 ExpressionElement* binary_int(ExpressionElement* d); 411 ExpressionElement* mult(void); 412 ExpressionElement* mult(ExpressionElement* d); 413 ExpressionElement* mult_int(ExpressionElement* d); 414 ExpressionElement* power(void); 415 ExpressionElement* power(ExpressionElement* d); 416 ExpressionElement* power_int(ExpressionElement* d ); 417 ExpressionElement* unary(void); 418 419 /* helper for expr, which evaluates [built-in] functions */ 420 ExpressionElement* parsefunc(MathParser::MathFunc_t* f); 421 422 /* evaluates expressions */ 423 ExpressionElement* expr(void); 424 425 /* evaluates statements and statement lists */ 426 ExpressionElement* stmt(void); 427 ExpressionElement* stmtlist(void); 428 429 ExpressionElement* readplugin(void); 430 431 #else // ! USE_EE 432 TypedValue logical(void); 433 TypedValue logical(TypedValue d); 434 TypedValue logical_int(TypedValue d); 435 TypedValue relational(void); 436 TypedValue relational(TypedValue d); 437 TypedValue relational_int(TypedValue d); 438 TypedValue binary(void); 439 TypedValue binary(TypedValue d); 440 TypedValue binary_int(TypedValue d); 441 TypedValue mult(void); 442 TypedValue mult(TypedValue d); 443 TypedValue mult_int(TypedValue d); 444 TypedValue power(void); 445 TypedValue power(TypedValue d); 446 TypedValue power_int(TypedValue d); 447 TypedValue unary(void); 448 449 /* helper per expr, che valuta le funzioni built-in */ 450 TypedValue evalfunc(MathParser::NameSpace *ns, MathParser::MathFunc_t* f); 451 452 /* evaluates expressions */ 453 TypedValue expr(void); 454 455 /* evaluates statements and statement lists */ 456 TypedValue stmt(void); 457 TypedValue stmtlist(void); 458 459 TypedValue readplugin(void); 460 #endif // ! USE_EE 461 462 private: 463 // no copy constructor 464 MathParser(const MathParser&); 465 466 public: 467 MathParser(const InputStream& strm, Table& t, bool bRedefineVars = false); 468 MathParser(Table& t, bool bRedefineVars = false); 469 ~MathParser(void); 470 471 NamedValue * 472 InsertSym(const char* const s, const Real& v, int redefine = 0); 473 NamedValue * 474 InsertSym(const char* const s, const Int& v, int redefine = 0); 475 476 /* 477 * interpreta una sequenza di stmt e restituisce il valore 478 * dell'ultimo 479 */ 480 Real GetLastStmt(Real d = 0., Token t = ARGSEP); 481 Real GetLastStmt(const InputStream& strm, Real d = 0., 482 Token t = ARGSEP); 483 484 #ifdef USE_EE 485 /* interpreta uno stmt e ne restitutisce il valore */ 486 ExpressionElement *GetExpr(void); 487 ExpressionElement *GetExpr(const InputStream& strm); 488 #endif // USE_EE 489 490 Real Get(Real d = 0.); 491 Real Get(const InputStream& strm, Real d = 0.); 492 TypedValue Get(const TypedValue& v); 493 TypedValue Get(const InputStream& strm, const TypedValue& v); 494 495 /* modalita' calcolatrice: elabora e stampa ogni stmt */ 496 void GetForever(std::ostream& out, const char* const sep = "\n"); 497 void GetForever(const InputStream& strm, std::ostream& out, 498 const char* const sep = "\n"); 499 500 int RegisterPlugIn(const char *name, 501 MathParser::PlugIn * (*)(MathParser&, void *), 502 void *arg); 503 504 int RegisterNameSpace(NameSpace *ns); 505 506 NameSpace *GetNameSpace(const std::string& name) const; 507 508 /* validates a name */ 509 bool bNameValidate(const std::string& s) const; 510 }; 511 512 extern std::ostream& 513 operator << (std::ostream& out, const MathParser::MathArgVoid_t& v); 514 extern std::ostream& 515 operator << (std::ostream& out, const MathParser::MathArgBool_t& v); 516 extern std::ostream& 517 operator << (std::ostream& out, const MathParser::MathArgInt_t& v); 518 extern std::ostream& 519 operator << (std::ostream& out, const MathParser::MathArgReal_t& v); 520 extern std::ostream& 521 operator << (std::ostream& out, const MathParser::MathArgString_t& v); 522 523 #endif /* MATHP_H */ 524 525