]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/INTERP_KERNEL/ExprEval/InterpKernelExprParser.cxx
Salome HOME
Copyright update 2021
[tools/medcoupling.git] / src / INTERP_KERNEL / ExprEval / InterpKernelExprParser.cxx
1 // Copyright (C) 2007-2021  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! Send a mail to Salome support with expression.");
85   _value=valuesInExpr[pos];
86 }
87
88 LeafExprVal *LeafExprVal::deepCopy() 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::deepCopy() 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->deepCopy();
205   for(std::vector<Function *>::iterator it=_funcs.begin();it!=_funcs.end();it++)
206     if(*it)
207       *it=(*it)->deepCopy();
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 ExprParser::ExprParser(ExprParser&& other):_father(other._father),_leaf(other._leaf),_is_parsing_ok(std::move(other._is_parsing_ok)),_expr(std::move(other._expr)),_sub_expr(std::move(other._sub_expr)),_func_btw_sub_expr(std::move(other._func_btw_sub_expr))
463 {
464   other._leaf=0;
465 }
466
467 ExprParser& ExprParser::operator=(ExprParser&& other)
468 {
469   _father=other._father;
470   _is_parsing_ok=std::move(other._is_parsing_ok);
471   _leaf=other._leaf;
472   _expr=std::move(other._expr);
473   _sub_expr=std::move(other._sub_expr);
474   _func_btw_sub_expr=std::move(other._func_btw_sub_expr);
475   other._leaf=other._leaf;
476   other._leaf=0;
477   return *this;
478 }
479
480 void ExprParser::reverseThis()
481 {
482   if(_leaf)
483     return ;
484   for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
485     (*iter).reverseThis();
486   std::size_t sz(_sub_expr.size());
487   std::size_t nbOfTurn(sz/2);
488   for(std::size_t i=0;i<nbOfTurn;i++)
489     std::swap(_sub_expr[i],_sub_expr[sz-i-1]);
490 }
491
492 ExprParserOfEval ExprParser::convertMeTo() const
493 {
494   std::size_t sz(_sub_expr.size());
495   std::vector<ExprParserOfEval> subExpr(sz);
496   for(std::size_t i=0;i<sz;i++)
497     subExpr[i]=_sub_expr[i].convertMeTo();
498   return ExprParserOfEval(_leaf,subExpr,_func_btw_sub_expr);
499 }
500
501 void ExprParser::getSetOfVars(std::set<std::string>& vars) const
502 {
503   if(_leaf)
504     {
505       LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
506       if(leafC)
507         vars.insert(leafC->getVar());
508     }
509   else
510     for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
511       (*iter).getSetOfVars(vars);
512 }
513
514 void ExprParser::getTrueSetOfVars(std::set<std::string>& trueVars) const
515 {
516   std::set<std::string> vars;
517   getSetOfVars(vars);
518   trueVars.clear();
519   for(std::set<std::string>::const_iterator iter=vars.begin();iter!=vars.end();iter++)
520     {
521       int tmp;
522       if(!LeafExprVar::isRecognizedKeyVar(*iter,tmp))
523         trueVars.insert(*iter);
524     }
525 }
526
527 void ExprParser::parseDeeper()
528 {
529   for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
530     if(!(*iter).simplify())
531       (*iter).parseDeeper();
532 }
533
534 /*!
535  * This method has the responsibility to see if this->_expr can be seen as a unary function of something.
536  * Something defined as the contain of highest level barckets.
537  * Typically '(3*x+2)' and 'cos(4*l+p*n)' will be intercepted by this method whereas '3*x+2' not...etc..
538  */
539 void ExprParser::parseUnaryFunc()
540 {
541   if(_expr[_expr.length()-1]!=')')
542     return ;
543   //at this level of code _expr
544   std::size_t pos1=_expr.find_first_of('(');
545   std::size_t pos4=FindCorrespondingOpenBracket(_expr,_expr.length()-1);
546   if(pos4!=pos1)
547     return ;
548   std::string funcName=_expr.substr(0,pos1);
549   std::size_t pos2=funcName.find_first_of("+-*/^><",0,7);
550   std::size_t pos3=funcName.find_first_not_of("+-*/^><",0,7);
551   if(pos2!=std::string::npos && pos3!=std::string::npos)
552     return ;//Bracket group is not alone, can't conclude not recursively.
553   std::string newExp2=_expr.substr(pos1+1,_expr.length()-pos1-2);
554   std::size_t nbOfParamsInFunc=std::count(newExp2.begin(),newExp2.end(),',')+1;
555   if(pos3!=std::string::npos)
556     _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(funcName.c_str(),(int)nbOfParamsInFunc));
557   else
558     {
559       std::size_t lgth=funcName.length();
560       char tmp[2]; tmp[1]='\0';
561       for(std::size_t i=0;i<lgth;i++)
562         {
563           tmp[0]=funcName[i];
564           _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(tmp,(int)nbOfParamsInFunc));
565         }
566     }
567   std::size_t pos6=0;
568   for(std::size_t i=0;i<nbOfParamsInFunc;i++)
569     {
570       std::size_t pos5=newExp2.find_first_of(',',pos6);
571       std::size_t len=std::string::npos;
572       if(pos5!=std::string::npos)
573         len=pos5-pos6;
574       std::string newExp3=newExp2.substr(pos6,len);
575       _sub_expr.push_back(ExprParser(newExp3.c_str(),this));
576       pos6=pos5+1;
577     }
578   _is_parsing_ok=true;
579 }
580
581 /*!
582  *  This method has the responsibility to see if this->_expr is interpretable without any recursion.
583  * \return true if no recursion needed, false if this->_expr is too complex to be interpreted at this level.
584  * \throw exception if this->_expr is simple enough to try to interpret this and this expression contains an error.
585  */
586 bool ExprParser::tryToInterpALeaf()
587 {
588   std::size_t pos=_expr.find_first_not_of("+-",0,2);
589   std::string minimizedExpr=_expr.substr(pos);
590   std::size_t pos2=minimizedExpr.find_first_of("+-*/^()<>",0,9);
591   if(pos2!=std::string::npos)
592     return false;
593   delete _leaf;
594   _leaf=LeafExpr::buildInstanceFrom(minimizedExpr);
595   int nbOfNegs=0;
596   for(std::size_t i=0;i<pos;i++)
597     if(_expr[i]=='-')
598       nbOfNegs++;
599   if(nbOfNegs%2)
600     _func_btw_sub_expr.push_back(FunctionsFactory::buildUnaryFuncFromString("-"));
601   _is_parsing_ok=true;
602   return true;
603 }
604
605 void ExprParser::parseForCmp()
606 {
607   std::string::const_iterator iter;
608   int curLevel=0;
609   std::string curPart;
610   bool isParsingSucceed=false;
611   for(iter=_expr.begin();iter!=_expr.end();iter++)
612     {
613       switch(*iter)
614         {
615         case '>':
616         case '<':
617           {
618             isParsingSucceed=true;
619             if(!curPart.empty())
620               {
621                 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
622                 curPart.clear();
623                 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
624               }
625             else
626               {
627                 std::ostringstream errMsg;
628                 char MSGTYP1[]="Error non unary function for '";
629                 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
630                 std::string tmp=_expr.substr(iter-_expr.begin());
631                 LocateError(errMsg,tmp,0);
632                 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
633               }
634             break;
635           }
636         case '(':
637           curLevel++;
638           curPart+=*iter;
639           break;
640         case ')':
641           curLevel--;
642           curPart+=*iter;
643           break;
644         default:
645           curPart+=*iter;
646         }
647     }
648   if(isParsingSucceed)
649     {
650       if(!curPart.empty())
651         {
652           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
653           _is_parsing_ok=true;
654         }
655       else
656         {
657           std::ostringstream errMsg;
658           char MSGTYP4[]="Error following expression finished by > / < without right part.";
659           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
660           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
661         }
662     }
663 }
664
665 void ExprParser::parseForAddMin()
666 {
667   std::string::const_iterator iter;
668   int curLevel=0;
669   std::string curPart;
670   bool isParsingSucceed=false;
671   for(iter=_expr.begin();iter!=_expr.end();iter++)
672     {
673       switch(*iter)
674         {
675         case '+':
676         case '-':
677           if(curLevel!=0)
678             curPart+=*iter;
679           else
680             {
681               if(!curPart.empty())
682                 {
683                   std::string::reverse_iterator accessor=curPart.rbegin();
684                   if(*accessor!='*' && *accessor!='/' && *accessor!='^')
685                     {
686                       isParsingSucceed=true;
687                       _sub_expr.push_back(ExprParser(curPart.c_str(),this));
688                       curPart.clear();
689                       _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
690                     }
691                   else
692                     curPart+=*iter;
693                 }
694               else
695                 curPart+=*iter;
696             }
697         break;
698         case '(':
699           curLevel++;
700           curPart+=*iter;
701           break;
702         case ')':
703           curLevel--;
704           curPart+=*iter;
705           break;
706         default:
707           curPart+=*iter;
708         }
709     }
710   if(isParsingSucceed)
711     {
712       if(!curPart.empty())
713         {
714           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
715           _is_parsing_ok=true;
716         }
717       else
718         {
719           std::ostringstream errMsg;
720           char MSGTYP4[]="Error following expression finished by +/- without right part.";
721           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
722           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
723         }
724     }
725 }
726
727 void ExprParser::parseForMulDiv()
728 {
729   std::string::const_iterator iter;
730   int curLevel=0;
731   std::string curPart;
732   bool isParsingSucceed=false;
733   for(iter=_expr.begin();iter!=_expr.end();iter++)
734     {
735       switch(*iter)
736         {
737         case '/':
738         case '*':
739           if(curLevel!=0)
740             curPart+=*iter;
741           else
742             {
743               isParsingSucceed=true;
744               if(!curPart.empty())
745                 {
746                   _sub_expr.push_back(ExprParser(curPart.c_str(),this));
747                   curPart.clear();
748                   _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
749                 }
750               else
751                 {
752                   std::ostringstream errMsg;
753                   char MSGTYP1[]="Error non unary function for '";
754                   errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
755                   std::string tmp=_expr.substr(iter-_expr.begin());
756                   LocateError(errMsg,tmp,0);
757                   throw INTERP_KERNEL::Exception(errMsg.str().c_str());
758                 }
759             }
760         break;
761         case '(':
762           curLevel++;
763           curPart+=*iter;
764           break;
765         case ')':
766           curLevel--;
767           curPart+=*iter;
768           break;
769         default:
770           curPart+=*iter;
771         }
772     }
773   if(isParsingSucceed)
774     {
775       if(!curPart.empty())
776         {
777           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
778           _is_parsing_ok=true;
779         }
780       else
781         {
782           std::ostringstream errMsg;
783           char MSGTYP5[]="Error following expression finished by *// without right part.";
784           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP5 << _expr;
785           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
786         }
787     }
788 }
789
790 void ExprParser::parseForPow()
791 {
792   std::string::const_iterator iter;
793   int curLevel=0;
794   std::string curPart;
795   bool isParsingSucceed=false;
796   for(iter=_expr.begin();iter!=_expr.end();iter++)
797     {
798       switch(*iter)
799         {
800         case '^':
801           if(curLevel!=0)
802             curPart+=*iter;
803           else
804             if(!curPart.empty())
805               {
806                 isParsingSucceed=true;
807                 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
808                 curPart.clear();
809                 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
810               }
811             else
812               {
813                 std::ostringstream errMsg;
814                 char MSGTYP1[]="Error non unary function for '";
815                 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
816                 std::string tmp=_expr.substr(iter-_expr.begin());
817                 LocateError(errMsg,tmp,0);curPart+=*iter;
818                 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
819               }
820           break;
821         case '(':
822           curLevel++;
823           curPart+=*iter;
824           break;
825         case ')':
826           curLevel--;
827           curPart+=*iter;
828           break;
829         default:
830           curPart+=*iter;
831         }
832     }
833   if(isParsingSucceed)
834     {
835       if(!curPart.empty())
836         {
837           _sub_expr.push_back(ExprParser(curPart.c_str(),this));
838           _is_parsing_ok=true;
839         }
840       else
841         {
842           std::ostringstream errMsg;
843           char MSGTYP6[]="Error following expression finished by ^ without right part.";
844           errMsg << EXPR_PARSE_ERR_MSG << MSGTYP6 << _expr;
845           throw INTERP_KERNEL::Exception(errMsg.str().c_str());
846         }
847     }
848 }
849
850 void ExprParser::releaseFunctions()
851 {
852   for(std::vector<Function *>::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++)
853     delete *iter;
854   _func_btw_sub_expr.clear();
855 }
856
857 /*!
858  * This method parse this->_expr at the current level.
859  * 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)
860  * 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.
861  */
862 bool ExprParser::simplify()
863 {
864   if(tryToInterpALeaf())
865     return true;
866   parseUnaryFunc();
867   if(!_is_parsing_ok)
868     {
869       parseForCmp();
870       if(!_is_parsing_ok)
871         {
872           parseForAddMin();
873           if(!_is_parsing_ok)
874             {
875               parseForMulDiv();
876               if(!_is_parsing_ok)
877                 parseForPow();
878             }
879         }
880     }
881   if(!_is_parsing_ok)
882     {
883       std::ostringstream errMsg;
884       char MSGTYP3[]="Error in interpreting : ";
885       errMsg << EXPR_PARSE_ERR_MSG << MSGTYP3 << _expr;
886       LocateError(errMsg,_expr,0);
887       throw INTERP_KERNEL::Exception(errMsg.str().c_str());
888     }
889   return false;
890 }
891
892 void ExprParser::checkBracketsParity() const
893 {
894   std::string::const_iterator iter;
895   int curLevel=0;
896   for(iter=_expr.begin();iter!=_expr.end();iter++)
897     {
898       if(*iter=='(')
899         curLevel++;
900       else if(*iter==')')
901         {
902           if(curLevel==0)
903             {
904               std::ostringstream errMsg;
905               char MSGTYP1[]="Error in brackets : closing brackets ')' before opening '('";
906               errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1;
907               LocateError(errMsg,_expr,(int)std::distance(_expr.begin(),iter));
908               throw INTERP_KERNEL::Exception(errMsg.str().c_str());
909             }
910           curLevel--;
911         }
912     }
913   if(curLevel!=0)
914     {
915       std::ostringstream errMsg;
916       char MSGTYP2[]="Error in brackets : not finally closed expr.";
917       errMsg << EXPR_PARSE_ERR_MSG << MSGTYP2;
918       throw INTERP_KERNEL::Exception(errMsg.str().c_str());
919     }
920 }
921
922 /*!
923  * 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).
924  * If double representation is invalid an exception is thrown.
925  * This method returns a delta that is the delta to operate to pos in expr after substitution.
926  */
927 double ExprParser::ReplaceAndTraduce(std::string& expr, int id, std::size_t bg, std::size_t end, int& delta)
928 {
929   static const char MSG[]="Internal error : A string expected to be a float is not one ! Bug to signal !";
930   std::istringstream stream;
931   std::ostringstream oss;
932   std::size_t end2=end!=std::string::npos?end-bg:end;
933   std::string tmp=expr.substr(bg,end2);
934   stream.str(tmp);
935   double ret=std::numeric_limits<double>::max();
936   stream >> ret;
937   if(stream.fail())
938     throw INTERP_KERNEL::Exception(MSG);
939   if(!stream.eof())
940     throw INTERP_KERNEL::Exception(MSG);
941   oss << id;
942   std::string tmp2(oss.str());
943   std::size_t l1=tmp.length();
944   delta=(int)tmp2.length()-(int)l1;
945   expr.replace(bg,l1,tmp2);
946   return ret;
947 }
948
949 /*!
950  * This method makes the assumption that _expr has no white space.
951  * This method scans _expr finding in greedy mode the following pattern :
952  * {0..9}+{.}?{0..9}*{{eE}{-}?{0..9}+}?
953  */
954 void ExprParser::fillValuesInExpr(std::vector<double>& valuesInExpr)
955 {
956   const char FIGURES[]="0123456789";
957   const std::string other("+-*^/(<>,");
958   std::size_t lgth=_expr.length();
959   int id=0,delta;
960   for(std::size_t pos=0;pos!=std::string::npos;id++)
961     {
962       std::size_t pos2=_expr.find_first_of(FIGURES,pos,10);
963       if(pos2==std::string::npos)
964         break;
965       if(pos2>0)
966         {//treat case of "x*log10(x)" -> "10" should NOT be intercepted by this
967           if(other.find_first_of(_expr[pos2-1])==std::string::npos)
968             {
969               pos=_expr.find_first_not_of(FIGURES,pos2,10);
970               id--;
971               continue;
972             }
973           if(_expr[pos2-1]==')')
974             {
975               pos=_expr.find_first_not_of(FIGURES,pos2,10);
976               std::ostringstream oss; oss << "Problem on parsing : Number \"" << _expr.substr(pos2,pos!=std::string::npos?pos2-pos:std::string::npos);
977               oss << "\" is right after close parenthesis... ')'";
978               throw INTERP_KERNEL::Exception(oss.str().c_str());
979             }
980         }
981       std::size_t pos3=_expr.find_first_not_of(FIGURES,pos2,10);
982       if(pos3==std::string::npos)
983         {//"x+1223442320"
984           valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
985           break;
986         }
987       if(_expr[pos3]=='.')
988         pos3++;
989       if(pos3<lgth)
990         {
991           std::size_t pos4=_expr.find_first_not_of(FIGURES,pos3,10);
992           if(pos4==std::string::npos)
993             {//"x+1223334.223"
994               valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
995               break;
996             }
997           else
998             {
999               if(_expr[pos4]!='e' && _expr[pos4]!='E')
1000                 {//"x+1223334.223+x"
1001                   valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos4,delta));
1002                   pos=pos4+delta;
1003                   continue;
1004                 }
1005               else
1006                 {
1007                   if(++pos4<lgth)
1008                     {
1009                       if(_expr[pos4]=='+' || _expr[pos4]=='-')
1010                         pos4++;
1011                       if(pos4>=lgth)
1012                         {//"x+1223334.223e+" or "1223334.223E-"
1013                           std::ostringstream oss; oss << "Invalid expr : float number at the end of expr is invalid lacking number after exponential and sign ! -> \"" << _expr.substr(pos2) << "\"";
1014                           throw INTERP_KERNEL::Exception(oss.str().c_str());
1015                         }
1016                       std::size_t pos5=_expr.find_first_not_of(FIGURES,pos4,10);
1017                       if(pos4==pos5)
1018                         {//"x+1223334.223e+x" or "1223334.223E-y"
1019                           std::ostringstream oss; oss << "Invalid expr : float number in expr is invalid lacking number after exponential ! -> \"" << _expr.substr(pos2,pos4-pos2) << "\"";
1020                           throw INTERP_KERNEL::Exception(oss.str().c_str());
1021                         }
1022                       //OK, normal case
1023                       valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos5,delta));
1024                       pos=pos5+delta;
1025                       continue;
1026                     }
1027                   else//"x+1223334.223e"
1028                     {
1029                       std::ostringstream oss; oss << "Invalid expr : float number at the end of expr is invalid lacking number after exponential ! " << _expr.substr(pos2);
1030                       throw INTERP_KERNEL::Exception(oss.str().c_str());
1031                     }
1032                 }
1033             }
1034         }
1035       else
1036         {//"x+1223334."
1037           valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
1038           break;
1039         }
1040     }
1041 }
1042
1043 void ExprParser::replaceValues(const std::vector<double>& valuesInExpr)
1044 {
1045   if(_leaf)
1046     _leaf->replaceValues(valuesInExpr);
1047   else
1048     {
1049       for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1050         (*iter).replaceValues(valuesInExpr);
1051     }
1052 }
1053
1054 void ExprParser::LocateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr)
1055 {
1056   stringToDisp << "Position is " << posOfErr << " of string : \"" <<  srcOfErr << "\"" << std::endl;
1057 }
1058
1059 char *ExprParser::compileX86() const
1060 {
1061   std::vector<std::string> ass;
1062   //need in stack
1063   ass.push_back("push ebp");
1064   ass.push_back("mov ebp,esp");
1065   compileX86LowLev(ass);
1066   ass.push_back("pop ebp");
1067   ass.push_back("ret");
1068   std::cout << std::endl;
1069   for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
1070     std::cout << "        " << *iter << std::endl;
1071   AsmX86 asmb;
1072   std::vector<char> output=asmb.convertIntoMachineLangage(ass);
1073   for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
1074     std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
1075   std::cout << std::endl;
1076   unsigned offset;
1077   return asmb.copyToExecMemZone(output,offset);
1078 }
1079
1080 char *ExprParser::compileX86_64() const
1081 {
1082   std::vector<std::string> ass;
1083   //need in stack
1084   ass.push_back("push rbp");
1085   ass.push_back("mov rbp,rsp");
1086   compileX86_64LowLev(ass);
1087   ass.push_back("sub rsp,8");
1088   ass.push_back("fst qword [rsp]");
1089   ass.push_back("movsd xmm0,[rsp]");
1090   ass.push_back("add rsp,8");
1091   ass.push_back("leave");
1092   ass.push_back("ret");
1093   std::cout << std::endl;
1094   for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
1095     std::cout << "        " << *iter << std::endl;
1096   AsmX86 asmb;
1097   std::vector<char> output=asmb.convertIntoMachineLangage(ass);
1098   for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
1099     std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
1100   std::cout << std::endl;
1101   unsigned offset;
1102   return asmb.copyToExecMemZone(output,offset);
1103 }
1104
1105 void ExprParser::compileX86LowLev(std::vector<std::string>& ass) const
1106 {
1107   if(_leaf)
1108     _leaf->compileX86(ass);
1109   else
1110     {
1111       for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1112         (*iter).compileX86LowLev(ass);
1113     }
1114   for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1115     (*iter2)->operateX86(ass);
1116 }
1117
1118 void ExprParser::compileX86_64LowLev(std::vector<std::string>& ass) const
1119 {
1120   if(_leaf)
1121     _leaf->compileX86_64(ass);
1122   else
1123     {
1124       for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1125         (*iter).compileX86_64LowLev(ass);
1126     }
1127   for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1128     (*iter2)->operateX86(ass);
1129 }
1130
1131 double LeafExprVal::getDoubleValue() const
1132 {
1133   return _value;
1134 }
1135
1136 void LeafExprVal::compileX86(std::vector<std::string>& ass) const
1137 {
1138   ass.push_back("sub esp,8");
1139   const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1140   c++;
1141   std::ostringstream oss;
1142   oss << std::hex;
1143   oss << "mov dword [esp+4],0x" << *c;
1144   ass.push_back(oss.str());
1145   oss.str("");
1146   oss << "mov dword [esp],0x" << *b;
1147   ass.push_back(oss.str());
1148   ass.push_back("fld qword [esp]");
1149   ass.push_back("add esp,8");
1150 }
1151
1152 void LeafExprVal::compileX86_64(std::vector<std::string>& ass) const
1153 {
1154   ass.push_back("sub rsp,8");
1155   const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1156   c++;
1157   std::ostringstream oss;
1158   oss << std::hex;
1159   oss << "mov dword [rsp+4],0x" << *c;
1160   ass.push_back(oss.str());
1161   oss.str("");
1162   oss << "mov dword [rsp],0x" << *b;
1163   ass.push_back(oss.str());
1164   ass.push_back("fld qword [rsp]");
1165   ass.push_back("add rsp,8");
1166 }
1167
1168 double LeafExprVar::getDoubleValue() const
1169 {
1170   if(_fast_pos>=0)
1171     return _val[_fast_pos];
1172   else
1173     {
1174       int pos(-7-_fast_pos);
1175       return pos==_ref_pos?1.:0.;
1176     }
1177 }
1178
1179 void LeafExprVar::compileX86(std::vector<std::string>& ass) const
1180 {
1181   ass.push_back("fld qword [ebp+8]");
1182 }
1183
1184 void LeafExprVar::compileX86_64(std::vector<std::string>& ass) const
1185 {
1186   ass.push_back("sub rsp,8");
1187   ass.push_back("movsd [rsp],xmm0");
1188   ass.push_back("fld qword [rsp]");
1189   ass.push_back("add rsp,8");
1190 }
1191
1192 int ExprParser::getStackSizeToPlayX86(const ExprParser *asker) const
1193 {
1194   if(asker)
1195     {
1196       int sz=_father->getStackSizeToPlayX86(this);
1197       int i=0;
1198       for(std::vector<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
1199         {
1200           const ExprParser& obj=(*iter);
1201           const ExprParser *pt=&obj;
1202           if(pt==asker)
1203             return sz-i;
1204         }
1205       throw INTERP_KERNEL::Exception("error getStackSizeToPlayX86 an object ExprParser called as father, whereas it is not one !");
1206     }
1207   else
1208     {
1209       if(!_father)
1210         return MAX_X86_FP_ST;
1211       return _father->getStackSizeToPlayX86(this);
1212     }
1213 }