Coverage Report

Created: 2025-12-31 08:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/muparser/include/muParserToken.h
Line
Count
Source
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_TOKEN_H
30
#define MU_PARSER_TOKEN_H
31
32
#include <string>
33
#include <stack>
34
#include <vector>
35
#include <memory>
36
#include <utility>
37
#include <type_traits>
38
#include <cstddef>
39
40
#if defined(_MSC_VER)
41
  #pragma warning(push)
42
  #pragma warning(disable : 26812) 
43
#endif
44
45
#include "muParserError.h"
46
#include "muParserCallback.h"
47
48
/** \file
49
  \brief This file contains the parser token definition.
50
*/
51
52
namespace mu
53
{
54
  template <std::size_t NbParams> struct TplCallType;
55
  template <> struct TplCallType<0> { using fun_type = fun_type0; using fun_userdata_type = fun_userdata_type0; using bulkfun_type = bulkfun_type0; using bulkfun_userdata_type = bulkfun_userdata_type0; };
56
  template <> struct TplCallType<1> { using fun_type = fun_type1; using fun_userdata_type = fun_userdata_type1; using bulkfun_type = bulkfun_type1; using bulkfun_userdata_type = bulkfun_userdata_type1; using strfun_type = strfun_type1; using strfun_userdata_type = strfun_userdata_type1; };
57
  template <> struct TplCallType<2> { using fun_type = fun_type2; using fun_userdata_type = fun_userdata_type2; using bulkfun_type = bulkfun_type2; using bulkfun_userdata_type = bulkfun_userdata_type2; using strfun_type = strfun_type2; using strfun_userdata_type = strfun_userdata_type2; };
58
  template <> struct TplCallType<3> { using fun_type = fun_type3; using fun_userdata_type = fun_userdata_type3; using bulkfun_type = bulkfun_type3; using bulkfun_userdata_type = bulkfun_userdata_type3; using strfun_type = strfun_type3; using strfun_userdata_type = strfun_userdata_type3; };
59
  template <> struct TplCallType<4> { using fun_type = fun_type4; using fun_userdata_type = fun_userdata_type4; using bulkfun_type = bulkfun_type4; using bulkfun_userdata_type = bulkfun_userdata_type4; using strfun_type = strfun_type4; using strfun_userdata_type = strfun_userdata_type4; };
60
  template <> struct TplCallType<5> { using fun_type = fun_type5; using fun_userdata_type = fun_userdata_type5; using bulkfun_type = bulkfun_type5; using bulkfun_userdata_type = bulkfun_userdata_type5; using strfun_type = strfun_type5; using strfun_userdata_type = strfun_userdata_type5; };
61
  template <> struct TplCallType<6> { using fun_type = fun_type6; using fun_userdata_type = fun_userdata_type6; using bulkfun_type = bulkfun_type6; using bulkfun_userdata_type = bulkfun_userdata_type6; using strfun_type = strfun_type6; using strfun_userdata_type = strfun_userdata_type6; };
62
  template <> struct TplCallType<7> { using fun_type = fun_type7; using fun_userdata_type = fun_userdata_type7; using bulkfun_type = bulkfun_type7; using bulkfun_userdata_type = bulkfun_userdata_type7; };
63
  template <> struct TplCallType<8> { using fun_type = fun_type8; using fun_userdata_type = fun_userdata_type8; using bulkfun_type = bulkfun_type8; using bulkfun_userdata_type = bulkfun_userdata_type8; };
64
  template <> struct TplCallType<9> { using fun_type = fun_type9; using fun_userdata_type = fun_userdata_type9; using bulkfun_type = bulkfun_type9; using bulkfun_userdata_type = bulkfun_userdata_type9; };
65
  template <> struct TplCallType<10> { using fun_type = fun_type10; using fun_userdata_type = fun_userdata_type10; using bulkfun_type = bulkfun_type10; using bulkfun_userdata_type = bulkfun_userdata_type10; };
66
67
  struct generic_callable_type
68
  {
69
    // Note: we keep generic_callable_type a pod for the purpose of layout
70
71
    erased_fun_type _pRawFun;
72
    void*           _pUserData;
73
74
    template <std::size_t NbParams, typename... Args>
75
    value_type call_fun(Args&&... args) const
76
0
    {
77
0
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
0
      if (_pUserData == nullptr) 
79
0
      {
80
0
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
0
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
0
      } 
83
0
      else 
84
0
      {
85
0
        auto fun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_userdata_type>(_pRawFun);
86
0
        return (*fun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
87
0
      }
88
0
    }
Unexecuted instantiation: double mu::generic_callable_type::call_fun<0ul>() const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<1ul, double&>(double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<2ul, double&, double&>(double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<3ul, double&, double&, double&>(double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<4ul, double&, double&, double&, double&>(double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<5ul, double&, double&, double&, double&, double&>(double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<6ul, double&, double&, double&, double&, double&, double&>(double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<7ul, double&, double&, double&, double&, double&, double&, double&>(double&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<8ul, double&, double&, double&, double&, double&, double&, double&, double&>(double&, double&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<9ul, double&, double&, double&, double&, double&, double&, double&, double&, double&>(double&, double&, double&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_fun<10ul, double&, double&, double&, double&, double&, double&, double&, double&, double&, double&>(double&, double&, double&, double&, double&, double&, double&, double&, double&, double&) const
89
90
    template <std::size_t NbParams, typename... Args>
91
    value_type call_bulkfun(Args&&... args) const
92
0
    {
93
0
      static_assert(NbParams == sizeof...(Args) - 2, "mismatch between NbParams and Args");
94
0
      if (_pUserData == nullptr) {
95
0
        auto bulkfun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::bulkfun_type>(_pRawFun);
96
0
        return (*bulkfun_typed_ptr)(std::forward<Args>(args)...);
97
0
      } else {
98
0
        auto bulkfun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::bulkfun_userdata_type>(_pRawFun);
99
0
        return (*bulkfun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
100
0
      }
101
0
    }
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<0ul, int&, int&>(int&, int&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<1ul, int&, int&, double&>(int&, int&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<2ul, int&, int&, double&, double&>(int&, int&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<3ul, int&, int&, double&, double&, double&>(int&, int&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<4ul, int&, int&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<5ul, int&, int&, double&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<6ul, int&, int&, double&, double&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<7ul, int&, int&, double&, double&, double&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<8ul, int&, int&, double&, double&, double&, double&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<9ul, int&, int&, double&, double&, double&, double&, double&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&, double&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_bulkfun<10ul, int&, int&, double&, double&, double&, double&, double&, double&, double&, double&, double&, double&>(int&, int&, double&, double&, double&, double&, double&, double&, double&, double&, double&, double&) const
102
103
    value_type call_multfun(const value_type* a_afArg, int a_iArgc) const
104
0
    {
105
0
      if (_pUserData == nullptr) {
106
0
        auto multfun_typed_ptr = reinterpret_cast<multfun_type>(_pRawFun);
107
0
        return (*multfun_typed_ptr)(a_afArg, a_iArgc);
108
0
      } else {
109
0
        auto multfun_userdata_typed_ptr = reinterpret_cast<multfun_userdata_type>(_pRawFun);
110
0
        return (*multfun_userdata_typed_ptr)(_pUserData, a_afArg, a_iArgc);
111
0
      }
112
0
    }
113
114
    template <std::size_t NbParams, typename... Args>
115
    value_type call_strfun(Args&&... args) const
116
0
    {
117
0
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
118
0
      if (_pUserData == nullptr) 
119
0
      {
120
0
        auto strfun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::strfun_type>(_pRawFun);
121
0
        return (*strfun_typed_ptr)(std::forward<Args>(args)...);
122
0
      } 
123
0
      else 
124
0
      {
125
0
        auto strfun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::strfun_userdata_type>(_pRawFun);
126
0
        return (*strfun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
127
0
      }
128
0
    }
Unexecuted instantiation: double mu::generic_callable_type::call_strfun<1ul, char const*>(char const*&&) const
Unexecuted instantiation: double mu::generic_callable_type::call_strfun<2ul, char const*, double&>(char const*&&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_strfun<3ul, char const*, double&, double&>(char const*&&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_strfun<4ul, char const*, double&, double&, double&>(char const*&&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_strfun<5ul, char const*, double&, double&, double&, double&>(char const*&&, double&, double&, double&, double&) const
Unexecuted instantiation: double mu::generic_callable_type::call_strfun<6ul, char const*, double&, double&, double&, double&, double&>(char const*&&, double&, double&, double&, double&, double&) const
129
130
    bool operator==(generic_callable_type other) const 
131
0
    {
132
0
      return _pRawFun == other._pRawFun && _pUserData == other._pUserData; 
133
0
    }
134
135
    explicit operator bool() const 
136
0
    {
137
0
      return _pRawFun != nullptr; 
138
0
    }
139
140
    bool operator==(std::nullptr_t) const 
141
0
    {
142
0
      return _pRawFun == nullptr; 
143
0
    }
144
    
145
    bool operator!=(std::nullptr_t) const 
146
0
    {
147
0
      return _pRawFun != nullptr; 
148
0
    }
149
  };
150
151
  static_assert(std::is_trivial<generic_callable_type>::value, "generic_callable_type shall be trivial");
152
  static_assert(std::is_standard_layout<generic_callable_type>::value, "generic_callable_type shall have standard layout");
153
  // C++17: static_assert(std::is_aggregate<generic_callable_type>::value, "generic_callable_type shall be an aggregate");
154
155
  /** \brief Encapsulation of the data for a single formula token.
156
157
    Formula token implementation. Part of the Math Parser Package.
158
    Formula tokens can be either one of the following:
159
    <ul>
160
      <li>value</li>
161
      <li>variable</li>
162
      <li>function with numerical arguments</li>
163
      <li>functions with a string as argument</li>
164
      <li>prefix operators</li>
165
      <li>infix operators</li>
166
      <li>binary operator</li>
167
    </ul>
168
  */
169
  template<typename TBase, typename TString>
170
  class ParserToken final
171
  {
172
  private:
173
174
    ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.
175
    ETypeCode m_iType;
176
    void* m_pTok;   ///< Stores Token pointer; not applicable for all tokens
177
    int  m_iIdx;    ///< An otional index to an external buffer storing the token data
178
    TString m_strTok;   ///< Token string
179
    TString m_strVal;   ///< Value for string variables
180
    value_type m_fVal;  ///< the value 
181
    std::unique_ptr<ParserCallback> m_pCallback;
182
183
  public:
184
185
    /** \brief Constructor (default).
186
187
      Sets token to an neutral state of type cmUNKNOWN.
188
      \throw nothrow
189
      \sa ECmdCode
190
    */
191
    ParserToken()
192
0
      :m_iCode(cmUNKNOWN)
193
0
      , m_iType(tpVOID)
194
0
      , m_pTok(0)
195
0
      , m_iIdx(-1)
196
0
      , m_strTok()
197
0
      , m_strVal()
198
0
      , m_fVal(0)
199
0
      , m_pCallback()
200
0
    {}
201
202
    //------------------------------------------------------------------------------
203
    /** \brief Create token from another one.
204
205
      Implemented by calling Assign(...)
206
      \throw nothrow
207
      \post m_iType==cmUNKNOWN
208
      \sa #Assign
209
    */
210
    ParserToken(const ParserToken& a_Tok)
211
0
    {
212
0
      Assign(a_Tok);
213
0
    }
214
215
    
216
    /** \brief Assignment operator.
217
218
      Copy token state from another token and return this.
219
      Implemented by calling Assign(...).
220
      \throw nothrow
221
    */
222
    ParserToken& operator=(const ParserToken& a_Tok)
223
0
    {
224
0
      Assign(a_Tok);
225
0
      return *this;
226
0
    }
227
228
229
    /** \brief Copy token information from argument.
230
231
      \throw nothrow
232
    */
233
    void Assign(const ParserToken& a_Tok)
234
0
    {
235
0
      m_iCode = a_Tok.m_iCode;
236
0
      m_pTok = a_Tok.m_pTok;
237
0
      m_strTok = a_Tok.m_strTok;
238
0
      m_iIdx = a_Tok.m_iIdx;
239
0
      m_strVal = a_Tok.m_strVal;
240
0
      m_iType = a_Tok.m_iType;
241
0
      m_fVal = a_Tok.m_fVal;
242
      // create new callback object if a_Tok has one 
243
0
      m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
244
0
    }
245
246
    //------------------------------------------------------------------------------
247
    /** \brief Assign a token type.
248
249
      Token may not be of type value, variable or function. Those have separate set functions.
250
251
      \pre [assert] a_iType!=cmVAR
252
      \pre [assert] a_iType!=cmVAL
253
      \pre [assert] a_iType!=cmFUNC
254
      \post m_fVal = 0
255
      \post m_pTok = 0
256
    */
257
    ParserToken& Set(ECmdCode a_iType, const TString& a_strTok = TString())
258
0
    {
259
      // The following types can't be set this way, they have special Set functions
260
0
      MUP_ASSERT(a_iType != cmVAR);
261
0
      MUP_ASSERT(a_iType != cmVAL);
262
0
      MUP_ASSERT(a_iType != cmFUNC);
263
264
0
      m_iCode = a_iType;
265
0
      m_iType = tpVOID;
266
0
      m_pTok = 0;
267
0
      m_strTok = a_strTok;
268
0
      m_iIdx = -1;
269
270
0
      return *this;
271
0
    }
272
273
    //------------------------------------------------------------------------------
274
    /** \brief Set Callback type. */
275
    ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
276
0
    {
277
0
      MUP_ASSERT(a_pCallback.IsValid());
278
279
0
      m_iCode = a_pCallback.GetCode();
280
0
      m_iType = tpVOID;
281
0
      m_strTok = a_sTok;
282
0
      m_pCallback.reset(new ParserCallback(a_pCallback));
283
284
0
      m_pTok = 0;
285
0
      m_iIdx = -1;
286
287
0
      return *this;
288
0
    }
289
290
    //------------------------------------------------------------------------------
291
    /** \brief Make this token a value token.
292
293
      Member variables not necessary for value tokens will be invalidated.
294
      \throw nothrow
295
    */
296
    ParserToken& SetVal(TBase a_fVal, const TString& a_strTok = TString())
297
0
    {
298
0
      m_iCode = cmVAL;
299
0
      m_iType = tpDBL;
300
0
      m_fVal = a_fVal;
301
0
      m_strTok = a_strTok;
302
0
      m_iIdx = -1;
303
304
0
      m_pTok = 0;
305
0
      m_pCallback.reset(0);
306
307
0
      return *this;
308
0
    }
309
310
    //------------------------------------------------------------------------------
311
    /** \brief make this token a variable token.
312
313
      Member variables not necessary for variable tokens will be invalidated.
314
      \throw nothrow
315
    */
316
    ParserToken& SetVar(TBase* a_pVar, const TString& a_strTok)
317
0
    {
318
0
      m_iCode = cmVAR;
319
0
      m_iType = tpDBL;
320
0
      m_strTok = a_strTok;
321
0
      m_iIdx = -1;
322
0
      m_pTok = (void*)a_pVar;
323
0
      m_pCallback.reset(0);
324
0
      return *this;
325
0
    }
326
327
    //------------------------------------------------------------------------------
328
    /** \brief Make this token a variable token.
329
330
      Member variables not necessary for variable tokens will be invalidated.
331
      \throw nothrow
332
    */
333
    ParserToken& SetString(const TString& a_strTok, std::size_t a_iSize)
334
0
    {
335
0
      m_iCode = cmSTRING;
336
0
      m_iType = tpSTR;
337
0
      m_strTok = a_strTok;
338
0
      m_iIdx = static_cast<int>(a_iSize);
339
340
0
      m_pTok = 0;
341
0
      m_pCallback.reset(0);
342
0
      return *this;
343
0
    }
344
345
    //------------------------------------------------------------------------------
346
    /** \brief Set an index associated with the token related data.
347
348
      In cmSTRFUNC - This is the index to a string table in the main parser.
349
      \param a_iIdx The index the string function result will take in the bytecode parser.
350
      \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
351
    */
352
    void SetIdx(int a_iIdx)
353
0
    {
354
0
      if (m_iCode != cmSTRING || a_iIdx < 0)
355
0
        throw ParserError(ecINTERNAL_ERROR);
356
357
0
      m_iIdx = a_iIdx;
358
0
    }
359
360
    //------------------------------------------------------------------------------
361
    /** \brief Return Index associated with the token related data.
362
363
      In cmSTRFUNC - This is the index to a string table in the main parser.
364
365
      \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
366
      \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
367
    */
368
    int GetIdx() const
369
0
    {
370
0
      if (m_iIdx < 0 || m_iCode != cmSTRING)
371
0
        throw ParserError(ecINTERNAL_ERROR);
372
373
0
      return m_iIdx;
374
0
    }
375
376
    //------------------------------------------------------------------------------
377
    /** \brief Return the token type.
378
379
      \return #m_iType
380
      \throw nothrow
381
    */
382
    ECmdCode GetCode() const
383
0
    {
384
0
      if (m_pCallback.get())
385
0
      {
386
0
        return m_pCallback->GetCode();
387
0
      }
388
0
      else
389
0
      {
390
0
        return m_iCode;
391
0
      }
392
0
    }
393
394
    //------------------------------------------------------------------------------
395
    ETypeCode GetType() const
396
0
    {
397
0
      if (m_pCallback.get())
398
0
      {
399
0
        return m_pCallback->GetType();
400
0
      }
401
0
      else
402
0
      {
403
0
        return m_iType;
404
0
      }
405
0
    }
406
407
    //------------------------------------------------------------------------------
408
    int GetPri() const
409
0
    {
410
0
      if (!m_pCallback.get())
411
0
        throw ParserError(ecINTERNAL_ERROR);
412
413
0
      if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
414
0
        throw ParserError(ecINTERNAL_ERROR);
415
416
0
      return m_pCallback->GetPri();
417
0
    }
418
419
    //------------------------------------------------------------------------------
420
    EOprtAssociativity GetAssociativity() const
421
0
    {
422
0
      if (m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN)
423
0
        throw ParserError(ecINTERNAL_ERROR);
424
425
0
      return m_pCallback->GetAssociativity();
426
0
    }
427
428
    //------------------------------------------------------------------------------
429
    /** \brief Return the address of the callback function assoziated with
430
           function and operator tokens.
431
432
      \return The pointer stored in #m_pTok.
433
      \throw exception_type if token type is non of:
434
           <ul>
435
           <li>cmFUNC</li>
436
           <li>cmSTRFUNC</li>
437
           <li>cmPOSTOP</li>
438
           <li>cmINFIXOP</li>
439
           <li>cmOPRT_BIN</li>
440
           </ul>
441
      \sa ECmdCode
442
    */
443
    generic_callable_type GetFuncAddr() const
444
0
    {
445
0
      return (m_pCallback.get())
446
0
        ? generic_callable_type{(erased_fun_type)m_pCallback->GetAddr(),
447
0
                                m_pCallback->GetUserData()}
448
0
        : generic_callable_type{};
449
0
    }
450
451
    //------------------------------------------------------------------------------
452
    /** \biref Get value of the token.
453
454
      Only applicable to variable and value tokens.
455
      \throw exception_type if token is no value/variable token.
456
    */
457
    TBase GetVal() const
458
0
    {
459
0
      switch (m_iCode)
460
0
      {
461
0
      case cmVAL:  return m_fVal;
462
0
      case cmVAR:  return *((TBase*)m_pTok);
463
0
      default:     throw ParserError(ecVAL_EXPECTED);
464
0
      }
465
0
    }
466
467
    //------------------------------------------------------------------------------
468
    /** \brief Get address of a variable token.
469
470
      Valid only if m_iType==CmdVar.
471
      \throw exception_type if token is no variable token.
472
    */
473
    TBase* GetVar() const
474
0
    {
475
0
      if (m_iCode != cmVAR)
476
0
        throw ParserError(ecINTERNAL_ERROR);
477
478
0
      return (TBase*)m_pTok;
479
0
    }
480
481
    //------------------------------------------------------------------------------
482
    /** \brief Return the number of function arguments.
483
484
      Valid only if m_iType==CmdFUNC.
485
    */
486
    int GetArgCount() const
487
0
    {
488
0
      MUP_ASSERT(m_pCallback.get());
489
490
0
      if (!m_pCallback->IsValid())
491
0
        throw ParserError(ecINTERNAL_ERROR);
492
493
0
      return m_pCallback->GetArgc();
494
0
    }
495
496
    //------------------------------------------------------------------------------
497
    /** \brief Return true if the token is a function token that can be optimized.
498
    */
499
    bool IsOptimizable() const
500
0
    {
501
0
      return m_pCallback->IsValid() && m_pCallback->IsOptimizable();
502
0
    }
503
504
    //------------------------------------------------------------------------------
505
    /** \brief Return the token identifier.
506
507
      If #m_iType is cmSTRING the token identifier is the value of the string argument
508
      for a string function.
509
      \return #m_strTok
510
      \throw nothrow
511
      \sa m_strTok
512
    */
513
    const TString& GetAsString() const
514
0
    {
515
0
      return m_strTok;
516
0
    }
517
  };
518
} // namespace mu
519
520
#if defined(_MSC_VER)
521
  #pragma warning(pop)
522
#endif
523
524
#endif