Coverage Report

Created: 2025-08-03 07:01

/src/muparser/include/muParserToken.h
Line
Count
Source (jump to first uncovered line)
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
9.77k
    {
77
9.77k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
9.77k
      if (_pUserData == nullptr) 
79
9.77k
      {
80
9.77k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
9.77k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
9.77k
      } 
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
9.77k
    }
double mu::generic_callable_type::call_fun<0ul>() const
Line
Count
Source
76
464
    {
77
464
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
464
      if (_pUserData == nullptr) 
79
464
      {
80
464
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
464
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
464
      } 
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
464
    }
double mu::generic_callable_type::call_fun<1ul, double&>(double&) const
Line
Count
Source
76
8.90k
    {
77
8.90k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
8.90k
      if (_pUserData == nullptr) 
79
8.90k
      {
80
8.90k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
8.90k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
8.90k
      } 
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
8.90k
    }
double mu::generic_callable_type::call_fun<2ul, double&, double&>(double&, double&) const
Line
Count
Source
76
404
    {
77
404
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
404
      if (_pUserData == nullptr) 
79
404
      {
80
404
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
404
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
404
      } 
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
404
    }
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
3.39k
    {
105
3.39k
      if (_pUserData == nullptr) {
106
3.39k
        auto multfun_typed_ptr = reinterpret_cast<multfun_type>(_pRawFun);
107
3.39k
        return (*multfun_typed_ptr)(a_afArg, a_iArgc);
108
3.39k
      } 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
3.39k
    }
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
73.0k
    {
132
73.0k
      return _pRawFun == other._pRawFun && _pUserData == other._pUserData; 
133
73.0k
    }
134
135
    explicit operator bool() const 
136
0
    {
137
0
      return _pRawFun != nullptr; 
138
0
    }
139
140
    bool operator==(std::nullptr_t) const 
141
77.4k
    {
142
77.4k
      return _pRawFun == nullptr; 
143
77.4k
    }
144
    
145
    bool operator!=(std::nullptr_t) const 
146
125k
    {
147
125k
      return _pRawFun != nullptr; 
148
125k
    }
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
2.66M
      :m_iCode(cmUNKNOWN)
193
2.66M
      , m_iType(tpVOID)
194
2.66M
      , m_pTok(0)
195
2.66M
      , m_iIdx(-1)
196
2.66M
      , m_strTok()
197
2.66M
      , m_strVal()
198
2.66M
      , m_fVal(0)
199
2.66M
      , m_pCallback()
200
2.66M
    {}
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
5.68M
    {
212
5.68M
      Assign(a_Tok);
213
5.68M
    }
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
7.05M
    {
224
7.05M
      Assign(a_Tok);
225
7.05M
      return *this;
226
7.05M
    }
227
228
229
    /** \brief Copy token information from argument.
230
231
      \throw nothrow
232
    */
233
    void Assign(const ParserToken& a_Tok)
234
12.7M
    {
235
12.7M
      m_iCode = a_Tok.m_iCode;
236
12.7M
      m_pTok = a_Tok.m_pTok;
237
12.7M
      m_strTok = a_Tok.m_strTok;
238
12.7M
      m_iIdx = a_Tok.m_iIdx;
239
12.7M
      m_strVal = a_Tok.m_strVal;
240
12.7M
      m_iType = a_Tok.m_iType;
241
12.7M
      m_fVal = a_Tok.m_fVal;
242
      // create new callback object if a_Tok has one 
243
12.7M
      m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
244
12.7M
    }
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
1.66M
    {
259
      // The following types can't be set this way, they have special Set functions
260
1.66M
      MUP_ASSERT(a_iType != cmVAR);
261
1.66M
      MUP_ASSERT(a_iType != cmVAL);
262
1.66M
      MUP_ASSERT(a_iType != cmFUNC);
263
264
1.66M
      m_iCode = a_iType;
265
1.66M
      m_iType = tpVOID;
266
1.66M
      m_pTok = 0;
267
1.66M
      m_strTok = a_strTok;
268
1.66M
      m_iIdx = -1;
269
270
1.66M
      return *this;
271
1.66M
    }
272
273
    //------------------------------------------------------------------------------
274
    /** \brief Set Callback type. */
275
    ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
276
81.0k
    {
277
81.0k
      MUP_ASSERT(a_pCallback.IsValid());
278
279
81.0k
      m_iCode = a_pCallback.GetCode();
280
81.0k
      m_iType = tpVOID;
281
81.0k
      m_strTok = a_sTok;
282
81.0k
      m_pCallback.reset(new ParserCallback(a_pCallback));
283
284
81.0k
      m_pTok = 0;
285
81.0k
      m_iIdx = -1;
286
287
81.0k
      return *this;
288
81.0k
    }
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
744k
    {
298
744k
      m_iCode = cmVAL;
299
744k
      m_iType = tpDBL;
300
744k
      m_fVal = a_fVal;
301
744k
      m_strTok = a_strTok;
302
744k
      m_iIdx = -1;
303
304
744k
      m_pTok = 0;
305
744k
      m_pCallback.reset(0);
306
307
744k
      return *this;
308
744k
    }
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
14.2k
    {
335
14.2k
      m_iCode = cmSTRING;
336
14.2k
      m_iType = tpSTR;
337
14.2k
      m_strTok = a_strTok;
338
14.2k
      m_iIdx = static_cast<int>(a_iSize);
339
340
14.2k
      m_pTok = 0;
341
14.2k
      m_pCallback.reset(0);
342
14.2k
      return *this;
343
14.2k
    }
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
14.0k
    {
354
14.0k
      if (m_iCode != cmSTRING || a_iIdx < 0)
355
0
        throw ParserError(ecINTERNAL_ERROR);
356
357
14.0k
      m_iIdx = a_iIdx;
358
14.0k
    }
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
10.3M
    {
384
10.3M
      if (m_pCallback.get())
385
985k
      {
386
985k
        return m_pCallback->GetCode();
387
985k
      }
388
9.38M
      else
389
9.38M
      {
390
9.38M
        return m_iCode;
391
9.38M
      }
392
10.3M
    }
393
394
    //------------------------------------------------------------------------------
395
    ETypeCode GetType() const
396
905k
    {
397
905k
      if (m_pCallback.get())
398
154k
      {
399
154k
        return m_pCallback->GetType();
400
154k
      }
401
750k
      else
402
750k
      {
403
750k
        return m_iType;
404
750k
      }
405
905k
    }
406
407
    //------------------------------------------------------------------------------
408
    int GetPri() const
409
63.5k
    {
410
63.5k
      if (!m_pCallback.get())
411
0
        throw ParserError(ecINTERNAL_ERROR);
412
413
63.5k
      if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
414
0
        throw ParserError(ecINTERNAL_ERROR);
415
416
63.5k
      return m_pCallback->GetPri();
417
63.5k
    }
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
280k
    {
445
280k
      return (m_pCallback.get())
446
280k
        ? generic_callable_type{(erased_fun_type)m_pCallback->GetAddr(),
447
242k
                                m_pCallback->GetUserData()}
448
280k
        : generic_callable_type{};
449
280k
    }
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
577k
    {
459
577k
      switch (m_iCode)
460
577k
      {
461
577k
      case cmVAL:  return m_fVal;
462
0
      case cmVAR:  return *((TBase*)m_pTok);
463
1
      default:     throw ParserError(ecVAL_EXPECTED);
464
577k
      }
465
577k
    }
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
309k
    {
488
309k
      MUP_ASSERT(m_pCallback.get());
489
490
309k
      if (!m_pCallback->IsValid())
491
0
        throw ParserError(ecINTERNAL_ERROR);
492
493
309k
      return m_pCallback->GetArgc();
494
309k
    }
495
496
    //------------------------------------------------------------------------------
497
    /** \brief Return true if the token is a function token that can be optimized.
498
    */
499
    bool IsOptimizable() const
500
77.3k
    {
501
77.3k
      return m_pCallback->IsValid() && m_pCallback->IsOptimizable();
502
77.3k
    }
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
14.4k
    {
515
14.4k
      return m_strTok;
516
14.4k
    }
517
  };
518
} // namespace mu
519
520
#if defined(_MSC_VER)
521
  #pragma warning(pop)
522
#endif
523
524
#endif