muParserBase.h 11.8 KB
Newer Older
1
/*
2
3
                 __________
    _____   __ __\______   \_____  _______  ______  ____ _______
4
5
   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
6
7
  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|
        \/                       \/            \/      \/
8
9
  Copyright (C) 2010 Ingo Berg

10
  Permission is hereby granted, free of charge, to any person obtaining a copy of this
11
  software and associated documentation files (the "Software"), to deal in the Software
12
13
  without restriction, including without limitation the rights to use, copy, modify,
  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
14
15
  permit persons to whom the Software is furnished to do so, subject to the following conditions:

16
  The above copyright notice and this permission notice shall be included in all copies or
17
18
19
  substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
20
21
22
23
  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
*/
#ifndef MU_PARSER_BASE_H
#define MU_PARSER_BASE_H

//--- Standard includes ------------------------------------------------------------------------
#include <cmath>
#include <string>
#include <iostream>
#include <map>
#include <memory>

//--- Parser includes --------------------------------------------------------------------------
#include "muParserDef.h"
#include "muParserStack.h"
#include "muParserTokenReader.h"
#include "muParserBytecode.h"
#include "muParserError.h"


namespace mu
{
/** \file
    \brief This file contains the class definition of the muparser engine.
*/

//--------------------------------------------------------------------------------------------------
/** \brief Mathematical expressions parser (base parser engine).
    \author (C) 2010 Ingo Berg

53
54
  This is the implementation of a bytecode based mathematical expressions parser.
  The formula will be parsed from string and converted into a bytecode.
55
  Future calculations will be done with the bytecode instead the formula string
56
57
58
  resulting in a significant performance increase.
  Complementary to a set of internally implemented functions the parser is able to handle
  user defined functions and variables.
59
*/
60
class ParserBase
61
62
63
64
65
{
friend class ParserTokenReader;

private:

66
67
    /** \brief Typedef for the parse functions.

68
      The parse function do the actual work. The parser exchanges
69
      the function pointer to the parser function depending on
70
71
      which state it is in. (i.e. bytecode parser vs. string parser)
    */
72
    typedef value_type (ParserBase::*ParseFunction)() const;
73
74
75
76
77
78
79
80
81

    /** \brief Type used for storing an array of values. */
    typedef std::vector<value_type> valbuf_type;

    /** \brief Type for a vector of strings. */
    typedef std::vector<string_type> stringbuf_type;

    /** \brief Typedef for the token reader. */
    typedef ParserTokenReader token_reader_type;
82

83
84
85
86
87
    /** \brief Type used for parser tokens. */
    typedef ParserToken<value_type, string_type> token_type;

 public:

88
89
    /** \brief Type of the error class.

90
91
92
93
      Included for backwards compatibility.
    */
    typedef ParserError exception_type;

94
    ParserBase();
95
96
97
98
    ParserBase(const ParserBase &a_Parser);
    ParserBase& operator=(const ParserBase &a_Parser);

    virtual ~ParserBase();
99

100
101
102
    //---------------------------------------------------------------------------
    /** \brief Calculate the result.

103
      A note on const correctness:
104
105
106
      I consider it important that Calc is a const function.
      Due to caching operations Calc changes only the state of internal variables with one exception
      m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
107
      Calc non const GetUsedVar is non const because it explicitely calls Eval() forcing this update.
108
109
110

      \pre A formula must be set.
      \pre Variables must have been set (if needed)
111

112
113
114
115
116
117
      \sa #m_pParseFormula
      \return The evaluation result
      \throw ParseException if no Formula is set or in case of any other error related to the formula.
    */
	  inline value_type Eval() const
    {
118
      return (this->*m_pParseFormula)();
119
120
121
122
123
124
125
126
127
128
129
130
    }

    void SetExpr(const string_type &a_sExpr);
    void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);

    void EnableOptimizer(bool a_bIsOn=true);
    void EnableByteCode(bool a_bIsOn=true);
    void EnableBuiltInOprt(bool a_bIsOn=true);

    bool HasBuiltInOprt() const;
    void AddValIdent(identfun_type a_pCallback);

131
/** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
    \brief Define a parser function without arguments.
    \param a_strName Name of the function
    \param a_pFun Pointer to the callback function
    \param a_bAllowOpt A flag indicating this function may be optimized
*/

#define MUP_DEFINE_FUNC(TYPE)                                                                  \
    inline void DefineFun(const string_type &a_strName, TYPE a_pFun, bool a_bAllowOpt = true)  \
    {                                                                                          \
      AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt),                             \
                   m_FunDef, ValidNameChars() );                                               \
    }

    MUP_DEFINE_FUNC(fun_type0)
    MUP_DEFINE_FUNC(fun_type1)
    MUP_DEFINE_FUNC(fun_type2)
    MUP_DEFINE_FUNC(fun_type3)
    MUP_DEFINE_FUNC(fun_type4)
    MUP_DEFINE_FUNC(fun_type5)
    MUP_DEFINE_FUNC(multfun_type)
    MUP_DEFINE_FUNC(strfun_type1)
    MUP_DEFINE_FUNC(strfun_type2)
    MUP_DEFINE_FUNC(strfun_type3)
#undef MUP_DEFINE_FUNC

157
158
159
    void DefineOprt(const string_type &a_strName,
                    fun_type2 a_pFun,
                    unsigned a_iPri=0,
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
                    EOprtAssociativity a_eAssociativity = oaLEFT,
                    bool a_bAllowOpt = false);
    void DefineConst(const string_type &a_sName, value_type a_fVal);
    void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);
//  void DefineArrayVar(const string_type &a_sName, value_type *a_fVar, std::size_t sz);
    void DefineVar(const string_type &a_sName, value_type *a_fVar);
    void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);
    void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);

    // Clear user defined variables, constants or functions
    void ClearVar();
    void ClearFun();
    void ClearConst();
    void ClearInfixOprt();
    void ClearPostfixOprt();
    void ClearOprt();
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
    void RemoveVar(const string_type &a_strVarName);
    const varmap_type& GetUsedVar() const;
    const varmap_type& GetVar() const;
    const valmap_type& GetConst() const;
    const string_type& GetExpr() const;
    const funmap_type& GetFunDef() const;
    string_type GetVersion() const;

    const char_type ** GetOprtDef() const;
    void DefineNameChars(const char_type *a_szCharset);
    void DefineOprtChars(const char_type *a_szCharset);
    void DefineInfixOprtChars(const char_type *a_szCharset);

    const char_type* ValidNameChars() const;
    const char_type* ValidOprtChars() const;
    const char_type* ValidInfixOprtChars() const;

    void SetArgSep(char_type cArgSep);
    char_type GetArgSep() const;
196
197
198

    void  Error(EErrorCodes a_iErrc,
                int a_iPos = (int)mu::string_type::npos,
199
200
201
                const string_type &a_strTok = string_type() ) const;

 protected:
202

203
204
205
206
207
    void Init();

    virtual void InitCharSets() = 0;
    virtual void InitFun() = 0;
    virtual void InitConst() = 0;
208
    virtual void InitOprt() = 0;
209
210

    virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
211
    static const char_type *c_DefaultOprt[];
212
213
214
215
216
217
218

 private:

    void Assign(const ParserBase &a_Parser);
    void InitTokenReader();
    void ReInit() const;

219
220
    void AddCallback( const string_type &a_strName,
                      const ParserCallback &a_Callback,
221
222
223
224
225
226
227
                      funmap_type &a_Storage,
                      const char_type *a_szCharSet );

    void ApplyBinOprt(ParserStack<token_type> &a_stOpt,
                      ParserStack<token_type> &a_stVal) const;

    void ApplyFunc(ParserStack<token_type> &a_stOpt,
228
229
                   ParserStack<token_type> &a_stVal,
                   int iArgCount) const;
230
231
232
233
234
235
236
237
238
239

    token_type ApplyNumFunc(const token_type &a_FunTok,
                            const std::vector<token_type> &a_vArg) const;

    token_type ApplyStrFunc(const token_type &a_FunTok,
                            const std::vector<token_type> &a_vArg) const;

    int GetOprtPrecedence(const token_type &a_Tok) const;
    EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;

240
    value_type ParseString() const;
241
242
243
244
245
246
247
248
249
250
    value_type ParseCmdCode() const;
    value_type ParseValue() const;

    void  ClearFormula();
    void  CheckName(const string_type &a_strName, const string_type &a_CharSet) const;
    void  CheckOprt(const string_type &a_sName,
                    const ParserCallback &a_Callback,
                    const string_type &a_szCharSet) const;

#if defined(MUP_DUMP_STACK) | defined(MUP_DUMP_CMDCODE)
251
    void StackDump(const ParserStack<token_type > &a_stVal,
252
253
254
                   const ParserStack<token_type > &a_stOprt) const;
#endif

255
256
    /** \brief Pointer to the parser function.

257
258
259
260
261
262
263
264
      Eval() calls the function whose address is stored there.
    */
    mutable ParseFunction  m_pParseFormula;
    mutable const bytecode_type *m_pCmdCode; ///< Formula converted to bytecode, points to the data of the bytecode class.
    mutable ParserByteCode m_vByteCode;   ///< The Bytecode class.
    mutable stringbuf_type  m_vStringBuf; ///< String buffer, used for storing string function arguments
    stringbuf_type  m_vStringVarBuf;

265
#if AMDIS_HAS_CXX11
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
    std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
#else
    std::auto_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
#endif

    funmap_type  m_FunDef;        ///< Map of function names and pointers.
    funmap_type  m_PostOprtDef;   ///< Postfix operator callbacks
    funmap_type  m_InfixOprtDef;  ///< unary infix operator.
    funmap_type  m_OprtDef;       ///< Binary operator callbacks
    valmap_type  m_ConstDef;      ///< user constants.
    strmap_type  m_StrVarDef;     ///< user defined string constants
    varmap_type  m_VarDef;        ///< user defind variables.

    bool m_bOptimize;             ///< Flag that indicates if the optimizer is on or off.
    bool m_bUseByteCode;          ///< Flag that indicates if bytecode parsing is on or off.
    bool m_bBuiltInOp;            ///< Flag that can be used for switching built in operators on and off

    string_type m_sNameChars;      ///< Charset for names
    string_type m_sOprtChars;      ///< Charset for postfix/ binary operator tokens
    string_type m_sInfixOprtChars; ///< Charset for infix operator tokens

    // items merely used for caching state information
    mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
    mutable int m_nFinalResultIdx;
};

} // namespace mu

#endif