Coverage Report

Created: 2025-07-12 06:20

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