Coverage Report

Created: 2026-11-12 06:17

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
165k
    {
77
165k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
165k
      if (_pUserData == nullptr) 
79
165k
      {
80
165k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
165k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
165k
      } 
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
165k
    }
double mu::generic_callable_type::call_fun<0ul>() const
Line
Count
Source
76
3.56k
    {
77
3.56k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
3.56k
      if (_pUserData == nullptr) 
79
3.56k
      {
80
3.56k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
3.56k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
3.56k
      } 
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
3.56k
    }
double mu::generic_callable_type::call_fun<1ul, double&>(double&) const
Line
Count
Source
76
67.2k
    {
77
67.2k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
67.2k
      if (_pUserData == nullptr) 
79
67.2k
      {
80
67.2k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
67.2k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
67.2k
      } 
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
67.2k
    }
double mu::generic_callable_type::call_fun<2ul, double&, double&>(double&, double&) const
Line
Count
Source
76
93.1k
    {
77
93.1k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
93.1k
      if (_pUserData == nullptr) 
79
93.1k
      {
80
93.1k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
93.1k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
93.1k
      } 
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
93.1k
    }
double mu::generic_callable_type::call_fun<3ul, double&, double&, double&>(double&, double&, double&) const
Line
Count
Source
76
1.04k
    {
77
1.04k
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
78
1.04k
      if (_pUserData == nullptr) 
79
1.04k
      {
80
1.04k
        auto fun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::fun_type>(_pRawFun);
81
1.04k
        return (*fun_typed_ptr)(std::forward<Args>(args)...);
82
1.04k
      } 
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
1.04k
    }
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
9.28k
    {
105
9.28k
      if (_pUserData == nullptr) {
106
9.28k
        auto multfun_typed_ptr = reinterpret_cast<multfun_type>(_pRawFun);
107
9.28k
        return (*multfun_typed_ptr)(a_afArg, a_iArgc);
108
9.28k
      } 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
9.28k
    }
113
114
    value_type call_multstrfun(const char_type* a_sArg, const value_type* a_afArg, int a_iArgc) const
115
0
    {
116
0
      auto multstrfun_typed_ptr = reinterpret_cast<multstrfun_type>(_pRawFun);
117
0
      return (*multstrfun_typed_ptr)(a_sArg, a_afArg, a_iArgc);
118
0
    }
119
120
    template <std::size_t NbParams, typename... Args>
121
    value_type call_strfun(Args&&... args) const
122
0
    {
123
0
      static_assert(NbParams == sizeof...(Args), "mismatch between NbParams and Args");
124
0
      if (_pUserData == nullptr) 
125
0
      {
126
0
        auto strfun_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::strfun_type>(_pRawFun);
127
0
        return (*strfun_typed_ptr)(std::forward<Args>(args)...);
128
0
      } 
129
0
      else 
130
0
      {
131
0
        auto strfun_userdata_typed_ptr = reinterpret_cast<typename TplCallType<NbParams>::strfun_userdata_type>(_pRawFun);
132
0
        return (*strfun_userdata_typed_ptr)(_pUserData, std::forward<Args>(args)...);
133
0
      }
134
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
135
136
    bool operator==(generic_callable_type other) const 
137
29.8k
    {
138
29.8k
      return _pRawFun == other._pRawFun && _pUserData == other._pUserData; 
139
29.8k
    }
140
141
    explicit operator bool() const 
142
0
    {
143
0
      return _pRawFun != nullptr; 
144
0
    }
145
146
    bool operator==(std::nullptr_t) const 
147
164k
    {
148
164k
      return _pRawFun == nullptr; 
149
164k
    }
150
    
151
    bool operator!=(std::nullptr_t) const 
152
169k
    {
153
169k
      return _pRawFun != nullptr; 
154
169k
    }
155
  };
156
157
  static_assert(std::is_trivial<generic_callable_type>::value, "generic_callable_type shall be trivial");
158
  static_assert(std::is_standard_layout<generic_callable_type>::value, "generic_callable_type shall have standard layout");
159
  // C++17: static_assert(std::is_aggregate<generic_callable_type>::value, "generic_callable_type shall be an aggregate");
160
161
  /** \brief Encapsulation of the data for a single formula token.
162
163
    Formula token implementation. Part of the Math Parser Package.
164
    Formula tokens can be either one of the following:
165
    <ul>
166
      <li>value</li>
167
      <li>variable</li>
168
      <li>function with numerical arguments</li>
169
      <li>functions with a string as argument</li>
170
      <li>prefix operators</li>
171
      <li>infix operators</li>
172
      <li>binary operator</li>
173
    </ul>
174
  */
175
  template<typename TBase, typename TString>
176
  class ParserToken final
177
  {
178
  private:
179
180
    ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.
181
    ETypeCode m_iType;
182
    void* m_pTok;   ///< Stores Token pointer; not applicable for all tokens
183
    int  m_iIdx;    ///< An otional index to an external buffer storing the token data
184
    TString m_strTok;   ///< Token string
185
    TString m_strVal;   ///< Value for string variables
186
    value_type m_fVal;  ///< the value 
187
    std::unique_ptr<ParserCallback> m_pCallback;
188
189
  public:
190
191
    /** \brief Constructor (default).
192
193
      Sets token to an neutral state of type cmUNKNOWN.
194
      \throw nothrow
195
      \sa ECmdCode
196
    */
197
    ParserToken()
198
2.94M
      :m_iCode(cmUNKNOWN)
199
2.94M
      , m_iType(tpVOID)
200
2.94M
      , m_pTok(0)
201
2.94M
      , m_iIdx(-1)
202
2.94M
      , m_strTok()
203
2.94M
      , m_strVal()
204
2.94M
      , m_fVal(0)
205
2.94M
      , m_pCallback()
206
2.94M
    {}
207
208
    //------------------------------------------------------------------------------
209
    /** \brief Create token from another one.
210
211
      Implemented by calling Assign(...)
212
      \throw nothrow
213
      \post m_iType==cmUNKNOWN
214
      \sa #Assign
215
    */
216
    ParserToken(const ParserToken& a_Tok)
217
6.36M
    {
218
6.36M
      Assign(a_Tok);
219
6.36M
    }
220
221
    
222
    /** \brief Assignment operator.
223
224
      Copy token state from another token and return this.
225
      Implemented by calling Assign(...).
226
      \throw nothrow
227
    */
228
    ParserToken& operator=(const ParserToken& a_Tok)
229
7.32M
    {
230
7.32M
      Assign(a_Tok);
231
7.32M
      return *this;
232
7.32M
    }
233
234
235
    /** \brief Copy token information from argument.
236
237
      \throw nothrow
238
    */
239
    void Assign(const ParserToken& a_Tok)
240
13.6M
    {
241
13.6M
      m_iCode = a_Tok.m_iCode;
242
13.6M
      m_pTok = a_Tok.m_pTok;
243
13.6M
      m_strTok = a_Tok.m_strTok;
244
13.6M
      m_iIdx = a_Tok.m_iIdx;
245
13.6M
      m_strVal = a_Tok.m_strVal;
246
13.6M
      m_iType = a_Tok.m_iType;
247
13.6M
      m_fVal = a_Tok.m_fVal;
248
      // create new callback object if a_Tok has one 
249
13.6M
      m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
250
13.6M
    }
251
252
    //------------------------------------------------------------------------------
253
    /** \brief Assign a token type.
254
255
      Token may not be of type value, variable or function. Those have separate set functions.
256
257
      \pre [assert] a_iType!=cmVAR
258
      \pre [assert] a_iType!=cmVAL
259
      \pre [assert] a_iType!=cmFUNC
260
      \post m_fVal = 0
261
      \post m_pTok = 0
262
    */
263
    ParserToken& Set(ECmdCode a_iType, const TString& a_strTok = TString())
264
1.13M
    {
265
      // The following types can't be set this way, they have special Set functions
266
1.13M
      MUP_ASSERT(a_iType != cmVAR);
267
1.13M
      MUP_ASSERT(a_iType != cmVAL);
268
1.13M
      MUP_ASSERT(a_iType != cmFUNC);
269
270
1.13M
      m_iCode = a_iType;
271
1.13M
      m_iType = tpVOID;
272
1.13M
      m_pTok = 0;
273
1.13M
      m_strTok = a_strTok;
274
1.13M
      m_iIdx = -1;
275
276
1.13M
      return *this;
277
1.13M
    }
278
279
    //------------------------------------------------------------------------------
280
    /** \brief Set Callback type. */
281
    ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
282
279k
    {
283
279k
      MUP_ASSERT(a_pCallback.IsValid());
284
285
279k
      m_iCode = a_pCallback.GetCode();
286
279k
      m_iType = tpVOID;
287
279k
      m_strTok = a_sTok;
288
279k
      m_pCallback.reset(new ParserCallback(a_pCallback));
289
290
279k
      m_pTok = 0;
291
279k
      m_iIdx = -1;
292
293
279k
      return *this;
294
279k
    }
295
296
    //------------------------------------------------------------------------------
297
    /** \brief Make this token a value token.
298
299
      Member variables not necessary for value tokens will be invalidated.
300
      \throw nothrow
301
    */
302
    ParserToken& SetVal(TBase a_fVal, const TString& a_strTok = TString())
303
611k
    {
304
611k
      m_iCode = cmVAL;
305
611k
      m_iType = tpDBL;
306
611k
      m_fVal = a_fVal;
307
611k
      m_strTok = a_strTok;
308
611k
      m_iIdx = -1;
309
310
611k
      m_pTok = 0;
311
611k
      m_pCallback.reset(0);
312
313
611k
      return *this;
314
611k
    }
315
316
    //------------------------------------------------------------------------------
317
    /** \brief make this token a variable token.
318
319
      Member variables not necessary for variable tokens will be invalidated.
320
      \throw nothrow
321
    */
322
    ParserToken& SetVar(TBase* a_pVar, const TString& a_strTok)
323
607k
    {
324
607k
      m_iCode = cmVAR;
325
607k
      m_iType = tpDBL;
326
607k
      m_strTok = a_strTok;
327
607k
      m_iIdx = -1;
328
607k
      m_pTok = (void*)a_pVar;
329
607k
      m_pCallback.reset(0);
330
607k
      return *this;
331
607k
    }
332
333
    //------------------------------------------------------------------------------
334
    /** \brief Make this token a variable token.
335
336
      Member variables not necessary for variable tokens will be invalidated.
337
      \throw nothrow
338
    */
339
    ParserToken& SetString(const TString& a_strTok, std::size_t a_iSize)
340
17.8k
    {
341
17.8k
      m_iCode = cmSTRING;
342
17.8k
      m_iType = tpSTR;
343
17.8k
      m_strTok = a_strTok;
344
17.8k
      m_iIdx = static_cast<int>(a_iSize);
345
346
17.8k
      m_pTok = 0;
347
17.8k
      m_pCallback.reset(0);
348
17.8k
      return *this;
349
17.8k
    }
350
351
    //------------------------------------------------------------------------------
352
    /** \brief Set an index associated with the token related data.
353
354
      In cmSTRFUNC - This is the index to a string table in the main parser.
355
      \param a_iIdx The index the string function result will take in the bytecode parser.
356
      \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
357
    */
358
    void SetIdx(int a_iIdx)
359
    {
360
      if (m_iCode != cmSTRING || a_iIdx < 0)
361
        throw ParserError(ecINTERNAL_ERROR);
362
363
      m_iIdx = a_iIdx;
364
    }
365
366
    //------------------------------------------------------------------------------
367
    /** \brief Return Index associated with the token related data.
368
369
      In cmSTRFUNC - This is the index to a string table in the main parser.
370
371
      \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
372
      \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
373
    */
374
    int GetIdx() const
375
0
    {
376
0
      if (m_iIdx < 0 || m_iCode != cmSTRING)
377
0
        throw ParserError(ecINTERNAL_ERROR);
378
379
0
      return m_iIdx;
380
0
    }
381
382
    //------------------------------------------------------------------------------
383
    /** \brief Return the token type.
384
385
      \return #m_iType
386
      \throw nothrow
387
    */
388
    ECmdCode GetCode() const
389
12.2M
    {
390
12.2M
      if (m_pCallback.get())
391
4.12M
      {
392
4.12M
        return m_pCallback->GetCode();
393
4.12M
      }
394
8.13M
      else
395
8.13M
      {
396
8.13M
        return m_iCode;
397
8.13M
      }
398
12.2M
    }
399
400
    //------------------------------------------------------------------------------
401
    ETypeCode GetType() const
402
1.46M
    {
403
1.46M
      if (m_pCallback.get())
404
329k
      {
405
329k
        return m_pCallback->GetType();
406
329k
      }
407
1.13M
      else
408
1.13M
      {
409
1.13M
        return m_iType;
410
1.13M
      }
411
1.46M
    }
412
413
    //------------------------------------------------------------------------------
414
    int GetPri() const
415
464k
    {
416
464k
      if (!m_pCallback.get())
417
0
        throw ParserError(ecINTERNAL_ERROR);
418
419
464k
      if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
420
0
        throw ParserError(ecINTERNAL_ERROR);
421
422
464k
      return m_pCallback->GetPri();
423
464k
    }
424
425
    //------------------------------------------------------------------------------
426
    EOprtAssociativity GetAssociativity() const
427
191k
    {
428
191k
      if (m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN)
429
0
        throw ParserError(ecINTERNAL_ERROR);
430
431
191k
      return m_pCallback->GetAssociativity();
432
191k
    }
433
434
    //------------------------------------------------------------------------------
435
    /** \brief Return the address of the callback function assoziated with
436
           function and operator tokens.
437
438
      \return The pointer stored in #m_pTok.
439
      \throw exception_type if token type is non of:
440
           <ul>
441
           <li>cmFUNC</li>
442
           <li>cmSTRFUNC</li>
443
           <li>cmPOSTOP</li>
444
           <li>cmINFIXOP</li>
445
           <li>cmOPRT_BIN</li>
446
           </ul>
447
      \sa ECmdCode
448
    */
449
    generic_callable_type GetFuncAddr() const
450
503k
    {
451
503k
      return (m_pCallback.get())
452
503k
        ? generic_callable_type{(erased_fun_type)m_pCallback->GetAddr(),
453
498k
                                m_pCallback->GetUserData()}
454
503k
        : generic_callable_type{};
455
503k
    }
456
457
    //------------------------------------------------------------------------------
458
    /** \biref Get value of the token.
459
460
      Only applicable to variable and value tokens.
461
      \throw exception_type if token is no value/variable token.
462
    */
463
    TBase GetVal() const
464
368k
    {
465
368k
      switch (m_iCode)
466
368k
      {
467
323k
      case cmVAL:  return m_fVal;
468
44.3k
      case cmVAR:  return *((TBase*)m_pTok);
469
1
      default:     throw ParserError(ecVAL_EXPECTED);
470
368k
      }
471
368k
    }
472
473
    //------------------------------------------------------------------------------
474
    /** \brief Get address of a variable token.
475
476
      Valid only if m_iType==CmdVar.
477
      \throw exception_type if token is no variable token.
478
    */
479
    TBase* GetVar() const
480
614k
    {
481
614k
      if (m_iCode != cmVAR)
482
0
        throw ParserError(ecINTERNAL_ERROR);
483
484
614k
      return (TBase*)m_pTok;
485
614k
    }
486
487
    //------------------------------------------------------------------------------
488
    /** \brief Return the number of function arguments.
489
490
      Valid only if m_iType==CmdFUNC.
491
    */
492
    int GetArgCount() const
493
796k
    {
494
796k
      MUP_ASSERT(m_pCallback.get());
495
496
796k
      if (!m_pCallback->IsValid())
497
0
        throw ParserError(ecINTERNAL_ERROR);
498
499
796k
      return m_pCallback->GetArgc();
500
796k
    }
501
502
    //------------------------------------------------------------------------------
503
    /** \brief Return true if the token is a function token that can be optimized.
504
    */
505
    bool IsOptimizable() const
506
164k
    {
507
164k
      return m_pCallback->IsValid() && m_pCallback->IsOptimizable();
508
164k
    }
509
510
    //------------------------------------------------------------------------------
511
    /** \brief Return the token identifier.
512
513
      If #m_iType is cmSTRING the token identifier is the value of the string argument
514
      for a string function.
515
      \return #m_strTok
516
      \throw nothrow
517
      \sa m_strTok
518
    */
519
    const TString& GetAsString() const
520
423
    {
521
423
      return m_strTok;
522
423
    }
523
  };
524
} // namespace mu
525
526
#if defined(_MSC_VER)
527
  #pragma warning(pop)
528
#endif
529
530
#endif