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