/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 |