/src/gdal/muparser/include/muParserBase.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | |
3 | | _____ __ _____________ _______ ______ ___________ |
4 | | / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \ |
5 | | | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/ |
6 | | |__|_| /____/| __(____ /__| /____ >\___ >__| |
7 | | \/ |__| \/ \/ \/ |
8 | | Copyright (C) 2004 - 2022 Ingo Berg |
9 | | |
10 | | Redistribution and use in source and binary forms, with or without modification, are permitted |
11 | | provided that the following conditions are met: |
12 | | |
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. |
18 | | |
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. |
27 | | */ |
28 | | |
29 | | #ifndef MU_PARSER_BASE_H |
30 | | #define MU_PARSER_BASE_H |
31 | | |
32 | | //--- Standard includes ------------------------------------------------------------------------ |
33 | | #include <cmath> |
34 | | #include <string> |
35 | | #include <iostream> |
36 | | #include <map> |
37 | | #include <memory> |
38 | | #include <locale> |
39 | | #include <limits.h> |
40 | | |
41 | | //--- Parser includes -------------------------------------------------------------------------- |
42 | | #include "muParserDef.h" |
43 | | #include "muParserTokenReader.h" |
44 | | #include "muParserBytecode.h" |
45 | | #include "muParserError.h" |
46 | | |
47 | | #if defined(_MSC_VER) |
48 | | #pragma warning(push) |
49 | | #pragma warning(disable : 4251) // ...needs to have dll-interface to be used by clients of class ... |
50 | | #endif |
51 | | |
52 | | |
53 | | namespace mu |
54 | | { |
55 | | /** \file |
56 | | \brief This file contains the class definition of the muparser engine. |
57 | | */ |
58 | | |
59 | | /** \brief Mathematical expressions parser (base parser engine). |
60 | | |
61 | | This is the implementation of a bytecode based mathematical expressions parser. |
62 | | The formula will be parsed from string and converted into a bytecode. |
63 | | Future calculations will be done with the bytecode instead the formula string |
64 | | resulting in a significant performance increase. |
65 | | Complementary to a set of internally implemented functions the parser is able to handle |
66 | | user defined functions and variables. |
67 | | */ |
68 | | class API_EXPORT_CXX ParserBase |
69 | | { |
70 | | friend class ParserTokenReader; |
71 | | |
72 | | private: |
73 | | |
74 | | /** \brief Typedef for the parse functions. |
75 | | |
76 | | The parse function do the actual work. The parser exchanges |
77 | | the function pointer to the parser function depending on |
78 | | which state it is in. (i.e. bytecode parser vs. string parser) |
79 | | */ |
80 | | typedef value_type(ParserBase::* ParseFunction)() const; |
81 | | |
82 | | /** \brief Type used for storing an array of values. */ |
83 | | typedef std::vector<value_type> valbuf_type; |
84 | | |
85 | | /** \brief Type for a vector of strings. */ |
86 | | typedef std::vector<string_type> stringbuf_type; |
87 | | |
88 | | /** \brief Typedef for the token reader. */ |
89 | | typedef ParserTokenReader token_reader_type; |
90 | | |
91 | | /** \brief Type used for parser tokens. */ |
92 | | typedef ParserToken<value_type, string_type> token_type; |
93 | | |
94 | | /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ |
95 | | static const int s_MaxNumOpenMPThreads; |
96 | | |
97 | | public: |
98 | | |
99 | | /** \brief Type of the error class. |
100 | | |
101 | | Included for backwards compatibility. |
102 | | */ |
103 | | typedef ParserError exception_type; |
104 | | |
105 | | static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); |
106 | | |
107 | | ParserBase(); |
108 | | ParserBase(const ParserBase& a_Parser); |
109 | | ParserBase& operator=(const ParserBase& a_Parser); |
110 | | |
111 | | virtual ~ParserBase(); |
112 | | |
113 | | value_type Eval() const; |
114 | | value_type* Eval(int& nStackSize) const; |
115 | | void Eval(value_type* results, int nBulkSize); |
116 | | |
117 | | int GetNumResults() const; |
118 | | |
119 | | void SetExpr(const string_type& a_sExpr); |
120 | | void SetVarFactory(facfun_type a_pFactory, void* pUserData = nullptr); |
121 | | |
122 | | void SetDecSep(char_type cDecSep); |
123 | | void SetThousandsSep(char_type cThousandsSep = 0); |
124 | | void ResetLocale(); |
125 | | |
126 | | void EnableOptimizer(bool a_bIsOn = true); |
127 | | void EnableBuiltInOprt(bool a_bIsOn = true); |
128 | | |
129 | | bool HasBuiltInOprt() const; |
130 | | void AddValIdent(identfun_type a_pCallback); |
131 | | |
132 | | /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) |
133 | | \brief Define a parser function without arguments. |
134 | | \param a_strName Name of the function |
135 | | \param a_pFun Pointer to the callback function |
136 | | \param a_bAllowOpt A flag indicating this function may be optimized |
137 | | */ |
138 | | template<typename T> |
139 | | void DefineFun(const string_type& a_strName, T a_pFun, bool a_bAllowOpt = true) |
140 | 0 | { |
141 | 0 | AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars()); |
142 | 0 | } Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)(double)>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(double), bool) Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)(double, double)>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(double, double), bool) Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)(double const*, int)>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(double const*, int), bool) Unexecuted instantiation: void mu::ParserBase::DefineFun<double (*)()>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, double (*)(), bool) |
143 | | |
144 | | /** \fn void mu::ParserBase::DefineFunUserData |
145 | | \brief Define a parser function with user data (not null). |
146 | | \param a_strName Name of the function |
147 | | \param a_pFun Pointer to the callback function |
148 | | \param a_pUserData Pointer that will be passed back to callback (shall not be nullptr) |
149 | | \param a_bAllowOpt A flag indicating this function may be optimized |
150 | | */ |
151 | | template<typename T> |
152 | | void DefineFunUserData(const string_type& a_strName, T a_pFun, void* a_pUserData, bool a_bAllowOpt = true) |
153 | | { |
154 | | AddCallback(a_strName, ParserCallback(a_pFun, a_pUserData, a_bAllowOpt), m_FunDef, ValidNameChars()); |
155 | | } |
156 | | |
157 | | void DefineOprt(const string_type& a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false); |
158 | | void DefineConst(const string_type& a_sName, value_type a_fVal); |
159 | | void DefineStrConst(const string_type& a_sName, const string_type& a_strVal); |
160 | | void DefineVar(const string_type& a_sName, value_type* a_fVar); |
161 | | void DefinePostfixOprt(const string_type& a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true); |
162 | | void DefineInfixOprt(const string_type& a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, bool a_bAllowOpt = true); |
163 | | |
164 | | // Clear user defined variables, constants or functions |
165 | | void ClearVar(); |
166 | | void ClearFun(); |
167 | | void ClearConst(); |
168 | | void ClearInfixOprt(); |
169 | | void ClearPostfixOprt(); |
170 | | void ClearOprt(); |
171 | | |
172 | | void RemoveVar(const string_type& a_strVarName); |
173 | | const varmap_type& GetUsedVar() const; |
174 | | const varmap_type& GetVar() const; |
175 | | const valmap_type& GetConst() const; |
176 | | const string_type& GetExpr() const; |
177 | | const funmap_type& GetFunDef() const; |
178 | | string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; |
179 | | const ParserByteCode& GetByteCode() const; |
180 | | |
181 | | const char_type** GetOprtDef() const; |
182 | | void DefineNameChars(const char_type* a_szCharset); |
183 | | void DefineOprtChars(const char_type* a_szCharset); |
184 | | void DefineInfixOprtChars(const char_type* a_szCharset); |
185 | | |
186 | | const char_type* ValidNameChars() const; |
187 | | const char_type* ValidOprtChars() const; |
188 | | const char_type* ValidInfixOprtChars() const; |
189 | | |
190 | | void SetArgSep(char_type cArgSep); |
191 | | void SetByteCode(const ParserByteCode& a_ByteCode); |
192 | | |
193 | | char_type GetArgSep() const; |
194 | | |
195 | | protected: |
196 | | |
197 | | void Init(); |
198 | | void Error(EErrorCodes a_iErrc, int a_iPos = static_cast<int>(mu::string_type::npos), const string_type& a_strTok = string_type()) const; |
199 | | |
200 | | virtual void InitCharSets() = 0; |
201 | | virtual void InitFun() = 0; |
202 | | virtual void InitConst() = 0; |
203 | | virtual void InitOprt() = 0; |
204 | | |
205 | | virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd); |
206 | | |
207 | | static const char_type* c_DefaultOprt[]; |
208 | | static std::locale s_locale; ///< The locale used by the parser |
209 | | static bool g_DbgDumpCmdCode; |
210 | | static bool g_DbgDumpStack; |
211 | | |
212 | | /** \brief A facet class used to change decimal and thousands separator. */ |
213 | | template<class TChar> |
214 | | class change_dec_sep : public std::numpunct<TChar> |
215 | | { |
216 | | public: |
217 | | |
218 | | explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) |
219 | 2 | :std::numpunct<TChar>() |
220 | 2 | ,m_nGroup(nGroup) |
221 | 2 | ,m_cDecPoint(cDecSep) |
222 | 2 | ,m_cThousandsSep(cThousandsSep) |
223 | 2 | {} |
224 | | |
225 | | protected: |
226 | | |
227 | | char_type do_decimal_point() const override |
228 | 0 | { |
229 | 0 | return m_cDecPoint; |
230 | 0 | } |
231 | | |
232 | | char_type do_thousands_sep() const override |
233 | 0 | { |
234 | 0 | return m_cThousandsSep; |
235 | 0 | } |
236 | | |
237 | | std::string do_grouping() const override |
238 | 0 | { |
239 | | // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 |
240 | | // courtesy of Jens Bartsch |
241 | | // original code: |
242 | | // return std::string(1, (char)m_nGroup); |
243 | | // new code: |
244 | 0 | return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); |
245 | 0 | } |
246 | | |
247 | | private: |
248 | | |
249 | | int m_nGroup; |
250 | | char_type m_cDecPoint; |
251 | | char_type m_cThousandsSep; |
252 | | }; |
253 | | |
254 | | private: |
255 | | |
256 | | void Assign(const ParserBase& a_Parser); |
257 | | void InitTokenReader(); |
258 | | void ReInit() const; |
259 | | |
260 | | void AddCallback(const string_type& a_strName, const ParserCallback& a_Callback, funmap_type& a_Storage, const char_type* a_szCharSet); |
261 | | void ApplyRemainingOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const; |
262 | | void ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const; |
263 | | void ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const; |
264 | | void ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int iArgCount) const; |
265 | | |
266 | | token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector<token_type>& a_vArg) const; |
267 | | |
268 | | int GetOprtPrecedence(const token_type& a_Tok) const; |
269 | | EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const; |
270 | | |
271 | | void CreateRPN() const; |
272 | | |
273 | | value_type ParseString() const; |
274 | | value_type ParseCmdCode() const; |
275 | | value_type ParseCmdCodeShort() const; |
276 | | value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; |
277 | | |
278 | | void CheckName(const string_type& a_strName, const string_type& a_CharSet) const; |
279 | | void CheckOprt(const string_type& a_sName, const ParserCallback& a_Callback, const string_type& a_szCharSet) const; |
280 | | |
281 | | void StackDump(const std::stack<token_type >& a_stVal, const std::stack<token_type >& a_stOprt) const; |
282 | | |
283 | | /** \brief Pointer to the parser function. |
284 | | |
285 | | Eval() calls the function whose address is stored there. |
286 | | */ |
287 | | mutable ParseFunction m_pParseFormula; |
288 | | mutable ParserByteCode m_vRPN; ///< The Bytecode class. |
289 | | mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments |
290 | | stringbuf_type m_vStringVarBuf; |
291 | | |
292 | | std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object. |
293 | | |
294 | | funmap_type m_FunDef; ///< Map of function names and pointers. |
295 | | funmap_type m_PostOprtDef; ///< Postfix operator callbacks |
296 | | funmap_type m_InfixOprtDef; ///< unary infix operator. |
297 | | funmap_type m_OprtDef; ///< Binary operator callbacks |
298 | | valmap_type m_ConstDef; ///< user constants. |
299 | | strmap_type m_StrVarDef; ///< user defined string constants |
300 | | varmap_type m_VarDef; ///< user defind variables. |
301 | | |
302 | | bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off |
303 | | |
304 | | string_type m_sNameChars; ///< Charset for names |
305 | | string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens |
306 | | string_type m_sInfixOprtChars; ///< Charset for infix operator tokens |
307 | | |
308 | | // items merely used for caching state information |
309 | | mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine |
310 | | mutable int m_nFinalResultIdx; |
311 | | }; |
312 | | |
313 | | } // namespace mu |
314 | | |
315 | | #if defined(_MSC_VER) |
316 | | #pragma warning(pop) |
317 | | #endif |
318 | | |
319 | | #endif |