source: Sophya/trunk/SophyaLib/SysTools/cexpre.cc@ 2518

Last change on this file since 2518 was 2518, checked in by ansari, 22 years ago

Suite (presque finie) des modifications de l'interpreteur - gestion des variables en particulier - Reste au moins un bug ds CExpressionEvaluator - Reza 18/03/2004

File size: 13.0 KB
Line 
1#include <stdlib.h>
2#include <stdio.h>
3#include <ctype.h>
4#include <string.h>
5#include "cexpre.h"
6#include <stack>
7#include <math.h>
8
9namespace SOPHYA {
10
11long CExprBase::totnexp_create = 0;
12long CExprBase::totnexp_delete = 0;
13CExprBase::CExprBase()
14{
15 totnexp_create++;
16 // cout << "CExprBase::CExprBase()-Creation " << hex << this << dec << endl;
17}
18
19CExprBase::~CExprBase()
20{
21 totnexp_delete++;
22 // cout << "CExprBase::~CExprBase() " << hex << this << dec << endl;
23}
24
25void CExprBase::CheckThrow(const char * msg) const
26{
27 string errmsg;
28 bool ok = CheckE(errmsg);
29 if (ok) return;
30 else {
31 errmsg += msg;
32 throw CExprException(errmsg);
33 }
34}
35
36//---------------------------------------------------------
37class CE_NumberExp : public CExprBase {
38public:
39 CE_NumberExp(double v) { _val = v; }
40 CE_NumberExp(string const & s);
41 virtual ~CE_NumberExp() {}
42 virtual double Evaluate() const { return _val; }
43 virtual void Print(ostream& os) const { os << _val; }
44protected:
45 double _val;
46};
47
48CE_NumberExp::CE_NumberExp(string const & s)
49{
50 size_t l = s.length();
51 if (l < 1) {
52 string errmsg = "CE_NumberExp::CE_NumberExp() Empty expression";
53 throw CExprException(errmsg);
54 }
55 if (s == "Pi") _val = M_PI;
56 else if (s == "E") _val = M_E;
57 else {
58 string errmsg = "CE_NumberExp::CE_NumberExp() Bad numerical constant: ";
59 errmsg += s;
60
61 char* lcc;
62 _val = strtod(s.c_str(), &lcc);
63 if (*lcc != '\0') throw CExprException(errmsg);
64 }
65}
66
67
68//---------------------------------------------------------
69class CE_BinExp : public CExprBase {
70public:
71 explicit CE_BinExp(char op, int prior);
72 virtual ~CE_BinExp() { if (_e1) delete _e1; if (_e2) delete _e2; }
73 inline void SetE1(CExprBase * e) { _e1 = e; }
74 inline void SetE2(CExprBase * e) { _e2 = e; }
75 virtual bool CheckE(string& errmsg) const;
76 virtual void Print(ostream& os) const;
77 inline char BOpC() const { return _bop; }
78 inline int Priority() const { return _priority; }
79 protected:
80 CExprBase * _e1;
81 CExprBase * _e2;
82 char _bop; // Caractere identificateur d'operation (+,-,*,/ ...)
83 int _priority; // Niveau de priorite: 1= +,- 2: *,/ 3: ^...
84};
85
86CE_BinExp::CE_BinExp(char op, int prior)
87{
88 _e1 = NULL; _e2 = NULL;
89 _bop = op;
90 _priority = prior;
91}
92
93bool CE_BinExp::CheckE(string& errmsg) const
94{
95 if ((_e1 == NULL) || (_e2 == NULL)) {
96 errmsg += "CE_BinExp::CheckE: Binary expression-missing argument ";
97 return false;
98 }
99 return true;
100}
101
102void CE_BinExp::Print(ostream& os) const
103{
104 os << "(" << (*_e1) << _bop << (*_e2) << ")" ;
105}
106
107//---------------------------------------------------------
108class CE_AddExp : public CE_BinExp {
109public:
110 CE_AddExp() : CE_BinExp('+',1) {}
111 virtual double Evaluate() const { CheckThrow("CE_AddExp::Evaluate"); return _e1->Evaluate()+_e2->Evaluate();
112 }
113};
114class CE_MulExp : public CE_BinExp {
115public:
116 CE_MulExp() : CE_BinExp('*',2) {}
117 virtual double Evaluate() const { CheckThrow("CE_MulExp::Evaluate"); return _e1->Evaluate()*_e2->Evaluate(); }
118};
119class CE_SubExp : public CE_BinExp {
120public:
121 CE_SubExp() : CE_BinExp('-',1) {}
122 virtual double Evaluate() const { CheckThrow("CE_SubExp::Evaluate"); return _e1->Evaluate()-_e2->Evaluate(); }
123};
124class CE_DivExp : public CE_BinExp {
125public:
126 CE_DivExp() : CE_BinExp('/',2) {}
127 virtual double Evaluate() const { CheckThrow("CE_DivExp::Evaluate"); return _e1->Evaluate()/_e2->Evaluate(); }
128};
129
130//---------------------------------------------------------
131typedef double (* f0exp) ();
132typedef double (* f1exp) (double x);
133typedef double (* f2exp) (double x, double y);
134typedef double (* f3exp) (double x, double y, double z);
135
136//---------------------------------------------------------
137#define FMXARG 3
138class CE_FuncExp : public CExprBase {
139public:
140 CE_FuncExp(string const & func);
141 virtual ~CE_FuncExp();
142 virtual double Evaluate() const ;
143 inline void AddArg(CExprBase * e);
144 virtual bool CheckE(string& errmsg) const;
145 virtual void Print(ostream& os) const;
146protected:
147 f0exp _f0;
148 f1exp _f1;
149 f2exp _f2;
150 f3exp _f3;
151 int _ne, _maxne;
152 CExprBase * _e[FMXARG];
153 string _fname;
154};
155
156//---------------------------------------------------------
157CE_FuncExp::CE_FuncExp(string const & func)
158{
159 _ne = 0; _maxne = -1;
160 for(int k=0; k<FMXARG; k++) _e[k] = NULL;
161 _f0 = NULL;
162 _f1 = NULL;
163 _f2 = NULL;
164 _f3 = NULL;
165 if (func == "sin") _f1 = sin;
166 else if (func == "cos") _f1 = cos;
167 else if (func == "tan") _f1 = tan;
168 else if (func == "asin") _f1 = asin;
169 else if (func == "acos") _f1 = acos;
170 else if (func == "atan") _f1 = atan;
171 else if (func == "atan2") _f2 = atan2;
172 else if (func == "sqrt") _f1 = sqrt;
173 else if (func == "fabs") _f1 = fabs;
174 else if (func == "floor") _f1 = floor;
175 else if (func == "exp") _f1 = exp;
176 else if (func == "log") _f1 = log;
177 else if (func == "log10") _f1 = log10;
178 else if (func == "pow") _f2 = pow;
179 else if (func == "hypot") _f2 = hypot;
180 else if (func == "sinh") _f1 = sinh;
181 else if (func == "cosh") _f1 = cosh;
182 else if (func == "tanh") _f1 = tanh;
183 else {
184 string errmsg = "CE_FuncExp::CE_FuncExp() - Uknown function " ;
185 errmsg += func;
186 throw CExprException(errmsg);
187 }
188 if (_f0) _maxne = 0;
189 else if (_f1) _maxne = 1;
190 else if (_f2) _maxne = 2;
191 else if (_f3) _maxne = 3;
192 _fname = func;
193}
194
195
196CE_FuncExp::~CE_FuncExp()
197{
198for(int k=0; k<FMXARG; k++) if (_e[k]) delete _e[k];
199}
200
201void CE_FuncExp::AddArg(CExprBase * e)
202{
203 if ((e != NULL) && (_ne < _maxne)) { _e[_ne] = e; _ne++; }
204 else throw CExprException("CE_FuncExp::AddArg() e=NULL or too many arguments ");
205}
206
207double CE_FuncExp::Evaluate() const
208{
209 if ((_ne != _maxne) || (_maxne < 1) ) {
210 throw CExprException("CE_FuncExp::Evaluate() - Wrong argument number ");
211 }
212 if (_ne == 1) return _f1(_e[0]->Evaluate());
213 else if (_ne == 2) return _f2(_e[0]->Evaluate(), _e[1]->Evaluate());
214 else if (_ne == 3) return _f3(_e[0]->Evaluate(), _e[1]->Evaluate(),
215 _e[2]->Evaluate());
216 else return 0.;
217}
218
219bool CE_FuncExp::CheckE(string& errmsg) const
220{
221 if ((_ne != _maxne) || (_maxne < 0) ) {
222 char buff[128];
223 sprintf(buff, "CE_FuncExp::CheckE() %s - Wrong argument number - ne=%d maxne=%d ",
224 _fname.c_str(), _ne, _maxne);
225 errmsg += buff;
226 return false;
227 }
228 return true;
229}
230
231void CE_FuncExp::Print(ostream& os) const
232{
233 if ((_ne != _maxne) || (_maxne < 1) )
234 os << _fname << "(ArgError)" ;
235 else {
236 if (_ne == 1) os << _fname << "(" << *(_e[0]) << ")";
237 else if (_ne == 2) os << _fname << "(" << *(_e[0]) << "," << *(_e[1]) << ")";
238 else if (_ne == 3) os << _fname << "(" << *(_e[0])
239 << "," << *(_e[1]) << "," << *(_e[2]) << ")";
240 }
241}
242
243//---------------------------------------------------------
244CExpressionEvaluator::CExpressionEvaluator(string const & sex)
245{
246 _exp = NULL;
247 size_t off=0,stop=0;
248 string fname = "";
249 string errmsg;
250 _exp= ParseString(0,fname,sex,off,stop,errmsg);
251 if (_exp == NULL) throw CExprException(errmsg);
252}
253
254CExpressionEvaluator::~CExpressionEvaluator()
255{
256 if (_exp) delete _exp;
257}
258
259double CExpressionEvaluator::Evaluate() const
260{
261 if (_exp) return _exp->Evaluate();
262 else return 0.;
263}
264
265void CExpressionEvaluator::Print(ostream& os) const
266{
267 if (_exp) _exp->Print(os);
268 else os << "CExpressionEvaluator ???";
269}
270
271// cette fonction rearrange le stack des operations binaires en attente
272CExprBase* Arrange_CE_BinExpStack(stack<CE_BinExp* >& sbx, CExprBase* cex, CE_BinExp* nbx)
273{
274 while ( !sbx.empty() && (nbx->Priority() <= sbx.top()->Priority()) ) {
275 sbx.top()->SetE2(cex);
276 cex = sbx.top(); sbx.pop();
277 }
278 nbx->SetE1(cex);
279 sbx.push(nbx);
280 return NULL;
281}
282
283// cette fonction rearrange le stack des operations binaires en attente
284CExprBase* Arrange_CE_BinExpStack(stack<CE_BinExp* >& sbx, CExprBase* cex)
285{
286 if (sbx.empty()) return cex;
287 while ( !sbx.empty() ) {
288 sbx.top()->SetE2(cex);
289 cex = sbx.top(); sbx.pop();
290 }
291 return cex;
292}
293
294
295CExprBase* CExpressionEvaluator::ParseString(int extype, string fname, string const & sex,
296 size_t off, size_t& stop, string& errmsg)
297{
298 size_t len = sex.length();
299 if (len < 1) {
300 string errmsg = "CExpressionEvaluator::ParseString() Empty expression";
301 throw CExprException(errmsg);
302 }
303 errmsg = "";
304 CExprBase* rx = NULL; // Expression resultat
305 stack< CE_BinExp* > sbx; // Stack des expressions binaires
306 CE_FuncExp* fx = NULL; // Expression fonction
307 CExprBase* cx = NULL; // Element d'expression (courante)
308
309 if (extype == 2) fx = new CE_FuncExp(fname);
310
311 size_t p=0, q=0;
312 char lastopc=0, opc=0; // Last/current operation sign (+,-,*,/,...)
313 bool finok = false;
314 bool fgcont = true;
315 bool checkok = true;
316 // cout << " DBG-ParseString off= " << off << " sex[off]= " << sex[off]
317 // << " extype= " << extype << endl;
318 p = stop = off;
319 while ((p < len) && (fgcont) && (checkok) ) {
320 // cout << " DBG-2-ParseString p=" << p << " q=" << q << endl;
321
322 cx = NULL;
323 q = sex.find_first_of("+-*/(),",p);
324 if (q < len) { // operateur trouve
325 opc = sex[q]; // signe operateur courant
326 switch (opc) {
327 case '(' :
328 if (q == p) {
329 string fname = "";
330 cx = ParseString(1, fname, sex, q+1, stop, errmsg);
331 }
332 else cx = ParseString(2, sex.substr(p,q-p), sex, q+1, stop, errmsg);
333 if (!cx) { checkok = false; p = stop+1; }
334 else {
335 if (rx) {
336 checkok = false; p = stop+1; fgcont = false;
337 delete cx;
338 errmsg = "CExpressionEvaluator::ParseString()/ Syntax Error - rx&&cx (A)";
339 }
340 else {
341 if (stop == len-1) {
342 rx = Arrange_CE_BinExpStack(sbx, cx);
343 finok = true;
344 }
345 else rx = cx;
346 p = stop+1; lastopc = opc;
347 }
348 }
349 break;
350
351 case ')' :
352 case ',' :
353 if (extype == 0) {
354 checkok = false; p = q; fgcont = false;
355 errmsg = "CExpressionEvaluator::ParseString() Unexpected ) or ,";
356 }
357 if ( (extype == 1) && (opc == ',')) {
358 checkok = false; p = q; fgcont = false;
359 errmsg = "CExpressionEvaluator::ParseString() Unexpected ,";
360 }
361 if ((q > p) && (rx)) {
362 checkok = false; p = q; fgcont = false;
363 errmsg = "CExpressionEvaluator::ParseString()/ Syntax Error - rx&&cx (B)";
364 }
365 if (q > p) cx = new CE_NumberExp(sex.substr(p,q-p));
366 else cx = rx;
367
368 if (!cx) {
369 checkok = false; p = q; fgcont = false;
370 errmsg = "CExpressionEvaluator::ParseString()/ Syntax Error - farg=NULL (BB)";
371 }
372 else {
373 rx = Arrange_CE_BinExpStack(sbx, cx);
374 if (extype == 2) {
375 // cout << " DBG-ParseString-AddArg " << *(cx) << endl;
376 fx->AddArg(rx); rx = NULL;
377 }
378 if (opc == ')') { // Signe de fin de traitement d'une portion d'expression
379 if (extype == 2) { rx = fx; fx = NULL; }
380 stop = q; lastopc = opc;
381 fgcont = false;
382 finok = true;
383 }
384 else {
385 if (q == (len-1)) finok = true;
386 p = q+1; lastopc = opc;
387 }
388 }
389 break;
390
391 case '+' :
392 case '-' :
393 case '*' :
394 case '/' :
395 // Traitement des signes +/- qui pourrait faire partie d'une constante numerique
396 if (!( ((opc=='+')||(opc=='-')) && ( (q==off) || ( (q==p) && (rx == NULL) ) ) ) ) {
397 // ((lastopc=='+')||(lastopc=='-')||(lastopc=='*')||(lastopc=='/')) ) ) ) ) {
398 CE_BinExp* nbx;
399 if (opc == '+') nbx = new CE_AddExp;
400 else if (opc == '-') nbx = new CE_SubExp;
401 else if (opc == '*') nbx = new CE_MulExp;
402 else nbx = new CE_DivExp;
403 if ((p == q) && (rx == NULL)) {
404 checkok = false; p = q; fgcont = false;
405 delete nbx;
406 errmsg = "CExpressionEvaluator::ParseString() Syntax Error - rx==NULL (C)";
407 }
408 else {
409 if (p == q) cx = rx;
410 else cx = new CE_NumberExp(sex.substr(p,q-p));
411 rx = Arrange_CE_BinExpStack(sbx, cx, nbx);
412 p = q+1; lastopc = opc;
413 }
414 }
415 break;
416 default:
417 throw CExprException("CExpressionEvaluator::ParseString() BUG-BUG-BUG");
418 break;
419 } // Fin de switch
420 }
421 else { // dernier element
422 if ( (p<len) && (rx != NULL)) {
423 checkok = false; p = len-1; fgcont = false;
424 errmsg = "CExpressionEvaluator::ParseString() Syntax Error - rx!=NULL at end (D)";
425 }
426 else {
427 if (p<len) cx = new CE_NumberExp(sex.substr(p));
428 else cx = rx;
429 rx = Arrange_CE_BinExpStack(sbx, cx);
430 stop = p = len; fgcont = false;
431 finok = true;
432 }
433 }
434 }
435 // cout << " DBG-ParseString-out stop= " << stop << " sex[stop]= " << sex[stop] << endl;
436 if (finok && checkok) {
437 if( !sbx.empty() ) {
438 checkok = false;
439 errmsg = "CExpressionEvaluator::ParseString() !sbx.empty() at the end (E)";
440 }
441 else {
442 checkok = rx->CheckE(errmsg);
443 }
444 }
445 if (!finok || !checkok || !rx) {
446 char buff[128];
447 if (errmsg.length() < 1) {
448 errmsg = "CExpressionEvaluator::ParseString() Error - " ;
449 if (!finok) errmsg += " !finok " ;
450 if (!checkok) errmsg += " !checkok " ;
451 if (!rx) errmsg += " !rx " ;
452 errmsg += " (F)";
453 }
454 sprintf(buff,"\n CExprError... S=[%s] (p=%ld , len=%ld)", sex.c_str(), (long)p,(long)len);
455 errmsg += buff;
456 if (rx) delete rx;
457 rx = NULL;
458 while (!sbx.empty()) {
459 delete sbx.top();
460 sbx.pop();
461 }
462 }
463 if (fx) delete fx;
464 return rx;
465}
466
467} // End of namespace SOPHYA
468
Note: See TracBrowser for help on using the repository browser.