30 #include "muParserTemplateMagic.h"
51 #pragma warning(disable : 26812)
62 std::locale ParserBase::s_locale = std::locale(std::locale::classic(),
new change_dec_sep<char_type>(
'.'));
64 bool ParserBase::g_DbgDumpCmdCode =
false;
65 bool ParserBase::g_DbgDumpStack =
false;
73 const char_type* ParserBase::c_DefaultOprt[] =
75 _T(
"<="),
_T(
">="),
_T(
"!="),
76 _T(
"=="),
_T(
"<"),
_T(
">"),
78 _T(
"/"),
_T(
"^"),
_T(
"&&"),
79 _T(
"||"),
_T(
"="),
_T(
"("),
80 _T(
")"),
_T(
"?"),
_T(
":"), 0
83 const int ParserBase::s_MaxNumOpenMPThreads = 16;
90 ParserBase::ParserBase()
105 , m_sInfixOprtChars()
107 , m_nFinalResultIdx(0)
133 , m_sInfixOprtChars()
140 ParserBase::~ParserBase()
166 void ParserBase::Assign(
const ParserBase& a_Parser)
168 if (&a_Parser ==
this)
175 m_ConstDef = a_Parser.m_ConstDef;
176 m_VarDef = a_Parser.m_VarDef;
177 m_bBuiltInOp = a_Parser.m_bBuiltInOp;
178 m_vStringBuf = a_Parser.m_vStringBuf;
179 m_vStackBuffer = a_Parser.m_vStackBuffer;
180 m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;
181 m_StrVarDef = a_Parser.m_StrVarDef;
182 m_vStringVarBuf = a_Parser.m_vStringVarBuf;
183 m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(
this));
186 m_FunDef = a_Parser.m_FunDef;
187 m_PostOprtDef = a_Parser.m_PostOprtDef;
188 m_InfixOprtDef = a_Parser.m_InfixOprtDef;
189 m_OprtDef = a_Parser.m_OprtDef;
191 m_sNameChars = a_Parser.m_sNameChars;
192 m_sOprtChars = a_Parser.m_sOprtChars;
193 m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
206 char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(
s_locale).thousands_sep();
220 char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(
s_locale).decimal_point();
245 void ParserBase::InitTokenReader()
247 m_pTokenReader.reset(
new token_reader_type(
this));
256 void ParserBase::ReInit()
const
258 m_pParseFormula = &ParserBase::ParseString;
259 m_vStringBuf.clear();
261 m_pTokenReader->ReInit();
265 void ParserBase::OnDetectVar(
string_type* ,
int& ,
int& )
294 std::tie(expr, m_vStringBuf) = a_ByteCode.RestoreEnvironment();
295 m_pTokenReader->SetFormula(expr);
297 m_pParseFormula = &ParserBase::ParseCmdCode;
314 if (eInfo == pviFULL)
316 ss <<
_T(
" (") << ParserVersionDate;
317 ss << std::dec <<
_T(
"; ") <<
sizeof(
void*) * 8 <<
_T(
"BIT");
322 ss <<
_T(
"; RELEASE");
326 ss <<
_T(
"; UNICODE");
335 #ifdef MUP_USE_OPENMP
336 ss <<
_T(
"; OPENMP");
354 m_pTokenReader->AddValIdent(a_pCallback);
364 m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
369 void ParserBase::AddCallback(
381 if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end())
384 if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end())
387 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end())
390 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end())
393 CheckOprt(a_strName, a_Callback, a_szCharSet);
394 a_Storage[a_strName] = a_Callback;
403 void ParserBase::CheckOprt(
const string_type& a_sName,
404 const ParserCallback& a_Callback,
407 if (!a_sName.length() ||
408 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
409 (a_sName[0] >=
'0' && a_sName[0] <=
'9'))
411 switch (a_Callback.GetCode())
426 if (!a_sName.length() ||
427 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
428 (a_sName[0] >=
'0' && a_sName[0] <=
'9'))
444 if (m_pTokenReader->GetArgSep() == std::use_facet<numpunct<char_type> >(
s_locale).decimal_point())
448 if (a_sExpr.length() >= MaxLenExpression)
451 m_pTokenReader->SetFormula(a_sExpr +
_T(
" "));
470 m_sNameChars = a_szCharset;
479 m_sOprtChars = a_szCharset;
488 m_sInfixOprtChars = a_szCharset;
498 return m_sNameChars.c_str();
508 return m_sOprtChars.c_str();
518 return m_sInfixOprtChars.c_str();
527 if (a_sName.length() > MaxLenIdentifier)
557 if (a_sName.length() > MaxLenIdentifier)
576 if (a_sName.length() > MaxLenIdentifier)
580 for (
int i = 0; m_bBuiltInOp && i <
cmENDIF; ++i)
599 if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
604 m_vStringVarBuf.push_back(a_strVal);
605 m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1;
622 if (a_sName.length() > MaxLenIdentifier)
626 if (m_ConstDef.find(a_sName) != m_ConstDef.end())
630 m_VarDef[a_sName] = a_pVar;
643 if (a_sName.length() > MaxLenIdentifier)
647 m_ConstDef[a_sName] = a_fVal;
655 int ParserBase::GetOprtPrecedence(
const token_type& a_Tok)
const
657 switch (a_Tok.GetCode())
660 case cmEND:
return -5;
665 case cmLAND:
return prLAND;
666 case cmLOR:
return prLOR;
693 switch (a_Tok.GetCode())
707 case cmDIV:
return oaLEFT;
708 case cmPOW:
return oaRIGHT;
709 case cmOPRT_BIN:
return a_Tok.GetAssociativity();
710 default:
return oaNONE;
720 m_pTokenReader->IgnoreUndefVar(
true);
723 m_pParseFormula = &ParserBase::ParseString;
724 m_pTokenReader->IgnoreUndefVar(
false);
730 m_pParseFormula = &ParserBase::ParseString;
731 m_pTokenReader->IgnoreUndefVar(
false);
735 return m_pTokenReader->GetUsedVar();
772 return m_pTokenReader->GetExpr();
781 const token_type& a_FunTok,
782 const std::vector<token_type>& a_vArg)
const
784 if (a_vArg.back().GetCode() !=
cmSTRING)
794 switch (a_FunTok.GetArgCount())
796 case 0: valTok.SetVal(1); a_vArg[0].GetAsString();
break;
797 case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal();
break;
798 case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
799 case 3: valTok.SetVal(1); a_vArg[3].GetAsString(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
800 case 4: valTok.SetVal(1); a_vArg[4].GetAsString(); a_vArg[3].GetVal(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
801 case 5: valTok.SetVal(1); a_vArg[5].GetAsString(); a_vArg[4].GetVal(); a_vArg[3].GetVal(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
811 m_vRPN.
AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
824 void ParserBase::ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal,
int a_iArgCount)
const
829 if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0)
832 token_type funTok = a_stOpt.top();
839 int iArgCount = (funTok.GetCode() ==
cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
843 int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() ==
tpSTR) ? 1 : 0);
846 int iArgNumerical = iArgCount - ((funTok.GetType() ==
tpSTR) ? 1 : 0);
848 if (funTok.GetCode() ==
cmFUNC_STR && iArgCount - iArgNumerical > 1)
851 if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
854 if (funTok.GetCode() !=
cmOPRT_BIN && iArgCount < iArgRequired)
857 if (funTok.GetCode() ==
cmFUNC_STR && iArgCount > iArgRequired)
862 std::vector<token_type> stArg;
863 for (
int i = 0; i < iArgNumerical; ++i)
868 stArg.push_back(a_stVal.top());
871 if (stArg.back().GetType() ==
tpSTR && funTok.GetType() !=
tpSTR)
875 switch (funTok.GetCode())
881 stArg.push_back(a_stVal.top());
884 if (stArg.back().GetType() ==
tpSTR && funTok.GetType() !=
tpSTR)
887 ApplyStrFunc(funTok, stArg);
891 m_vRPN.
AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
898 if (funTok.GetArgCount() == -1 && iArgCount == 0)
901 m_vRPN.
AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical, funTok.IsOptimizable());
914 void ParserBase::ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal)
const
917 while (a_stOpt.size() && a_stOpt.top().GetCode() ==
cmELSE)
920 token_type opElse = a_stOpt.top();
925 token_type vVal2 = a_stVal.top();
926 if (vVal2.GetType() !=
tpDBL)
934 token_type vVal1 = a_stVal.top();
935 if (vVal1.GetType() !=
tpDBL)
941 token_type vExpr = a_stVal.top();
944 a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2);
946 token_type opIf = a_stOpt.top();
951 if (opIf.GetCode() !=
cmIF)
952 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
962 void ParserBase::ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal)
const
967 ApplyFunc(a_stOpt, a_stVal, 2);
971 if (a_stVal.size() < 2)
974 token_type valTok1 = a_stVal.top();
977 token_type valTok2 = a_stVal.top();
980 token_type optTok = a_stOpt.top();
985 if (valTok1.GetType() != valTok2.GetType() ||
986 (valTok1.GetType() ==
tpSTR && valTok2.GetType() ==
tpSTR))
991 if (valTok2.GetCode() !=
cmVAR)
997 m_vRPN.
AddOp(optTok.GetCode());
1000 a_stVal.push(resTok);
1009 void ParserBase::ApplyRemainingOprt(std::stack<token_type>& stOpt, std::stack<token_type>& stVal)
const
1011 while (stOpt.size() &&
1012 stOpt.top().GetCode() !=
cmBO &&
1013 stOpt.top().GetCode() !=
cmIF)
1015 token_type tok = stOpt.top();
1016 switch (tok.GetCode())
1035 ApplyFunc(stOpt, stVal, 1);
1037 ApplyBinOprt(stOpt, stVal);
1041 ApplyIfElse(stOpt, stVal);
1060 return ParseCmdCodeBulk(0, 0);
1063 value_type ParserBase::ParseCmdCodeShort()
const
1065 const SToken *
const tok = m_vRPN.GetBase();
1071 return tok->Val.data2;
1074 return *tok->Val.ptr;
1077 return *tok->Val.ptr * tok->Val.data + tok->Val.data2;
1080 buf = *(tok->Val.ptr);
1084 buf = *(tok->Val.ptr);
1085 return buf * buf * buf;
1088 buf = *(tok->Val.ptr);
1089 return buf * buf * buf * buf;
1093 return tok->Fun.cb.call_fun<0>();
1097 return tok->Fun.cb.call_strfun<1>(m_vStringBuf[0].c_str());
1109 value_type ParserBase::ParseCmdCodeBulk(
int nOffset,
int nThreadID)
const
1111 assert(nThreadID <= s_MaxNumOpenMPThreads);
1115 value_type *stack = ((nOffset == 0) && (nThreadID == 0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
1118 for (
const SToken* pTok = m_vRPN.GetBase(); pTok->Cmd !=
cmEND; ++pTok)
1123 case cmLE: --sidx; stack[sidx] = stack[sidx] <= stack[sidx + 1];
continue;
1124 case cmGE: --sidx; stack[sidx] = stack[sidx] >= stack[sidx + 1];
continue;
1125 case cmNEQ: --sidx; stack[sidx] = stack[sidx] != stack[sidx + 1];
continue;
1126 case cmEQ: --sidx; stack[sidx] = stack[sidx] == stack[sidx + 1];
continue;
1127 case cmLT: --sidx; stack[sidx] = stack[sidx] < stack[sidx + 1];
continue;
1128 case cmGT: --sidx; stack[sidx] = stack[sidx] > stack[sidx + 1];
continue;
1129 case cmADD: --sidx; stack[sidx] += stack[1 + sidx];
continue;
1130 case cmSUB: --sidx; stack[sidx] -= stack[1 + sidx];
continue;
1131 case cmMUL: --sidx; stack[sidx] *= stack[1 + sidx];
continue;
1133 stack[sidx] /= stack[1 + sidx];
1137 --sidx; stack[sidx] = MathImpl<value_type>::Pow(stack[sidx], stack[1 + sidx]);
1140 case cmLAND: --sidx; stack[sidx] = stack[sidx] && stack[sidx + 1];
continue;
1141 case cmLOR: --sidx; stack[sidx] = stack[sidx] || stack[sidx + 1];
continue;
1148 stack[sidx] = *(pTok->Oprt.ptr + nOffset) = stack[sidx + 1];
1154 if (stack[sidx--] == 0)
1157 pTok += pTok->Oprt.offset;
1162 pTok += pTok->Oprt.offset;
1169 case cmVAR: stack[++sidx] = *(pTok->Val.ptr + nOffset);
continue;
1170 case cmVAL: stack[++sidx] = pTok->Val.data2;
continue;
1172 case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
1173 stack[++sidx] = buf * buf;
1176 case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
1177 stack[++sidx] = buf * buf * buf;
1180 case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
1181 stack[++sidx] = buf * buf * buf * buf;
1185 stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
1191 int iArgCount = pTok->Fun.argc;
1196 case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_fun<0 >();
continue;
1197 case 1: stack[sidx] = pTok->Fun.cb.call_fun<1 >(stack[sidx]);
continue;
1198 case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_fun<2 >(stack[sidx], stack[sidx + 1]);
continue;
1199 case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_fun<3 >(stack[sidx], stack[sidx + 1], stack[sidx + 2]);
continue;
1200 case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_fun<4 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]);
continue;
1201 case 5: sidx -= 4; stack[sidx] = pTok->Fun.cb.call_fun<5 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]);
continue;
1202 case 6: sidx -= 5; stack[sidx] = pTok->Fun.cb.call_fun<6 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5]);
continue;
1203 case 7: sidx -= 6; stack[sidx] = pTok->Fun.cb.call_fun<7 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6]);
continue;
1204 case 8: sidx -= 7; stack[sidx] = pTok->Fun.cb.call_fun<8 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6], stack[sidx + 7]);
continue;
1205 case 9: sidx -= 8; stack[sidx] = pTok->Fun.cb.call_fun<9 >(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;
1206 case 10:sidx -= 9; stack[sidx] = pTok->Fun.cb.call_fun<10>(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;
1212 sidx -= -iArgCount - 1;
1224 stack[sidx] = pTok->Fun.cb.call_multfun(&stack[sidx], -iArgCount);
1232 sidx -= pTok->Fun.argc - 1;
1235 int iIdxStack = pTok->Fun.idx;
1236 if (iIdxStack < 0 || iIdxStack >= (
int)m_vStringBuf.size())
1239 switch (pTok->Fun.argc)
1241 case 0: stack[sidx] = pTok->Fun.cb.call_strfun<1>(m_vStringBuf[iIdxStack].c_str());
continue;
1242 case 1: stack[sidx] = pTok->Fun.cb.call_strfun<2>(m_vStringBuf[iIdxStack].c_str(), stack[sidx]);
continue;
1243 case 2: stack[sidx] = pTok->Fun.cb.call_strfun<3>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1]);
continue;
1244 case 3: stack[sidx] = pTok->Fun.cb.call_strfun<4>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2]);
continue;
1245 case 4: stack[sidx] = pTok->Fun.cb.call_strfun<5>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]);
continue;
1246 case 5: stack[sidx] = pTok->Fun.cb.call_strfun<6>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]);
continue;
1254 int iArgCount = pTok->Fun.argc;
1259 case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<0 >(nOffset, nThreadID);
continue;
1260 case 1: stack[sidx] = pTok->Fun.cb.call_bulkfun<1 >(nOffset, nThreadID, stack[sidx]);
continue;
1261 case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<2 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1]);
continue;
1262 case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_bulkfun<3 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2]);
continue;
1263 case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_bulkfun<4 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]);
continue;
1264 case 5: sidx -= 4; stack[sidx] = pTok->Fun.cb.call_bulkfun<5 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4]);
continue;
1265 case 6: sidx -= 5; stack[sidx] = pTok->Fun.cb.call_bulkfun<6 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5]);
continue;
1266 case 7: sidx -= 6; stack[sidx] = pTok->Fun.cb.call_bulkfun<7 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3], stack[sidx + 4], stack[sidx + 5], stack[sidx + 6]);
continue;
1267 case 8: sidx -= 7; stack[sidx] = pTok->Fun.cb.call_bulkfun<8 >(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;
1268 case 9: sidx -= 8; stack[sidx] = pTok->Fun.cb.call_bulkfun<9 >(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;
1269 case 10:sidx -= 9; stack[sidx] = pTok->Fun.cb.call_bulkfun<10>(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;
1280 return stack[m_nFinalResultIdx];
1284 void ParserBase::CreateRPN()
const
1286 if (!m_pTokenReader->GetExpr().length())
1289 std::stack<token_type> stOpt, stVal;
1290 std::stack<int> stArgCount;
1291 token_type opta, opt;
1292 token_type val, tval;
1293 int ifElseCounter = 0;
1303 opt = m_pTokenReader->ReadNextToken();
1305 switch (opt.GetCode())
1312 Error(
ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString());
1314 opt.SetIdx((
int)m_vStringBuf.size());
1316 m_vStringBuf.push_back(opt.GetAsString());
1321 m_vRPN.AddVar(static_cast<value_type*>(opt.GetVar()));
1326 m_vRPN.AddVal(opt.GetVal());
1330 if (stArgCount.empty())
1331 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1333 if (stArgCount.top() > 1)
1339 if (ifElseCounter < 0)
1340 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1342 ApplyRemainingOprt(stOpt, stVal);
1343 m_vRPN.AddIfElse(
cmELSE);
1348 if (!stOpt.empty() && stOpt.top().GetCode() ==
cmIF)
1351 if (stArgCount.empty())
1359 ApplyRemainingOprt(stOpt, stVal);
1368 if (opta.GetCode() ==
cmBO)
1371 ApplyRemainingOprt(stOpt, stVal);
1374 if (stOpt.size() && stOpt.top().GetCode() ==
cmBO)
1383 int iArgCount = stArgCount.top();
1388 if (iArgCount > 1 && (stOpt.size() == 0 ||
1389 (stOpt.top().GetCode() !=
cmFUNC &&
1399 stOpt.top().GetFuncAddr() != 0)
1401 ApplyFunc(stOpt, stVal, iArgCount);
1435 stOpt.top().GetCode() !=
cmBO &&
1436 stOpt.top().GetCode() !=
cmELSE &&
1437 stOpt.top().GetCode() !=
cmIF)
1439 int nPrec1 = GetOprtPrecedence(stOpt.top()),
1440 nPrec2 = GetOprtPrecedence(opt);
1442 if (stOpt.top().GetCode() == opt.GetCode())
1447 if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
1448 (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)))
1453 else if (nPrec1 < nPrec2)
1460 ApplyFunc(stOpt, stVal, 1);
1462 ApplyBinOprt(stOpt, stVal);
1465 if (opt.GetCode() ==
cmIF)
1466 m_vRPN.AddIfElse(opt.GetCode());
1489 ApplyFunc(stOpt, stVal, 1);
1497 if (opt.GetCode() ==
cmEND)
1503 if (ParserBase::g_DbgDumpStack)
1505 StackDump(stVal, stOpt);
1513 if (ParserBase::g_DbgDumpCmdCode)
1516 if (ifElseCounter > 0)
1517 Error(ecMISSING_ELSE_CLAUSE);
1521 m_nFinalResultIdx = stArgCount.top();
1522 if (m_nFinalResultIdx == 0)
1525 if (stVal.size() == 0)
1531 while (stVal.size())
1533 if (stVal.top().GetType() !=
tpDBL)
1539 m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
1557 if (m_vRPN.GetSize() == 2)
1559 m_vRPN.StoreEnvironment(m_pTokenReader->GetExpr(), m_vStringBuf);
1560 m_pParseFormula = &ParserBase::ParseCmdCodeShort;
1561 m_vStackBuffer[1] = (this->*m_pParseFormula)();
1562 return m_vStackBuffer[1];
1566 m_vRPN.StoreEnvironment(m_pTokenReader->GetExpr(), m_vStringBuf);
1567 m_pParseFormula = &ParserBase::ParseCmdCode;
1568 return (this->*m_pParseFormula)();
1571 catch (ParserError& exc)
1573 exc.SetFormula(m_pTokenReader->GetExpr());
1591 throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
1600 void ParserBase::ClearVar()
1614 varmap_type::iterator item = m_VarDef.find(a_strVarName);
1615 if (item != m_VarDef.end())
1617 m_VarDef.erase(item);
1627 void ParserBase::ClearFun()
1640 void ParserBase::ClearConst()
1643 m_StrVarDef.clear();
1652 void ParserBase::ClearPostfixOprt()
1654 m_PostOprtDef.clear();
1663 void ParserBase::ClearOprt()
1674 void ParserBase::ClearInfixOprt()
1676 m_InfixOprtDef.clear();
1685 void ParserBase::EnableOptimizer(
bool a_bIsOn)
1687 m_vRPN.EnableOptimizer(a_bIsOn);
1698 void ParserBase::EnableDebugDump(
bool bDumpCmd,
bool bDumpStack)
1700 ParserBase::g_DbgDumpCmdCode = bDumpCmd;
1701 ParserBase::g_DbgDumpStack = bDumpStack;
1714 void ParserBase::EnableBuiltInOprt(
bool a_bIsOn)
1716 m_bBuiltInOp = a_bIsOn;
1725 bool ParserBase::HasBuiltInOprt()
const
1727 return m_bBuiltInOp;
1735 return m_pTokenReader->GetArgSep();
1744 m_pTokenReader->SetArgSep(cArgSep);
1752 void ParserBase::StackDump(
const std::stack<token_type>& a_stVal,
const std::stack<token_type>& a_stOprt)
const
1754 std::stack<token_type> stOprt(a_stOprt);
1755 std::stack<token_type> stVal(a_stVal);
1758 while (!stVal.empty())
1760 token_type val = stVal.top();
1763 if (val.GetType() ==
tpSTR)
1770 while (!stOprt.empty())
1772 if (stOprt.top().GetCode() <=
cmASSIGN)
1775 << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
1780 switch (stOprt.top().GetCode())
1787 << stOprt.top().GetAsString()
1793 <<
_T(
"FUNC_BULK \"")
1794 << stOprt.top().GetAsString()
1800 << stOprt.top().GetAsString()
1806 << stOprt.top().GetAsString()
1818 default:
mu::console() << stOprt.top().GetCode() <<
_T(
" ");
break;
1844 return (this->*m_pParseFormula)();
1857 if (m_vRPN.GetSize() > 0)
1866 nStackSize = m_nFinalResultIdx;
1869 return &m_vStackBuffer[1];
1879 int ParserBase::GetNumResults()
const
1881 return m_nFinalResultIdx;
1885 void ParserBase::Eval(
value_type* results,
int nBulkSize)
1891 #ifdef MUP_USE_OPENMP
1893 #ifdef DEBUG_OMP_STUFF
1894 int* pThread =
new int[nBulkSize];
1895 int* pIdx =
new int[nBulkSize];
1898 int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
1901 #ifdef DEBUG_OMP_STUFF
1904 omp_set_num_threads(nMaxThreads);
1906 const int chunkSize = std::max(nBulkSize/nMaxThreads, 1);
1907 #pragma omp parallel for schedule(static, chunkSize) private(nThreadID)
1908 for (i = 0; i < nBulkSize; ++i)
1910 nThreadID = omp_get_thread_num();
1911 results[i] = ParseCmdCodeBulk(i, nThreadID);
1913 #ifdef DEBUG_OMP_STUFF
1914 #pragma omp critical
1916 pThread[ct] = nThreadID;
1923 #ifdef DEBUG_OMP_STUFF
1924 FILE* pFile = fopen(
"bulk_dbg.txt",
"w");
1925 for (i = 0; i < nBulkSize; ++i)
1927 fprintf(pFile,
"idx: %d thread: %d \n", pIdx[i], pThread[i]);
1937 for (i = 0; i < nBulkSize; ++i)
1939 results[i] = ParseCmdCodeBulk(i, 0);
1946 #if defined(_MSC_VER)
1947 #pragma warning(pop)
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.
void SetByteCode(const ParserByteCode &a_ByteCode)
Restore a previously saved bytecode.
user defined binary operator
#define _T(x)
Activate this option in order to compile with OpenMP support.
void AddStrFun(generic_callable_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
binary operators may only be applied to value items of the same type
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
void DefineNameChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of functions, variables, constants.
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.
std::ostream & console()
Encapsulate cout.
An unexpected argument has been found.
const funmap_type & GetFunDef() const
Return prototypes of all parser functions.
Throw an exception if the expression has more than 10000 characters. (an arbitrary limit) ...
static std::locale s_locale
The locale used by the parser.
Postfix operator priority (currently unused)
bool IsValid() const
Check that the callback looks valid.
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.
code for postfix operators
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.
void SetVarFactory(facfun_type a_pFactory, void *pUserData=nullptr)
Set a function that can create variable pointer for unknown expression variables. ...
For use in the ternary if-then-else operator.
value_type(* fun_type1)(value_type)
Callback type used for functions with a single arguments.
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.
power operator priority (highest)
void SetDecSep(char_type cDecSep)
Set the decimal separator.
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.
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.
void SetThousandsSep(char_type cThousandsSep=0)
Sets the thousands operator.
std::map< string_type, value_type > valmap_type
Type used for storing constants.
For use in the ternary if-then-else operator.
void AddBulkFun(generic_callable_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
const valmap_type & GetConst() const
Return a map containing all parser constants.
Invalid variable pointer.
Invalid function, variable or constant name.
value_type(* fun_type2)(value_type, value_type)
Callback type used for functions with two arguments.
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.
void AddFun(generic_callable_type a_pFun, int a_iArgc, bool isOptimizable)
Add function to bytecode.
const varmap_type & GetVar() const
Return a map containing the used variables only.
This file contains the class definition of the muparser engine.
#define MUP_ASSERT(COND)
An assertion that does not kill the program.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
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.
int(* identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal)
Callback used for functions that identify values in a string.
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.
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.
string_type::value_type char_type
The character type used by the parser.
Code for a function with a string parameter.
Token reader for the ParserBase class.
Thrown when an identifier with more then 255 characters is used.
ParserBase & operator=(const ParserBase &a_Parser)
Assignment operator.
void DefineConst(const string_type &a_sName, value_type a_fVal)
Add a user defined constant.
Operator item: Assignment operator.
Unexpected binary operator found.
Bytecode implementation of the Math Parser.
MUP_STRING_TYPE string_type
The stringtype used by the parser.
ParserError exception_type
Type of the error class.
void clear()
Delete the bytecode.
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.
Invalid callback function pointer.
Floating point variables.
void Error(EErrorCodes a_iErrc, int a_iPos=static_cast< int >(mu::string_type::npos), const string_type &a_strTok=string_type()) const
Create an error containing the parse error position.
void Init()
Initialize user defined functions.
Encapsulation of prototypes for a numerical parser function.
A string has been found at an inapropriate position.
const ParserByteCode & GetByteCode() const
Returns a copy of the bytecode of the current expression.
Invalid function, variable or constant name.
Mathematical expressions parser (base parser engine).
Operator item: opening bracket.
const varmap_type & GetUsedVar() const
Return a map containing the used variables only.