3 _____ __ _____________ _______ ______ ___________
4 / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5 | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6 |__|_| /____/| __(____ /__| /____ >\___ >__|
8 Copyright (C) 2004 - 2020 Ingo Berg
10 Redistribution and use in source and binary forms, with or without modification, are permitted
11 provided that the following conditions are met:
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.
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.
29 #ifndef MU_PARSER_TOKEN_H
30 #define MU_PARSER_TOKEN_H
39 #pragma warning(disable : 26812)
42 #include "muParserError.h"
43 #include "muParserCallback.h"
46 \brief This file contains the parser token definition.
51 /** \brief Encapsulation of the data for a single formula token.
53 Formula token implementation. Part of the Math Parser Package.
54 Formula tokens can be either one of the following:
58 <li>function with numerical arguments</li>
59 <li>functions with a string as argument</li>
60 <li>prefix operators</li>
61 <li>infix operators</li>
62 <li>binary operator</li>
65 template<typename TBase, typename TString>
66 class ParserToken final
70 ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode.
72 void* m_pTok; ///< Stores Token pointer; not applicable for all tokens
73 int m_iIdx; ///< An otional index to an external buffer storing the token data
74 TString m_strTok; ///< Token string
75 TString m_strVal; ///< Value for string variables
76 value_type m_fVal; ///< the value
77 std::unique_ptr<ParserCallback> m_pCallback;
81 /** \brief Constructor (default).
83 Sets token to an neutral state of type cmUNKNOWN.
98 //------------------------------------------------------------------------------
99 /** \brief Create token from another one.
101 Implemented by calling Assign(...)
103 \post m_iType==cmUNKNOWN
106 ParserToken(const ParserToken& a_Tok)
112 /** \brief Assignment operator.
114 Copy token state from another token and return this.
115 Implemented by calling Assign(...).
118 ParserToken& operator=(const ParserToken& a_Tok)
125 /** \brief Copy token information from argument.
129 void Assign(const ParserToken& a_Tok)
131 m_iCode = a_Tok.m_iCode;
132 m_pTok = a_Tok.m_pTok;
133 m_strTok = a_Tok.m_strTok;
134 m_iIdx = a_Tok.m_iIdx;
135 m_strVal = a_Tok.m_strVal;
136 m_iType = a_Tok.m_iType;
137 m_fVal = a_Tok.m_fVal;
138 // create new callback object if a_Tok has one
139 m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
142 //------------------------------------------------------------------------------
143 /** \brief Assign a token type.
145 Token may not be of type value, variable or function. Those have separate set functions.
147 \pre [assert] a_iType!=cmVAR
148 \pre [assert] a_iType!=cmVAL
149 \pre [assert] a_iType!=cmFUNC
153 ParserToken& Set(ECmdCode a_iType, const TString& a_strTok = TString())
155 // The following types can't be set this way, they have special Set functions
156 MUP_ASSERT(a_iType != cmVAR);
157 MUP_ASSERT(a_iType != cmVAL);
158 MUP_ASSERT(a_iType != cmFUNC);
169 //------------------------------------------------------------------------------
170 /** \brief Set Callback type. */
171 ParserToken& Set(const ParserCallback& a_pCallback, const TString& a_sTok)
173 MUP_ASSERT(a_pCallback.GetAddr());
175 m_iCode = a_pCallback.GetCode();
178 m_pCallback.reset(new ParserCallback(a_pCallback));
186 //------------------------------------------------------------------------------
187 /** \brief Make this token a value token.
189 Member variables not necessary for value tokens will be invalidated.
192 ParserToken& SetVal(TBase a_fVal, const TString& a_strTok = TString())
201 m_pCallback.reset(0);
206 //------------------------------------------------------------------------------
207 /** \brief make this token a variable token.
209 Member variables not necessary for variable tokens will be invalidated.
212 ParserToken& SetVar(TBase* a_pVar, const TString& a_strTok)
218 m_pTok = (void*)a_pVar;
219 m_pCallback.reset(0);
223 //------------------------------------------------------------------------------
224 /** \brief Make this token a variable token.
226 Member variables not necessary for variable tokens will be invalidated.
229 ParserToken& SetString(const TString& a_strTok, std::size_t a_iSize)
234 m_iIdx = static_cast<int>(a_iSize);
237 m_pCallback.reset(0);
241 //------------------------------------------------------------------------------
242 /** \brief Set an index associated with the token related data.
244 In cmSTRFUNC - This is the index to a string table in the main parser.
245 \param a_iIdx The index the string function result will take in the bytecode parser.
246 \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
248 void SetIdx(int a_iIdx)
250 if (m_iCode != cmSTRING || a_iIdx < 0)
251 throw ParserError(ecINTERNAL_ERROR);
256 //------------------------------------------------------------------------------
257 /** \brief Return Index associated with the token related data.
259 In cmSTRFUNC - This is the index to a string table in the main parser.
261 \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
262 \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
266 if (m_iIdx < 0 || m_iCode != cmSTRING)
267 throw ParserError(ecINTERNAL_ERROR);
272 //------------------------------------------------------------------------------
273 /** \brief Return the token type.
278 ECmdCode GetCode() const
280 if (m_pCallback.get())
282 return m_pCallback->GetCode();
290 //------------------------------------------------------------------------------
291 ETypeCode GetType() const
293 if (m_pCallback.get())
295 return m_pCallback->GetType();
303 //------------------------------------------------------------------------------
306 if (!m_pCallback.get())
307 throw ParserError(ecINTERNAL_ERROR);
309 if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX)
310 throw ParserError(ecINTERNAL_ERROR);
312 return m_pCallback->GetPri();
315 //------------------------------------------------------------------------------
316 EOprtAssociativity GetAssociativity() const
318 if (m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN)
319 throw ParserError(ecINTERNAL_ERROR);
321 return m_pCallback->GetAssociativity();
324 //------------------------------------------------------------------------------
325 /** \brief Return the address of the callback function assoziated with
326 function and operator tokens.
328 \return The pointer stored in #m_pTok.
329 \throw exception_type if token type is non of:
339 generic_fun_type GetFuncAddr() const
341 return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;
344 //------------------------------------------------------------------------------
345 /** \biref Get value of the token.
347 Only applicable to variable and value tokens.
348 \throw exception_type if token is no value/variable token.
354 case cmVAL: return m_fVal;
355 case cmVAR: return *((TBase*)m_pTok);
356 default: throw ParserError(ecVAL_EXPECTED);
360 //------------------------------------------------------------------------------
361 /** \brief Get address of a variable token.
363 Valid only if m_iType==CmdVar.
364 \throw exception_type if token is no variable token.
366 TBase* GetVar() const
368 if (m_iCode != cmVAR)
369 throw ParserError(ecINTERNAL_ERROR);
371 return (TBase*)m_pTok;
374 //------------------------------------------------------------------------------
375 /** \brief Return the number of function arguments.
377 Valid only if m_iType==CmdFUNC.
379 int GetArgCount() const
381 MUP_ASSERT(m_pCallback.get());
383 if (!m_pCallback->GetAddr())
384 throw ParserError(ecINTERNAL_ERROR);
386 return m_pCallback->GetArgc();
389 //------------------------------------------------------------------------------
390 /** \brief Return the token identifier.
392 If #m_iType is cmSTRING the token identifier is the value of the string argument
393 for a string function.
398 const TString& GetAsString() const
405 #if defined(_MSC_VER)