Coverage Report

Created: 2026-04-12 06:47

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