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

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

Ajout fichiers des classes RPNExpressionEvaluator et CExpressionEvaluator (expression arithmetiques) et MAJ du fichier Makefile et objlist.list - Reza 15 Mars 2003

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