Add HeFFTe based FFT backend
[alexxy/gromacs.git] / src / external / muparser / muParserToken.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_TOKEN_H
30 #define MU_PARSER_TOKEN_H
31
32 #include <string>
33 #include <stack>
34 #include <vector>
35 #include <memory>
36
37 #if defined(_MSC_VER)
38         #pragma warning(push)
39         #pragma warning(disable : 26812) 
40 #endif
41
42 #include "muParserError.h"
43 #include "muParserCallback.h"
44
45 /** \file
46         \brief This file contains the parser token definition.
47 */
48
49 namespace mu
50 {
51         /** \brief Encapsulation of the data for a single formula token.
52
53                 Formula token implementation. Part of the Math Parser Package.
54                 Formula tokens can be either one of the following:
55                 <ul>
56                         <li>value</li>
57                         <li>variable</li>
58                         <li>function with numerical arguments</li>
59                         <li>functions with a string as argument</li>
60                         <li>prefix operators</li>
61                         <li>infix operators</li>
62                         <li>binary operator</li>
63                 </ul>
64         */
65         template<typename TBase, typename TString>
66         class ParserToken final
67         {
68         private:
69
70                 ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.
71                 ETypeCode m_iType;
72                 void* m_pTok;           ///< Stores Token pointer; not applicable for all tokens
73                 int  m_iIdx;            ///< An otional index to an external buffer storing the token data
74                 TString m_strTok;   ///< Token string
75                 TString m_strVal;   ///< Value for string variables
76                 value_type m_fVal;  ///< the value 
77                 std::unique_ptr<ParserCallback> m_pCallback;
78
79         public:
80
81                 /** \brief Constructor (default).
82
83                         Sets token to an neutral state of type cmUNKNOWN.
84                         \throw nothrow
85                         \sa ECmdCode
86                 */
87                 ParserToken()
88                         :m_iCode(cmUNKNOWN)
89                         , m_iType(tpVOID)
90                         , m_pTok(0)
91                         , m_iIdx(-1)
92                         , m_strTok()
93                         , m_strVal()
94                         , m_fVal(0)
95                         , m_pCallback()
96                 {}
97
98                 //------------------------------------------------------------------------------
99                 /** \brief Create token from another one.
100
101                         Implemented by calling Assign(...)
102                         \throw nothrow
103                         \post m_iType==cmUNKNOWN
104                         \sa #Assign
105                 */
106                 ParserToken(const ParserToken& a_Tok)
107                 {
108                         Assign(a_Tok);
109                 }
110
111                 
112                 /** \brief Assignment operator.
113
114                         Copy token state from another token and return this.
115                         Implemented by calling Assign(...).
116                         \throw nothrow
117                 */
118                 ParserToken& operator=(const ParserToken& a_Tok)
119                 {
120                         Assign(a_Tok);
121                         return *this;
122                 }
123
124
125                 /** \brief Copy token information from argument.
126
127                         \throw nothrow
128                 */
129                 void Assign(const ParserToken& a_Tok)
130                 {
131                         m_iCode = a_Tok.m_iCode;
132                         m_pTok = a_Tok.m_pTok;
133                         m_strTok = a_Tok.m_strTok;
134                         m_iIdx = a_Tok.m_iIdx;
135                         m_strVal = a_Tok.m_strVal;
136                         m_iType = a_Tok.m_iType;
137                         m_fVal = a_Tok.m_fVal;
138                         // create new callback object if a_Tok has one 
139                         m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
140                 }
141
142                 //------------------------------------------------------------------------------
143                 /** \brief Assign a token type.
144
145                   Token may not be of type value, variable or function. Those have separate set functions.
146
147                   \pre [assert] a_iType!=cmVAR
148                   \pre [assert] a_iType!=cmVAL
149                   \pre [assert] a_iType!=cmFUNC
150                   \post m_fVal = 0
151                   \post m_pTok = 0
152                 */
153                 ParserToken& Set(ECmdCode a_iType, const TString& a_strTok = TString())
154                 {
155                         // The following types can't be set this way, they have special Set functions
156                         MUP_ASSERT(a_iType != cmVAR);
157                         MUP_ASSERT(a_iType != cmVAL);
158                         MUP_ASSERT(a_iType != cmFUNC);
159
160                         m_iCode = a_iType;
161                         m_iType = tpVOID;
162                         m_pTok = 0;
163                         m_strTok = a_strTok;
164                         m_iIdx = -1;
165
166                         return *this;
167                 }
168
169                 //------------------------------------------------------------------------------
170                 /** \brief Set Callback type. */
171                 ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
172                 {
173                         MUP_ASSERT(a_pCallback.GetAddr());
174
175                         m_iCode = a_pCallback.GetCode();
176                         m_iType = tpVOID;
177                         m_strTok = a_sTok;
178                         m_pCallback.reset(new ParserCallback(a_pCallback));
179
180                         m_pTok = 0;
181                         m_iIdx = -1;
182
183                         return *this;
184                 }
185
186                 //------------------------------------------------------------------------------
187                 /** \brief Make this token a value token.
188
189                         Member variables not necessary for value tokens will be invalidated.
190                         \throw nothrow
191                 */
192                 ParserToken& SetVal(TBase a_fVal, const TString& a_strTok = TString())
193                 {
194                         m_iCode = cmVAL;
195                         m_iType = tpDBL;
196                         m_fVal = a_fVal;
197                         m_strTok = a_strTok;
198                         m_iIdx = -1;
199
200                         m_pTok = 0;
201                         m_pCallback.reset(0);
202
203                         return *this;
204                 }
205
206                 //------------------------------------------------------------------------------
207                 /** \brief make this token a variable token.
208
209                         Member variables not necessary for variable tokens will be invalidated.
210                         \throw nothrow
211                 */
212                 ParserToken& SetVar(TBase* a_pVar, const TString& a_strTok)
213                 {
214                         m_iCode = cmVAR;
215                         m_iType = tpDBL;
216                         m_strTok = a_strTok;
217                         m_iIdx = -1;
218                         m_pTok = (void*)a_pVar;
219                         m_pCallback.reset(0);
220                         return *this;
221                 }
222
223                 //------------------------------------------------------------------------------
224                 /** \brief Make this token a variable token.
225
226                         Member variables not necessary for variable tokens will be invalidated.
227                         \throw nothrow
228                 */
229                 ParserToken& SetString(const TString& a_strTok, std::size_t a_iSize)
230                 {
231                         m_iCode = cmSTRING;
232                         m_iType = tpSTR;
233                         m_strTok = a_strTok;
234                         m_iIdx = static_cast<int>(a_iSize);
235
236                         m_pTok = 0;
237                         m_pCallback.reset(0);
238                         return *this;
239                 }
240
241                 //------------------------------------------------------------------------------
242                 /** \brief Set an index associated with the token related data.
243
244                         In cmSTRFUNC - This is the index to a string table in the main parser.
245                         \param a_iIdx The index the string function result will take in the bytecode parser.
246                         \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
247                 */
248                 void SetIdx(int a_iIdx)
249                 {
250                         if (m_iCode != cmSTRING || a_iIdx < 0)
251                                 throw ParserError(ecINTERNAL_ERROR);
252
253                         m_iIdx = a_iIdx;
254                 }
255
256                 //------------------------------------------------------------------------------
257                 /** \brief Return Index associated with the token related data.
258
259                         In cmSTRFUNC - This is the index to a string table in the main parser.
260
261                         \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
262                         \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
263                 */
264                 int GetIdx() const
265                 {
266                         if (m_iIdx < 0 || m_iCode != cmSTRING)
267                                 throw ParserError(ecINTERNAL_ERROR);
268
269                         return m_iIdx;
270                 }
271
272                 //------------------------------------------------------------------------------
273                 /** \brief Return the token type.
274
275                         \return #m_iType
276                         \throw nothrow
277                 */
278                 ECmdCode GetCode() const
279                 {
280                         if (m_pCallback.get())
281                         {
282                                 return m_pCallback->GetCode();
283                         }
284                         else
285                         {
286                                 return m_iCode;
287                         }
288                 }
289
290                 //------------------------------------------------------------------------------
291                 ETypeCode GetType() const
292                 {
293                         if (m_pCallback.get())
294                         {
295                                 return m_pCallback->GetType();
296                         }
297                         else
298                         {
299                                 return m_iType;
300                         }
301                 }
302
303                 //------------------------------------------------------------------------------
304                 int GetPri() const
305                 {
306                         if (!m_pCallback.get())
307                                 throw ParserError(ecINTERNAL_ERROR);
308
309                         if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
310                                 throw ParserError(ecINTERNAL_ERROR);
311
312                         return m_pCallback->GetPri();
313                 }
314
315                 //------------------------------------------------------------------------------
316                 EOprtAssociativity GetAssociativity() const
317                 {
318                         if (m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN)
319                                 throw ParserError(ecINTERNAL_ERROR);
320
321                         return m_pCallback->GetAssociativity();
322                 }
323
324                 //------------------------------------------------------------------------------
325                 /** \brief Return the address of the callback function assoziated with
326                                    function and operator tokens.
327
328                         \return The pointer stored in #m_pTok.
329                         \throw exception_type if token type is non of:
330                                    <ul>
331                                          <li>cmFUNC</li>
332                                          <li>cmSTRFUNC</li>
333                                          <li>cmPOSTOP</li>
334                                          <li>cmINFIXOP</li>
335                                          <li>cmOPRT_BIN</li>
336                                    </ul>
337                         \sa ECmdCode
338                 */
339                 generic_fun_type GetFuncAddr() const
340                 {
341                         return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;
342                 }
343
344                 //------------------------------------------------------------------------------
345                 /** \biref Get value of the token.
346
347                         Only applicable to variable and value tokens.
348                         \throw exception_type if token is no value/variable token.
349                 */
350                 TBase GetVal() const
351                 {
352                         switch (m_iCode)
353                         {
354                         case cmVAL:  return m_fVal;
355                         case cmVAR:  return *((TBase*)m_pTok);
356                         default:     throw ParserError(ecVAL_EXPECTED);
357                         }
358                 }
359
360                 //------------------------------------------------------------------------------
361                 /** \brief Get address of a variable token.
362
363                   Valid only if m_iType==CmdVar.
364                   \throw exception_type if token is no variable token.
365                 */
366                 TBase* GetVar() const
367                 {
368                         if (m_iCode != cmVAR)
369                                 throw ParserError(ecINTERNAL_ERROR);
370
371                         return (TBase*)m_pTok;
372                 }
373
374                 //------------------------------------------------------------------------------
375                 /** \brief Return the number of function arguments.
376
377                   Valid only if m_iType==CmdFUNC.
378                 */
379                 int GetArgCount() const
380                 {
381                         MUP_ASSERT(m_pCallback.get());
382
383                         if (!m_pCallback->GetAddr())
384                                 throw ParserError(ecINTERNAL_ERROR);
385
386                         return m_pCallback->GetArgc();
387                 }
388
389                 //------------------------------------------------------------------------------
390                 /** \brief Return the token identifier.
391
392                         If #m_iType is cmSTRING the token identifier is the value of the string argument
393                         for a string function.
394                         \return #m_strTok
395                         \throw nothrow
396                         \sa m_strTok
397                 */
398                 const TString& GetAsString() const
399                 {
400                         return m_strTok;
401                 }
402         };
403 } // namespace mu
404
405 #if defined(_MSC_VER)
406         #pragma warning(pop)
407 #endif
408
409 #endif