1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "InterpKernelExprParser.hxx"
22 #include "InterpKernelValue.hxx"
23 #include "InterpKernelAsmX86.hxx"
24 #include "InterpKernelAutoPtr.hxx"
34 using namespace INTERP_KERNEL;
36 const char LeafExprVar::END_OF_RECOGNIZED_VAR[]="Vec";
38 const char ExprParser::WHITE_SPACES[]=" \n";
40 const char ExprParser::EXPR_PARSE_ERR_MSG[]="Invalid expression detected : ";
42 LeafExpr *LeafExpr::buildInstanceFrom(const std::string& expr)
44 std::istringstream stream;
50 return new LeafExprVal(val);
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());
59 return new LeafExprVar(expr);
66 LeafExprVal::LeafExprVal(double value):_value(value)
70 LeafExprVal::~LeafExprVal()
74 void LeafExprVal::fillValue(Value *val) const
76 val->setDouble(_value);
79 void LeafExprVal::replaceValues(const std::vector<double>& valuesInExpr)
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];
88 LeafExprVal *LeafExprVal::deepCopy() const
90 return new LeafExprVal(*this);
93 LeafExprVar::LeafExprVar(const std::string& var):_fast_pos(-1),_var_name(var),_val(0)
97 void LeafExprVar::fillValue(Value *val) const
100 val->setDouble(_val[_fast_pos]);
102 val->setVarname(_fast_pos,_var_name);
106 void LeafExprVar::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const
108 std::vector<std::string>::const_iterator iter=std::find(vars.begin(),vars.end(),_var_name);
111 if(!isRecognizedKeyVar(_var_name,_fast_pos))
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());
119 int relPos=-7-_fast_pos;
120 if(relPos>=targetNbOfCompo)
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());
130 _fast_pos=(int)std::distance(vars.begin(),iter);
131 if(_fast_pos>=nbOfCompo)
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());
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.
145 void LeafExprVar::prepareExprEvaluationDouble(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo, int refPos, const double *ptOfInputStart, const double *ptOfInputEnd) const
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);
154 void LeafExprVar::prepareExprEvaluationVec() const
156 if(!isRecognizedKeyVar(_var_name,_fast_pos))
160 bool LeafExprVar::isRecognizedKeyVar(const std::string& var, int& pos)
162 if(var.length()!=sizeof(END_OF_RECOGNIZED_VAR))
164 std::string end=var.substr(1);
165 if(end!=END_OF_RECOGNIZED_VAR)
168 if(first<'I' || first>'Z')
174 LeafExprVar *LeafExprVar::deepCopy() const
176 return new LeafExprVar(*this);
180 * Nothing to do it is not a bug.
182 void LeafExprVar::replaceValues(const std::vector<double>& valuesInExpr)
186 LeafExprVar::~LeafExprVar()
190 void ExprParserOfEval::clearSortedMemory()
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++)
199 void ExprParserOfEval::sortMemory()
201 for(std::vector<ExprParserOfEval>::iterator it=_sub_parts.begin();it!=_sub_parts.end();it++)
204 _leaf=_leaf->deepCopy();
205 for(std::vector<Function *>::iterator it=_funcs.begin();it!=_funcs.end();it++)
207 *it=(*it)->deepCopy();
210 ExprParser::ExprParser(const std::string& expr, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr)
212 _expr=deleteWhiteSpaces(_expr);
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)
218 _expr=buildStringFromFortran(expr,lgth);
219 _expr=deleteWhiteSpaces(_expr);
222 ExprParser::~ExprParser()
225 _for_eval.clearSortedMemory();
229 std::size_t ExprParser::FindCorrespondingOpenBracket(const std::string& expr, std::size_t posOfCloseBracket)
232 for(std::size_t iter=0;iter<posOfCloseBracket;iter++)
234 std::size_t iter2=posOfCloseBracket-1-iter;
237 else if(expr[iter2]=='(')
245 return std::string::npos;
248 std::string ExprParser::buildStringFromFortran(const char *expr, int lgth)
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)
256 ret.clear();//ret is all whitespace
260 std::string ExprParser::deleteWhiteSpaces(const std::string& expr)
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)
267 where1=ret.find_first_of(whiteSpaces.c_str(),where1,whiteSpaces.length());
268 if(where1!=std::string::npos)
270 where2=ret.find_first_not_of(whiteSpaces,where1);
271 if(where2!=std::string::npos)
272 ret.erase(ret.begin()+where1,ret.begin()+where2);
274 ret.erase(ret.begin()+where1,ret.end());
280 void ExprParser::parse()
283 _is_parsing_ok=false;
288 std::string tmp(_expr);
289 std::vector<double> valuesInExpr;
290 fillValuesInExpr(valuesInExpr);
291 checkBracketsParity();
294 replaceValues(valuesInExpr);
301 double ExprParser::evaluate() const
303 AutoCppPtr<Value> gen(new ValueDouble);
304 AutoCppPtr<ValueDouble> res(static_cast<ValueDouble *>(evaluateLowLev(gen)));
305 return res->getData();
308 DecompositionInUnitBase ExprParser::evaluateUnit() const
310 Value *gen=new ValueUnit;
314 res=(ValueUnit *)evaluateLowLev(gen);
316 catch(INTERP_KERNEL::Exception& e)
322 DecompositionInUnitBase ret=res->getData();
327 void ExprParser::evaluateExpr(int szOfOutParam, const double *inParam, double *outParam) const
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);
334 void ExprParser::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const
338 LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
340 leafC->prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
343 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
344 (*iter).prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
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.
354 void ExprParser::prepareExprEvaluationDouble(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo, int refPos, const double *ptOfInputStart, const double *ptOfInputEnd) const
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 !");
360 LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
362 leafC->prepareExprEvaluationDouble(vars,nbOfCompo,targetNbOfCompo,refPos,ptOfInputStart,ptOfInputEnd);
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);
369 void ExprParser::prepareFastEvaluator() const
371 _for_eval.clearSortedMemory();
372 _for_eval=convertMeTo();
373 _for_eval.sortMemory();
377 * \sa prepareExprEvaluationDouble
379 double ExprParser::evaluateDouble() const
381 checkForEvaluation();
382 std::vector<double> stackOfVal;
383 evaluateDoubleInternal(stackOfVal);
384 return stackOfVal.back();
387 void ExprParser::checkForEvaluation() const
390 throw INTERP_KERNEL::Exception("checkForEvaluation : Parsing fails ! Invalid expression !");
391 if(_sub_expr.empty() && !_leaf)
392 throw INTERP_KERNEL::Exception("checkForEvaluation : Empty expression !");
395 void ExprParser::prepareExprEvaluationVec() const
397 std::set<std::string> trueVars;
398 getTrueSetOfVars(trueVars);
399 if(trueVars.size()>1)
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());
406 prepareExprEvaluationVecLowLev();
409 void ExprParser::prepareExprEvaluationVecLowLev() const
413 LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
415 leafC->prepareExprEvaluationVec();
418 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
419 (*iter).prepareExprEvaluationVecLowLev();
422 Value *ExprParser::evaluateLowLev(Value *valGen) const
424 checkForEvaluation();
425 std::vector<Value *> stackOfVal;
430 Value *ret=valGen->newInstance();
433 _leaf->fillValue(ret);
435 catch(INTERP_KERNEL::Exception& e)
440 stackOfVal.resize(1);
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);
450 for(std::vector<Function *>::const_iterator iter3=_func_btw_sub_expr.begin();iter3!=_func_btw_sub_expr.end();iter3++)
451 (*iter3)->operate(stackOfVal);
453 catch(INTERP_KERNEL::Exception& e)
455 for(std::vector<Value *>::iterator iter4=stackOfVal.begin();iter4!=stackOfVal.end();iter4++)
459 return stackOfVal.back();
462 #if __cplusplus >= 201103L
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))
469 ExprParser& ExprParser::operator=(ExprParser&& other)
471 _father=other._father;
472 _is_parsing_ok=std::move(other._is_parsing_ok);
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;
484 void ExprParser::reverseThis()
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]);
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++)
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));
507 ExprParserOfEval ExprParser::convertMeTo() const
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);
516 void ExprParser::getSetOfVars(std::set<std::string>& vars) const
520 LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
522 vars.insert(leafC->getVar());
525 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
526 (*iter).getSetOfVars(vars);
529 void ExprParser::getTrueSetOfVars(std::set<std::string>& trueVars) const
531 std::set<std::string> vars;
534 for(std::set<std::string>::const_iterator iter=vars.begin();iter!=vars.end();iter++)
537 if(!LeafExprVar::isRecognizedKeyVar(*iter,tmp))
538 trueVars.insert(*iter);
542 void ExprParser::parseDeeper()
544 for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
545 if(!(*iter).simplify())
546 (*iter).parseDeeper();
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..
554 void ExprParser::parseUnaryFunc()
556 if(_expr[_expr.length()-1]!=')')
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);
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));
574 std::size_t lgth=funcName.length();
575 char tmp[2]; tmp[1]='\0';
576 for(std::size_t i=0;i<lgth;i++)
579 _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(tmp,(int)nbOfParamsInFunc));
583 for(std::size_t i=0;i<nbOfParamsInFunc;i++)
585 std::size_t pos5=newExp2.find_first_of(',',pos6);
586 std::size_t len=std::string::npos;
587 if(pos5!=std::string::npos)
589 std::string newExp3=newExp2.substr(pos6,len);
590 _sub_expr.push_back(ExprParser(newExp3.c_str(),this));
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.
601 bool ExprParser::tryToInterpALeaf()
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)
609 _leaf=LeafExpr::buildInstanceFrom(minimizedExpr);
611 for(std::size_t i=0;i<pos;i++)
615 _func_btw_sub_expr.push_back(FunctionsFactory::buildUnaryFuncFromString("-"));
620 void ExprParser::parseForCmp()
622 std::string::const_iterator iter;
625 bool isParsingSucceed=false;
626 for(iter=_expr.begin();iter!=_expr.end();iter++)
633 isParsingSucceed=true;
636 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
638 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
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());
667 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
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());
680 void ExprParser::parseForAddMin()
682 std::string::const_iterator iter;
685 bool isParsingSucceed=false;
686 for(iter=_expr.begin();iter!=_expr.end();iter++)
698 std::string::reverse_iterator accessor=curPart.rbegin();
699 if(*accessor!='*' && *accessor!='/' && *accessor!='^')
701 isParsingSucceed=true;
702 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
704 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
729 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
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());
742 void ExprParser::parseForMulDiv()
744 std::string::const_iterator iter;
747 bool isParsingSucceed=false;
748 for(iter=_expr.begin();iter!=_expr.end();iter++)
758 isParsingSucceed=true;
761 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
763 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
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());
792 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
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());
805 void ExprParser::parseForPow()
807 std::string::const_iterator iter;
810 bool isParsingSucceed=false;
811 for(iter=_expr.begin();iter!=_expr.end();iter++)
821 isParsingSucceed=true;
822 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
824 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
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());
852 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
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());
865 void ExprParser::releaseFunctions()
867 for(std::vector<Function *>::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++)
869 _func_btw_sub_expr.clear();
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.
877 bool ExprParser::simplify()
879 if(tryToInterpALeaf())
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());
907 void ExprParser::checkBracketsParity() const
909 std::string::const_iterator iter;
911 for(iter=_expr.begin();iter!=_expr.end();iter++)
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());
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());
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.
942 double ExprParser::ReplaceAndTraduce(std::string& expr, int id, std::size_t bg, std::size_t end, int& delta)
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);
950 double ret=std::numeric_limits<double>::max();
953 throw INTERP_KERNEL::Exception(MSG);
955 throw INTERP_KERNEL::Exception(MSG);
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);
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}+}?
969 void ExprParser::fillValuesInExpr(std::vector<double>& valuesInExpr)
971 const char FIGURES[]="0123456789";
972 const std::string other("+-*^/(<>,");
973 std::size_t lgth=_expr.length();
975 for(std::size_t pos=0;pos!=std::string::npos;id++)
977 std::size_t pos2=_expr.find_first_of(FIGURES,pos,10);
978 if(pos2==std::string::npos)
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)
984 pos=_expr.find_first_not_of(FIGURES,pos2,10);
988 if(_expr[pos2-1]==')')
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());
996 std::size_t pos3=_expr.find_first_not_of(FIGURES,pos2,10);
997 if(pos3==std::string::npos)
999 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
1002 if(_expr[pos3]=='.')
1006 std::size_t pos4=_expr.find_first_not_of(FIGURES,pos3,10);
1007 if(pos4==std::string::npos)
1009 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
1014 if(_expr[pos4]!='e' && _expr[pos4]!='E')
1015 {//"x+1223334.223+x"
1016 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos4,delta));
1024 if(_expr[pos4]=='+' || _expr[pos4]=='-')
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());
1031 std::size_t pos5=_expr.find_first_not_of(FIGURES,pos4,10);
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());
1038 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos5,delta));
1042 else//"x+1223334.223e"
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());
1052 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
1058 void ExprParser::replaceValues(const std::vector<double>& valuesInExpr)
1061 _leaf->replaceValues(valuesInExpr);
1064 for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1065 (*iter).replaceValues(valuesInExpr);
1069 void ExprParser::LocateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr)
1071 stringToDisp << "Position is " << posOfErr << " of string : \"" << srcOfErr << "\"" << std::endl;
1074 char *ExprParser::compileX86() const
1076 std::vector<std::string> ass;
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;
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;
1092 return asmb.copyToExecMemZone(output,offset);
1095 char *ExprParser::compileX86_64() const
1097 std::vector<std::string> ass;
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;
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;
1117 return asmb.copyToExecMemZone(output,offset);
1120 void ExprParser::compileX86LowLev(std::vector<std::string>& ass) const
1123 _leaf->compileX86(ass);
1126 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1127 (*iter).compileX86LowLev(ass);
1129 for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1130 (*iter2)->operateX86(ass);
1133 void ExprParser::compileX86_64LowLev(std::vector<std::string>& ass) const
1136 _leaf->compileX86_64(ass);
1139 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1140 (*iter).compileX86_64LowLev(ass);
1142 for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1143 (*iter2)->operateX86(ass);
1146 double LeafExprVal::getDoubleValue() const
1151 void LeafExprVal::compileX86(std::vector<std::string>& ass) const
1153 ass.push_back("sub esp,8");
1154 const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1156 std::ostringstream oss;
1158 oss << "mov dword [esp+4],0x" << *c;
1159 ass.push_back(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");
1167 void LeafExprVal::compileX86_64(std::vector<std::string>& ass) const
1169 ass.push_back("sub rsp,8");
1170 const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1172 std::ostringstream oss;
1174 oss << "mov dword [rsp+4],0x" << *c;
1175 ass.push_back(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");
1183 double LeafExprVar::getDoubleValue() const
1186 return _val[_fast_pos];
1189 int pos(-7-_fast_pos);
1190 return pos==_ref_pos?1.:0.;
1194 void LeafExprVar::compileX86(std::vector<std::string>& ass) const
1196 ass.push_back("fld qword [ebp+8]");
1199 void LeafExprVar::compileX86_64(std::vector<std::string>& ass) const
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");
1207 int ExprParser::getStackSizeToPlayX86(const ExprParser *asker) const
1211 int sz=_father->getStackSizeToPlayX86(this);
1213 for(std::vector<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
1215 const ExprParser& obj=(*iter);
1216 const ExprParser *pt=&obj;
1220 throw INTERP_KERNEL::Exception("error getStackSizeToPlayX86 an object ExprParser called as father, whereas it is not one !");
1225 return MAX_X86_FP_ST;
1226 return _father->getStackSizeToPlayX86(this);