Salome HOME
1c213b796ad846bef66c46ced6945c3831664350
[tools/medcoupling.git] / src / INTERP_KERNEL / ExprEval / InterpKernelExprParser.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "InterpKernelExprParser.hxx"
22 #include "InterpKernelValue.hxx"
23 #include "InterpKernelAsmX86.hxx"
24 #include "InterpKernelAutoPtr.hxx"
25
26 #include <cctype>
27 #include <sstream>
28 #include <limits>
29 #include <vector>
30 #include <iterator>
31 #include <iostream>
32 #include <algorithm>
33
34 using namespace INTERP_KERNEL;
35
36 const char LeafExprVar::END_OF_RECOGNIZED_VAR[]="Vec";
37
38 const char ExprParser::WHITE_SPACES[]=" \n";
39
40 const char ExprParser::EXPR_PARSE_ERR_MSG[]="Invalid expression detected : ";
41
42 LeafExpr *LeafExpr::buildInstanceFrom(const std::string& expr)
43 {
44   std::istringstream stream;
45   stream.str(expr);
46   double val;
47   stream >> val;
48   if(!stream.fail())
49     if(stream.eof())
50       return new LeafExprVal(val);
51     else
52       {
53         std::ostringstream errMsg;
54         char MSGTYP6[]="Error following expression is not consedered as a double value : ";
55         errMsg << MSGTYP6 << expr;
56         throw INTERP_KERNEL::Exception(errMsg.str().c_str());
57       }
58   else
59     return new LeafExprVar(expr);
60 }
61
62 LeafExpr::~LeafExpr()
63 {
64 }
65
66 LeafExprVal::LeafExprVal(double value):_value(value)
67 {
68 }
69
70 LeafExprVal::~LeafExprVal()
71 {
72 }
73
74 void LeafExprVal::fillValue(Value *val) const
75 {
76   val->setDouble(_value);
77 }
78
79 void LeafExprVal::replaceValues(const std::vector<double>& valuesInExpr)
80 {
81   int pos=(int)_value;
82   int lgth=(int)valuesInExpr.size();
83   if(pos>=lgth || pos<0)
84     throw INTERP_KERNEL::Exception("LeafExprVal::replaceValues : Big Problem detected !");
85   _value=valuesInExpr[pos];
86 }
87
88 LeafExprVal *LeafExprVal::deepCpy() const
89 {
90   return new LeafExprVal(*this);
91 }
92
93 LeafExprVar::LeafExprVar(const std::string& var):_fast_pos(-1),_var_name(var),_val(0)
94 {
95 }
96
97 void LeafExprVar::fillValue(Value *val) const
98 {
99   if(_val)
100     val->setDouble(_val[_fast_pos]);
101   else
102     val->setVarname(_fast_pos,_var_name);
103
104 }
105
106 void LeafExprVar::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const
107 {
108   std::vector<std::string>::const_iterator iter=std::find(vars.begin(),vars.end(),_var_name);
109   if(iter==vars.end())
110     {
111       if(!isRecognizedKeyVar(_var_name,_fast_pos))
112         {
113           std::ostringstream oss; oss << "Var : " << _var_name << " not in : ";
114           std::copy(vars.begin(),vars.end(),std::ostream_iterator<std::string>(oss,", "));
115           throw INTERP_KERNEL::Exception(oss.str().c_str());
116         }
117       else
118         {
119           int relPos=-7-_fast_pos;
120           if(relPos>=targetNbOfCompo)
121             {
122               std::ostringstream oss; oss << "LeafExprVar::prepareExprEvaluation : Found recognized unitary vector \"" << _var_name << "\" which implies that component #" << relPos;
123               oss << " exists, but it is not the case component id should be in [0," << targetNbOfCompo << ") !";
124               throw INTERP_KERNEL::Exception(oss.str().c_str());
125             }
126           else
127             return;
128         }
129     }
130   _fast_pos=(int)std::distance(vars.begin(),iter);
131   if(_fast_pos>=nbOfCompo)
132     {
133       std::ostringstream oss; oss << "LeafExprVar::prepareExprEvaluation : Found var \"" << _var_name << "\" on place " << _fast_pos << " whereas only must be in [0," << nbOfCompo << ") !";
134       throw INTERP_KERNEL::Exception(oss.str().c_str());
135     }
136 }
137
138 /*!
139  * \param [in] vars - the sorted list of vars
140  * \param [in] nbOfCompo - the size of the input tuples (it is used to scan if no problem occurs)
141  * \param [in] targetNbOfCompo - the size of the output tuple (it is used to check that no problem occurs)
142  * \param [in] refPos - is an integer in [0,targetNbOfCompo), that tell the id of \a this. It is for multi interpreters.
143  * \sa evaluateDouble
144  */
145 void LeafExprVar::prepareExprEvaluationDouble(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo, int refPos, const double *ptOfInputStart, const double *ptOfInputEnd) const
146 {
147   if((int)vars.size()!=std::distance(ptOfInputStart,ptOfInputEnd))
148     throw INTERP_KERNEL::Exception("LeafExprVar::prepareExprEvaluationDouble : size of input vector must be equal to the input vector !");
149   prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
150   _ref_pos=refPos;
151   _val=ptOfInputStart;
152 }
153
154 void LeafExprVar::prepareExprEvaluationVec() const
155 {
156   if(!isRecognizedKeyVar(_var_name,_fast_pos))
157     _fast_pos=-2;
158 }
159
160 bool LeafExprVar::isRecognizedKeyVar(const std::string& var, int& pos)
161 {
162   if(var.length()!=sizeof(END_OF_RECOGNIZED_VAR))
163     return false;
164   std::string end=var.substr(1);
165   if(end!=END_OF_RECOGNIZED_VAR)
166     return false;
167   char first=var[0];
168   if(first<'I' || first>'Z')
169     return false;
170   pos=-7-(first-'I');
171   return true;
172 }
173
174 LeafExprVar *LeafExprVar::deepCpy() const
175 {
176   return new LeafExprVar(*this);
177 }
178
179 /*!
180  * Nothing to do it is not a bug.
181  */
182 void LeafExprVar::replaceValues(const std::vector<double>& valuesInExpr)
183 {
184 }
185
186 LeafExprVar::~LeafExprVar()
187 {
188 }
189
190 void ExprParserOfEval::clearSortedMemory()
191 {
192   delete _leaf;
193   for(std::vector<ExprParserOfEval>::iterator it=_sub_parts.begin();it!=_sub_parts.end();it++)
194     (*it).clearSortedMemory();
195   for(std::vector<Function *>::iterator it=_funcs.begin();it!=_funcs.end();it++)
196     delete *it;
197 }
198
199 void ExprParserOfEval::sortMemory()
200 {
201   for(std::vector<ExprParserOfEval>::iterator it=_sub_parts.begin();it!=_sub_parts.end();it++)
202     (*it).sortMemory();
203   if(_leaf)
204     _leaf=_leaf->deepCpy();
205   for(std::vector<Function *>::iterator it=_funcs.begin();it!=_funcs.end();it++)
206     if(*it)
207       *it=(*it)->deepCpy();
208 }
209
210 ExprParser::ExprParser(const std::string& expr, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr)
211 {
212   _expr=deleteWhiteSpaces(_expr);
213 }
214
215 //! For \b NOT null terminated strings coming from FORTRAN.
216 ExprParser::ExprParser(const char *expr, int lgth, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false)
217 {
218   _expr=buildStringFromFortran(expr,lgth);
219   _expr=deleteWhiteSpaces(_expr);
220 }
221
222 ExprParser::~ExprParser()
223 {
224   delete _leaf;
225   _for_eval.clearSortedMemory();
226   releaseFunctions();
227 }
228
229 std::size_t ExprParser::FindCorrespondingOpenBracket(const std::string& expr, std::size_t posOfCloseBracket)
230 {
231   int level=0;
232   for(std::size_t iter=0;iter<posOfCloseBracket;iter++)
233     {
234       std::size_t iter2=posOfCloseBracket-1-iter;
235       if(expr[iter2]==')')
236         level++;
237       else if(expr[iter2]=='(')
238         {
239           if(level==0)
240             return iter2;
241           else
242             level--;
243         }
244     }
245   return std::string::npos;
246 }
247
248 std::string ExprParser::buildStringFromFortran(const char *expr, int lgth)
249 {
250   std::string ret(expr,lgth);
251   std::string whiteSpaces(WHITE_SPACES);
252   std::size_t found=ret.find_last_not_of(whiteSpaces);
253   if (found!=std::string::npos)
254     ret.erase(found+1);
255   else
256     ret.clear();//ret is all whitespace
257   return ret;
258 }
259
260 std::string ExprParser::deleteWhiteSpaces(const std::string& expr)
261 {
262   std::string ret(expr);
263   std::string whiteSpaces(WHITE_SPACES);
264   std::size_t where1=0,where2=0;
265   while(where2!=std::string::npos && where1!=std::string::npos)
266     {
267       where1=ret.find_first_of(whiteSpaces.c_str(),where1,whiteSpaces.length());
268       if(where1!=std::string::npos)
269         {
270           where2=ret.find_first_not_of(whiteSpaces,where1);
271           if(where2!=std::string::npos)
272             ret.erase(ret.begin()+where1,ret.begin()+where2);
273           else
274             ret.erase(ret.begin()+where1,ret.end());
275         }
276     }
277   return ret;
278 }
279
280 void ExprParser::parse()
281 {
282   _is_parsed=true;
283   _is_parsing_ok=false;
284   _sub_expr.clear();
285   releaseFunctions();
286   if(!_expr.empty())
287     {
288       std::string tmp(_expr);
289       std::vector<double> valuesInExpr;
290       fillValuesInExpr(valuesInExpr);
291       checkBracketsParity();
292       if(!simplify())
293         parseDeeper();
294       replaceValues(valuesInExpr);
295       _expr=tmp;
296     }
297   reverseThis();
298   _is_parsing_ok=true;
299 }
300
301 double ExprParser::evaluate() const
302 {
303   AutoCppPtr<Value> gen(new ValueDouble);
304   AutoCppPtr<ValueDouble> res(static_cast<ValueDouble *>(evaluateLowLev(gen)));
305   return res->getData();
306 }
307
308 DecompositionInUnitBase ExprParser::evaluateUnit() const
309 {
310   Value *gen=new ValueUnit;
311   ValueUnit *res=0;
312   try
313     {
314       res=(ValueUnit *)evaluateLowLev(gen);
315     }
316   catch(INTERP_KERNEL::Exception& e)
317     {
318       delete gen;
319       throw e;
320     }
321   delete gen;
322   DecompositionInUnitBase ret=res->getData();
323   delete res;
324   return ret;
325 }
326
327 void ExprParser::evaluateExpr(int szOfOutParam, const double *inParam, double *outParam) const
328 {
329   AutoCppPtr<Value> gen(new ValueDoubleExpr(szOfOutParam,inParam));
330   AutoCppPtr<ValueDoubleExpr> res(static_cast<ValueDoubleExpr *>(evaluateLowLev(gen)));
331   std::copy(res->getData(),res->getData()+szOfOutParam,outParam);
332 }
333
334 void ExprParser::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const
335 {
336   if(_leaf)
337     {
338       LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
339       if(leafC)
340         leafC->prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
341     }
342   else
343     for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
344       (*iter).prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
345 }
346
347 /*!
348  * \param [in] vars - the sorted list of vars
349  * \param [in] nbOfCompo - the size of the input tuples (it is used to scan if no problem occurs)
350  * \param [in] targetNbOfCompo - the size of the output tuple (it is used to check that no problem occurs)
351  * \param [in] refPos - is an integer in [0,targetNbOfCompo), that tell the id of \a this. It is for multi interpreters.
352  * \sa evaluateDouble
353  */
354 void ExprParser::prepareExprEvaluationDouble(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo, int refPos, const double *ptOfInputStart, const double *ptOfInputEnd) const
355 {
356   if((int)vars.size()!=std::distance(ptOfInputStart,ptOfInputEnd))
357     throw INTERP_KERNEL::Exception("ExprParser::prepareExprEvaluationDouble : size of input vector must be equal to the input vector !");
358   if(_leaf)
359     {
360       LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
361       if(leafC)
362         leafC->prepareExprEvaluationDouble(vars,nbOfCompo,targetNbOfCompo,refPos,ptOfInputStart,ptOfInputEnd);
363     }
364   else
365     for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
366       (*iter).prepareExprEvaluationDouble(vars,nbOfCompo,targetNbOfCompo,refPos,ptOfInputStart,ptOfInputEnd);
367 }
368
369 void ExprParser::prepareFastEvaluator() const
370 {
371   _for_eval.clearSortedMemory();
372   _for_eval=convertMeTo();
373   _for_eval.sortMemory();
374 }
375
376 /*!
377  * \sa prepareExprEvaluationDouble
378  */
379 double ExprParser::evaluateDouble() const
380 {
381   checkForEvaluation();
382   std::vector<double> stackOfVal;
383   evaluateDoubleInternal(stackOfVal);
384   return stackOfVal.back();
385 }
386
387 void ExprParser::checkForEvaluation() const
388 {
389   if(!_is_parsing_ok)
390     throw INTERP_KERNEL::Exception("checkForEvaluation : Parsing fails ! Invalid expression !");
391   if(_sub_expr.empty() && !_leaf)
392     throw INTERP_KERNEL::Exception("checkForEvaluation : Empty expression !");
393 }
394
395 void ExprParser::prepareExprEvaluationVec() const
396 {
397   std::set<std::string> trueVars;
398   getTrueSetOfVars(trueVars);
399   if(trueVars.size()>1)
400     {
401       std::ostringstream oss; oss << "For this type of evaluation only one not keyword variable authorized : ";
402       oss << "having " << trueVars.size() << " : ";
403       std::copy(trueVars.begin(),trueVars.end(),std::ostream_iterator<std::string>(oss," ")); oss << " !";
404       throw INTERP_KERNEL::Exception(oss.str().c_str());
405     }
406   prepareExprEvaluationVecLowLev();
407 }
408
409 void ExprParser::prepareExprEvaluationVecLowLev() const
410 {
411   if(_leaf)
412     {
413       LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
414       if(leafC)
415         leafC->prepareExprEvaluationVec();
416     }
417   else
418     for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
419       (*iter).prepareExprEvaluationVecLowLev();
420 }
421
422 Value *ExprParser::evaluateLowLev(Value *valGen) const
423 {
424   checkForEvaluation();
425   std::vector<Value *> stackOfVal;
426   try
427     {
428       if(_leaf)
429         {
430           Value *ret=valGen->newInstance();
431           try
432             {
433               _leaf->fillValue(ret);
434             }
435           catch(INTERP_KERNEL::Exception& e)
436             {
437               delete ret;
438               throw e;
439             }
440           stackOfVal.resize(1);
441           stackOfVal[0]=ret;
442         }
443       else
444         {
445           stackOfVal.resize(_sub_expr.size());
446           std::vector<Value *>::iterator iter2=stackOfVal.begin();
447           for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++,iter2++)
448             *iter2=(*iter).evaluateLowLev(valGen);
449         }
450       for(std::vector<Function *>::const_iterator iter3=_func_btw_sub_expr.begin();iter3!=_func_btw_sub_expr.end();iter3++)
451         (*iter3)->operate(stackOfVal);
452     }
453   catch(INTERP_KERNEL::Exception& e)
454     {
455       for(std::vector<Value *>::iterator iter4=stackOfVal.begin();iter4!=stackOfVal.end();iter4++)
456         delete *iter4;
457       throw e;
458     }
459   return stackOfVal.back();
460 }
461
462 void ExprParser::reverseThis()
463 {
464   if(_leaf)
465     return ;
466   for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
467     (*iter).reverseThis();
468   AutoPtr<char> buf(new char[sizeof(ExprParser)]);
469   char *loc(reinterpret_cast<char *>(&_sub_expr[0])),*bufPtr(buf);
470   std::size_t sz(_sub_expr.size());
471   std::size_t nbOfTurn(sz/2);
472   for(std::size_t i=0;i<nbOfTurn;i++)
473     {
474       std::copy(loc+i*sizeof(ExprParser),loc+(i+1)*sizeof(ExprParser),bufPtr);
475       std::copy(loc+(sz-i-1)*sizeof(ExprParser),loc+(sz-i)*sizeof(ExprParser),loc+i*sizeof(ExprParser));
476       std::copy(bufPtr,bufPtr+sizeof(ExprParser),loc+(sz-i-1)*sizeof(ExprParser));
477     }
478 }
479
480 ExprParserOfEval ExprParser::convertMeTo() const
481 {
482   std::size_t sz(_sub_expr.size());
483   std::vector<ExprParserOfEval> subExpr(sz);
484   for(std::size_t i=0;i<sz;i++)
485     subExpr[i]=_sub_expr[i].convertMeTo();
486   return ExprParserOfEval(_leaf,subExpr,_func_btw_sub_expr);
487 }
488
489 void ExprParser::getSetOfVars(std::set<std::string>& vars) const
490 {
491   if(_leaf)
492     {
493       LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
494       if(leafC)
495         vars.insert(leafC->getVar());
496     }
497   else
498     for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
499       (*iter).getSetOfVars(vars);
500 }
501
502 void ExprParser::getTrueSetOfVars(std::set<std::string>& trueVars) const
503 {
504   std::set<std::string> vars;
505   getSetOfVars(vars);
506   trueVars.clear();
507   for(std::set<std::string>::const_iterator iter=vars.begin();iter!=vars.end();iter++)
508     {
509       int tmp;
510       if(!LeafExprVar::isRecognizedKeyVar(*iter,tmp))
511         trueVars.insert(*iter);
512     }
513 }
514
515 void ExprParser::parseDeeper()
516 {
517   for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
518     if(!(*iter).simplify())
519       (*iter).parseDeeper();
520 }
521
522 /*!
523  * This method has the responsability to see if this->_expr can be seen as a unary function of something.
524  * Something defined as the contain of highest level barckets.
525  * Typically '(3*x+2)' and 'cos(4*l+p*n)' will be intercepted by this method whereas '3*x+2' not...etc..
526  */
527 void ExprParser::parseUnaryFunc()
528 {
529   if(_expr[_expr.length()-1]!=')')
530     return ;
531   //at this level of code _expr
532   std::size_t pos1=_expr.find_first_of('(');
533   std::size_t pos4=FindCorrespondingOpenBracket(_expr,_expr.length()-1);
534   if(pos4!=pos1)
535     return ;
536   std::string funcName=_expr.substr(0,pos1);
537   std::size_t pos2=funcName.find_first_of("+-*/^><",0,7);
538   std::size_t pos3=funcName.find_first_not_of("+-*/^><",0,7);
539   if(pos2!=std::string::npos && pos3!=std::string::npos)
540     return ;//Bracket group is not alone, can't conclude not recursively.
541   std::string newExp2=_expr.substr(pos1+1,_expr.length()-pos1-2);
542   std::size_t nbOfParamsInFunc=std::count(newExp2.begin(),newExp2.end(),',')+1;
543   if(pos3!=std::string::npos)
544     _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(funcName.c_str(),(int)nbOfParamsInFunc));
545   else
546     {
547       std::size_t lgth=funcName.length();
548       char tmp[2]; tmp[1]='\0';
549       for(std::size_t i=0;i<lgth;i++)
550         {
551           tmp[0]=funcName[i];
552           _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(tmp,(int)nbOfParamsInFunc));
553         }
554     }
555   std::size_t pos6=0;
556   for(std::size_t i=0;i<nbOfParamsInFunc;i++)
557     {
558       std::size_t pos5=newExp2.find_first_of(',',pos6);
559       std::size_t len=std::string::npos;
560       if(pos5!=std::string::npos)
561         len=pos5-pos6;
562       std::string newExp3=newExp2.substr(pos6,len);
563       _sub_expr.push_back(ExprParser(newExp3.c_str(),this));
564       pos6=pos5+1;
565     }
566   _is_parsing_ok=true;
567 }
568
569 /*!
570  *  This method has the responsability to see if this->_expr is interpretable without any recursion.
571  * \return true if no recursion needed, false if this->_expr is too complex to be interpreted at this level.
572  * \throw exception if this->_expr is simple enough to try to interprate this and this expression contains an error.
573  */
574 bool ExprParser::tryToInterpALeaf()
575 {
576   std::size_t pos=_expr.find_first_not_of("+-",0,2);
577   std::string minimizedExpr=_expr.substr(pos);
578   std::size_t pos2=minimizedExpr.find_first_of("+-*/^()<>",0,9);
579   if(pos2!=std::string::npos)
580     return false;
581   delete _leaf;
582   _leaf=LeafExpr::buildInstanceFrom(minimizedExpr);
583   int nbOfNegs=0;
584   for(std::size_t i=0;i<pos;i++)
585     if(_expr[i]=='-')
586       nbOfNegs++;
587   if(nbOfNegs%2)
588     _func_btw_sub_expr.push_back(FunctionsFactory::buildUnaryFuncFromString("-"));
589   _is_parsing_ok=true;
590   return true;
591 }
592
593 void ExprParser::parseForCmp()
594 {
595   std::string::const_iterator iter;
596   int curLevel=0;
597   std::string curPart;
598   bool isParsingSucceed=false;
599   for(iter=_expr.begin();iter!=_expr.end();iter++)
600     {
601       switch(*iter)
602         {
603         case '>':
604         case '<':
605           {
606             isParsingSucceed=true;
607             if(!curPart.empty())
608               {
609                 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
610                 curPart.clear();
611                 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
612               }
613             else
614               {
615                 std::ostringstream errMsg;
616                 char MSGTYP1[]="Error non unary function for '";
617                 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
618                 std::string tmp=_expr.substr(iter-_expr.begin());
619                 LocateError(errMsg,tmp,0);
620                 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
621               }
622             break;
623           }
624         case '(':
625           curLevel++;
626           curPart+=*iter;
627           break;
628         case ')':
629           curLevel--;
630           curPart+=*iter;
631           break;
632         default:
633           curPart+=*iter;
634         }
635     }
636   if(isParsingSucceed)
637     {
638       if(!curPart.empty())
639         {
640           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
641           _is_parsing_ok=true;
642         }
643       else
644         {
645           std::ostringstream errMsg;
646           char MSGTYP4[]="Error following expression finished by > / < without right part.";
647           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
648           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
649         }
650     }
651 }
652
653 void ExprParser::parseForAddMin()
654 {
655   std::string::const_iterator iter;
656   int curLevel=0;
657   std::string curPart;
658   bool isParsingSucceed=false;
659   for(iter=_expr.begin();iter!=_expr.end();iter++)
660     {
661       switch(*iter)
662         {
663         case '+':
664         case '-':
665           if(curLevel!=0)
666             curPart+=*iter;
667           else
668             {
669               if(!curPart.empty())
670                 {
671                   std::string::reverse_iterator accessor=curPart.rbegin();
672                   if(*accessor!='*' && *accessor!='/' && *accessor!='^')
673                     {
674                       isParsingSucceed=true;
675                       _sub_expr.push_back(ExprParser(curPart.c_str(),this));
676                       curPart.clear();
677                       _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
678                     }
679                   else
680                     curPart+=*iter;
681                 }
682               else
683                 curPart+=*iter;
684             }
685         break;
686         case '(':
687           curLevel++;
688           curPart+=*iter;
689           break;
690         case ')':
691           curLevel--;
692           curPart+=*iter;
693           break;
694         default:
695           curPart+=*iter;
696         }
697     }
698   if(isParsingSucceed)
699     {
700       if(!curPart.empty())
701         {
702           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
703           _is_parsing_ok=true;
704         }
705       else
706         {
707           std::ostringstream errMsg;
708           char MSGTYP4[]="Error following expression finished by +/- without right part.";
709           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
710           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
711         }
712     }
713 }
714
715 void ExprParser::parseForMulDiv()
716 {
717   std::string::const_iterator iter;
718   int curLevel=0;
719   std::string curPart;
720   bool isParsingSucceed=false;
721   for(iter=_expr.begin();iter!=_expr.end();iter++)
722     {
723       switch(*iter)
724         {
725         case '/':
726         case '*':
727           if(curLevel!=0)
728             curPart+=*iter;
729           else
730             {
731               isParsingSucceed=true;
732               if(!curPart.empty())
733                 {
734                   _sub_expr.push_back(ExprParser(curPart.c_str(),this));
735                   curPart.clear();
736                   _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
737                 }
738               else
739                 {
740                   std::ostringstream errMsg;
741                   char MSGTYP1[]="Error non unary function for '";
742                   errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
743                   std::string tmp=_expr.substr(iter-_expr.begin());
744                   LocateError(errMsg,tmp,0);
745                   throw INTERP_KERNEL::Exception(errMsg.str().c_str());
746                 }
747             }
748         break;
749         case '(':
750           curLevel++;
751           curPart+=*iter;
752           break;
753         case ')':
754           curLevel--;
755           curPart+=*iter;
756           break;
757         default:
758           curPart+=*iter;
759         }
760     }
761   if(isParsingSucceed)
762     {
763       if(!curPart.empty())
764         {
765           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
766           _is_parsing_ok=true;
767         }
768       else
769         {
770           std::ostringstream errMsg;
771           char MSGTYP5[]="Error following expression finished by *// without right part.";
772           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP5 << _expr;
773           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
774         }
775     }
776 }
777
778 void ExprParser::parseForPow()
779 {
780   std::string::const_iterator iter;
781   int curLevel=0;
782   std::string curPart;
783   bool isParsingSucceed=false;
784   for(iter=_expr.begin();iter!=_expr.end();iter++)
785     {
786       switch(*iter)
787         {
788         case '^':
789           if(curLevel!=0)
790             curPart+=*iter;
791           else
792             if(!curPart.empty())
793               {
794                 isParsingSucceed=true;
795                 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
796                 curPart.clear();
797                 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
798               }
799             else
800               {
801                 std::ostringstream errMsg;
802                 char MSGTYP1[]="Error non unary function for '";
803                 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
804                 std::string tmp=_expr.substr(iter-_expr.begin());
805                 LocateError(errMsg,tmp,0);curPart+=*iter;
806                 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
807               }
808           break;
809         case '(':
810           curLevel++;
811           curPart+=*iter;
812           break;
813         case ')':
814           curLevel--;
815           curPart+=*iter;
816           break;
817         default:
818           curPart+=*iter;
819         }
820     }
821   if(isParsingSucceed)
822     {
823       if(!curPart.empty())
824         {
825           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
826           _is_parsing_ok=true;
827         }
828       else
829         {
830           std::ostringstream errMsg;
831           char MSGTYP6[]="Error following expression finished by ^ without right part.";
832           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP6 << _expr;
833           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
834         }
835     }
836 }
837
838 void ExprParser::releaseFunctions()
839 {
840   for(std::vector<Function *>::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++)
841     delete *iter;
842   _func_btw_sub_expr.clear();
843 }
844
845 /*!
846  * This method parse this->_expr at the current level.
847  * This method first try to see if this->_expr is a leaf, if not it try a unary function of something (see INTERP_KERNEL::ExprParser::parseUnaryFunc method)
848  * If true is returned, no deeper parsing needed, if false is returned for a full parsing of this->_expr INTERP_KERNEL::ExprParser::parseDeeper call needed.
849  */
850 bool ExprParser::simplify()
851 {
852   if(tryToInterpALeaf())
853     return true;
854   parseUnaryFunc();
855   if(!_is_parsing_ok)
856     {
857       parseForCmp();
858       if(!_is_parsing_ok)
859         {
860           parseForAddMin();
861           if(!_is_parsing_ok)
862             {
863               parseForMulDiv();
864               if(!_is_parsing_ok)
865                 parseForPow();
866             }
867         }
868     }
869   if(!_is_parsing_ok)
870     {
871       std::ostringstream errMsg;
872       char MSGTYP3[]="Error in interpreting : ";
873       errMsg << EXPR_PARSE_ERR_MSG << MSGTYP3 << _expr;
874       LocateError(errMsg,_expr,0);
875       throw INTERP_KERNEL::Exception(errMsg.str().c_str());
876     }
877   return false;
878 }
879
880 void ExprParser::checkBracketsParity() const
881 {
882   std::string::const_iterator iter;
883   int curLevel=0;
884   for(iter=_expr.begin();iter!=_expr.end();iter++)
885     {
886       if(*iter=='(')
887         curLevel++;
888       else if(*iter==')')
889         {
890           if(curLevel==0)
891             {
892               std::ostringstream errMsg;
893               char MSGTYP1[]="Error in brackets : closing brackets ')' before openning '('";
894               errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1;
895               LocateError(errMsg,_expr,(int)std::distance(_expr.begin(),iter));
896               throw INTERP_KERNEL::Exception(errMsg.str().c_str());
897             }
898           curLevel--;
899         }
900     }
901   if(curLevel!=0)
902     {
903       std::ostringstream errMsg;
904       char MSGTYP2[]="Error in brackets : not finally closed expr.";
905       errMsg << EXPR_PARSE_ERR_MSG << MSGTYP2;
906       throw INTERP_KERNEL::Exception(errMsg.str().c_str());
907     }
908 }
909
910 /*!
911  * This method substitutes part in [bg,end) in expr by the content of (str(id)) and returns the double value representation in expr[bg,end).
912  * If double representation is invalid an exception is thrown.
913  * This method returns a delta that is the delta to operate to pos in expr after substitution.
914  */
915 double ExprParser::ReplaceAndTraduce(std::string& expr, int id, std::size_t bg, std::size_t end, int& delta)
916 {
917   static const char MSG[]="Interal error : A string expected to be a float is not one ! Bug to signal !";
918   std::istringstream stream;
919   std::ostringstream oss;
920   std::size_t end2=end!=std::string::npos?end-bg:end;
921   std::string tmp=expr.substr(bg,end2);
922   stream.str(tmp);
923   double ret=std::numeric_limits<double>::max();
924   stream >> ret;
925   if(stream.fail())
926     throw INTERP_KERNEL::Exception(MSG);
927   if(!stream.eof())
928     throw INTERP_KERNEL::Exception(MSG);
929   oss << id;
930   std::string tmp2(oss.str());
931   std::size_t l1=tmp.length();
932   delta=(int)tmp2.length()-(int)l1;
933   expr.replace(bg,l1,tmp2);
934   return ret;
935 }
936
937 /*!
938  * This method makes the assumption that _expr has no white space.
939  * This method scans _expr finding in greedy mode the following pattern :
940  * {0..9}+{.}?{0..9}*{{eE}{-}?{0..9}+}?
941  */
942 void ExprParser::fillValuesInExpr(std::vector<double>& valuesInExpr)
943 {
944   const char FIGURES[]="0123456789";
945   const std::string other("+-*^/(<>,");
946   std::size_t lgth=_expr.length();
947   int id=0,delta;
948   for(std::size_t pos=0;pos!=std::string::npos;id++)
949     {
950       std::size_t pos2=_expr.find_first_of(FIGURES,pos,10);
951       if(pos2==std::string::npos)
952         break;
953       if(pos2>0)
954         {//treat case of "x*log10(x)" -> "10" should NOT be intercepted by this
955           if(other.find_first_of(_expr[pos2-1])==std::string::npos)
956             {
957               pos=_expr.find_first_not_of(FIGURES,pos2,10);
958               id--;
959               continue;
960             }
961           if(_expr[pos2-1]==')')
962             {
963               pos=_expr.find_first_not_of(FIGURES,pos2,10);
964               std::ostringstream oss; oss << "Problem on parsing : Number \"" << _expr.substr(pos2,pos!=std::string::npos?pos2-pos:std::string::npos);
965               oss << "\" is right after close parenthesis... ')'";
966               throw INTERP_KERNEL::Exception(oss.str().c_str());
967             }
968         }
969       std::size_t pos3=_expr.find_first_not_of(FIGURES,pos2,10);
970       if(pos3==std::string::npos)
971         {//"x+1223442320"
972           valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
973           break;
974         }
975       if(_expr[pos3]=='.')
976         pos3++;
977       if(pos3<lgth)
978         {
979           std::size_t pos4=_expr.find_first_not_of(FIGURES,pos3,10);
980           if(pos4==std::string::npos)
981             {//"x+1223334.223"
982               valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
983               break;
984             }
985           else
986             {
987               if(_expr[pos4]!='e' && _expr[pos4]!='E')
988                 {//"x+1223334.223+x"
989                   valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos4,delta));
990                   pos=pos4+delta;
991                   continue;
992                 }
993               else
994                 {
995                   if(++pos4<lgth)
996                     {
997                       if(_expr[pos4]=='+' || _expr[pos4]=='-')
998                         pos4++;
999                       if(pos4>=lgth)
1000                         {//"x+1223334.223e+" or "1223334.223E-"
1001                           std::ostringstream oss; oss << "Invalid expr : float number at the end of expr is invalid lacking number after exponential and sign ! -> \"" << _expr.substr(pos2) << "\"";
1002                           throw INTERP_KERNEL::Exception(oss.str().c_str());
1003                         }
1004                       std::size_t pos5=_expr.find_first_not_of(FIGURES,pos4,10);
1005                       if(pos4==pos5)
1006                         {//"x+1223334.223e+x" or "1223334.223E-y"
1007                           std::ostringstream oss; oss << "Invalid expr : float number in expr is invalid lacking number after exponential ! -> \"" << _expr.substr(pos2,pos4-pos2) << "\"";
1008                           throw INTERP_KERNEL::Exception(oss.str().c_str());
1009                         }
1010                       //OK, normal case
1011                       valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos5,delta));
1012                       pos=pos5+delta;
1013                       continue;
1014                     }
1015                   else//"x+1223334.223e"
1016                     {
1017                       std::ostringstream oss; oss << "Invalid expr : float number at the end of expr is invalid lacking number after exponential ! " << _expr.substr(pos2);
1018                       throw INTERP_KERNEL::Exception(oss.str().c_str());
1019                     }
1020                 }
1021             }
1022         }
1023       else
1024         {//"x+1223334."
1025           valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
1026           break;
1027         }
1028     }
1029 }
1030
1031 void ExprParser::replaceValues(const std::vector<double>& valuesInExpr)
1032 {
1033   if(_leaf)
1034     _leaf->replaceValues(valuesInExpr);
1035   else
1036     {
1037       for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1038         (*iter).replaceValues(valuesInExpr);
1039     }
1040 }
1041
1042 void ExprParser::LocateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr)
1043 {
1044   stringToDisp << "Position is " << posOfErr << " of string : \"" <<  srcOfErr << "\"" << std::endl;
1045 }
1046
1047 char *ExprParser::compileX86() const
1048 {
1049   std::vector<std::string> ass;
1050   //need in stack
1051   ass.push_back("push ebp");
1052   ass.push_back("mov ebp,esp");
1053   compileX86LowLev(ass);
1054   ass.push_back("pop ebp");
1055   ass.push_back("ret");
1056   std::cout << std::endl;
1057   for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
1058     std::cout << "        " << *iter << std::endl;
1059   AsmX86 asmb;
1060   std::vector<char> output=asmb.convertIntoMachineLangage(ass);
1061   for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
1062     std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
1063   std::cout << std::endl;
1064   unsigned offset;
1065   return asmb.copyToExecMemZone(output,offset);
1066 }
1067
1068 char *ExprParser::compileX86_64() const
1069 {
1070   std::vector<std::string> ass;
1071   //need in stack
1072   ass.push_back("push rbp");
1073   ass.push_back("mov rbp,rsp");
1074   compileX86_64LowLev(ass);
1075   ass.push_back("sub rsp,8");
1076   ass.push_back("fst qword [rsp]");
1077   ass.push_back("movsd xmm0,[rsp]");
1078   ass.push_back("add rsp,8");
1079   ass.push_back("leave");
1080   ass.push_back("ret");
1081   std::cout << std::endl;
1082   for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
1083     std::cout << "        " << *iter << std::endl;
1084   AsmX86 asmb;
1085   std::vector<char> output=asmb.convertIntoMachineLangage(ass);
1086   for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
1087     std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
1088   std::cout << std::endl;
1089   unsigned offset;
1090   return asmb.copyToExecMemZone(output,offset);
1091 }
1092
1093 void ExprParser::compileX86LowLev(std::vector<std::string>& ass) const
1094 {
1095   if(_leaf)
1096     _leaf->compileX86(ass);
1097   else
1098     {
1099       for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1100         (*iter).compileX86LowLev(ass);
1101     }
1102   for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1103     (*iter2)->operateX86(ass);
1104 }
1105
1106 void ExprParser::compileX86_64LowLev(std::vector<std::string>& ass) const
1107 {
1108   if(_leaf)
1109     _leaf->compileX86_64(ass);
1110   else
1111     {
1112       for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1113         (*iter).compileX86_64LowLev(ass);
1114     }
1115   for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1116     (*iter2)->operateX86(ass);
1117 }
1118
1119 double LeafExprVal::getDoubleValue() const
1120 {
1121   return _value;
1122 }
1123
1124 void LeafExprVal::compileX86(std::vector<std::string>& ass) const
1125 {
1126   ass.push_back("sub esp,8");
1127   const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1128   c++;
1129   std::ostringstream oss;
1130   oss << std::hex;
1131   oss << "mov dword [esp+4],0x" << *c;
1132   ass.push_back(oss.str());
1133   oss.str("");
1134   oss << "mov dword [esp],0x" << *b;
1135   ass.push_back(oss.str());
1136   ass.push_back("fld qword [esp]");
1137   ass.push_back("add esp,8");
1138 }
1139
1140 void LeafExprVal::compileX86_64(std::vector<std::string>& ass) const
1141 {
1142   ass.push_back("sub rsp,8");
1143   const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1144   c++;
1145   std::ostringstream oss;
1146   oss << std::hex;
1147   oss << "mov dword [rsp+4],0x" << *c;
1148   ass.push_back(oss.str());
1149   oss.str("");
1150   oss << "mov dword [rsp],0x" << *b;
1151   ass.push_back(oss.str());
1152   ass.push_back("fld qword [rsp]");
1153   ass.push_back("add rsp,8");
1154 }
1155
1156 double LeafExprVar::getDoubleValue() const
1157 {
1158   if(_fast_pos>=0)
1159     return _val[_fast_pos];
1160   else
1161     {
1162       int pos(-7-_fast_pos);
1163       return pos==_ref_pos?1.:0.;
1164     }
1165 }
1166
1167 void LeafExprVar::compileX86(std::vector<std::string>& ass) const
1168 {
1169   ass.push_back("fld qword [ebp+8]");
1170 }
1171
1172 void LeafExprVar::compileX86_64(std::vector<std::string>& ass) const
1173 {
1174   ass.push_back("sub rsp,8");
1175   ass.push_back("movsd [rsp],xmm0");
1176   ass.push_back("fld qword [rsp]");
1177   ass.push_back("add rsp,8");
1178 }
1179
1180 int ExprParser::getStackSizeToPlayX86(const ExprParser *asker) const
1181 {
1182   if(asker)
1183     {
1184       int sz=_father->getStackSizeToPlayX86(this);
1185       int i=0;
1186       for(std::vector<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
1187         {
1188           const ExprParser& obj=(*iter);
1189           const ExprParser *pt=&obj;
1190           if(pt==asker)
1191             return sz-i;
1192         }
1193       throw INTERP_KERNEL::Exception("error getStackSizeToPlayX86 an object ExprParser called as father, whereas it is not one !");
1194     }
1195   else
1196     {
1197       if(!_father)
1198         return MAX_X86_FP_ST;
1199       return _father->getStackSizeToPlayX86(this);
1200     }
1201 }