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