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

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

suppression variables inutilisees ds cexpr.cc - Reza 16 Mars 2004

File size: 12.9 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 errmsg = "";
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 bool finok = false;
310 bool fgcont = true;
311 bool checkok = true;
312 // cout << " DBG-ParseString off= " << off << " sex[off]= " << sex[off]
313 // << " extype= " << extype << endl;
314 p = stop = off;
315 while ((p < len) && (fgcont) && (checkok) ) {
316 // cout << " DBG-2-ParseString p=" << p << " q=" << q << endl;
317
318 cx = NULL;
319 q = sex.find_first_of("+-*/(),",p);
320 if (q < len) { // operateur trouve
321 opc = sex[q]; // signe operateur courant
322 switch (opc) {
323 case '(' :
324 if (q == p) {
325 string fname = "";
326 cx = ParseString(1, fname, sex, q+1, stop, errmsg);
327 }
328 else cx = ParseString(2, sex.substr(p,q-p), sex, q+1, stop, errmsg);
329 if (!cx) { checkok = false; p = stop+1; }
330 else {
331 if (rx) {
332 checkok = false; p = stop+1; fgcont = false;
333 delete cx;
334 errmsg = "CExpressionEvaluator::ParseString()/ Syntax Error - rx&&cx (A)";
335 }
336 else {
337 if (stop == len-1) {
338 rx = Arrange_CE_BinExpStack(sbx, cx);
339 finok = true;
340 }
341 else rx = cx;
342 p = stop+1; lastopc = opc;
343 }
344 }
345 break;
346
347 case ')' :
348 case ',' :
349 if (extype == 0) {
350 checkok = false; p = q; fgcont = false;
351 errmsg = "CExpressionEvaluator::ParseString() Unexpected ) or ,";
352 }
353 if ( (extype == 1) && (opc == ',')) {
354 checkok = false; p = q; fgcont = false;
355 errmsg = "CExpressionEvaluator::ParseString() Unexpected ,";
356 }
357 if ((q > p) && (rx)) {
358 checkok = false; p = q; fgcont = false;
359 errmsg = "CExpressionEvaluator::ParseString()/ Syntax Error - rx&&cx (B)";
360 }
361 if (q > p) cx = new CE_NumberExp(sex.substr(p,q-p));
362 else cx = rx;
363
364 if (!cx) {
365 checkok = false; p = q; fgcont = false;
366 errmsg = "CExpressionEvaluator::ParseString()/ Syntax Error - farg=NULL (BB)";
367 }
368 else {
369 rx = Arrange_CE_BinExpStack(sbx, cx);
370 if (extype == 2) {
371 // cout << " DBG-ParseString-AddArg " << *(cx) << endl;
372 fx->AddArg(rx); rx = NULL;
373 }
374 if (opc == ')') { // Signe de fin de traitement d'une portion d'expression
375 if (extype == 2) { rx = fx; fx = NULL; }
376 stop = q; lastopc = opc;
377 fgcont = false;
378 finok = true;
379 }
380 else {
381 if (q == (len-1)) finok = true;
382 p = q+1; lastopc = opc;
383 }
384 }
385 break;
386
387 case '+' :
388 case '-' :
389 case '*' :
390 case '/' :
391 // Traitement des signes +/- qui pourrait faire partie d'une constante numerique
392 if (!( ((opc=='+')||(opc=='-')) && ( (q==off) || ( (q==p) && (rx == NULL) ) ) ) ) {
393 // ((lastopc=='+')||(lastopc=='-')||(lastopc=='*')||(lastopc=='/')) ) ) ) ) {
394 CE_BinExp* nbx;
395 if (opc == '+') nbx = new CE_AddExp;
396 else if (opc == '-') nbx = new CE_SubExp;
397 else if (opc == '*') nbx = new CE_MulExp;
398 else nbx = new CE_DivExp;
399 if ((p == q) && (rx == NULL)) {
400 checkok = false; p = q; fgcont = false;
401 delete nbx;
402 errmsg = "CExpressionEvaluator::ParseString() Syntax Error - rx==NULL (C)";
403 }
404 else {
405 if (p == q) cx = rx;
406 else cx = new CE_NumberExp(sex.substr(p,q-p));
407 rx = Arrange_CE_BinExpStack(sbx, cx, nbx);
408 p = q+1; lastopc = opc;
409 }
410 }
411 break;
412 default:
413 throw CExprException("CExpressionEvaluator::ParseString() BUG-BUG-BUG");
414 break;
415 } // Fin de switch
416 }
417 else { // dernier element
418 if ( (p<len) && (rx != NULL)) {
419 checkok = false; p = len-1; fgcont = false;
420 errmsg = "CExpressionEvaluator::ParseString() Syntax Error - rx!=NULL at end (D)";
421 }
422 else {
423 if (p<len) cx = new CE_NumberExp(sex.substr(p));
424 else cx = rx;
425 rx = Arrange_CE_BinExpStack(sbx, cx);
426 stop = p = len; fgcont = false;
427 finok = true;
428 }
429 }
430 }
431 // cout << " DBG-ParseString-out stop= " << stop << " sex[stop]= " << sex[stop] << endl;
432 if (finok && checkok) {
433 if( !sbx.empty() ) {
434 checkok = false;
435 errmsg = "CExpressionEvaluator::ParseString() !sbx.empty() at the end (E)";
436 }
437 else {
438 checkok = rx->CheckE(errmsg);
439 }
440 }
441 if (!finok || !checkok || !rx) {
442 char buff[128];
443 if (errmsg.length() < 1) {
444 errmsg = "CExpressionEvaluator::ParseString() Error - " ;
445 if (!finok) errmsg += " !finok " ;
446 if (!checkok) errmsg += " !checkok " ;
447 if (!rx) errmsg += " !rx " ;
448 errmsg += " (F)";
449 }
450 sprintf(buff,"\n CExprError... S=[%s] (p=%ld , len=%ld)", sex.c_str(), (long)p,(long)len);
451 errmsg += buff;
452 if (rx) delete rx;
453 rx = NULL;
454 while (!sbx.empty()) {
455 delete sbx.top();
456 sbx.pop();
457 }
458 }
459 if (fx) delete fx;
460 return rx;
461}
462
463} // End of namespace SOPHYA
464
Note: See TracBrowser for help on using the repository browser.