27 #include "muParserTemplateMagic.h"
51 std::locale ParserBase::s_locale = std::locale(std::locale::classic(),
new change_dec_sep<char_type>(
'.'));
53 bool ParserBase::g_DbgDumpCmdCode =
false;
54 bool ParserBase::g_DbgDumpStack =
false;
62 const char_type* ParserBase::c_DefaultOprt[] =
64 _T(
"<="),
_T(
">="),
_T(
"!="),
65 _T(
"=="),
_T(
"<"),
_T(
">"),
67 _T(
"/"),
_T(
"^"),
_T(
"&&"),
68 _T(
"||"),
_T(
"="),
_T(
"("),
69 _T(
")"),
_T(
"?"),
_T(
":"), 0
77 ParserBase::ParserBase()
129 ParserBase::~ParserBase()
155 void ParserBase::Assign(
const ParserBase &a_Parser)
164 m_ConstDef = a_Parser.m_ConstDef;
165 m_VarDef = a_Parser.m_VarDef;
166 m_bBuiltInOp = a_Parser.m_bBuiltInOp;
167 m_vStringBuf = a_Parser.m_vStringBuf;
168 m_vStackBuffer = a_Parser.m_vStackBuffer;
169 m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;
170 m_StrVarDef = a_Parser.m_StrVarDef;
171 m_vStringVarBuf = a_Parser.m_vStringVarBuf;
172 m_nIfElseCounter = a_Parser.m_nIfElseCounter;
173 m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(
this));
176 m_FunDef = a_Parser.m_FunDef;
177 m_PostOprtDef = a_Parser.m_PostOprtDef;
178 m_InfixOprtDef = a_Parser.m_InfixOprtDef;
179 m_OprtDef = a_Parser.m_OprtDef;
181 m_sNameChars = a_Parser.m_sNameChars;
182 m_sOprtChars = a_Parser.m_sOprtChars;
183 m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
196 char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(
s_locale).thousands_sep();
210 char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(
s_locale).decimal_point();
235 void ParserBase::InitTokenReader()
237 m_pTokenReader.reset(
new token_reader_type(
this));
246 void ParserBase::ReInit()
const
248 m_pParseFormula = &ParserBase::ParseString;
249 m_vStringBuf.clear();
251 m_pTokenReader->ReInit();
252 m_nIfElseCounter = 0;
256 void ParserBase::OnDetectVar(
string_type * ,
int & ,
int & )
275 ss <<
_T(
" (") << MUP_VERSION_DATE;
276 ss << std::dec <<
_T(
"; ") <<
sizeof(
void*)*8 <<
_T(
"BIT");
281 ss <<
_T(
"; RELEASE");
285 ss <<
_T(
"; UNICODE");
294 #ifdef MUP_USE_OPENMP
295 ss <<
_T(
"; OPENMP");
300 #if defined(MUP_MATH_EXCEPTIONS)
301 ss <<
_T(
"; MATHEXC");
321 m_pTokenReader->AddValIdent(a_pCallback);
331 m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
336 void ParserBase::AddCallback(
const string_type &a_strName,
347 if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() )
350 if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() )
353 if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() )
356 if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() )
359 CheckOprt(a_strName, a_Callback, a_szCharSet);
360 a_Storage[a_strName] = a_Callback;
369 void ParserBase::CheckOprt(
const string_type &a_sName,
370 const ParserCallback &a_Callback,
373 if ( !a_sName.length() ||
374 (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
375 (a_sName[0]>=
'0' && a_sName[0]<=
'9'))
377 switch(a_Callback.GetCode())
391 void ParserBase::CheckName(
const string_type &a_sName,
394 if ( !a_sName.length() ||
395 (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
396 (a_sName[0]>=
'0' && a_sName[0]<=
'9'))
414 if (m_pTokenReader->GetArgSep()==std::use_facet<numpunct<char_type> >(loc).decimal_point())
423 m_pTokenReader->SetFormula(sBuf);
442 m_sNameChars = a_szCharset;
451 m_sOprtChars = a_szCharset;
460 m_sInfixOprtChars = a_szCharset;
469 assert(m_sNameChars.size());
470 return m_sNameChars.c_str();
479 assert(m_sOprtChars.size());
480 return m_sOprtChars.c_str();
489 assert(m_sInfixOprtChars.size());
490 return m_sInfixOprtChars.c_str();
558 for (
int i=0; m_bBuiltInOp && i<
cmENDIF; ++i)
576 if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())
581 m_vStringVarBuf.push_back(a_strVal);
582 m_StrVarDef[a_strName] = m_vStringVarBuf.size()-1;
600 if (m_ConstDef.find(a_sName)!=m_ConstDef.end())
604 m_VarDef[a_sName] = a_pVar;
618 m_ConstDef[a_sName] = a_fVal;
626 int ParserBase::GetOprtPrecedence(
const token_type &a_Tok)
const
628 switch (a_Tok.GetCode())
631 case cmEND:
return -5;
636 case cmLAND:
return prLAND;
637 case cmLOR:
return prLOR;
664 switch (a_Tok.GetCode())
678 case cmDIV:
return oaLEFT;
679 case cmPOW:
return oaRIGHT;
680 case cmOPRT_BIN:
return a_Tok.GetAssociativity();
681 default:
return oaNONE;
691 m_pTokenReader->IgnoreUndefVar(
true);
694 m_pParseFormula = &ParserBase::ParseString;
695 m_pTokenReader->IgnoreUndefVar(
false);
701 m_pParseFormula = &ParserBase::ParseString;
702 m_pTokenReader->IgnoreUndefVar(
false);
706 return m_pTokenReader->GetUsedVar();
743 return m_pTokenReader->GetExpr();
752 const std::vector<token_type> &a_vArg)
const
754 if (a_vArg.back().GetCode()!=
cmSTRING)
764 switch(a_FunTok.GetArgCount())
766 case 0: valTok.SetVal(1); a_vArg[0].GetAsString();
break;
767 case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal();
break;
768 case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
778 m_vRPN.
AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
791 void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt,
792 ParserStack<token_type> &a_stVal,
793 int a_iArgCount)
const
795 assert(m_pTokenReader.get());
798 if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 )
801 token_type funTok = a_stOpt.pop();
802 assert(funTok.GetFuncAddr());
811 int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==
tpSTR) ? 1 : 0);
814 int iArgNumerical = iArgCount - ((funTok.GetType()==
tpSTR) ? 1 : 0);
816 if (funTok.GetCode()==
cmFUNC_STR && iArgCount-iArgNumerical>1)
819 if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired)
822 if (funTok.GetCode()!=
cmOPRT_BIN && iArgCount<iArgRequired )
825 if (funTok.GetCode()==
cmFUNC_STR && iArgCount>iArgRequired )
830 std::vector<token_type> stArg;
831 for (
int i=0; i<iArgNumerical; ++i)
833 stArg.push_back( a_stVal.pop() );
834 if ( stArg.back().GetType()==
tpSTR && funTok.GetType()!=
tpSTR )
838 switch(funTok.GetCode())
841 stArg.push_back(a_stVal.pop());
843 if ( stArg.back().GetType()==
tpSTR && funTok.GetType()!=
tpSTR )
846 ApplyStrFunc(funTok, stArg);
850 m_vRPN.
AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
857 if (funTok.GetArgCount()==-1 && iArgCount==0)
860 m_vRPN.
AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical);
871 void ParserBase::ApplyIfElse(ParserStack<token_type> &a_stOpt,
872 ParserStack<token_type> &a_stVal)
const
875 while (a_stOpt.size() && a_stOpt.top().GetCode()==
cmELSE)
877 token_type opElse = a_stOpt.pop();
878 MUP_ASSERT(a_stOpt.size()>0);
881 token_type vVal2 = a_stVal.pop();
883 MUP_ASSERT(a_stOpt.size()>0);
884 MUP_ASSERT(a_stVal.size()>=2);
888 token_type vVal1 = a_stVal.pop();
889 token_type vExpr = a_stVal.pop();
891 a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2);
893 token_type opIf = a_stOpt.pop();
894 MUP_ASSERT(opElse.GetCode()==
cmELSE);
895 MUP_ASSERT(opIf.GetCode()==
cmIF);
905 void ParserBase::ApplyBinOprt(ParserStack<token_type> &a_stOpt,
906 ParserStack<token_type> &a_stVal)
const
911 ApplyFunc(a_stOpt, a_stVal, 2);
915 MUP_ASSERT(a_stVal.size()>=2);
916 token_type valTok1 = a_stVal.pop(),
917 valTok2 = a_stVal.pop(),
918 optTok = a_stOpt.pop(),
921 if ( valTok1.GetType()!=valTok2.GetType() ||
922 (valTok1.GetType()==
tpSTR && valTok2.GetType()==
tpSTR) )
927 if (valTok2.GetCode()!=
cmVAR)
933 m_vRPN.
AddOp(optTok.GetCode());
936 a_stVal.push(resTok);
945 void ParserBase::ApplyRemainingOprt(ParserStack<token_type> &stOpt,
946 ParserStack<token_type> &stVal)
const
948 while (stOpt.size() &&
949 stOpt.top().GetCode() !=
cmBO &&
950 stOpt.top().GetCode() !=
cmIF)
952 token_type tok = stOpt.top();
953 switch (tok.GetCode())
972 ApplyFunc(stOpt, stVal, 1);
974 ApplyBinOprt(stOpt, stVal);
978 ApplyIfElse(stOpt, stVal);
997 return ParseCmdCodeBulk(0, 0);
1005 value_type ParserBase::ParseCmdCodeBulk(
int nOffset,
int nThreadID)
const
1007 assert(nThreadID<=s_MaxNumOpenMPThreads);
1011 value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
1014 for (
const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=
cmEND ; ++pTok)
1019 case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1];
continue;
1020 case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1];
continue;
1021 case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1];
continue;
1022 case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1];
continue;
1023 case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1];
continue;
1024 case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1];
continue;
1025 case cmADD: --sidx; Stack[sidx] += Stack[1+sidx];
continue;
1026 case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx];
continue;
1027 case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx];
continue;
1030 #if defined(MUP_MATH_EXCEPTIONS)
1031 if (Stack[1+sidx]==0)
1034 Stack[sidx] /= Stack[1+sidx];
1038 --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1+sidx]);
1041 case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1];
continue;
1042 case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1];
continue;
1048 --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1];
continue;
1058 if (Stack[sidx--]==0)
1059 pTok += pTok->Oprt.offset;
1063 pTok += pTok->Oprt.offset;
1074 case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset);
continue;
1075 case cmVAL: Stack[++sidx] = pTok->Val.data2;
continue;
1077 case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
1078 Stack[++sidx] = buf*buf;
1081 case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
1082 Stack[++sidx] = buf*buf*buf;
1085 case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
1086 Stack[++sidx] = buf*buf*buf*buf;
1089 case cmVARMUL: Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
1095 int iArgCount = pTok->Fun.argc;
1100 case 0: sidx += 1; Stack[sidx] = (*(
fun_type0)pTok->Fun.ptr)();
continue;
1101 case 1: Stack[sidx] = (*(
fun_type1)pTok->Fun.ptr)(Stack[sidx]);
continue;
1102 case 2: sidx -= 1; Stack[sidx] = (*(
fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1]);
continue;
1103 case 3: sidx -= 2; Stack[sidx] = (*(
fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]);
continue;
1104 case 4: sidx -= 3; Stack[sidx] = (*(
fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]);
continue;
1105 case 5: sidx -= 4; Stack[sidx] = (*(
fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]);
continue;
1106 case 6: sidx -= 5; Stack[sidx] = (*(
fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]);
continue;
1107 case 7: sidx -= 6; Stack[sidx] = (*(
fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]);
continue;
1108 case 8: sidx -= 7; Stack[sidx] = (*(
fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]);
continue;
1109 case 9: sidx -= 8; Stack[sidx] = (*(
fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]);
continue;
1110 case 10:sidx -= 9; Stack[sidx] = (*(
fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]);
continue;
1115 sidx -= -iArgCount - 1;
1116 Stack[sidx] =(*(
multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
1124 sidx -= pTok->Fun.argc -1;
1127 int iIdxStack = pTok->Fun.idx;
1128 MUP_ASSERT( iIdxStack>=0 && iIdxStack<(
int)m_vStringBuf.size() );
1130 switch(pTok->Fun.argc)
1132 case 0: Stack[sidx] = (*(
strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str());
continue;
1133 case 1: Stack[sidx] = (*(
strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]);
continue;
1134 case 2: Stack[sidx] = (*(
strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]);
continue;
1142 int iArgCount = pTok->Fun.argc;
1147 case 0: sidx += 1; Stack[sidx] = (*(
bulkfun_type0 )pTok->Fun.ptr)(nOffset, nThreadID);
continue;
1148 case 1: Stack[sidx] = (*(
bulkfun_type1 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]);
continue;
1149 case 2: sidx -= 1; Stack[sidx] = (*(
bulkfun_type2 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]);
continue;
1150 case 3: sidx -= 2; Stack[sidx] = (*(
bulkfun_type3 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]);
continue;
1151 case 4: sidx -= 3; Stack[sidx] = (*(
bulkfun_type4 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]);
continue;
1152 case 5: sidx -= 4; Stack[sidx] = (*(
bulkfun_type5 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]);
continue;
1153 case 6: sidx -= 5; Stack[sidx] = (*(
bulkfun_type6 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]);
continue;
1154 case 7: sidx -= 6; Stack[sidx] = (*(
bulkfun_type7 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]);
continue;
1155 case 8: sidx -= 7; Stack[sidx] = (*(
bulkfun_type8 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]);
continue;
1156 case 9: sidx -= 8; Stack[sidx] = (*(
bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]);
continue;
1157 case 10:sidx -= 9; Stack[sidx] = (*(
bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]);
continue;
1170 return Stack[m_nFinalResultIdx];
1174 void ParserBase::CreateRPN()
const
1176 if (!m_pTokenReader->GetExpr().length())
1179 ParserStack<token_type> stOpt, stVal;
1180 ParserStack<int> stArgCount;
1181 token_type opta, opt;
1182 token_type val, tval;
1192 opt = m_pTokenReader->ReadNextToken();
1194 switch (opt.GetCode())
1200 opt.SetIdx((
int)m_vStringBuf.size());
1202 m_vStringBuf.push_back(opt.GetAsString());
1207 m_vRPN.AddVar( static_cast<value_type*>(opt.GetVar()) );
1212 m_vRPN.AddVal( opt.GetVal() );
1217 if (m_nIfElseCounter<0)
1218 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1220 ApplyRemainingOprt(stOpt, stVal);
1221 m_vRPN.AddIfElse(
cmELSE);
1227 if (stArgCount.empty())
1234 ApplyRemainingOprt(stOpt, stVal);
1243 if (opta.GetCode()==
cmBO)
1246 ApplyRemainingOprt(stOpt, stVal);
1249 if (stOpt.size() && stOpt.top().GetCode()==
cmBO)
1257 assert(stArgCount.size());
1258 int iArgCount = stArgCount.pop();
1262 if (iArgCount>1 && ( stOpt.size()==0 ||
1263 (stOpt.top().GetCode()!=
cmFUNC &&
1273 stOpt.top().GetFuncAddr()!=0)
1275 ApplyFunc(stOpt, stVal, iArgCount);
1308 while ( stOpt.size() &&
1309 stOpt.top().GetCode() !=
cmBO &&
1310 stOpt.top().GetCode() !=
cmELSE &&
1311 stOpt.top().GetCode() !=
cmIF)
1313 int nPrec1 = GetOprtPrecedence(stOpt.top()),
1314 nPrec2 = GetOprtPrecedence(opt);
1316 if (stOpt.top().GetCode()==opt.GetCode())
1321 if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) ||
1322 (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) )
1327 else if (nPrec1 < nPrec2)
1334 ApplyFunc(stOpt, stVal, 1);
1336 ApplyBinOprt(stOpt, stVal);
1339 if (opt.GetCode()==
cmIF)
1340 m_vRPN.AddIfElse(opt.GetCode());
1363 ApplyFunc(stOpt, stVal, 1);
1371 if ( opt.GetCode() ==
cmEND )
1377 if (ParserBase::g_DbgDumpStack)
1379 StackDump(stVal, stOpt);
1384 if (ParserBase::g_DbgDumpCmdCode)
1387 if (m_nIfElseCounter>0)
1388 Error(ecMISSING_ELSE_CLAUSE);
1391 MUP_ASSERT(stArgCount.size()==1);
1392 m_nFinalResultIdx = stArgCount.top();
1393 if (m_nFinalResultIdx==0)
1396 if (stVal.size()==0)
1399 if (stVal.top().GetType()!=
tpDBL)
1402 m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
1419 m_pParseFormula = &ParserBase::ParseCmdCode;
1420 return (this->*m_pParseFormula)();
1422 catch(ParserError &exc)
1424 exc.SetFormula(m_pTokenReader->GetExpr());
1442 throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
1451 void ParserBase::ClearVar()
1465 varmap_type::iterator item = m_VarDef.find(a_strVarName);
1466 if (item!=m_VarDef.end())
1468 m_VarDef.erase(item);
1478 void ParserBase::ClearFun()
1491 void ParserBase::ClearConst()
1494 m_StrVarDef.clear();
1503 void ParserBase::ClearPostfixOprt()
1505 m_PostOprtDef.clear();
1514 void ParserBase::ClearOprt()
1525 void ParserBase::ClearInfixOprt()
1527 m_InfixOprtDef.clear();
1536 void ParserBase::EnableOptimizer(
bool a_bIsOn)
1538 m_vRPN.EnableOptimizer(a_bIsOn);
1549 void ParserBase::EnableDebugDump(
bool bDumpCmd,
bool bDumpStack)
1551 ParserBase::g_DbgDumpCmdCode = bDumpCmd;
1552 ParserBase::g_DbgDumpStack = bDumpStack;
1565 void ParserBase::EnableBuiltInOprt(
bool a_bIsOn)
1567 m_bBuiltInOp = a_bIsOn;
1576 bool ParserBase::HasBuiltInOprt()
const
1578 return m_bBuiltInOp;
1586 return m_pTokenReader->GetArgSep();
1595 m_pTokenReader->SetArgSep(cArgSep);
1610 while ( !stVal.empty() )
1612 token_type val = stVal.pop();
1613 if (val.GetType()==
tpSTR)
1620 while ( !stOprt.empty() )
1622 if (stOprt.top().GetCode()<=
cmASSIGN)
1625 << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
1630 switch(stOprt.top().GetCode())
1635 << stOprt.top().GetAsString()
1636 <<
_T(
"\"\n");
break;
1638 << stOprt.top().GetAsString()
1639 <<
_T(
"\"\n");
break;
1641 << stOprt.top().GetAsString()
1642 <<
_T(
"\"\n");
break;
1644 << stOprt.top().GetAsString()
1645 <<
_T(
"\"\n");
break;
1654 default:
mu::console() << stOprt.top().GetCode() <<
_T(
" ");
break;
1673 (this->*m_pParseFormula)();
1674 nStackSize = m_nFinalResultIdx;
1677 return &m_vStackBuffer[1];
1687 int ParserBase::GetNumResults()
const
1689 return m_nFinalResultIdx;
1710 return (this->*m_pParseFormula)();
1714 void ParserBase::Eval(
value_type *results,
int nBulkSize)
1730 #ifdef MUP_USE_OPENMP
1732 #ifdef DEBUG_OMP_STUFF
1733 int *pThread =
new int[nBulkSize];
1734 int *pIdx =
new int[nBulkSize];
1737 int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
1738 int nThreadID = 0, ct = 0;
1739 omp_set_num_threads(nMaxThreads);
1741 #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID)
1742 for (i=0; i<nBulkSize; ++i)
1744 nThreadID = omp_get_thread_num();
1745 results[i] = ParseCmdCodeBulk(i, nThreadID);
1747 #ifdef DEBUG_OMP_STUFF
1748 #pragma omp critical
1750 pThread[ct] = nThreadID;
1757 #ifdef DEBUG_OMP_STUFF
1758 FILE *pFile = fopen(
"bulk_dbg.txt",
"w");
1759 for (i=0; i<nBulkSize; ++i)
1761 fprintf(pFile,
"idx: %d thread: %d \n", pIdx[i], pThread[i]);
1771 for (i=0; i<nBulkSize; ++i)
1773 results[i] = ParseCmdCodeBulk(i, 0);
void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true)
Add a user defined operator.
Operator item: closing bracket.
void DefineInfixOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of infix operators.
user defined binary operator
#define _T(x)
Activate this option in order to compile with OpenMP support.
binary operators may only be applied to value items of the same type
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
void DefineNameChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of functions, variables, constants.
value_type(* bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
An unexpected comma has been found. (Example: "1,23")
void DefineVar(const string_type &a_sName, value_type *a_fVar)
Add a user defined variable.
int GetArgCount() const
Return the number of function arguments.
std::ostream & console()
Encapsulate cout.
An unexpected argument has been found.
const funmap_type & GetFunDef() const
Return prototypes of all parser functions.
Division by zero (currently unused)
static std::locale s_locale
The locale used by the parser.
Postfix operator priority (currently unused)
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Operator item: y to the power of ...
function argument separator
Internal error of any kind.
value_type(* strfun_type3)(const char_type *, value_type, value_type)
Callback type used for functions taking a string and two values as arguments.
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
code for postfix operators
value_type(* fun_type3)(value_type, value_type, value_type)
Callback type used for functions with three arguments.
Trying to overload builtin operator.
static const char_type * c_DefaultOprt[]
Identifiers for built in binary operators.
void AddAssignOp(value_type *a_pVar)
Add an assignment operator.
Operator item: not equal.
value_type(* bulkfun_type2)(int, int, value_type, value_type)
Callback type used for functions with two arguments.
For use in the ternary if-then-else operator.
const char_type * ValidInfixOprtChars() const
Virtual function that defines the characters allowed in infix operator definitions.
void SetArgSep(char_type cArgSep)
Set argument separator.
const char_type * ValidOprtChars() const
Virtual function that defines the characters allowed in operator definitions.
void AddValIdent(identfun_type a_pCallback)
Add a value parsing function.
ParserToken & SetVal(TBase a_fVal, const TString &a_strTok=TString())
Make this token a value token.
value_type(* bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
value_type(* bulkfun_type0)(int, int)
Callback type used for functions without arguments.
value_type(* fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
value_type(* bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
void AddFun(generic_fun_type a_pFun, int a_iArgc)
Add function to bytecode.
power operator priority (highest)
void SetDecSep(char_type cDecSep)
Set the decimal separator.
Parser stack implementation.
void ResetLocale()
Resets the locale.
std::basic_stringstream< char_type, std::char_traits< char_type >, std::allocator< char_type > > stringstream_type
Typedef for easily using stringstream that respect the parser stringtype.
std::map< string_type, ParserCallback > funmap_type
Container for Callback objects.
void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true)
Add a user defined operator.
void Error(EErrorCodes a_iErrc, int a_iPos=(int) mu::string_type::npos, const string_type &a_strTok=string_type()) const
Create an error containing the parse error position.
void SetVarFactory(facfun_type a_pFactory, void *pUserData=NULL)
Set a function that can create variable pointer for unknown expression variables. ...
const string_type & GetExpr() const
Retrieve the formula.
Code for a generic function item.
EOprtAssociativity
Parser operator precedence values.
void DefineOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of binary operators and postfix operators...
const char_type * ValidNameChars() const
Virtual function that defines the characters allowed in name identifiers.
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
Conflict with current locale.
value_type(* strfun_type1)(const char_type *)
Callback type used for functions taking a string as an argument.
void SetThousandsSep(char_type cThousandsSep=0)
Sets the thousands operator.
std::map< string_type, value_type > valmap_type
Type used for storing constants.
value_type(* strfun_type2)(const char_type *, value_type)
Callback type used for functions taking a string and a value as arguments.
For use in the ternary if-then-else operator.
const valmap_type & GetConst() const
Return a map containing all parser constants.
Invalid variable pointer.
value_type(* bulkfun_type1)(int, int, value_type)
Callback type used for functions with a single arguments.
Invalid function, variable or constant name.
void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri=0, EOprtAssociativity a_eAssociativity=oaLEFT, bool a_bAllowOpt=false)
Define a binary operator.
Error class of the parser.
For use in the ternary if-then-else operator.
const varmap_type & GetVar() const
Return a map containing the used variables only.
This file contains the class definition of the muparser engine.
value_type(* bulkfun_type4)(int, int, value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
value_type(* bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
A facet class used to change decimal and thousands separator.
String type (Function arguments and constants only, no string variables)
void SetExpr(const string_type &a_sExpr)
Set the formula.
Too many function parameters.
A numerical function has been called with a non value type of argument.
Namespace for mathematical applications.
Unexpected end of formula. (Example: "2+sin(")
Operator item: less than.
Too few function parameters. (Example: "ite(1<2,2)")
string_type GetVersion(EParserVersionInfo eInfo=pviFULL) const
Returns the version of muparser.
A string function has been called with a different type of argument.
Operator item: greater than.
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
const char_type ** GetOprtDef() const
Get the default symbols used for the built in operators.
Special callbacks for Bulk mode with an additional parameter for the bulk index.
value_type(* fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
value_type(* fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
string_type::value_type char_type
The character type used by the parser.
value_type(* fun_type0)()
Callback type used for functions without arguments.
Code for a function with a string parameter.
Token reader for the ParserBase class.
void * GetAddr() const
Get the callback address for the parser function.
ParserBase & operator=(const ParserBase &a_Parser)
Assignment operator.
void DefineConst(const string_type &a_sName, value_type a_fVal)
Add a user defined constant.
value_type(* fun_type4)(value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
Operator item: Assignment operator.
Unexpected binary operator found.
MUP_STRING_TYPE string_type
The stringtype used by the parser.
value_type(* fun_type1)(value_type)
Callback type used for functions with a single arguments.
int(* identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal)
Callback used for functions that identify values in a string.
void clear()
Delete the bytecode.
value_type(* bulkfun_type3)(int, int, value_type, value_type, value_type)
Callback type used for functions with three arguments.
Operator item: less or equal.
void DefineStrConst(const string_type &a_sName, const string_type &a_strVal)
Define a new string constant.
Invalid function, variable or constant name.
Operator item: greater or equal.
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
value_type(* bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
Invalid callback function pointer.
value_type(* fun_type5)(value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
Floating point variables.
value_type(* fun_type2)(value_type, value_type)
Callback type used for functions with two arguments.
value_type(* fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
void Init()
Initialize user defined functions.
Encapsulation of prototypes for a numerical parser function.
value_type(* bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
value_type(* fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
Invalid function, variable or constant name.
Mathematical expressions parser (base parser engine).
Operator item: opening bracket.
value_type(* multfun_type)(const value_type *, int)
Callback type used for functions with a variable argument list.
const varmap_type & GetUsedVar() const
Return a map containing the used variables only.