Build internal muparser more simply
[alexxy/gromacs.git] / src / external / muparser / include / muParserBase.h
1 /*
2
3          _____  __ _____________ _______  ______ ___________
4         /     \|  |  \____ \__  \\_  __ \/  ___// __ \_  __ \
5    |  Y Y  \  |  /  |_> > __ \|  | \/\___ \\  ___/|  | \/
6    |__|_|  /____/|   __(____  /__|  /____  >\___  >__|
7                  \/      |__|       \/           \/     \/
8    Copyright (C) 2004 - 2020 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
48 namespace mu
49 {
50         /** \file
51                 \brief This file contains the class definition of the muparser engine.
52         */
53
54         /** \brief Mathematical expressions parser (base parser engine).
55
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.
62         */
63         class API_EXPORT_CXX ParserBase
64         {
65                 friend class ParserTokenReader;
66
67         private:
68
69                 /** \brief Typedef for the parse functions.
70
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)
74                 */
75                 typedef value_type(ParserBase::* ParseFunction)() const;
76
77                 /** \brief Type used for storing an array of values. */
78                 typedef std::vector<value_type> valbuf_type;
79
80                 /** \brief Type for a vector of strings. */
81                 typedef std::vector<string_type> stringbuf_type;
82
83                 /** \brief Typedef for the token reader. */
84                 typedef ParserTokenReader token_reader_type;
85
86                 /** \brief Type used for parser tokens. */
87                 typedef ParserToken<value_type, string_type> token_type;
88
89                 /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
90                 static const int s_MaxNumOpenMPThreads;
91
92         public:
93
94                 /** \brief Type of the error class.
95
96                   Included for backwards compatibility.
97                 */
98                 typedef ParserError exception_type;
99
100                 static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
101
102                 ParserBase();
103                 ParserBase(const ParserBase& a_Parser);
104                 ParserBase& operator=(const ParserBase& a_Parser);
105
106                 virtual ~ParserBase();
107
108                 value_type Eval() const;
109                 value_type* Eval(int& nStackSize) const;
110                 void Eval(value_type* results, int nBulkSize);
111
112                 int GetNumResults() const;
113
114                 void SetExpr(const string_type& a_sExpr);
115                 void SetVarFactory(facfun_type a_pFactory, void* pUserData = nullptr);
116
117                 void SetDecSep(char_type cDecSep);
118                 void SetThousandsSep(char_type cThousandsSep = 0);
119                 void ResetLocale();
120
121                 void EnableOptimizer(bool a_bIsOn = true);
122                 void EnableBuiltInOprt(bool a_bIsOn = true);
123
124                 bool HasBuiltInOprt() const;
125                 void AddValIdent(identfun_type a_pCallback);
126
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
132                 */
133                 template<typename T>
134                 void DefineFun(const string_type& a_strName, T a_pFun, bool a_bAllowOpt = true)
135                 {
136                         AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars());
137                 }
138
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);
145
146                 // Clear user defined variables, constants or functions
147                 void ClearVar();
148                 void ClearFun();
149                 void ClearConst();
150                 void ClearInfixOprt();
151                 void ClearPostfixOprt();
152                 void ClearOprt();
153
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;
161
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);
166
167                 const char_type* ValidNameChars() const;
168                 const char_type* ValidOprtChars() const;
169                 const char_type* ValidInfixOprtChars() const;
170
171                 void SetArgSep(char_type cArgSep);
172                 char_type GetArgSep() const;
173
174         protected:
175
176                 void Init();
177                 void Error(EErrorCodes a_iErrc, int a_iPos = (int)mu::string_type::npos, const string_type& a_strTok = string_type()) const;
178
179                 virtual void InitCharSets() = 0;
180                 virtual void InitFun() = 0;
181                 virtual void InitConst() = 0;
182                 virtual void InitOprt() = 0;
183
184                 virtual void OnDetectVar(string_type* pExpr, int& nStart, int& nEnd);
185
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;
190
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>
194                 {
195                 public:
196
197                         explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
198                                 :std::numpunct<TChar>()
199                                 , m_nGroup(nGroup)
200                                 , m_cDecPoint(cDecSep)
201                                 , m_cThousandsSep(cThousandsSep)
202                         {}
203
204                 protected:
205
206                         virtual char_type do_decimal_point() const
207                         {
208                                 return m_cDecPoint;
209                         }
210
211                         virtual char_type do_thousands_sep() const
212                         {
213                                 return m_cThousandsSep;
214                         }
215
216                         virtual std::string do_grouping() const
217                         {
218                                 // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4
219                                 // courtesy of Jens Bartsch
220                                 // original code:
221                                 //        return std::string(1, (char)m_nGroup); 
222                                 // new code:
223                                 return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX));
224                         }
225
226                 private:
227
228                         int m_nGroup;
229                         char_type m_cDecPoint;
230                         char_type m_cThousandsSep;
231                 };
232
233         private:
234
235                 void Assign(const ParserBase& a_Parser);
236                 void InitTokenReader();
237                 void ReInit() const;
238
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;
244
245                 token_type ApplyStrFunc(const token_type& a_FunTok, const std::vector<token_type>& a_vArg) const;
246
247                 int GetOprtPrecedence(const token_type& a_Tok) const;
248                 EOprtAssociativity GetOprtAssociativity(const token_type& a_Tok) const;
249
250                 void CreateRPN() const;
251
252                 value_type ParseString() const;
253                 value_type ParseCmdCode() const;
254                 value_type ParseCmdCodeShort() const;
255                 value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const;
256
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;
259
260                 void StackDump(const std::stack<token_type >& a_stVal, const std::stack<token_type >& a_stOprt) const;
261
262                 /** \brief Pointer to the parser function.
263
264                   Eval() calls the function whose address is stored there.
265                 */
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;
270
271                 std::unique_ptr<token_reader_type> m_pTokenReader; ///< Managed pointer to the token reader object.
272
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.
280
281                 bool m_bBuiltInOp;             ///< Flag that can be used for switching built in operators on and off
282
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
286
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;
290         };
291
292 } // namespace mu
293
294 #endif