Coverage Report

Created: 2026-09-04 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/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
11.8k
    {
77
11.8k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
11.8k
      if (_pUserData == nullptr) 
79
11.8k
      {
80
11.8k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
11.8k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
11.8k
      } 
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.8k
    }
double mu::generic_callable_type::call_fun<0ul>() const
Line
Count
Source
76
835
    {
77
835
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
835
      if (_pUserData == nullptr) 
79
835
      {
80
835
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
835
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
835
      } 
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
835
    }
double mu::generic_callable_type::call_fun<1ul, double&>(double&) const
Line
Count
Source
76
10.5k
    {
77
10.5k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
10.5k
      if (_pUserData == nullptr) 
79
10.5k
      {
80
10.5k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
10.5k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
10.5k
      } 
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.5k
    }
double mu::generic_callable_type::call_fun<2ul, double&, double&>(double&, double&) const
Line
Count
Source
76
447
    {
77
447
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
447
      if (_pUserData == nullptr) 
79
447
      {
80
447
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
447
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
447
      } 
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
447
    }
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.69k
    {
105
3.69k
      if (_pUserData == nullptr) {
106
3.69k
        auto multfun_typed_ptr = reinterpret_cast<multfun_type>(_pRawFun);
107
3.69k
        return (*multfun_typed_ptr)(a_afArg, a_iArgc);
108
3.69k
      } 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.69k
    }
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
28.0k
    {
132
28.0k
      return _pRawFun == other._pRawFun && _pUserData == other._pUserData; 
133
28.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
20.5k
    {
142
20.5k
      return _pRawFun == nullptr; 
143
20.5k
    }
144
    
145
    bool operator!=(std::nullptr_t) const 
146
35.4k
    {
147
35.4k
      return _pRawFun != nullptr; 
148
35.4k
    }
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.64M
      :m_iCode(cmUNKNOWN)
193
2.64M
      , m_iType(tpVOID)
194
2.64M
      , m_pTok(0)
195
2.64M
      , m_iIdx(-1)
196
2.64M
      , m_strTok()
197
2.64M
      , m_strVal()
198
2.64M
      , m_fVal(0)
199
2.64M
      , m_pCallback()
200
2.64M
    {}
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.65M
    {
212
5.65M
      Assign(a_Tok);
213
5.65M
    }
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.06M
    {
224
7.06M
      Assign(a_Tok);
225
7.06M
      return *this;
226
7.06M
    }
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.32M
    {
259
      // The following types can't be set this way, they have special Set functions
260
1.32M
      MUP_ASSERT(a_iType != cmVAR);
261
1.32M
      MUP_ASSERT(a_iType != cmVAL);
262
1.32M
      MUP_ASSERT(a_iType != cmFUNC);
263
264
1.32M
      m_iCode = a_iType;
265
1.32M
      m_iType = tpVOID;
266
1.32M
      m_pTok = 0;
267
1.32M
      m_strTok = a_strTok;
268
1.32M
      m_iIdx = -1;
269
270
1.32M
      return *this;
271
1.32M
    }
272
273
    //------------------------------------------------------------------------------
274
    /** \brief Set Callback type. */
275
    ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
276
75.8k
    {
277
75.8k
      MUP_ASSERT(a_pCallback.IsValid());
278
279
75.8k
      m_iCode = a_pCallback.GetCode();
280
75.8k
      m_iType = tpVOID;
281
75.8k
      m_strTok = a_sTok;
282
75.8k
      m_pCallback.reset(new ParserCallback(a_pCallback));
283
284
75.8k
      m_pTok = 0;
285
75.8k
      m_iIdx = -1;
286
287
75.8k
      return *this;
288
75.8k
    }
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
1.06M
    {
298
1.06M
      m_iCode = cmVAL;
299
1.06M
      m_iType = tpDBL;
300
1.06M
      m_fVal = a_fVal;
301
1.06M
      m_strTok = a_strTok;
302
1.06M
      m_iIdx = -1;
303
304
1.06M
      m_pTok = 0;
305
1.06M
      m_pCallback.reset(0);
306
307
1.06M
      return *this;
308
1.06M
    }
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.9k
    {
335
11.9k
      m_iCode = cmSTRING;
336
11.9k
      m_iType = tpSTR;
337
11.9k
      m_strTok = a_strTok;
338
11.9k
      m_iIdx = static_cast<int>(a_iSize);
339
340
11.9k
      m_pTok = 0;
341
11.9k
      m_pCallback.reset(0);
342
11.9k
      return *this;
343
11.9k
    }
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
    {
354
      if (m_iCode != cmSTRING || a_iIdx < 0)
355
        throw ParserError(ecINTERNAL_ERROR);
356
357
      m_iIdx = a_iIdx;
358
    }
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.5M
    {
384
10.5M
      if (m_pCallback.get())
385
586k
      {
386
586k
        return m_pCallback->GetCode();
387
586k
      }
388
9.97M
      else
389
9.97M
      {
390
9.97M
        return m_iCode;
391
9.97M
      }
392
10.5M
    }
393
394
    //------------------------------------------------------------------------------
395
    ETypeCode GetType() const
396
990k
    {
397
990k
      if (m_pCallback.get())
398
41.0k
      {
399
41.0k
        return m_pCallback->GetType();
400
41.0k
      }
401
948k
      else
402
948k
      {
403
948k
        return m_iType;
404
948k
      }
405
990k
    }
406
407
    //------------------------------------------------------------------------------
408
    int GetPri() const
409
52.6k
    {
410
52.6k
      if (!m_pCallback.get())
411
0
        throw ParserError(ecINTERNAL_ERROR);
412
413
52.6k
      if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
414
0
        throw ParserError(ecINTERNAL_ERROR);
415
416
52.6k
      return m_pCallback->GetPri();
417
52.6k
    }
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
89.2k
    {
445
89.2k
      return (m_pCallback.get())
446
89.2k
        ? generic_callable_type{(erased_fun_type)m_pCallback->GetAddr(),
447
73.8k
                                m_pCallback->GetUserData()}
448
89.2k
        : generic_callable_type{};
449
89.2k
    }
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
933k
    {
459
933k
      switch (m_iCode)
460
933k
      {
461
933k
      case cmVAL:  return m_fVal;
462
0
      case cmVAR:  return *((TBase*)m_pTok);
463
3
      default:     throw ParserError(ecVAL_EXPECTED);
464
933k
      }
465
933k
    }
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
82.0k
    {
488
82.0k
      MUP_ASSERT(m_pCallback.get());
489
490
82.0k
      if (!m_pCallback->IsValid())
491
0
        throw ParserError(ecINTERNAL_ERROR);
492
493
82.0k
      return m_pCallback->GetArgc();
494
82.0k
    }
495
496
    //------------------------------------------------------------------------------
497
    /** \brief Return true if the token is a function token that can be optimized.
498
    */
499
    bool IsOptimizable() const
500
20.4k
    {
501
20.4k
      return m_pCallback->IsValid() && m_pCallback->IsOptimizable();
502
20.4k
    }
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
195
    {
515
195
      return m_strTok;
516
195
    }
517
  };
518
} // namespace mu
519
520
#if defined(_MSC_VER)
521
  #pragma warning(pop)
522
#endif
523
524
#endif