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 #ifndef MU_PARSER_BASE_H
30 #define MU_PARSER_BASE_H
32 //--- Standard includes ------------------------------------------------------------------------
41 //--- Parser includes --------------------------------------------------------------------------
42 #include "muParserDef.h"
43 #include "muParserTokenReader.h"
44 #include "muParserBytecode.h"
45 #include "muParserError.h"
51 \brief This file contains the class definition of the muparser engine.
54 /** \brief Mathematical expressions parser (base parser engine).
56 This is the implementation of a bytecode based mathematical expressions parser.
57 The formula will be parsed from string and converted into a bytecode.
58 Future calculations will be done with the bytecode instead the formula string
59 resulting in a significant performance increase.
60 Complementary to a set of internally implemented functions the parser is able to handle
61 user defined functions and variables.
63 class API_EXPORT_CXX ParserBase
65 friend class ParserTokenReader;
69 /** \brief Typedef for the parse functions.
71 The parse function do the actual work. The parser exchanges
72 the function pointer to the parser function depending on
73 which state it is in. (i.e. bytecode parser vs. string parser)
75 typedef value_type(ParserBase::* ParseFunction)() const;
77 /** \brief Type used for storing an array of values. */
78 typedef std::vector<value_type> valbuf_type;
80 /** \brief Type for a vector of strings. */
81 typedef std::vector<string_type> stringbuf_type;
83 /** \brief Typedef for the token reader. */
84 typedef ParserTokenReader token_reader_type;
86 /** \brief Type used for parser tokens. */
87 typedef ParserToken<value_type, string_type> token_type;
89 /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
90 static const int s_MaxNumOpenMPThreads;
94 /** \brief Type of the error class.
96 Included for backwards compatibility.
98 typedef ParserError exception_type;
100 static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
103 ParserBase(const ParserBase& a_Parser);
104 ParserBase& operator=(const ParserBase& a_Parser);
106 virtual ~ParserBase();
108 value_type Eval() const;
109 value_type* Eval(int& nStackSize) const;
110 void Eval(value_type* results, int nBulkSize);
112 int GetNumResults() const;
114 void SetExpr(const string_type& a_sExpr);
115 void SetVarFactory(facfun_type a_pFactory, void* pUserData = nullptr);
117 void SetDecSep(char_type cDecSep);
118 void SetThousandsSep(char_type cThousandsSep = 0);
121 void EnableOptimizer(bool a_bIsOn = true);
122 void EnableBuiltInOprt(bool a_bIsOn = true);
124 bool HasBuiltInOprt() const;
125 void AddValIdent(identfun_type a_pCallback);
127 /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
128 \brief Define a parser function without arguments.
129 \param a_strName Name of the function
130 \param a_pFun Pointer to the callback function
131 \param a_bAllowOpt A flag indicating this function may be optimized
134 void DefineFun(const string_type& a_strName, T a_pFun, bool a_bAllowOpt = true)
136 AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars());
139 void DefineOprt(const string_type& a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false);
140 void DefineConst(const string_type& a_sName, value_type a_fVal);
141 void DefineStrConst(const string_type& a_sName, const string_type& a_strVal);
142 void DefineVar(const string_type& a_sName, value_type* a_fVar);
143 void DefinePostfixOprt(const string_type& a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true);
144 void DefineInfixOprt(const string_type& a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, bool a_bAllowOpt = true);
146 // Clear user defined variables, constants or functions
150 void ClearInfixOprt();
151 void ClearPostfixOprt();
154 void RemoveVar(const string_type& a_strVarName);
155 const varmap_type& GetUsedVar() const;
156 const varmap_type& GetVar() const;
157 const valmap_type& GetConst() const;
158 const string_type& GetExpr() const;
159 const funmap_type& GetFunDef() const;
160 string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
162 const char_type** GetOprtDef() const;
163 void DefineNameChars(const char_type* a_szCharset);
164 void DefineOprtChars(const char_type* a_szCharset);
165 void DefineInfixOprtChars(const char_type* a_szCharset);
167 const char_type* ValidNameChars() const;
168 const char_type* ValidOprtChars() const;
169 const char_type* ValidInfixOprtChars() const;
171 void SetArgSep(char_type cArgSep);
172 char_type GetArgSep() const;
177 void Error(EErrorCodes a_iErrc, int a_iPos = (int)mu::string_type::npos, const string_type& a_strTok = string_type()) const;
179 virtual void InitCharSets() = 0;
180 virtual void InitFun() = 0;
181 virtual void InitConst() = 0;
182 virtual void InitOprt() = 0;
184 virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd);
186 static const char_type* c_DefaultOprt[];
187 static std::locale s_locale; ///< The locale used by the parser
188 static bool g_DbgDumpCmdCode;
189 static bool g_DbgDumpStack;
191 /** \brief A facet class used to change decimal and thousands separator. */
192 template<class TChar>
193 class change_dec_sep : public std::numpunct<TChar>
197 explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
198 :std::numpunct<TChar>()
200 , m_cDecPoint(cDecSep)
201 , m_cThousandsSep(cThousandsSep)
206 virtual char_type do_decimal_point() const
211 virtual char_type do_thousands_sep() const
213 return m_cThousandsSep;
216 virtual std::string do_grouping() const
218 // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
219 // courtesy of Jens Bartsch
221 // return std::string(1, (char)m_nGroup);
223 return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
229 char_type m_cDecPoint;
230 char_type m_cThousandsSep;
235 void Assign(const ParserBase& a_Parser);
236 void InitTokenReader();
239 void AddCallback(const string_type& a_strName, const ParserCallback& a_Callback, funmap_type& a_Storage, const char_type* a_szCharSet);
240 void ApplyRemainingOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
241 void ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
242 void ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
243 void ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int iArgCount) const;
245 token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector<token_type>& a_vArg) const;
247 int GetOprtPrecedence(const token_type& a_Tok) const;
248 EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const;
250 void CreateRPN() const;
252 value_type ParseString() const;
253 value_type ParseCmdCode() const;
254 value_type ParseCmdCodeShort() const;
255 value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
257 void CheckName(const string_type& a_strName, const string_type& a_CharSet) const;
258 void CheckOprt(const string_type& a_sName, const ParserCallback& a_Callback, const string_type& a_szCharSet) const;
260 void StackDump(const std::stack<token_type >& a_stVal, const std::stack<token_type >& a_stOprt) const;
262 /** \brief Pointer to the parser function.
264 Eval() calls the function whose address is stored there.
266 mutable ParseFunction m_pParseFormula;
267 mutable ParserByteCode m_vRPN; ///< The Bytecode class.
268 mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments
269 stringbuf_type m_vStringVarBuf;
271 std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
273 funmap_type m_FunDef; ///< Map of function names and pointers.
274 funmap_type m_PostOprtDef; ///< Postfix operator callbacks
275 funmap_type m_InfixOprtDef; ///< unary infix operator.
276 funmap_type m_OprtDef; ///< Binary operator callbacks
277 valmap_type m_ConstDef; ///< user constants.
278 strmap_type m_StrVarDef; ///< user defined string constants
279 varmap_type m_VarDef; ///< user defind variables.
281 bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off
283 string_type m_sNameChars; ///< Charset for names
284 string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens
285 string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
287 // items merely used for caching state information
288 mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
289 mutable int m_nFinalResultIdx;