1 // Copyright (C) 2007-2015 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 void ExprParser::reverseThis()
466 for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
467 (*iter).reverseThis();
468 AutoPtr<char> buf(new char[sizeof(ExprParser)]);
469 char *loc(reinterpret_cast<char *>(&_sub_expr[0])),*bufPtr(buf);
470 std::size_t sz(_sub_expr.size());
471 std::size_t nbOfTurn(sz/2);
472 for(std::size_t i=0;i<nbOfTurn;i++)
474 std::copy(loc+i*sizeof(ExprParser),loc+(i+1)*sizeof(ExprParser),bufPtr);
475 std::copy(loc+(sz-i-1)*sizeof(ExprParser),loc+(sz-i)*sizeof(ExprParser),loc+i*sizeof(ExprParser));
476 std::copy(bufPtr,bufPtr+sizeof(ExprParser),loc+(sz-i-1)*sizeof(ExprParser));
480 ExprParserOfEval ExprParser::convertMeTo() const
482 std::size_t sz(_sub_expr.size());
483 std::vector<ExprParserOfEval> subExpr(sz);
484 for(std::size_t i=0;i<sz;i++)
485 subExpr[i]=_sub_expr[i].convertMeTo();
486 return ExprParserOfEval(_leaf,subExpr,_func_btw_sub_expr);
489 void ExprParser::getSetOfVars(std::set<std::string>& vars) const
493 LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
495 vars.insert(leafC->getVar());
498 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
499 (*iter).getSetOfVars(vars);
502 void ExprParser::getTrueSetOfVars(std::set<std::string>& trueVars) const
504 std::set<std::string> vars;
507 for(std::set<std::string>::const_iterator iter=vars.begin();iter!=vars.end();iter++)
510 if(!LeafExprVar::isRecognizedKeyVar(*iter,tmp))
511 trueVars.insert(*iter);
515 void ExprParser::parseDeeper()
517 for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
518 if(!(*iter).simplify())
519 (*iter).parseDeeper();
523 * This method has the responsability to see if this->_expr can be seen as a unary function of something.
524 * Something defined as the contain of highest level barckets.
525 * Typically '(3*x+2)' and 'cos(4*l+p*n)' will be intercepted by this method whereas '3*x+2' not...etc..
527 void ExprParser::parseUnaryFunc()
529 if(_expr[_expr.length()-1]!=')')
531 //at this level of code _expr
532 std::size_t pos1=_expr.find_first_of('(');
533 std::size_t pos4=FindCorrespondingOpenBracket(_expr,_expr.length()-1);
536 std::string funcName=_expr.substr(0,pos1);
537 std::size_t pos2=funcName.find_first_of("+-*/^><",0,7);
538 std::size_t pos3=funcName.find_first_not_of("+-*/^><",0,7);
539 if(pos2!=std::string::npos && pos3!=std::string::npos)
540 return ;//Bracket group is not alone, can't conclude not recursively.
541 std::string newExp2=_expr.substr(pos1+1,_expr.length()-pos1-2);
542 std::size_t nbOfParamsInFunc=std::count(newExp2.begin(),newExp2.end(),',')+1;
543 if(pos3!=std::string::npos)
544 _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(funcName.c_str(),(int)nbOfParamsInFunc));
547 std::size_t lgth=funcName.length();
548 char tmp[2]; tmp[1]='\0';
549 for(std::size_t i=0;i<lgth;i++)
552 _func_btw_sub_expr.push_back(FunctionsFactory::buildFuncFromString(tmp,(int)nbOfParamsInFunc));
556 for(std::size_t i=0;i<nbOfParamsInFunc;i++)
558 std::size_t pos5=newExp2.find_first_of(',',pos6);
559 std::size_t len=std::string::npos;
560 if(pos5!=std::string::npos)
562 std::string newExp3=newExp2.substr(pos6,len);
563 _sub_expr.push_back(ExprParser(newExp3.c_str(),this));
570 * This method has the responsability to see if this->_expr is interpretable without any recursion.
571 * \return true if no recursion needed, false if this->_expr is too complex to be interpreted at this level.
572 * \throw exception if this->_expr is simple enough to try to interprate this and this expression contains an error.
574 bool ExprParser::tryToInterpALeaf()
576 std::size_t pos=_expr.find_first_not_of("+-",0,2);
577 std::string minimizedExpr=_expr.substr(pos);
578 std::size_t pos2=minimizedExpr.find_first_of("+-*/^()<>",0,9);
579 if(pos2!=std::string::npos)
582 _leaf=LeafExpr::buildInstanceFrom(minimizedExpr);
584 for(std::size_t i=0;i<pos;i++)
588 _func_btw_sub_expr.push_back(FunctionsFactory::buildUnaryFuncFromString("-"));
593 void ExprParser::parseForCmp()
595 std::string::const_iterator iter;
598 bool isParsingSucceed=false;
599 for(iter=_expr.begin();iter!=_expr.end();iter++)
606 isParsingSucceed=true;
609 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
611 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
615 std::ostringstream errMsg;
616 char MSGTYP1[]="Error non unary function for '";
617 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
618 std::string tmp=_expr.substr(iter-_expr.begin());
619 LocateError(errMsg,tmp,0);
620 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
640 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
645 std::ostringstream errMsg;
646 char MSGTYP4[]="Error following expression finished by > / < without right part.";
647 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
648 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
653 void ExprParser::parseForAddMin()
655 std::string::const_iterator iter;
658 bool isParsingSucceed=false;
659 for(iter=_expr.begin();iter!=_expr.end();iter++)
671 std::string::reverse_iterator accessor=curPart.rbegin();
672 if(*accessor!='*' && *accessor!='/' && *accessor!='^')
674 isParsingSucceed=true;
675 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
677 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
702 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
707 std::ostringstream errMsg;
708 char MSGTYP4[]="Error following expression finished by +/- without right part.";
709 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP4 << _expr;
710 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
715 void ExprParser::parseForMulDiv()
717 std::string::const_iterator iter;
720 bool isParsingSucceed=false;
721 for(iter=_expr.begin();iter!=_expr.end();iter++)
731 isParsingSucceed=true;
734 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
736 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
740 std::ostringstream errMsg;
741 char MSGTYP1[]="Error non unary function for '";
742 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
743 std::string tmp=_expr.substr(iter-_expr.begin());
744 LocateError(errMsg,tmp,0);
745 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
765 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
770 std::ostringstream errMsg;
771 char MSGTYP5[]="Error following expression finished by *// without right part.";
772 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP5 << _expr;
773 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
778 void ExprParser::parseForPow()
780 std::string::const_iterator iter;
783 bool isParsingSucceed=false;
784 for(iter=_expr.begin();iter!=_expr.end();iter++)
794 isParsingSucceed=true;
795 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
797 _func_btw_sub_expr.push_back(FunctionsFactory::buildBinaryFuncFromString(*iter));
801 std::ostringstream errMsg;
802 char MSGTYP1[]="Error non unary function for '";
803 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1 << *iter << "'";
804 std::string tmp=_expr.substr(iter-_expr.begin());
805 LocateError(errMsg,tmp,0);curPart+=*iter;
806 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
825 _sub_expr.push_back(ExprParser(curPart.c_str(),this));
830 std::ostringstream errMsg;
831 char MSGTYP6[]="Error following expression finished by ^ without right part.";
832 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP6 << _expr;
833 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
838 void ExprParser::releaseFunctions()
840 for(std::vector<Function *>::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++)
842 _func_btw_sub_expr.clear();
846 * This method parse this->_expr at the current level.
847 * This method first try to see if this->_expr is a leaf, if not it try a unary function of something (see INTERP_KERNEL::ExprParser::parseUnaryFunc method)
848 * If true is returned, no deeper parsing needed, if false is returned for a full parsing of this->_expr INTERP_KERNEL::ExprParser::parseDeeper call needed.
850 bool ExprParser::simplify()
852 if(tryToInterpALeaf())
871 std::ostringstream errMsg;
872 char MSGTYP3[]="Error in interpreting : ";
873 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP3 << _expr;
874 LocateError(errMsg,_expr,0);
875 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
880 void ExprParser::checkBracketsParity() const
882 std::string::const_iterator iter;
884 for(iter=_expr.begin();iter!=_expr.end();iter++)
892 std::ostringstream errMsg;
893 char MSGTYP1[]="Error in brackets : closing brackets ')' before openning '('";
894 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP1;
895 LocateError(errMsg,_expr,(int)std::distance(_expr.begin(),iter));
896 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
903 std::ostringstream errMsg;
904 char MSGTYP2[]="Error in brackets : not finally closed expr.";
905 errMsg << EXPR_PARSE_ERR_MSG << MSGTYP2;
906 throw INTERP_KERNEL::Exception(errMsg.str().c_str());
911 * This method substitutes part in [bg,end) in expr by the content of (str(id)) and returns the double value representation in expr[bg,end).
912 * If double representation is invalid an exception is thrown.
913 * This method returns a delta that is the delta to operate to pos in expr after substitution.
915 double ExprParser::ReplaceAndTraduce(std::string& expr, int id, std::size_t bg, std::size_t end, int& delta)
917 static const char MSG[]="Interal error : A string expected to be a float is not one ! Bug to signal !";
918 std::istringstream stream;
919 std::ostringstream oss;
920 std::size_t end2=end!=std::string::npos?end-bg:end;
921 std::string tmp=expr.substr(bg,end2);
923 double ret=std::numeric_limits<double>::max();
926 throw INTERP_KERNEL::Exception(MSG);
928 throw INTERP_KERNEL::Exception(MSG);
930 std::string tmp2(oss.str());
931 std::size_t l1=tmp.length();
932 delta=(int)tmp2.length()-(int)l1;
933 expr.replace(bg,l1,tmp2);
938 * This method makes the assumption that _expr has no white space.
939 * This method scans _expr finding in greedy mode the following pattern :
940 * {0..9}+{.}?{0..9}*{{eE}{-}?{0..9}+}?
942 void ExprParser::fillValuesInExpr(std::vector<double>& valuesInExpr)
944 const char FIGURES[]="0123456789";
945 const std::string other("+-*^/(<>,");
946 std::size_t lgth=_expr.length();
948 for(std::size_t pos=0;pos!=std::string::npos;id++)
950 std::size_t pos2=_expr.find_first_of(FIGURES,pos,10);
951 if(pos2==std::string::npos)
954 {//treat case of "x*log10(x)" -> "10" should NOT be intercepted by this
955 if(other.find_first_of(_expr[pos2-1])==std::string::npos)
957 pos=_expr.find_first_not_of(FIGURES,pos2,10);
961 if(_expr[pos2-1]==')')
963 pos=_expr.find_first_not_of(FIGURES,pos2,10);
964 std::ostringstream oss; oss << "Problem on parsing : Number \"" << _expr.substr(pos2,pos!=std::string::npos?pos2-pos:std::string::npos);
965 oss << "\" is right after close parenthesis... ')'";
966 throw INTERP_KERNEL::Exception(oss.str().c_str());
969 std::size_t pos3=_expr.find_first_not_of(FIGURES,pos2,10);
970 if(pos3==std::string::npos)
972 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
979 std::size_t pos4=_expr.find_first_not_of(FIGURES,pos3,10);
980 if(pos4==std::string::npos)
982 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
987 if(_expr[pos4]!='e' && _expr[pos4]!='E')
989 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos4,delta));
997 if(_expr[pos4]=='+' || _expr[pos4]=='-')
1000 {//"x+1223334.223e+" or "1223334.223E-"
1001 std::ostringstream oss; oss << "Invalid expr : float number at the end of expr is invalid lacking number after exponential and sign ! -> \"" << _expr.substr(pos2) << "\"";
1002 throw INTERP_KERNEL::Exception(oss.str().c_str());
1004 std::size_t pos5=_expr.find_first_not_of(FIGURES,pos4,10);
1006 {//"x+1223334.223e+x" or "1223334.223E-y"
1007 std::ostringstream oss; oss << "Invalid expr : float number in expr is invalid lacking number after exponential ! -> \"" << _expr.substr(pos2,pos4-pos2) << "\"";
1008 throw INTERP_KERNEL::Exception(oss.str().c_str());
1011 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,pos5,delta));
1015 else//"x+1223334.223e"
1017 std::ostringstream oss; oss << "Invalid expr : float number at the end of expr is invalid lacking number after exponential ! " << _expr.substr(pos2);
1018 throw INTERP_KERNEL::Exception(oss.str().c_str());
1025 valuesInExpr.push_back(ReplaceAndTraduce(_expr,id,pos2,std::string::npos,delta));
1031 void ExprParser::replaceValues(const std::vector<double>& valuesInExpr)
1034 _leaf->replaceValues(valuesInExpr);
1037 for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1038 (*iter).replaceValues(valuesInExpr);
1042 void ExprParser::LocateError(std::ostream& stringToDisp, const std::string& srcOfErr, int posOfErr)
1044 stringToDisp << "Position is " << posOfErr << " of string : \"" << srcOfErr << "\"" << std::endl;
1047 char *ExprParser::compileX86() const
1049 std::vector<std::string> ass;
1051 ass.push_back("push ebp");
1052 ass.push_back("mov ebp,esp");
1053 compileX86LowLev(ass);
1054 ass.push_back("pop ebp");
1055 ass.push_back("ret");
1056 std::cout << std::endl;
1057 for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
1058 std::cout << " " << *iter << std::endl;
1060 std::vector<char> output=asmb.convertIntoMachineLangage(ass);
1061 for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
1062 std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
1063 std::cout << std::endl;
1065 return asmb.copyToExecMemZone(output,offset);
1068 char *ExprParser::compileX86_64() const
1070 std::vector<std::string> ass;
1072 ass.push_back("push rbp");
1073 ass.push_back("mov rbp,rsp");
1074 compileX86_64LowLev(ass);
1075 ass.push_back("sub rsp,8");
1076 ass.push_back("fst qword [rsp]");
1077 ass.push_back("movsd xmm0,[rsp]");
1078 ass.push_back("add rsp,8");
1079 ass.push_back("leave");
1080 ass.push_back("ret");
1081 std::cout << std::endl;
1082 for(std::vector<std::string>::const_iterator iter=ass.begin();iter!=ass.end();iter++)
1083 std::cout << " " << *iter << std::endl;
1085 std::vector<char> output=asmb.convertIntoMachineLangage(ass);
1086 for(std::vector<char>::const_iterator iter=output.begin();iter!=output.end();iter++)
1087 std::cout << std::hex << (int)((unsigned char)(*iter)) << " ";
1088 std::cout << std::endl;
1090 return asmb.copyToExecMemZone(output,offset);
1093 void ExprParser::compileX86LowLev(std::vector<std::string>& ass) const
1096 _leaf->compileX86(ass);
1099 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1100 (*iter).compileX86LowLev(ass);
1102 for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1103 (*iter2)->operateX86(ass);
1106 void ExprParser::compileX86_64LowLev(std::vector<std::string>& ass) const
1109 _leaf->compileX86_64(ass);
1112 for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
1113 (*iter).compileX86_64LowLev(ass);
1115 for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
1116 (*iter2)->operateX86(ass);
1119 double LeafExprVal::getDoubleValue() const
1124 void LeafExprVal::compileX86(std::vector<std::string>& ass) const
1126 ass.push_back("sub esp,8");
1127 const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1129 std::ostringstream oss;
1131 oss << "mov dword [esp+4],0x" << *c;
1132 ass.push_back(oss.str());
1134 oss << "mov dword [esp],0x" << *b;
1135 ass.push_back(oss.str());
1136 ass.push_back("fld qword [esp]");
1137 ass.push_back("add esp,8");
1140 void LeafExprVal::compileX86_64(std::vector<std::string>& ass) const
1142 ass.push_back("sub rsp,8");
1143 const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
1145 std::ostringstream oss;
1147 oss << "mov dword [rsp+4],0x" << *c;
1148 ass.push_back(oss.str());
1150 oss << "mov dword [rsp],0x" << *b;
1151 ass.push_back(oss.str());
1152 ass.push_back("fld qword [rsp]");
1153 ass.push_back("add rsp,8");
1156 double LeafExprVar::getDoubleValue() const
1159 return _val[_fast_pos];
1162 int pos(-7-_fast_pos);
1163 return pos==_ref_pos?1.:0.;
1167 void LeafExprVar::compileX86(std::vector<std::string>& ass) const
1169 ass.push_back("fld qword [ebp+8]");
1172 void LeafExprVar::compileX86_64(std::vector<std::string>& ass) const
1174 ass.push_back("sub rsp,8");
1175 ass.push_back("movsd [rsp],xmm0");
1176 ass.push_back("fld qword [rsp]");
1177 ass.push_back("add rsp,8");
1180 int ExprParser::getStackSizeToPlayX86(const ExprParser *asker) const
1184 int sz=_father->getStackSizeToPlayX86(this);
1186 for(std::vector<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
1188 const ExprParser& obj=(*iter);
1189 const ExprParser *pt=&obj;
1193 throw INTERP_KERNEL::Exception("error getStackSizeToPlayX86 an object ExprParser called as father, whereas it is not one !");
1198 return MAX_X86_FP_ST;
1199 return _father->getStackSizeToPlayX86(this);