30 #include "muParserTemplateMagic.h"
49 #pragma warning(disable : 26812)
60 std::locale ParserBase::s_locale = std::locale(std::locale::classic(),
new change_dec_sep<char_type>(
'.'));
62 bool ParserBase::g_DbgDumpCmdCode =
false;
63 bool ParserBase::g_DbgDumpStack =
false;
71 const char_type* ParserBase::c_DefaultOprt[] =
73 _T(
"<="),
_T(
">="),
_T(
"!="),
74 _T(
"=="),
_T(
"<"),
_T(
">"),
76 _T(
"/"),
_T(
"^"),
_T(
"&&"),
77 _T(
"||"),
_T(
"="),
_T(
"("),
78 _T(
")"),
_T(
"?"),
_T(
":"), 0
81 const int ParserBase::s_MaxNumOpenMPThreads = 16;
88 ParserBase::ParserBase()
103 , m_sInfixOprtChars()
105 , m_nFinalResultIdx(0)
131 , m_sInfixOprtChars()
138 ParserBase::~ParserBase()
164 void ParserBase::Assign(
const ParserBase& a_Parser)
166 if (&a_Parser ==
this)
173 m_ConstDef = a_Parser.m_ConstDef;
174 m_VarDef = a_Parser.m_VarDef;
175 m_bBuiltInOp = a_Parser.m_bBuiltInOp;
176 m_vStringBuf = a_Parser.m_vStringBuf;
177 m_vStackBuffer = a_Parser.m_vStackBuffer;
178 m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;
179 m_StrVarDef = a_Parser.m_StrVarDef;
180 m_vStringVarBuf = a_Parser.m_vStringVarBuf;
181 m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(
this));
184 m_FunDef = a_Parser.m_FunDef;
185 m_PostOprtDef = a_Parser.m_PostOprtDef;
186 m_InfixOprtDef = a_Parser.m_InfixOprtDef;
187 m_OprtDef = a_Parser.m_OprtDef;
189 m_sNameChars = a_Parser.m_sNameChars;
190 m_sOprtChars = a_Parser.m_sOprtChars;
191 m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
204 char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(
s_locale).thousands_sep();
218 char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(
s_locale).decimal_point();
243 void ParserBase::InitTokenReader()
245 m_pTokenReader.reset(
new token_reader_type(
this));
254 void ParserBase::ReInit()
const
256 m_pParseFormula = &ParserBase::ParseString;
257 m_vStringBuf.clear();
259 m_pTokenReader->ReInit();
263 void ParserBase::OnDetectVar(
string_type* ,
int& ,
int& )
280 if (eInfo == pviFULL)
282 ss <<
_T(
" (") << ParserVersionDate;
283 ss << std::dec <<
_T(
"; ") <<
sizeof(
void*) * 8 <<
_T(
"BIT");
288 ss <<
_T(
"; RELEASE");
292 ss <<
_T(
"; UNICODE");
301 #ifdef MUP_USE_OPENMP
302 ss <<
_T(
"; OPENMP");
320 m_pTokenReader->AddValIdent(a_pCallback);
330 m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
335 void ParserBase::AddCallback(
const string_type& a_strName,
346 if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end())
349 if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end())
352 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end())
355 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end())
358 CheckOprt(a_strName, a_Callback, a_szCharSet);
359 a_Storage[a_strName] = a_Callback;
368 void ParserBase::CheckOprt(
const string_type& a_sName,
369 const ParserCallback& a_Callback,
372 if (!a_sName.length() ||
373 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
374 (a_sName[0] >=
'0' && a_sName[0] <=
'9'))
376 switch (a_Callback.GetCode())
390 void ParserBase::CheckName(
const string_type& a_sName,
393 if (!a_sName.length() ||
394 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
395 (a_sName[0] >=
'0' && a_sName[0] <=
'9'))
411 if (std::all_of(a_sExpr.begin(), a_sExpr.end(), [](
char c) {
return !std::isgraph(c); }))
417 if (m_pTokenReader->GetArgSep() == std::use_facet<numpunct<char_type> >(
s_locale).decimal_point())
421 if (a_sExpr.length() >= MaxLenExpression)
424 m_pTokenReader->SetFormula(a_sExpr +
_T(
" "));
443 m_sNameChars = a_szCharset;
452 m_sOprtChars = a_szCharset;
461 m_sInfixOprtChars = a_szCharset;
471 return m_sNameChars.c_str();
481 return m_sOprtChars.c_str();
491 return m_sInfixOprtChars.c_str();
500 if (a_sName.length() > MaxLenIdentifier)
530 if (a_sName.length() > MaxLenIdentifier)
549 if (a_sName.length() > MaxLenIdentifier)
553 for (
int i = 0; m_bBuiltInOp && i <
cmENDIF; ++i)
572 if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
577 m_vStringVarBuf.push_back(a_strVal);
578 m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1;
595 if (a_sName.length() > MaxLenIdentifier)
599 if (m_ConstDef.find(a_sName) != m_ConstDef.end())
603 m_VarDef[a_sName] = a_pVar;
616 if (a_sName.length() > MaxLenIdentifier)
620 m_ConstDef[a_sName] = a_fVal;
628 int ParserBase::GetOprtPrecedence(
const token_type& a_Tok)
const
630 switch (a_Tok.GetCode())
633 case cmEND:
return -5;
638 case cmLAND:
return prLAND;
639 case cmLOR:
return prLOR;
666 switch (a_Tok.GetCode())
680 case cmDIV:
return oaLEFT;
681 case cmPOW:
return oaRIGHT;
682 case cmOPRT_BIN:
return a_Tok.GetAssociativity();
683 default:
return oaNONE;
693 m_pTokenReader->IgnoreUndefVar(
true);
696 m_pParseFormula = &ParserBase::ParseString;
697 m_pTokenReader->IgnoreUndefVar(
false);
703 m_pParseFormula = &ParserBase::ParseString;
704 m_pTokenReader->IgnoreUndefVar(
false);
708 return m_pTokenReader->GetUsedVar();
745 return m_pTokenReader->GetExpr();
754 const std::vector<token_type>& a_vArg)
const
756 if (a_vArg.back().GetCode() !=
cmSTRING)
766 switch (a_FunTok.GetArgCount())
768 case 0: valTok.SetVal(1); a_vArg[0].GetAsString();
break;
769 case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal();
break;
770 case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
771 case 3: valTok.SetVal(1); a_vArg[3].GetAsString(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal();
break;
772 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;
782 m_vRPN.
AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
795 void ParserBase::ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal,
int a_iArgCount)
const
800 if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0)
803 token_type funTok = a_stOpt.top();
810 int iArgCount = (funTok.GetCode() ==
cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
814 int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() ==
tpSTR) ? 1 : 0);
817 int iArgNumerical = iArgCount - ((funTok.GetType() ==
tpSTR) ? 1 : 0);
819 if (funTok.GetCode() ==
cmFUNC_STR && iArgCount - iArgNumerical > 1)
822 if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
825 if (funTok.GetCode() !=
cmOPRT_BIN && iArgCount < iArgRequired)
828 if (funTok.GetCode() ==
cmFUNC_STR && iArgCount > iArgRequired)
833 std::vector<token_type> stArg;
834 for (
int i = 0; i < iArgNumerical; ++i)
839 stArg.push_back(a_stVal.top());
842 if (stArg.back().GetType() ==
tpSTR && funTok.GetType() !=
tpSTR)
846 switch (funTok.GetCode())
852 stArg.push_back(a_stVal.top());
855 if (stArg.back().GetType() ==
tpSTR && funTok.GetType() !=
tpSTR)
858 ApplyStrFunc(funTok, stArg);
862 m_vRPN.
AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
869 if (funTok.GetArgCount() == -1 && iArgCount == 0)
872 m_vRPN.
AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical);
885 void ParserBase::ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal)
const
888 while (a_stOpt.size() && a_stOpt.top().GetCode() ==
cmELSE)
891 token_type opElse = a_stOpt.top();
896 token_type vVal2 = a_stVal.top();
902 token_type vVal1 = a_stVal.top();
906 token_type vExpr = a_stVal.top();
909 a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2);
911 token_type opIf = a_stOpt.top();
916 if (opIf.GetCode() !=
cmIF)
917 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
927 void ParserBase::ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal)
const
932 ApplyFunc(a_stOpt, a_stVal, 2);
936 if (a_stVal.size() < 2)
939 token_type valTok1 = a_stVal.top();
942 token_type valTok2 = a_stVal.top();
945 token_type optTok = a_stOpt.top();
950 if (valTok1.GetType() != valTok2.GetType() ||
951 (valTok1.GetType() ==
tpSTR && valTok2.GetType() ==
tpSTR))
956 if (valTok2.GetCode() !=
cmVAR)
962 m_vRPN.
AddOp(optTok.GetCode());
965 a_stVal.push(resTok);
974 void ParserBase::ApplyRemainingOprt(std::stack<token_type>& stOpt, std::stack<token_type>& stVal)
const
976 while (stOpt.size() &&
977 stOpt.top().GetCode() !=
cmBO &&
978 stOpt.top().GetCode() !=
cmIF)
980 token_type tok = stOpt.top();
981 switch (tok.GetCode())
1000 ApplyFunc(stOpt, stVal, 1);
1002 ApplyBinOprt(stOpt, stVal);
1006 ApplyIfElse(stOpt, stVal);
1025 return ParseCmdCodeBulk(0, 0);
1028 value_type ParserBase::ParseCmdCodeShort()
const
1030 const SToken *
const tok = m_vRPN.GetBase();
1036 return tok->Val.data2;
1039 return *tok->Val.ptr;
1042 return *tok->Val.ptr * tok->Val.data + tok->Val.data2;
1045 buf = *(tok->Val.ptr);
1049 buf = *(tok->Val.ptr);
1050 return buf * buf * buf;
1053 buf = *(tok->Val.ptr);
1054 return buf * buf * buf * buf;
1062 return (*(
strfun_type1)tok->Fun.ptr)(m_vStringBuf[0].c_str());
1074 value_type ParserBase::ParseCmdCodeBulk(
int nOffset,
int nThreadID)
const
1076 assert(nThreadID <= s_MaxNumOpenMPThreads);
1080 value_type* Stack = ((nOffset == 0) && (nThreadID == 0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
1083 for (
const SToken* pTok = m_vRPN.GetBase(); pTok->Cmd !=
cmEND; ++pTok)
1088 case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx + 1];
continue;
1089 case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx + 1];
continue;
1090 case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx + 1];
continue;
1091 case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx + 1];
continue;
1092 case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx + 1];
continue;
1093 case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx + 1];
continue;
1094 case cmADD: --sidx; Stack[sidx] += Stack[1 + sidx];
continue;
1095 case cmSUB: --sidx; Stack[sidx] -= Stack[1 + sidx];
continue;
1096 case cmMUL: --sidx; Stack[sidx] *= Stack[1 + sidx];
continue;
1098 Stack[sidx] /= Stack[1 + sidx];
1102 --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1 + sidx]);
1105 case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx + 1];
continue;
1106 case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx + 1];
continue;
1112 --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1];
continue;
1117 if (Stack[sidx--] == 0)
1120 pTok += pTok->Oprt.offset;
1125 pTok += pTok->Oprt.offset;
1132 case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset);
continue;
1133 case cmVAL: Stack[++sidx] = pTok->Val.data2;
continue;
1135 case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
1136 Stack[++sidx] = buf * buf;
1139 case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
1140 Stack[++sidx] = buf * buf * buf;
1143 case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
1144 Stack[++sidx] = buf * buf * buf * buf;
1148 Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
1154 int iArgCount = pTok->Fun.argc;
1159 case 0: sidx += 1; Stack[sidx] = (*(
fun_type0)pTok->Fun.ptr)();
continue;
1160 case 1: Stack[sidx] = (*(
fun_type1)pTok->Fun.ptr)(Stack[sidx]);
continue;
1161 case 2: sidx -= 1; Stack[sidx] = (*(
fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1]);
continue;
1162 case 3: sidx -= 2; Stack[sidx] = (*(
fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]);
continue;
1163 case 4: sidx -= 3; Stack[sidx] = (*(
fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3]);
continue;
1164 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;
1165 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;
1166 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;
1167 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;
1168 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;
1169 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;
1175 sidx -= -iArgCount - 1;
1182 Stack[sidx] = (*(
multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
1190 sidx -= pTok->Fun.argc - 1;
1193 int iIdxStack = pTok->Fun.idx;
1194 if (iIdxStack < 0 || iIdxStack >= (
int)m_vStringBuf.size())
1197 switch (pTok->Fun.argc)
1199 case 0: Stack[sidx] = (*(
strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str());
continue;
1200 case 1: Stack[sidx] = (*(
strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]);
continue;
1201 case 2: Stack[sidx] = (*(
strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1]);
continue;
1202 case 3: Stack[sidx] = (*(
strfun_type4)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]);
continue;
1203 case 4: Stack[sidx] = (*(
strfun_type5)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3]);
continue;
1211 int iArgCount = pTok->Fun.argc;
1216 case 0: sidx += 1; Stack[sidx] = (*(
bulkfun_type0)pTok->Fun.ptr)(nOffset, nThreadID);
continue;
1217 case 1: Stack[sidx] = (*(
bulkfun_type1)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]);
continue;
1218 case 2: sidx -= 1; Stack[sidx] = (*(
bulkfun_type2)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1]);
continue;
1219 case 3: sidx -= 2; Stack[sidx] = (*(
bulkfun_type3)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]);
continue;
1220 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;
1221 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;
1222 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;
1223 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;
1224 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;
1225 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;
1226 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;
1239 return Stack[m_nFinalResultIdx];
1243 void ParserBase::CreateRPN()
const
1245 if (!m_pTokenReader->GetExpr().length())
1248 std::stack<token_type> stOpt, stVal;
1249 std::stack<int> stArgCount;
1250 token_type opta, opt;
1251 token_type val, tval;
1252 int ifElseCounter = 0;
1262 opt = m_pTokenReader->ReadNextToken();
1264 switch (opt.GetCode())
1271 Error(
ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString());
1273 opt.SetIdx((
int)m_vStringBuf.size());
1275 m_vStringBuf.push_back(opt.GetAsString());
1280 m_vRPN.AddVar(static_cast<value_type*>(opt.GetVar()));
1285 m_vRPN.AddVal(opt.GetVal());
1289 if (stArgCount.empty())
1290 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1292 if (stArgCount.top() > 1)
1298 if (ifElseCounter < 0)
1299 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1301 ApplyRemainingOprt(stOpt, stVal);
1302 m_vRPN.AddIfElse(
cmELSE);
1307 if (!stOpt.empty() && stOpt.top().GetCode() ==
cmIF)
1310 if (stArgCount.empty())
1318 ApplyRemainingOprt(stOpt, stVal);
1327 if (opta.GetCode() ==
cmBO)
1330 ApplyRemainingOprt(stOpt, stVal);
1333 if (stOpt.size() && stOpt.top().GetCode() ==
cmBO)
1342 int iArgCount = stArgCount.top();
1347 if (iArgCount > 1 && (stOpt.size() == 0 ||
1348 (stOpt.top().GetCode() !=
cmFUNC &&
1358 stOpt.top().GetFuncAddr() != 0)
1360 ApplyFunc(stOpt, stVal, iArgCount);
1394 stOpt.top().GetCode() !=
cmBO &&
1395 stOpt.top().GetCode() !=
cmELSE &&
1396 stOpt.top().GetCode() !=
cmIF)
1398 int nPrec1 = GetOprtPrecedence(stOpt.top()),
1399 nPrec2 = GetOprtPrecedence(opt);
1401 if (stOpt.top().GetCode() == opt.GetCode())
1406 if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
1407 (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)))
1412 else if (nPrec1 < nPrec2)
1419 ApplyFunc(stOpt, stVal, 1);
1421 ApplyBinOprt(stOpt, stVal);
1424 if (opt.GetCode() ==
cmIF)
1425 m_vRPN.AddIfElse(opt.GetCode());
1448 ApplyFunc(stOpt, stVal, 1);
1456 if (opt.GetCode() ==
cmEND)
1462 if (ParserBase::g_DbgDumpStack)
1464 StackDump(stVal, stOpt);
1472 if (ParserBase::g_DbgDumpCmdCode)
1475 if (ifElseCounter > 0)
1476 Error(ecMISSING_ELSE_CLAUSE);
1480 m_nFinalResultIdx = stArgCount.top();
1481 if (m_nFinalResultIdx == 0)
1484 if (stVal.size() == 0)
1487 if (stVal.top().GetType() !=
tpDBL)
1490 m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
1508 if (m_vRPN.GetSize() == 2)
1510 m_pParseFormula = &ParserBase::ParseCmdCodeShort;
1514 m_pParseFormula = &ParserBase::ParseCmdCode;
1517 return (this->*m_pParseFormula)();
1519 catch (ParserError& exc)
1521 exc.SetFormula(m_pTokenReader->GetExpr());
1539 throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
1548 void ParserBase::ClearVar()
1562 varmap_type::iterator item = m_VarDef.find(a_strVarName);
1563 if (item != m_VarDef.end())
1565 m_VarDef.erase(item);
1575 void ParserBase::ClearFun()
1588 void ParserBase::ClearConst()
1591 m_StrVarDef.clear();
1600 void ParserBase::ClearPostfixOprt()
1602 m_PostOprtDef.clear();
1611 void ParserBase::ClearOprt()
1622 void ParserBase::ClearInfixOprt()
1624 m_InfixOprtDef.clear();
1633 void ParserBase::EnableOptimizer(
bool a_bIsOn)
1635 m_vRPN.EnableOptimizer(a_bIsOn);
1646 void ParserBase::EnableDebugDump(
bool bDumpCmd,
bool bDumpStack)
1648 ParserBase::g_DbgDumpCmdCode = bDumpCmd;
1649 ParserBase::g_DbgDumpStack = bDumpStack;
1662 void ParserBase::EnableBuiltInOprt(
bool a_bIsOn)
1664 m_bBuiltInOp = a_bIsOn;
1673 bool ParserBase::HasBuiltInOprt()
const
1675 return m_bBuiltInOp;
1683 return m_pTokenReader->GetArgSep();
1692 m_pTokenReader->SetArgSep(cArgSep);
1700 void ParserBase::StackDump(
const std::stack<token_type>& a_stVal,
const std::stack<token_type>& a_stOprt)
const
1702 std::stack<token_type> stOprt(a_stOprt);
1703 std::stack<token_type> stVal(a_stVal);
1706 while (!stVal.empty())
1708 token_type val = stVal.top();
1711 if (val.GetType() ==
tpSTR)
1718 while (!stOprt.empty())
1720 if (stOprt.top().GetCode() <=
cmASSIGN)
1723 << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
1728 switch (stOprt.top().GetCode())
1735 << stOprt.top().GetAsString()
1741 <<
_T(
"FUNC_BULK \"")
1742 << stOprt.top().GetAsString()
1748 << stOprt.top().GetAsString()
1754 << stOprt.top().GetAsString()
1766 default:
mu::console() << stOprt.top().GetCode() <<
_T(
" ");
break;
1792 return (this->*m_pParseFormula)();
1805 if (m_vRPN.GetSize() > 0)
1814 nStackSize = m_nFinalResultIdx;
1817 return &m_vStackBuffer[1];
1827 int ParserBase::GetNumResults()
const
1829 return m_nFinalResultIdx;
1833 void ParserBase::Eval(
value_type* results,
int nBulkSize)
1839 #ifdef MUP_USE_OPENMP
1841 #ifdef DEBUG_OMP_STUFF
1842 int* pThread =
new int[nBulkSize];
1843 int* pIdx =
new int[nBulkSize];
1846 int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
1849 #ifdef DEBUG_OMP_STUFF
1852 omp_set_num_threads(nMaxThreads);
1854 #pragma omp parallel for schedule(static, std::max(nBulkSize/nMaxThreads, 1)) private(nThreadID)
1855 for (i = 0; i < nBulkSize; ++i)
1857 nThreadID = omp_get_thread_num();
1858 results[i] = ParseCmdCodeBulk(i, nThreadID);
1860 #ifdef DEBUG_OMP_STUFF
1861 #pragma omp critical
1863 pThread[ct] = nThreadID;
1870 #ifdef DEBUG_OMP_STUFF
1871 FILE* pFile = fopen(
"bulk_dbg.txt",
"w");
1872 for (i = 0; i < nBulkSize; ++i)
1874 fprintf(pFile,
"idx: %d thread: %d \n", pIdx[i], pThread[i]);
1884 for (i = 0; i < nBulkSize; ++i)
1886 results[i] = ParseCmdCodeBulk(i, 0);
1893 #if defined(_MSC_VER)
1894 #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.
value_type(* strfun_type1)(const char_type *)
Callback type used for functions taking a string as an argument.
user defined binary operator
#define _T(x)
Activate this option in order to compile with OpenMP support.
value_type(* bulkfun_type1)(int, int, value_type)
Callback type used for functions with a single arguments.
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 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.
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)
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.
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
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.
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 eight arguments.
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_type5)(value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
value_type(* bulkfun_type2)(int, int, value_type, value_type)
Callback type used for functions with two arguments.
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.
value_type(* strfun_type4)(const char_type *, value_type, value_type, value_type)
Callback type used for functions taking a string and a value as arguments.
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 nine 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.
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.
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 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.
value_type(* multfun_type)(const value_type *, int)
Callback type used for functions with a variable argument list.
const string_type & GetExpr() const
Retrieve the formula.
Code for a generic function item.
EOprtAssociativity
Parser operator precedence values.
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 eight arguments.
void DefineOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of binary operators and postfix operators...
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(* bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with six arguments.
const char_type * ValidNameChars() const
Virtual function that defines the characters allowed in name identifiers.
value_type(* strfun_type5)(const char_type *, value_type, value_type, value_type, value_type)
Callback type used for functions taking a string and two values as arguments.
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.
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 ten 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 nine arguments.
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.
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.
value_type(* strfun_type2)(const char_type *, value_type)
Callback type used for functions taking a string and a value as arguments.
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.
value_type(* fun_type3)(value_type, value_type, value_type)
Callback type used for functions with three arguments.
value_type(* fun_type0)()
Callback type used for functions without arguments.
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.
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.
void * GetAddr() const
Get the callback address for the parser function.
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 seven arguments.
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.
value_type(* fun_type4)(value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
Unexpected binary operator found.
MUP_STRING_TYPE string_type
The stringtype used by the parser.
value_type(* fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with seven arguments.
void clear()
Delete the bytecode.
Operator item: less or equal.
value_type(* bulkfun_type4)(int, int, value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
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.
The expression or identifier contains invalid non printable characters.
value_type(* bulkfun_type0)(int, int)
Callback type used for functions without arguments.
Floating point variables.
value_type(* bulkfun_type3)(int, int, value_type, value_type, value_type)
Callback type used for functions with three arguments.
void Init()
Initialize user defined functions.
Encapsulation of prototypes for a numerical parser function.
value_type(* fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with six arguments.
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.
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 ten arguments.