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& )
290 if (eInfo == pviFULL)
292 ss <<
_T(
" (") << ParserVersionDate;
293 ss << std::dec <<
_T(
"; ") <<
sizeof(
void*) * 8 <<
_T(
"BIT");
298 ss <<
_T(
"; RELEASE");
302 ss <<
_T(
"; UNICODE");
311 #ifdef MUP_USE_OPENMP
312 ss <<
_T(
"; OPENMP");
330 m_pTokenReader->AddValIdent(a_pCallback);
340 m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
345 void ParserBase::AddCallback(
357 if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end())
360 if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end())
363 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end())
366 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end())
369 CheckOprt(a_strName, a_Callback, a_szCharSet);
370 a_Storage[a_strName] = a_Callback;
379 void ParserBase::CheckOprt(
const string_type& a_sName,
380 const ParserCallback& a_Callback,
383 if (!a_sName.length() ||
384 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
385 (a_sName[0] >=
'0' && a_sName[0] <=
'9'))
387 switch (a_Callback.GetCode())
402 if (!a_sName.length() ||
403 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
404 (a_sName[0] >=
'0' && a_sName[0] <=
'9'))
420 if (m_pTokenReader->GetArgSep() == std::use_facet<numpunct<char_type> >(
s_locale).decimal_point())
424 if (a_sExpr.length() >= MaxLenExpression)
427 m_pTokenReader->SetFormula(a_sExpr +
_T(
" "));
446 m_sNameChars = a_szCharset;
455 m_sOprtChars = a_szCharset;
464 m_sInfixOprtChars = a_szCharset;
474 return m_sNameChars.c_str();
484 return m_sOprtChars.c_str();
494 return m_sInfixOprtChars.c_str();
503 if (a_sName.length() > MaxLenIdentifier)
533 if (a_sName.length() > MaxLenIdentifier)
552 if (a_sName.length() > MaxLenIdentifier)
556 for (
int i = 0; m_bBuiltInOp && i <
cmENDIF; ++i)
575 if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
580 m_vStringVarBuf.push_back(a_strVal);
581 m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1;
598 if (a_sName.length() > MaxLenIdentifier)
602 if (m_ConstDef.find(a_sName) != m_ConstDef.end())
606 m_VarDef[a_sName] = a_pVar;
619 if (a_sName.length() > MaxLenIdentifier)
623 m_ConstDef[a_sName] = a_fVal;
631 int ParserBase::GetOprtPrecedence(
const token_type& a_Tok)
const
633 switch (a_Tok.GetCode())
636 case cmEND:
return -5;
641 case cmLAND:
return prLAND;
642 case cmLOR:
return prLOR;
669 switch (a_Tok.GetCode())
683 case cmDIV:
return oaLEFT;
684 case cmPOW:
return oaRIGHT;
685 case cmOPRT_BIN:
return a_Tok.GetAssociativity();
686 default:
return oaNONE;
696 m_pTokenReader->IgnoreUndefVar(
true);
699 m_pParseFormula = &ParserBase::ParseString;
700 m_pTokenReader->IgnoreUndefVar(
false);
706 m_pParseFormula = &ParserBase::ParseString;
707 m_pTokenReader->IgnoreUndefVar(
false);
711 return m_pTokenReader->GetUsedVar();
748 return m_pTokenReader->GetExpr();
757 const token_type& a_FunTok,
758 const std::vector<token_type>& a_vArg)
const
760 if (a_vArg.back().GetCode() !=
cmSTRING)
770 switch (a_FunTok.GetArgCount())
772 case 0: valTok.SetVal(1); a_vArg[0].GetAsString();
break;
773 case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal();
break;
774 case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
775 case 3: valTok.SetVal(1); a_vArg[3].GetAsString(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
776 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;
777 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;
787 m_vRPN.
AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
800 void ParserBase::ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal,
int a_iArgCount)
const
805 if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0)
808 token_type funTok = a_stOpt.top();
815 int iArgCount = (funTok.GetCode() ==
cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
819 int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() ==
tpSTR) ? 1 : 0);
822 int iArgNumerical = iArgCount - ((funTok.GetType() ==
tpSTR) ? 1 : 0);
824 if (funTok.GetCode() ==
cmFUNC_STR && iArgCount - iArgNumerical > 1)
827 if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
830 if (funTok.GetCode() !=
cmOPRT_BIN && iArgCount < iArgRequired)
833 if (funTok.GetCode() ==
cmFUNC_STR && iArgCount > iArgRequired)
838 std::vector<token_type> stArg;
839 for (
int i = 0; i < iArgNumerical; ++i)
844 stArg.push_back(a_stVal.top());
847 if (stArg.back().GetType() ==
tpSTR && funTok.GetType() !=
tpSTR)
851 switch (funTok.GetCode())
857 stArg.push_back(a_stVal.top());
860 if (stArg.back().GetType() ==
tpSTR && funTok.GetType() !=
tpSTR)
863 ApplyStrFunc(funTok, stArg);
867 m_vRPN.
AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
874 if (funTok.GetArgCount() == -1 && iArgCount == 0)
877 m_vRPN.
AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical, funTok.IsOptimizable());
890 void ParserBase::ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal)
const
893 while (a_stOpt.size() && a_stOpt.top().GetCode() ==
cmELSE)
896 token_type opElse = a_stOpt.top();
901 token_type vVal2 = a_stVal.top();
902 if (vVal2.GetType() !=
tpDBL)
910 token_type vVal1 = a_stVal.top();
911 if (vVal1.GetType() !=
tpDBL)
917 token_type vExpr = a_stVal.top();
920 a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2);
922 token_type opIf = a_stOpt.top();
927 if (opIf.GetCode() !=
cmIF)
928 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
938 void ParserBase::ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal)
const
943 ApplyFunc(a_stOpt, a_stVal, 2);
947 if (a_stVal.size() < 2)
950 token_type valTok1 = a_stVal.top();
953 token_type valTok2 = a_stVal.top();
956 token_type optTok = a_stOpt.top();
961 if (valTok1.GetType() != valTok2.GetType() ||
962 (valTok1.GetType() ==
tpSTR && valTok2.GetType() ==
tpSTR))
967 if (valTok2.GetCode() !=
cmVAR)
973 m_vRPN.
AddOp(optTok.GetCode());
976 a_stVal.push(resTok);
985 void ParserBase::ApplyRemainingOprt(std::stack<token_type>& stOpt, std::stack<token_type>& stVal)
const
987 while (stOpt.size() &&
988 stOpt.top().GetCode() !=
cmBO &&
989 stOpt.top().GetCode() !=
cmIF)
991 token_type tok = stOpt.top();
992 switch (tok.GetCode())
1011 ApplyFunc(stOpt, stVal, 1);
1013 ApplyBinOprt(stOpt, stVal);
1017 ApplyIfElse(stOpt, stVal);
1036 return ParseCmdCodeBulk(0, 0);
1039 value_type ParserBase::ParseCmdCodeShort()
const
1041 const SToken *
const tok = m_vRPN.GetBase();
1047 return tok->Val.data2;
1050 return *tok->Val.ptr;
1053 return *tok->Val.ptr * tok->Val.data + tok->Val.data2;
1056 buf = *(tok->Val.ptr);
1060 buf = *(tok->Val.ptr);
1061 return buf * buf * buf;
1064 buf = *(tok->Val.ptr);
1065 return buf * buf * buf * buf;
1069 return tok->Fun.cb.call_fun<0>();
1073 return tok->Fun.cb.call_strfun<1>(m_vStringBuf[0].c_str());
1085 value_type ParserBase::ParseCmdCodeBulk(
int nOffset,
int nThreadID)
const
1087 assert(nThreadID <= s_MaxNumOpenMPThreads);
1091 value_type *stack = ((nOffset == 0) && (nThreadID == 0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
1094 for (
const SToken* pTok = m_vRPN.GetBase(); pTok->Cmd !=
cmEND; ++pTok)
1099 case cmLE: --sidx; stack[sidx] = stack[sidx] <= stack[sidx + 1];
continue;
1100 case cmGE: --sidx; stack[sidx] = stack[sidx] >= stack[sidx + 1];
continue;
1101 case cmNEQ: --sidx; stack[sidx] = stack[sidx] != stack[sidx + 1];
continue;
1102 case cmEQ: --sidx; stack[sidx] = stack[sidx] == stack[sidx + 1];
continue;
1103 case cmLT: --sidx; stack[sidx] = stack[sidx] < stack[sidx + 1];
continue;
1104 case cmGT: --sidx; stack[sidx] = stack[sidx] > stack[sidx + 1];
continue;
1105 case cmADD: --sidx; stack[sidx] += stack[1 + sidx];
continue;
1106 case cmSUB: --sidx; stack[sidx] -= stack[1 + sidx];
continue;
1107 case cmMUL: --sidx; stack[sidx] *= stack[1 + sidx];
continue;
1109 stack[sidx] /= stack[1 + sidx];
1113 --sidx; stack[sidx] = MathImpl<value_type>::Pow(stack[sidx], stack[1 + sidx]);
1116 case cmLAND: --sidx; stack[sidx] = stack[sidx] && stack[sidx + 1];
continue;
1117 case cmLOR: --sidx; stack[sidx] = stack[sidx] || stack[sidx + 1];
continue;
1124 stack[sidx] = *(pTok->Oprt.ptr + nOffset) = stack[sidx + 1];
1130 if (stack[sidx--] == 0)
1133 pTok += pTok->Oprt.offset;
1138 pTok += pTok->Oprt.offset;
1145 case cmVAR: stack[++sidx] = *(pTok->Val.ptr + nOffset);
continue;
1146 case cmVAL: stack[++sidx] = pTok->Val.data2;
continue;
1148 case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
1149 stack[++sidx] = buf * buf;
1152 case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
1153 stack[++sidx] = buf * buf * buf;
1156 case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
1157 stack[++sidx] = buf * buf * buf * buf;
1161 stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
1167 int iArgCount = pTok->Fun.argc;
1172 case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_fun<0 >();
continue;
1173 case 1: stack[sidx] = pTok->Fun.cb.call_fun<1 >(stack[sidx]);
continue;
1174 case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_fun<2 >(stack[sidx], stack[sidx + 1]);
continue;
1175 case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_fun<3 >(stack[sidx], stack[sidx + 1], stack[sidx + 2]);
continue;
1176 case 4: sidx -= 3; stack[sidx] = pTok->Fun.cb.call_fun<4 >(stack[sidx], stack[sidx + 1], stack[sidx + 2], stack[sidx + 3]);
continue;
1177 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;
1178 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;
1179 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;
1180 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;
1181 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;
1182 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;
1188 sidx -= -iArgCount - 1;
1200 stack[sidx] = pTok->Fun.cb.call_multfun(&stack[sidx], -iArgCount);
1208 sidx -= pTok->Fun.argc - 1;
1211 int iIdxStack = pTok->Fun.idx;
1212 if (iIdxStack < 0 || iIdxStack >= (
int)m_vStringBuf.size())
1215 switch (pTok->Fun.argc)
1217 case 0: stack[sidx] = pTok->Fun.cb.call_strfun<1>(m_vStringBuf[iIdxStack].c_str());
continue;
1218 case 1: stack[sidx] = pTok->Fun.cb.call_strfun<2>(m_vStringBuf[iIdxStack].c_str(), stack[sidx]);
continue;
1219 case 2: stack[sidx] = pTok->Fun.cb.call_strfun<3>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1]);
continue;
1220 case 3: stack[sidx] = pTok->Fun.cb.call_strfun<4>(m_vStringBuf[iIdxStack].c_str(), stack[sidx], stack[sidx + 1], stack[sidx + 2]);
continue;
1221 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;
1222 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;
1230 int iArgCount = pTok->Fun.argc;
1235 case 0: sidx += 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<0 >(nOffset, nThreadID);
continue;
1236 case 1: stack[sidx] = pTok->Fun.cb.call_bulkfun<1 >(nOffset, nThreadID, stack[sidx]);
continue;
1237 case 2: sidx -= 1; stack[sidx] = pTok->Fun.cb.call_bulkfun<2 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1]);
continue;
1238 case 3: sidx -= 2; stack[sidx] = pTok->Fun.cb.call_bulkfun<3 >(nOffset, nThreadID, stack[sidx], stack[sidx + 1], stack[sidx + 2]);
continue;
1239 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;
1240 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;
1241 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;
1242 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;
1243 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;
1244 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;
1245 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;
1256 return stack[m_nFinalResultIdx];
1260 void ParserBase::CreateRPN()
const
1262 if (!m_pTokenReader->GetExpr().length())
1265 std::stack<token_type> stOpt, stVal;
1266 std::stack<int> stArgCount;
1267 token_type opta, opt;
1268 token_type val, tval;
1269 int ifElseCounter = 0;
1279 opt = m_pTokenReader->ReadNextToken();
1281 switch (opt.GetCode())
1288 Error(
ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString());
1290 opt.SetIdx((
int)m_vStringBuf.size());
1292 m_vStringBuf.push_back(opt.GetAsString());
1297 m_vRPN.AddVar(static_cast<value_type*>(opt.GetVar()));
1302 m_vRPN.AddVal(opt.GetVal());
1306 if (stArgCount.empty())
1307 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1309 if (stArgCount.top() > 1)
1315 if (ifElseCounter < 0)
1316 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1318 ApplyRemainingOprt(stOpt, stVal);
1319 m_vRPN.AddIfElse(
cmELSE);
1324 if (!stOpt.empty() && stOpt.top().GetCode() ==
cmIF)
1327 if (stArgCount.empty())
1335 ApplyRemainingOprt(stOpt, stVal);
1344 if (opta.GetCode() ==
cmBO)
1347 ApplyRemainingOprt(stOpt, stVal);
1350 if (stOpt.size() && stOpt.top().GetCode() ==
cmBO)
1359 int iArgCount = stArgCount.top();
1364 if (iArgCount > 1 && (stOpt.size() == 0 ||
1365 (stOpt.top().GetCode() !=
cmFUNC &&
1375 stOpt.top().GetFuncAddr() != 0)
1377 ApplyFunc(stOpt, stVal, iArgCount);
1411 stOpt.top().GetCode() !=
cmBO &&
1412 stOpt.top().GetCode() !=
cmELSE &&
1413 stOpt.top().GetCode() !=
cmIF)
1415 int nPrec1 = GetOprtPrecedence(stOpt.top()),
1416 nPrec2 = GetOprtPrecedence(opt);
1418 if (stOpt.top().GetCode() == opt.GetCode())
1423 if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
1424 (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)))
1429 else if (nPrec1 < nPrec2)
1436 ApplyFunc(stOpt, stVal, 1);
1438 ApplyBinOprt(stOpt, stVal);
1441 if (opt.GetCode() ==
cmIF)
1442 m_vRPN.AddIfElse(opt.GetCode());
1465 ApplyFunc(stOpt, stVal, 1);
1473 if (opt.GetCode() ==
cmEND)
1479 if (ParserBase::g_DbgDumpStack)
1481 StackDump(stVal, stOpt);
1489 if (ParserBase::g_DbgDumpCmdCode)
1492 if (ifElseCounter > 0)
1493 Error(ecMISSING_ELSE_CLAUSE);
1497 m_nFinalResultIdx = stArgCount.top();
1498 if (m_nFinalResultIdx == 0)
1501 if (stVal.size() == 0)
1507 while (stVal.size())
1509 if (stVal.top().GetType() !=
tpDBL)
1515 m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
1533 if (m_vRPN.GetSize() == 2)
1535 m_pParseFormula = &ParserBase::ParseCmdCodeShort;
1536 m_vStackBuffer[1] = (this->*m_pParseFormula)();
1537 return m_vStackBuffer[1];
1541 m_pParseFormula = &ParserBase::ParseCmdCode;
1542 return (this->*m_pParseFormula)();
1545 catch (ParserError& exc)
1547 exc.SetFormula(m_pTokenReader->GetExpr());
1565 throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
1574 void ParserBase::ClearVar()
1588 varmap_type::iterator item = m_VarDef.find(a_strVarName);
1589 if (item != m_VarDef.end())
1591 m_VarDef.erase(item);
1601 void ParserBase::ClearFun()
1614 void ParserBase::ClearConst()
1617 m_StrVarDef.clear();
1626 void ParserBase::ClearPostfixOprt()
1628 m_PostOprtDef.clear();
1637 void ParserBase::ClearOprt()
1648 void ParserBase::ClearInfixOprt()
1650 m_InfixOprtDef.clear();
1659 void ParserBase::EnableOptimizer(
bool a_bIsOn)
1661 m_vRPN.EnableOptimizer(a_bIsOn);
1672 void ParserBase::EnableDebugDump(
bool bDumpCmd,
bool bDumpStack)
1674 ParserBase::g_DbgDumpCmdCode = bDumpCmd;
1675 ParserBase::g_DbgDumpStack = bDumpStack;
1688 void ParserBase::EnableBuiltInOprt(
bool a_bIsOn)
1690 m_bBuiltInOp = a_bIsOn;
1699 bool ParserBase::HasBuiltInOprt()
const
1701 return m_bBuiltInOp;
1709 return m_pTokenReader->GetArgSep();
1718 m_pTokenReader->SetArgSep(cArgSep);
1726 void ParserBase::StackDump(
const std::stack<token_type>& a_stVal,
const std::stack<token_type>& a_stOprt)
const
1728 std::stack<token_type> stOprt(a_stOprt);
1729 std::stack<token_type> stVal(a_stVal);
1732 while (!stVal.empty())
1734 token_type val = stVal.top();
1737 if (val.GetType() ==
tpSTR)
1744 while (!stOprt.empty())
1746 if (stOprt.top().GetCode() <=
cmASSIGN)
1749 << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
1754 switch (stOprt.top().GetCode())
1761 << stOprt.top().GetAsString()
1767 <<
_T(
"FUNC_BULK \"")
1768 << stOprt.top().GetAsString()
1774 << stOprt.top().GetAsString()
1780 << stOprt.top().GetAsString()
1792 default:
mu::console() << stOprt.top().GetCode() <<
_T(
" ");
break;
1818 return (this->*m_pParseFormula)();
1831 if (m_vRPN.GetSize() > 0)
1840 nStackSize = m_nFinalResultIdx;
1843 return &m_vStackBuffer[1];
1853 int ParserBase::GetNumResults()
const
1855 return m_nFinalResultIdx;
1859 void ParserBase::Eval(
value_type* results,
int nBulkSize)
1865 #ifdef MUP_USE_OPENMP
1867 #ifdef DEBUG_OMP_STUFF
1868 int* pThread =
new int[nBulkSize];
1869 int* pIdx =
new int[nBulkSize];
1872 int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
1875 #ifdef DEBUG_OMP_STUFF
1878 omp_set_num_threads(nMaxThreads);
1880 #pragma omp parallel for schedule(static, std::max(nBulkSize/nMaxThreads, 1)) private(nThreadID)
1881 for (i = 0; i < nBulkSize; ++i)
1883 nThreadID = omp_get_thread_num();
1884 results[i] = ParseCmdCodeBulk(i, nThreadID);
1886 #ifdef DEBUG_OMP_STUFF
1887 #pragma omp critical
1889 pThread[ct] = nThreadID;
1896 #ifdef DEBUG_OMP_STUFF
1897 FILE* pFile = fopen(
"bulk_dbg.txt",
"w");
1898 for (i = 0; i < nBulkSize; ++i)
1900 fprintf(pFile,
"idx: %d thread: %d \n", pIdx[i], pThread[i]);
1910 for (i = 0; i < nBulkSize; ++i)
1912 results[i] = ParseCmdCodeBulk(i, 0);
1919 #if defined(_MSC_VER)
1920 #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.
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 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.