muParser API -  1.35
muParserBase.h
Go to the documentation of this file.
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. */
90 
91  /** \brief Type used for parser tokens. */
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  */
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  {
141  AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars());
142  }
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  char_type GetArgSep() const;
192 
193  protected:
194 
195  void Init();
196  void Error(EErrorCodes a_iErrc, int a_iPos = static_cast<int>(mu::string_type::npos), const string_type& a_strTok = string_type()) const;
197 
198  virtual void InitCharSets() = 0;
199  virtual void InitFun() = 0;
200  virtual void InitConst() = 0;
201  virtual void InitOprt() = 0;
202 
203  virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd);
204 
205  static const char_type* c_DefaultOprt[];
206  static std::locale s_locale; ///< The locale used by the parser
207  static bool g_DbgDumpCmdCode;
208  static bool g_DbgDumpStack;
209 
210  /** \brief A facet class used to change decimal and thousands separator. */
211  template<class TChar>
212  class change_dec_sep : public std::numpunct<TChar>
213  {
214  public:
215 
216  explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
217  :std::numpunct<TChar>()
218  ,m_nGroup(nGroup)
219  ,m_cDecPoint(cDecSep)
220  ,m_cThousandsSep(cThousandsSep)
221  {}
222 
223  protected:
224 
225  char_type do_decimal_point() const override
226  {
227  return m_cDecPoint;
228  }
229 
230  char_type do_thousands_sep() const override
231  {
232  return m_cThousandsSep;
233  }
234 
235  std::string do_grouping() const override
236  {
237  // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
238  // courtesy of Jens Bartsch
239  // original code:
240  // return std::string(1, (char)m_nGroup);
241  // new code:
242  return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
243  }
244 
245  private:
246 
247  int m_nGroup;
248  char_type m_cDecPoint;
249  char_type m_cThousandsSep;
250  };
251 
252  private:
253 
254  void Assign(const ParserBase& a_Parser);
255  void InitTokenReader();
256  void ReInit() const;
257 
258  void AddCallback(const string_type& a_strName, const ParserCallback& a_Callback, funmap_type& a_Storage, const char_type* a_szCharSet);
259  void ApplyRemainingOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
260  void ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
261  void ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const;
262  void ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int iArgCount) const;
263 
264  token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector<token_type>& a_vArg) const;
265 
266  int GetOprtPrecedence(const token_type& a_Tok) const;
267  EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const;
268 
269  void CreateRPN() const;
270 
271  value_type ParseString() const;
272  value_type ParseCmdCode() const;
273  value_type ParseCmdCodeShort() const;
274  value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
275 
276  void CheckName(const string_type& a_strName, const string_type& a_CharSet) const;
277  void CheckOprt(const string_type& a_sName, const ParserCallback& a_Callback, const string_type& a_szCharSet) const;
278 
279  void StackDump(const std::stack<token_type >& a_stVal, const std::stack<token_type >& a_stOprt) const;
280 
281  /** \brief Pointer to the parser function.
282 
283  Eval() calls the function whose address is stored there.
284  */
285  mutable ParseFunction m_pParseFormula;
286  mutable ParserByteCode m_vRPN; ///< The Bytecode class.
287  mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments
288  stringbuf_type m_vStringVarBuf;
289 
290  std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
291 
292  funmap_type m_FunDef; ///< Map of function names and pointers.
293  funmap_type m_PostOprtDef; ///< Postfix operator callbacks
294  funmap_type m_InfixOprtDef; ///< unary infix operator.
295  funmap_type m_OprtDef; ///< Binary operator callbacks
296  valmap_type m_ConstDef; ///< user constants.
297  strmap_type m_StrVarDef; ///< user defined string constants
298  varmap_type m_VarDef; ///< user defind variables.
299 
300  bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off
301 
302  string_type m_sNameChars; ///< Charset for names
303  string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens
304  string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
305 
306  // items merely used for caching state information
307  mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
308  mutable int m_nFinalResultIdx;
309  };
310 
311 } // namespace mu
312 
313 #if defined(_MSC_VER)
314  #pragma warning(pop)
315 #endif
316 
317 #endif
Definition of the parser bytecode class.
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
Definition: muParserDef.h:505
static std::locale s_locale
The locale used by the parser.
Definition: muParserBase.h:206
std::map< string_type, std::size_t > strmap_type
Type for assigning a string name to an index in the internal string table.
Definition: muParserDef.h:320
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Definition: muParserDef.h:314
void DefineFunUserData(const string_type &a_strName, T a_pFun, void *a_pUserData, bool a_bAllowOpt=true)
Define a parser function with user data (not null).
Definition: muParserBase.h:152
value_type(* fun_type1)(value_type)
Callback type used for functions with a single arguments.
Definition: muParserDef.h:331
std::map< string_type, ParserCallback > funmap_type
Container for Callback objects.
EOprtAssociativity
Parser operator precedence values.
Definition: muParserDef.h:199
This file contains the parser token reader definition.
std::map< string_type, value_type > valmap_type
Type used for storing constants.
Definition: muParserDef.h:317
void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt=true)
Define a parser function without arguments.
Definition: muParserBase.h:139
value_type(* fun_type2)(value_type, value_type)
Callback type used for functions with two arguments.
Definition: muParserDef.h:334
Error class of the parser.
Definition: muParserError.h:74
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:294
A facet class used to change decimal and thousands separator.
Definition: muParserBase.h:212
Namespace for mathematical applications.
Definition: muParser.cpp:46
int(* identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal)
Callback used for functions that identify values in a string.
Definition: muParserDef.h:502
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:306
Token reader for the ParserBase class.
Bytecode implementation of the Math Parser.
MUP_STRING_TYPE string_type
The stringtype used by the parser.
Definition: muParserDef.h:300
ParserError exception_type
Type of the error class.
Definition: muParserBase.h:103
EErrorCodes
Error codes.
Definition: muParserDef.h:226
Encapsulation of prototypes for a numerical parser function.
Signs have a higher priority than ADD_SUB, but lower than power operator.
Definition: muParserDef.h:220
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:68
This file defines the error class used by the parser.
This file contains standard definitions used by the parser.