3 _____ __ _____________ _______ ______ ___________
4 / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5 | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6 |__|_| /____/| __(____ /__| /____ >\___ >__|
8 Copyright (C) 2004 - 2020 Ingo Berg
10 Redistribution and use in source and binary forms, with or without modification, are permitted
11 provided that the following conditions are met:
13 * Redistributions of source code must retain the above copyright notice, this list of
14 conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice, this list of
16 conditions and the following disclaimer in the documentation and/or other materials provided
17 with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "muParserBase.h"
30 #include "muParserTemplateMagic.h"
32 //--- Standard includes ------------------------------------------------------------------------
49 #pragma warning(disable : 26812)
55 \brief This file contains the basic implementation of the muparser engine.
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;
65 //------------------------------------------------------------------------------
66 /** \brief Identifiers for built in binary operators.
68 When defining custom binary operators with #AddOprt(...) make sure not to choose
69 names conflicting with these definitions.
71 const char_type* ParserBase::c_DefaultOprt[] =
73 _T("<="), _T(">="), _T("!="),
74 _T("=="), _T("<"), _T(">"),
75 _T("+"), _T("-"), _T("*"),
76 _T("/"), _T("^"), _T("&&"),
77 _T("||"), _T("="), _T("("),
78 _T(")"), _T("?"), _T(":"), 0
81 const int ParserBase::s_MaxNumOpenMPThreads = 16;
83 //------------------------------------------------------------------------------
84 /** \brief Constructor.
85 \param a_szFormula the formula to interpret.
86 \throw ParserException if a_szFormula is nullptr.
88 ParserBase::ParserBase()
89 : m_pParseFormula(&ParserBase::ParseString)
103 , m_sInfixOprtChars()
105 , m_nFinalResultIdx(0)
110 //---------------------------------------------------------------------------
111 /** \brief Copy constructor.
113 The parser can be safely copy constructed but the bytecode is reset during
116 ParserBase::ParserBase(const ParserBase& a_Parser)
117 : m_pParseFormula(&ParserBase::ParseString)
131 , m_sInfixOprtChars()
133 m_pTokenReader.reset(new token_reader_type(this));
137 //---------------------------------------------------------------------------
138 ParserBase::~ParserBase()
141 //---------------------------------------------------------------------------
142 /** \brief Assignment operator.
144 Implemented by calling Assign(a_Parser). Self assignment is suppressed.
145 \param a_Parser Object to copy to this.
149 ParserBase& ParserBase::operator=(const ParserBase& a_Parser)
155 //---------------------------------------------------------------------------
156 /** \brief Copy state of a parser object to this.
158 Clears Variables and Functions of this parser.
159 Copies the states of all internal variables.
160 Resets parse function to string parse mode.
162 \param a_Parser the source object.
164 void ParserBase::Assign(const ParserBase& a_Parser)
166 if (&a_Parser == this)
169 // Don't copy bytecode instead cause the parser to create new bytecode
170 // by resetting the parse function.
173 m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants
174 m_VarDef = a_Parser.m_VarDef; // Copy user defined variables
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));
183 // Copy function and operator callbacks
184 m_FunDef = a_Parser.m_FunDef; // Copy function definitions
185 m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators
186 m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation
187 m_OprtDef = a_Parser.m_OprtDef; // binary operators
189 m_sNameChars = a_Parser.m_sNameChars;
190 m_sOprtChars = a_Parser.m_sOprtChars;
191 m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
194 //---------------------------------------------------------------------------
195 /** \brief Set the decimal separator.
196 \param cDecSep Decimal separator as a character value.
199 By default muparser uses the "C" locale. The decimal separator of this
200 locale is overwritten by the one provided here.
202 void ParserBase::SetDecSep(char_type cDecSep)
204 char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();
205 s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
208 //---------------------------------------------------------------------------
209 /** \brief Sets the thousands operator.
210 \param cThousandsSep The thousands separator as a character
213 By default muparser uses the "C" locale. The thousands separator of this
214 locale is overwritten by the one provided here.
216 void ParserBase::SetThousandsSep(char_type cThousandsSep)
218 char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();
219 s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
222 //---------------------------------------------------------------------------
223 /** \brief Resets the locale.
225 The default locale used "." as decimal separator, no thousands separator and
226 "," as function argument separator.
228 void ParserBase::ResetLocale()
230 s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));
234 //---------------------------------------------------------------------------
235 /** \brief Initialize the token reader.
237 Create new token reader object and submit pointers to function, operator,
238 constant and variable definitions.
240 \post m_pTokenReader.get()!=0
243 void ParserBase::InitTokenReader()
245 m_pTokenReader.reset(new token_reader_type(this));
248 //---------------------------------------------------------------------------
249 /** \brief Reset parser to string parsing mode and clear internal buffers.
251 Clear bytecode, reset the token reader.
254 void ParserBase::ReInit() const
256 m_pParseFormula = &ParserBase::ParseString;
257 m_vStringBuf.clear();
259 m_pTokenReader->ReInit();
262 //---------------------------------------------------------------------------
263 void ParserBase::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/)
266 //---------------------------------------------------------------------------
267 /** \brief Returns the version of muparser.
268 \param eInfo A flag indicating whether the full version info should be
271 Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS
272 are returned only if eInfo==pviFULL.
274 string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const
276 stringstream_type ss;
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");
311 //---------------------------------------------------------------------------
312 /** \brief Add a value parsing function.
314 When parsing an expression muParser tries to detect values in the expression
315 string using different valident callbacks. Thus it's possible to parse
316 for hex values, binary values and floating point values.
318 void ParserBase::AddValIdent(identfun_type a_pCallback)
320 m_pTokenReader->AddValIdent(a_pCallback);
323 //---------------------------------------------------------------------------
324 /** \brief Set a function that can create variable pointer for unknown expression variables.
325 \param a_pFactory A pointer to the variable factory.
326 \param pUserData A user defined context pointer.
328 void ParserBase::SetVarFactory(facfun_type a_pFactory, void* pUserData)
330 m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
333 //---------------------------------------------------------------------------
334 /** \brief Add a function or operator callback to the parser. */
335 void ParserBase::AddCallback(const string_type& a_strName,
336 const ParserCallback& a_Callback,
337 funmap_type& a_Storage,
338 const char_type* a_szCharSet)
340 if (a_Callback.GetAddr() == 0)
341 Error(ecINVALID_FUN_PTR);
343 const funmap_type* pFunMap = &a_Storage;
345 // Check for conflicting operator or function names
346 if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end())
347 Error(ecNAME_CONFLICT, -1, a_strName);
349 if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end())
350 Error(ecNAME_CONFLICT, -1, a_strName);
352 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end())
353 Error(ecNAME_CONFLICT, -1, a_strName);
355 if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end())
356 Error(ecNAME_CONFLICT, -1, a_strName);
358 CheckOprt(a_strName, a_Callback, a_szCharSet);
359 a_Storage[a_strName] = a_Callback;
363 //---------------------------------------------------------------------------
364 /** \brief Check if a name contains invalid characters.
366 \throw ParserException if the name contains invalid characters.
368 void ParserBase::CheckOprt(const string_type& a_sName,
369 const ParserCallback& a_Callback,
370 const string_type& a_szCharSet) const
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())
378 case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); break;
379 case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); break;
380 default: Error(ecINVALID_NAME, -1, a_sName);
385 //---------------------------------------------------------------------------
386 /** \brief Check if a name contains invalid characters.
388 \throw ParserException if the name contains invalid characters.
390 void ParserBase::CheckName(const string_type& a_sName,
391 const string_type& a_szCharSet) const
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'))
397 Error(ecINVALID_NAME);
401 //---------------------------------------------------------------------------
402 /** \brief Set the formula.
403 \param a_strFormula Formula as string_type
404 \throw ParserException in case of syntax errors.
406 Triggers first time calculation thus the creation of the bytecode and
407 scanning of used variables.
409 void ParserBase::SetExpr(const string_type& a_sExpr)
411 if (std::all_of(a_sExpr.begin(), a_sExpr.end(), [](char c) { return !std::isgraph(c); }))
413 Error(ecINVALID_CHARACTERS_FOUND);
416 // Check locale compatibility
417 if (m_pTokenReader->GetArgSep() == std::use_facet<numpunct<char_type> >(s_locale).decimal_point())
420 // Check maximum allowed expression length. An arbitrary value small enough so i can debug expressions sent to me
421 if (a_sExpr.length() >= MaxLenExpression)
422 Error(ecEXPRESSION_TOO_LONG, 0, a_sExpr);
424 m_pTokenReader->SetFormula(a_sExpr + _T(" "));
428 //---------------------------------------------------------------------------
429 /** \brief Get the default symbols used for the built in operators.
432 const char_type** ParserBase::GetOprtDef() const
434 return (const char_type**)(&c_DefaultOprt[0]);
437 //---------------------------------------------------------------------------
438 /** \brief Define the set of valid characters to be used in names of
439 functions, variables, constants.
441 void ParserBase::DefineNameChars(const char_type* a_szCharset)
443 m_sNameChars = a_szCharset;
446 //---------------------------------------------------------------------------
447 /** \brief Define the set of valid characters to be used in names of
448 binary operators and postfix operators.
450 void ParserBase::DefineOprtChars(const char_type* a_szCharset)
452 m_sOprtChars = a_szCharset;
455 //---------------------------------------------------------------------------
456 /** \brief Define the set of valid characters to be used in names of
459 void ParserBase::DefineInfixOprtChars(const char_type* a_szCharset)
461 m_sInfixOprtChars = a_szCharset;
464 //---------------------------------------------------------------------------
465 /** \brief Virtual function that defines the characters allowed in name identifiers.
466 \sa #ValidOprtChars, #ValidPrefixOprtChars
468 const char_type* ParserBase::ValidNameChars() const
470 MUP_ASSERT(m_sNameChars.size());
471 return m_sNameChars.c_str();
474 //---------------------------------------------------------------------------
475 /** \brief Virtual function that defines the characters allowed in operator definitions.
476 \sa #ValidNameChars, #ValidPrefixOprtChars
478 const char_type* ParserBase::ValidOprtChars() const
480 MUP_ASSERT(m_sOprtChars.size());
481 return m_sOprtChars.c_str();
484 //---------------------------------------------------------------------------
485 /** \brief Virtual function that defines the characters allowed in infix operator definitions.
486 \sa #ValidNameChars, #ValidOprtChars
488 const char_type* ParserBase::ValidInfixOprtChars() const
490 MUP_ASSERT(m_sInfixOprtChars.size());
491 return m_sInfixOprtChars.c_str();
494 //---------------------------------------------------------------------------
495 /** \brief Add a user defined operator.
496 \post Will reset the Parser to string parsing mode.
498 void ParserBase::DefinePostfixOprt(const string_type& a_sName, fun_type1 a_pFun, bool a_bAllowOpt)
500 if (a_sName.length() > MaxLenIdentifier)
501 Error(ecIDENTIFIER_TOO_LONG);
503 AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), m_PostOprtDef, ValidOprtChars());
506 //---------------------------------------------------------------------------
507 /** \brief Initialize user defined functions.
509 Calls the virtual functions InitFun(), InitConst() and InitOprt().
511 void ParserBase::Init()
519 //---------------------------------------------------------------------------
520 /** \brief Add a user defined operator.
521 \post Will reset the Parser to string parsing mode.
522 \param [in] a_sName operator Identifier
523 \param [in] a_pFun Operator callback function
524 \param [in] a_iPrec Operator Precedence (default=prSIGN)
525 \param [in] a_bAllowOpt True if operator is volatile (default=false)
528 void ParserBase::DefineInfixOprt(const string_type& a_sName, fun_type1 a_pFun, int a_iPrec, bool a_bAllowOpt)
530 if (a_sName.length() > MaxLenIdentifier)
531 Error(ecIDENTIFIER_TOO_LONG);
533 AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, ValidInfixOprtChars());
537 //---------------------------------------------------------------------------
538 /** \brief Define a binary operator.
539 \param [in] a_sName The identifier of the operator.
540 \param [in] a_pFun Pointer to the callback function.
541 \param [in] a_iPrec Precedence of the operator.
542 \param [in] a_eAssociativity The associativity of the operator.
543 \param [in] a_bAllowOpt If this is true the operator may be optimized away.
545 Adds a new Binary operator the the parser instance.
547 void ParserBase::DefineOprt(const string_type& a_sName, fun_type2 a_pFun, unsigned a_iPrec, EOprtAssociativity a_eAssociativity, bool a_bAllowOpt)
549 if (a_sName.length() > MaxLenIdentifier)
550 Error(ecIDENTIFIER_TOO_LONG);
552 // Check for conflicts with built in operator names
553 for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i)
555 if (a_sName == string_type(c_DefaultOprt[i]))
557 Error(ecBUILTIN_OVERLOAD, -1, a_sName);
561 AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), m_OprtDef, ValidOprtChars());
564 //---------------------------------------------------------------------------
565 /** \brief Define a new string constant.
566 \param [in] a_strName The name of the constant.
567 \param [in] a_strVal the value of the constant.
569 void ParserBase::DefineStrConst(const string_type& a_strName, const string_type& a_strVal)
571 // Test if a constant with that names already exists
572 if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
573 Error(ecNAME_CONFLICT);
575 CheckName(a_strName, ValidNameChars());
577 m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer
578 m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1; // bind buffer index to variable name
583 //---------------------------------------------------------------------------
584 /** \brief Add a user defined variable.
585 \param [in] a_sName the variable name
586 \param [in] a_pVar A pointer to the variable value.
587 \post Will reset the Parser to string parsing mode.
588 \throw ParserException in case the name contains invalid signs or a_pVar is nullptr.
590 void ParserBase::DefineVar(const string_type& a_sName, value_type* a_pVar)
593 Error(ecINVALID_VAR_PTR);
595 if (a_sName.length() > MaxLenIdentifier)
596 Error(ecIDENTIFIER_TOO_LONG);
598 // Test if a constant with that names already exists
599 if (m_ConstDef.find(a_sName) != m_ConstDef.end())
600 Error(ecNAME_CONFLICT);
602 CheckName(a_sName, ValidNameChars());
603 m_VarDef[a_sName] = a_pVar;
607 //---------------------------------------------------------------------------
608 /** \brief Add a user defined constant.
609 \param [in] a_sName The name of the constant.
610 \param [in] a_fVal the value of the constant.
611 \post Will reset the Parser to string parsing mode.
612 \throw ParserException in case the name contains invalid signs.
614 void ParserBase::DefineConst(const string_type& a_sName, value_type a_fVal)
616 if (a_sName.length() > MaxLenIdentifier)
617 Error(ecIDENTIFIER_TOO_LONG);
619 CheckName(a_sName, ValidNameChars());
620 m_ConstDef[a_sName] = a_fVal;
624 //---------------------------------------------------------------------------
625 /** \brief Get operator priority.
626 \throw ParserException if a_Oprt is no operator code
628 int ParserBase::GetOprtPrecedence(const token_type& a_Tok) const
630 switch (a_Tok.GetCode())
632 // built in operators
633 case cmEND: return -5;
634 case cmARG_SEP: return -4;
635 case cmASSIGN: return -1;
638 case cmLAND: return prLAND;
639 case cmLOR: return prLOR;
645 case cmEQ: return prCMP;
647 case cmSUB: return prADD_SUB;
649 case cmDIV: return prMUL_DIV;
650 case cmPOW: return prPOW;
652 // user defined binary operators
654 case cmOPRT_BIN: return a_Tok.GetPri();
655 default: Error(ecINTERNAL_ERROR, 5);
660 //---------------------------------------------------------------------------
661 /** \brief Get operator priority.
662 \throw ParserException if a_Oprt is no operator code
664 EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type& a_Tok) const
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;
687 //---------------------------------------------------------------------------
688 /** \brief Return a map containing the used variables only. */
689 const varmap_type& ParserBase::GetUsedVar() const
693 m_pTokenReader->IgnoreUndefVar(true);
694 CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it
695 // may contain references to nonexisting variables.
696 m_pParseFormula = &ParserBase::ParseString;
697 m_pTokenReader->IgnoreUndefVar(false);
699 catch (exception_type& /*e*/)
701 // Make sure to stay in string parse mode, don't call ReInit()
702 // because it deletes the array with the used variables
703 m_pParseFormula = &ParserBase::ParseString;
704 m_pTokenReader->IgnoreUndefVar(false);
708 return m_pTokenReader->GetUsedVar();
711 //---------------------------------------------------------------------------
712 /** \brief Return a map containing the used variables only. */
713 const varmap_type& ParserBase::GetVar() const
718 //---------------------------------------------------------------------------
719 /** \brief Return a map containing all parser constants. */
720 const valmap_type& ParserBase::GetConst() const
725 //---------------------------------------------------------------------------
726 /** \brief Return prototypes of all parser functions.
731 The return type is a map of the public type #funmap_type containing the prototype
732 definitions for all numerical parser functions. String functions are not part of
733 this map. The Prototype definition is encapsulated in objects of the class FunProt
734 one per parser function each associated with function names via a map construct.
736 const funmap_type& ParserBase::GetFunDef() const
741 //---------------------------------------------------------------------------
742 /** \brief Retrieve the formula. */
743 const string_type& ParserBase::GetExpr() const
745 return m_pTokenReader->GetExpr();
748 //---------------------------------------------------------------------------
749 /** \brief Execute a function that takes a single string argument.
750 \param a_FunTok Function token.
751 \throw exception_type If the function token is not a string function
753 ParserBase::token_type ParserBase::ApplyStrFunc(const token_type& a_FunTok,
754 const std::vector<token_type>& a_vArg) const
756 if (a_vArg.back().GetCode() != cmSTRING)
757 Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
760 generic_fun_type pFunc = a_FunTok.GetFuncAddr();
765 // Check function arguments; write dummy value into valtok to represent the result
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;
773 default: Error(ecINTERNAL_ERROR);
778 Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
781 // string functions won't be optimized
782 m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
784 // Push dummy value representing the function result to the stack
788 //---------------------------------------------------------------------------
789 /** \brief Apply a function token.
790 \param iArgCount Number of Arguments actually gathered used only for multiarg functions.
791 \post The result is pushed to the value stack
792 \post The function token is removed from the stack
793 \throw exception_type if Argument count does not match function requirements.
795 void ParserBase::ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int a_iArgCount) const
797 MUP_ASSERT(m_pTokenReader.get());
799 // Operator stack empty or does not contain tokens with callback functions
800 if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0)
803 token_type funTok = a_stOpt.top();
805 MUP_ASSERT(funTok.GetFuncAddr() != nullptr);
807 // Binary operators must rely on their internal operator number
808 // since counting of operators relies on commas for function arguments
809 // binary operators do not have commas in their expression
810 int iArgCount = (funTok.GetCode() == cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
812 // determine how many parameters the function needs. To remember iArgCount includes the
813 // string parameter whilst GetArgCount() counts only numeric parameters.
814 int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() == tpSTR) ? 1 : 0);
816 // That's the number of numerical parameters
817 int iArgNumerical = iArgCount - ((funTok.GetType() == tpSTR) ? 1 : 0);
819 if (funTok.GetCode() == cmFUNC_STR && iArgCount - iArgNumerical > 1)
820 Error(ecINTERNAL_ERROR);
822 if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
823 Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
825 if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired)
826 Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
828 if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired)
829 Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
831 // Collect the numeric function arguments from the value stack and store them
833 std::vector<token_type> stArg;
834 for (int i = 0; i < iArgNumerical; ++i)
837 Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString());
839 stArg.push_back(a_stVal.top());
842 if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR)
843 Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
846 switch (funTok.GetCode())
850 Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString());
852 stArg.push_back(a_stVal.top());
855 if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR)
856 Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
858 ApplyStrFunc(funTok, stArg);
862 m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
869 if (funTok.GetArgCount() == -1 && iArgCount == 0)
870 Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());
872 m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical);
878 // Push dummy value representing the function result to the stack
884 //---------------------------------------------------------------------------
885 void ParserBase::ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const
887 // Check if there is an if Else clause to be calculated
888 while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE)
890 MUP_ASSERT(!a_stOpt.empty())
891 token_type opElse = a_stOpt.top();
894 // Take the value associated with the else branch from the value stack
895 MUP_ASSERT(!a_stVal.empty());
896 token_type vVal2 = a_stVal.top();
899 // it then else is a ternary operator Pop all three values from the value s
900 // tack and just return the right value
901 MUP_ASSERT(!a_stVal.empty());
902 token_type vVal1 = a_stVal.top();
905 MUP_ASSERT(!a_stVal.empty());
906 token_type vExpr = a_stVal.top();
909 a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2);
911 token_type opIf = a_stOpt.top();
914 MUP_ASSERT(opElse.GetCode() == cmELSE);
916 if (opIf.GetCode() != cmIF)
917 Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
919 m_vRPN.AddIfElse(cmENDIF);
920 } // while pending if-else-clause found
923 //---------------------------------------------------------------------------
924 /** \brief Performs the necessary steps to write code for
925 the execution of binary operators into the bytecode.
927 void ParserBase::ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const
929 // is it a user defined binary operator?
930 if (a_stOpt.top().GetCode() == cmOPRT_BIN)
932 ApplyFunc(a_stOpt, a_stVal, 2);
936 if (a_stVal.size() < 2)
937 Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), _T("ApplyBinOprt: not enough values in value stack!"));
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))
952 Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());
954 if (optTok.GetCode() == cmASSIGN)
956 if (valTok2.GetCode() != cmVAR)
957 Error(ecUNEXPECTED_OPERATOR, -1, _T("="));
959 m_vRPN.AddAssignOp(valTok2.GetVar());
962 m_vRPN.AddOp(optTok.GetCode());
965 a_stVal.push(resTok);
969 //---------------------------------------------------------------------------
970 /** \brief Apply a binary operator.
971 \param a_stOpt The operator stack
972 \param a_stVal The value stack
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())
999 if (stOpt.top().GetCode() == cmOPRT_INFIX)
1000 ApplyFunc(stOpt, stVal, 1);
1002 ApplyBinOprt(stOpt, stVal);
1006 ApplyIfElse(stOpt, stVal);
1010 Error(ecINTERNAL_ERROR);
1015 //---------------------------------------------------------------------------
1016 /** \brief Parse the command code.
1017 \sa ParseString(...)
1019 Command code contains precalculated stack positions of the values and the
1020 associated operators. The Stack is filled beginning from index one the
1021 value at index zero is not used at all.
1023 value_type ParserBase::ParseCmdCode() const
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;
1056 // numerical function without any argument
1058 return (*(fun_type0)tok->Fun.ptr)();
1060 // String function without a numerical argument
1062 return (*(strfun_type1)tok->Fun.ptr)(m_vStringBuf[0].c_str());
1065 throw ParserError(ecINTERNAL_ERROR);
1069 //---------------------------------------------------------------------------
1070 /** \brief Evaluate the RPN.
1071 \param nOffset The offset added to variable addresses (for bulk mode)
1072 \param nThreadID OpenMP Thread id of the calling thread
1074 value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const
1076 assert(nThreadID <= s_MaxNumOpenMPThreads);
1078 // Note: The check for nOffset==0 and nThreadID here is not necessary but
1079 // brings a minor performance gain when not in bulk mode.
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)
1087 // built in binary operators
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;
1109 // Bugfix for Bulkmode:
1111 // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws
1112 --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue;
1114 //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue;
1117 if (Stack[sidx--] == 0)
1119 MUP_ASSERT(sidx >= 0);
1120 pTok += pTok->Oprt.offset;
1125 pTok += pTok->Oprt.offset;
1131 // value and variable tokens
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;
1151 // Next is treatment of numeric functions
1154 int iArgCount = pTok->Fun.argc;
1156 // switch according to argument count
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;
1171 // function with variable arguments store the number as a negative value
1173 Error(ecINTERNAL_ERROR, -1);
1175 sidx -= -iArgCount - 1;
1177 // <ibg 2020-06-08/> From oss-fuzz. Happend when Multiarg functions and if-then-else are used incorrectly "sum(0?1,2,3,4,5:6)"
1178 // The final result normally lieas at position 1. If sixd is smaller there is something wrong.
1180 Error(ecINTERNAL_ERROR, -1);
1182 Stack[sidx] = (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
1187 // Next is treatment of string functions
1190 sidx -= pTok->Fun.argc - 1;
1192 // The index of the string argument in the string table
1193 int iIdxStack = pTok->Fun.idx;
1194 if (iIdxStack < 0 || iIdxStack >= (int)m_vStringBuf.size())
1195 Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos());
1197 switch (pTok->Fun.argc) // switch according to argument count
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;
1213 // switch according to argument count
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;
1228 Error(ecINTERNAL_ERROR, 2);
1234 Error(ecINTERNAL_ERROR, 3);
1237 } // for all bytecode tokens
1239 return Stack[m_nFinalResultIdx];
1242 //---------------------------------------------------------------------------
1243 void ParserBase::CreateRPN() const
1245 if (!m_pTokenReader->GetExpr().length())
1246 Error(ecUNEXPECTED_EOF, 0);
1248 std::stack<token_type> stOpt, stVal;
1249 std::stack<int> stArgCount;
1250 token_type opta, opt; // for storing operators
1251 token_type val, tval; // for storing value
1252 int ifElseCounter = 0;
1256 // The outermost counter counts the number of separated items
1257 // such as in "a=10,b=20,c=c+a"
1262 opt = m_pTokenReader->ReadNextToken();
1264 switch (opt.GetCode())
1267 // Next three are different kind of value entries
1271 Error(ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString());
1273 opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token
1275 m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer
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)
1293 Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
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)
1308 Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
1310 if (stArgCount.empty())
1311 Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
1315 // intentional (no break!)
1318 ApplyRemainingOprt(stOpt, stVal);
1323 // The argument count for parameterless functions is zero
1324 // by default an opening bracket sets parameter count to 1
1325 // in preparation of arguments to come. If the last token
1326 // was an opening bracket we know better...
1327 if (opta.GetCode() == cmBO)
1330 ApplyRemainingOprt(stOpt, stVal);
1332 // Check if the bracket content has been evaluated completely
1333 if (stOpt.size() && stOpt.top().GetCode() == cmBO)
1335 // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check
1336 // if there is either a function or a sign pending
1337 // neither the opening nor the closing bracket will be pushed back to
1338 // the operator stack
1339 // Check if a function is standing in front of the opening bracket,
1340 // if yes evaluate it afterwards check for infix operators
1341 MUP_ASSERT(stArgCount.size());
1342 int iArgCount = stArgCount.top();
1345 stOpt.pop(); // Take opening bracket from stack
1347 if (iArgCount > 1 && (stOpt.size() == 0 ||
1348 (stOpt.top().GetCode() != cmFUNC &&
1349 stOpt.top().GetCode() != cmFUNC_BULK &&
1350 stOpt.top().GetCode() != cmFUNC_STR)))
1351 Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());
1353 // The opening bracket was popped from the stack now check if there
1354 // was a function before this bracket
1356 stOpt.top().GetCode() != cmOPRT_INFIX &&
1357 stOpt.top().GetCode() != cmOPRT_BIN &&
1358 stOpt.top().GetFuncAddr() != 0)
1360 ApplyFunc(stOpt, stVal, iArgCount);
1363 } // if bracket content is evaluated
1367 // Next are the binary operator entries
1373 // intentional (no break!)
1391 // A binary operator (user defined or built in) has been found.
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())
1404 // Deal with operator associativity
1405 EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);
1406 if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
1407 (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)))
1412 else if (nPrec1 < nPrec2)
1414 // In case the operators are not equal the precedence decides alone...
1418 if (stOpt.top().GetCode() == cmOPRT_INFIX)
1419 ApplyFunc(stOpt, stVal, 1);
1421 ApplyBinOprt(stOpt, stVal);
1424 if (opt.GetCode() == cmIF)
1425 m_vRPN.AddIfElse(opt.GetCode());
1427 // The operator can't be evaluated right now, push back to the operator stack
1432 // Last section contains functions and operators implicitly mapped to functions
1446 case cmOPRT_POSTFIX:
1448 ApplyFunc(stOpt, stVal, 1); // this is the postfix operator
1451 default: Error(ecINTERNAL_ERROR, 3);
1452 } // end of switch operator-token
1456 if (opt.GetCode() == cmEND)
1462 if (ParserBase::g_DbgDumpStack)
1464 StackDump(stVal, stOpt);
1468 // if (ParserBase::g_DbgDumpCmdCode)
1469 //m_vRPN.AsciiDump();
1472 if (ParserBase::g_DbgDumpCmdCode)
1475 if (ifElseCounter > 0)
1476 Error(ecMISSING_ELSE_CLAUSE);
1478 // get the last value (= final result) from the stack
1479 MUP_ASSERT(stArgCount.size() == 1);
1480 m_nFinalResultIdx = stArgCount.top();
1481 if (m_nFinalResultIdx == 0)
1482 Error(ecINTERNAL_ERROR, 9);
1484 if (stVal.size() == 0)
1485 Error(ecEMPTY_EXPRESSION);
1487 if (stVal.top().GetType() != tpDBL)
1488 Error(ecSTR_RESULT);
1490 m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
1493 //---------------------------------------------------------------------------
1494 /** \brief One of the two main parse functions.
1495 \sa ParseCmdCode(...)
1497 Parse expression from input string. Perform syntax checking and create
1498 bytecode. After parsing the string and creating the bytecode the function
1499 pointer #m_pParseFormula will be changed to the second parse routine the
1500 uses bytecode instead of string parsing.
1502 value_type ParserBase::ParseString() const
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());
1526 //---------------------------------------------------------------------------
1527 /** \brief Create an error containing the parse error position.
1529 This function will create an Parser Exception object containing the error text and
1532 \param a_iErrc [in] The error code of type #EErrorCodes.
1533 \param a_iPos [in] The position where the error was detected.
1534 \param a_strTok [in] The token string representation associated with the error.
1535 \throw ParserException always throws that's the only purpose of this function.
1537 void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type& a_sTok) const
1539 throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
1542 //------------------------------------------------------------------------------
1543 /** \brief Clear all user defined variables.
1546 Resets the parser to string parsing mode by calling #ReInit.
1548 void ParserBase::ClearVar()
1554 //------------------------------------------------------------------------------
1555 /** \brief Remove a variable from internal storage.
1558 Removes a variable if it exists. If the Variable does not exist nothing will be done.
1560 void ParserBase::RemoveVar(const string_type& a_strVarName)
1562 varmap_type::iterator item = m_VarDef.find(a_strVarName);
1563 if (item != m_VarDef.end())
1565 m_VarDef.erase(item);
1570 //------------------------------------------------------------------------------
1571 /** \brief Clear all functions.
1572 \post Resets the parser to string parsing mode.
1575 void ParserBase::ClearFun()
1581 //------------------------------------------------------------------------------
1582 /** \brief Clear all user defined constants.
1584 Both numeric and string constants will be removed from the internal storage.
1585 \post Resets the parser to string parsing mode.
1588 void ParserBase::ClearConst()
1591 m_StrVarDef.clear();
1595 //------------------------------------------------------------------------------
1596 /** \brief Clear all user defined postfix operators.
1597 \post Resets the parser to string parsing mode.
1600 void ParserBase::ClearPostfixOprt()
1602 m_PostOprtDef.clear();
1606 //------------------------------------------------------------------------------
1607 /** \brief Clear all user defined binary operators.
1608 \post Resets the parser to string parsing mode.
1611 void ParserBase::ClearOprt()
1617 //------------------------------------------------------------------------------
1618 /** \brief Clear the user defined Prefix operators.
1619 \post Resets the parser to string parser mode.
1622 void ParserBase::ClearInfixOprt()
1624 m_InfixOprtDef.clear();
1628 //------------------------------------------------------------------------------
1629 /** \brief Enable or disable the formula optimization feature.
1630 \post Resets the parser to string parser mode.
1633 void ParserBase::EnableOptimizer(bool a_bIsOn)
1635 m_vRPN.EnableOptimizer(a_bIsOn);
1639 //---------------------------------------------------------------------------
1640 /** \brief Enable the dumping of bytecode and stack content on the console.
1641 \param bDumpCmd Flag to enable dumping of the current bytecode to the console.
1642 \param bDumpStack Flag to enable dumping of the stack content is written to the console.
1644 This function is for debug purposes only!
1646 void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)
1648 ParserBase::g_DbgDumpCmdCode = bDumpCmd;
1649 ParserBase::g_DbgDumpStack = bDumpStack;
1652 //------------------------------------------------------------------------------
1653 /** \brief Enable or disable the built in binary operators.
1655 \sa m_bBuiltInOp, ReInit()
1657 If you disable the built in binary operators there will be no binary operators
1658 defined. Thus you must add them manually one by one. It is not possible to
1659 disable built in operators selectively. This function will Reinitialize the
1660 parser by calling ReInit().
1662 void ParserBase::EnableBuiltInOprt(bool a_bIsOn)
1664 m_bBuiltInOp = a_bIsOn;
1668 //------------------------------------------------------------------------------
1669 /** \brief Query status of built in variables.
1670 \return #m_bBuiltInOp; true if built in operators are enabled.
1673 bool ParserBase::HasBuiltInOprt() const
1675 return m_bBuiltInOp;
1678 //------------------------------------------------------------------------------
1679 /** \brief Get the argument separator character.
1681 char_type ParserBase::GetArgSep() const
1683 return m_pTokenReader->GetArgSep();
1686 //------------------------------------------------------------------------------
1687 /** \brief Set argument separator.
1688 \param cArgSep the argument separator character.
1690 void ParserBase::SetArgSep(char_type cArgSep)
1692 m_pTokenReader->SetArgSep(cArgSep);
1695 //------------------------------------------------------------------------------
1696 /** \brief Dump stack content.
1698 This function is used for debugging only.
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);
1705 mu::console() << _T("\nValue stack:\n");
1706 while (!stVal.empty())
1708 token_type val = stVal.top();
1711 if (val.GetType() == tpSTR)
1712 mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");
1714 mu::console() << _T(" ") << val.GetVal() << _T(" ");
1716 mu::console() << "\nOperator stack:\n";
1718 while (!stOprt.empty())
1720 if (stOprt.top().GetCode() <= cmASSIGN)
1722 mu::console() << _T("OPRT_INTRNL \"")
1723 << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
1728 switch (stOprt.top().GetCode())
1730 case cmVAR: mu::console() << _T("VAR\n"); break;
1731 case cmVAL: mu::console() << _T("VAL\n"); break;
1735 << stOprt.top().GetAsString()
1741 << _T("FUNC_BULK \"")
1742 << stOprt.top().GetAsString()
1747 mu::console() << _T("OPRT_INFIX \"")
1748 << stOprt.top().GetAsString()
1753 mu::console() << _T("OPRT_BIN \"")
1754 << stOprt.top().GetAsString()
1758 case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break;
1759 case cmEND: mu::console() << _T("END\n"); break;
1760 case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break;
1761 case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break;
1762 case cmBC: mu::console() << _T("BRACKET \")\"\n"); break;
1763 case cmIF: mu::console() << _T("IF\n"); break;
1764 case cmELSE: mu::console() << _T("ELSE\n"); break;
1765 case cmENDIF: mu::console() << _T("ENDIF\n"); break;
1766 default: mu::console() << stOprt.top().GetCode() << _T(" "); break;
1772 mu::console() << dec << endl;
1775 /** \brief Calculate the result.
1777 A note on const correctness:
1778 I consider it important that Calc is a const function.
1779 Due to caching operations Calc changes only the state of internal variables with one exception
1780 m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
1781 Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update.
1783 \pre A formula must be set.
1784 \pre Variables must have been set (if needed)
1786 \sa #m_pParseFormula
1787 \return The evaluation result
1788 \throw ParseException if no Formula is set or in case of any other error related to the formula.
1790 value_type ParserBase::Eval() const
1792 return (this->*m_pParseFormula)();
1795 //------------------------------------------------------------------------------
1796 /** \brief Evaluate an expression containing comma separated subexpressions
1797 \param [out] nStackSize The total number of results available
1798 \return Pointer to the array containing all expression results
1800 This member function can be used to retrieve all results of an expression
1801 made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)")
1803 value_type* ParserBase::Eval(int& nStackSize) const
1805 if (m_vRPN.GetSize() > 0)
1814 nStackSize = m_nFinalResultIdx;
1816 // (for historic reasons the stack starts at position 1)
1817 return &m_vStackBuffer[1];
1820 //---------------------------------------------------------------------------
1821 /** \brief Return the number of results on the calculation stack.
1823 If the expression contains comma separated subexpressions (i.e. "sin(y), x+y").
1824 There may be more than one return value. This function returns the number of
1827 int ParserBase::GetNumResults() const
1829 return m_nFinalResultIdx;
1832 //---------------------------------------------------------------------------
1833 void ParserBase::Eval(value_type* results, int nBulkSize)
1839 #ifdef MUP_USE_OPENMP
1840 //#define DEBUG_OMP_STUFF
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)