1 /*
2                  __________
3     _____   __ __\______   \_____  _______  ______  ____ _______
4    /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
5   |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
6   |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|
7         \/                       \/            \/      \/
8   Copyright (C) 2004-2013 Ingo Berg
9 
10   Permission is hereby granted, free of charge, to any person obtaining a copy of this
11   software and associated documentation files (the "Software"), to deal in the Software
12   without restriction, including without limitation the rights to use, copy, modify,
13   merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
14   permit persons to whom the Software is furnished to do so, subject to the following conditions:
15 
16   The above copyright notice and this permission notice shall be included in all copies or
17   substantial portions of the Software.
18 
19   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
20   NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22   DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 
26 #ifndef MU_PARSER_TOKEN_H
27 #define MU_PARSER_TOKEN_H
28 
29 #include <cassert>
30 #include <string>
31 #include <stack>
32 #include <vector>
33 #include <memory>
34 
35 #include "muParserError.h"
36 #include "muParserCallback.h"
37 
38 /** \file
39     \brief This file contains the parser token definition.
40 */
41 
42 namespace mu
43 {
44   /** \brief Encapsulation of the data for a single formula token.
45 
46     Formula token implementation. Part of the Math Parser Package.
47     Formula tokens can be either one of the following:
48     <ul>
49       <li>value</li>
50       <li>variable</li>
51       <li>function with numerical arguments</li>
52       <li>functions with a string as argument</li>
53       <li>prefix operators</li>
54       <li>infix operators</li>
55 	    <li>binary operator</li>
56     </ul>
57 
58    \author (C) 2004-2013 Ingo Berg
59   */
60   template<typename TBase, typename TString>
61   class ParserToken
62   {
63   private:
64 
65       ECmdCode  m_iCode;  ///< Type of the token; The token type is a constant of type #ECmdCode.
66       ETypeCode m_iType;
67       void  *m_pTok;      ///< Stores Token pointer; not applicable for all tokens
68       int  m_iIdx;        ///< An otional index to an external buffer storing the token data
69       TString m_strTok;   ///< Token string
70       TString m_strVal;   ///< Value for string variables
71       value_type m_fVal;  ///< the value
72       std::auto_ptr<ParserCallback> m_pCallback;
73 
74   public:
75 
76       //---------------------------------------------------------------------------
77       /** \brief Constructor (default).
78 
79           Sets token to an neutral state of type cmUNKNOWN.
80           \throw nothrow
81           \sa ECmdCode
82       */
ParserToken()83       ParserToken()
84         :m_iCode(cmUNKNOWN)
85         ,m_iType(tpVOID)
86         ,m_pTok(0)
87         ,m_iIdx(-1)
88         ,m_strTok()
89 		,m_strVal()
90 		,m_fVal(0)
91         ,m_pCallback()
92       {}
93 
94       //------------------------------------------------------------------------------
95       /** \brief Create token from another one.
96 
97           Implemented by calling Assign(...)
98           \throw nothrow
99           \post m_iType==cmUNKNOWN
100           \sa #Assign
101       */
ParserToken(const ParserToken & a_Tok)102       ParserToken(const ParserToken &a_Tok)
103       {
104         Assign(a_Tok);
105       }
106 
107       //------------------------------------------------------------------------------
108       /** \brief Assignement operator.
109 
110           Copy token state from another token and return this.
111           Implemented by calling Assign(...).
112           \throw nothrow
113       */
114       ParserToken& operator=(const ParserToken &a_Tok)
115       {
116         Assign(a_Tok);
117         return *this;
118       }
119 
120       //------------------------------------------------------------------------------
121       /** \brief Copy token information from argument.
122 
123           \throw nothrow
124       */
Assign(const ParserToken & a_Tok)125       void Assign(const ParserToken &a_Tok)
126       {
127         m_iCode = a_Tok.m_iCode;
128         m_pTok = a_Tok.m_pTok;
129         m_strTok = a_Tok.m_strTok;
130         m_iIdx = a_Tok.m_iIdx;
131         m_strVal = a_Tok.m_strVal;
132         m_iType = a_Tok.m_iType;
133         m_fVal = a_Tok.m_fVal;
134         // create new callback object if a_Tok has one
135         m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
136       }
137 
138       //------------------------------------------------------------------------------
139       /** \brief Assign a token type.
140 
141         Token may not be of type value, variable or function. Those have seperate set functions.
142 
143         \pre [assert] a_iType!=cmVAR
144         \pre [assert] a_iType!=cmVAL
145         \pre [assert] a_iType!=cmFUNC
146         \post m_fVal = 0
147         \post m_pTok = 0
148       */
149       ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())
150       {
151         // The following types cant be set this way, they have special Set functions
152         assert(a_iType!=cmVAR);
153         assert(a_iType!=cmVAL);
154         assert(a_iType!=cmFUNC);
155 
156         m_iCode = a_iType;
157         m_iType = tpVOID;
158         m_pTok = 0;
159         m_strTok = a_strTok;
160         m_iIdx = -1;
161 
162         return *this;
163       }
164 
165       //------------------------------------------------------------------------------
166       /** \brief Set Callback type. */
Set(const ParserCallback & a_pCallback,const TString & a_sTok)167       ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)
168       {
169         assert(a_pCallback.GetAddr());
170 
171         m_iCode = a_pCallback.GetCode();
172         m_iType = tpVOID;
173         m_strTok = a_sTok;
174         m_pCallback.reset(new ParserCallback(a_pCallback));
175 
176         m_pTok = 0;
177         m_iIdx = -1;
178 
179         return *this;
180       }
181 
182       //------------------------------------------------------------------------------
183       /** \brief Make this token a value token.
184 
185           Member variables not necessary for value tokens will be invalidated.
186           \throw nothrow
187       */
188       ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())
189       {
190         m_iCode = cmVAL;
191         m_iType = tpDBL;
192         m_fVal = a_fVal;
193         m_strTok = a_strTok;
194         m_iIdx = -1;
195 
196         m_pTok = 0;
197         m_pCallback.reset(0);
198 
199         return *this;
200       }
201 
202       //------------------------------------------------------------------------------
203       /** \brief make this token a variable token.
204 
205           Member variables not necessary for variable tokens will be invalidated.
206           \throw nothrow
207       */
SetVar(TBase * a_pVar,const TString & a_strTok)208       ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)
209       {
210         m_iCode = cmVAR;
211         m_iType = tpDBL;
212         m_strTok = a_strTok;
213         m_iIdx = -1;
214         m_pTok = (void*)a_pVar;
215         m_pCallback.reset(0);
216         return *this;
217       }
218 
219       //------------------------------------------------------------------------------
220       /** \brief Make this token a variable token.
221 
222           Member variables not necessary for variable tokens will be invalidated.
223           \throw nothrow
224       */
SetString(const TString & a_strTok,std::size_t a_iSize)225       ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)
226       {
227         m_iCode = cmSTRING;
228         m_iType = tpSTR;
229         m_strTok = a_strTok;
230         m_iIdx = static_cast<int>(a_iSize);
231 
232         m_pTok = 0;
233         m_pCallback.reset(0);
234         return *this;
235       }
236 
237       //------------------------------------------------------------------------------
238       /** \brief Set an index associated with the token related data.
239 
240           In cmSTRFUNC - This is the index to a string table in the main parser.
241           \param a_iIdx The index the string function result will take in the bytecode parser.
242           \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
243       */
SetIdx(int a_iIdx)244       void SetIdx(int a_iIdx)
245       {
246         if (m_iCode!=cmSTRING || a_iIdx<0)
247 	        throw ParserError(ecINTERNAL_ERROR);
248 
249         m_iIdx = a_iIdx;
250       }
251 
252       //------------------------------------------------------------------------------
253       /** \brief Return Index associated with the token related data.
254 
255           In cmSTRFUNC - This is the index to a string table in the main parser.
256 
257           \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
258           \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
259       */
GetIdx()260       int GetIdx() const
261       {
262         if (m_iIdx<0 || m_iCode!=cmSTRING )
263           throw ParserError(ecINTERNAL_ERROR);
264 
265         return m_iIdx;
266       }
267 
268       //------------------------------------------------------------------------------
269       /** \brief Return the token type.
270 
271           \return #m_iType
272           \throw nothrow
273       */
GetCode()274       ECmdCode GetCode() const
275       {
276         if (m_pCallback.get())
277         {
278           return m_pCallback->GetCode();
279         }
280         else
281         {
282           return m_iCode;
283         }
284       }
285 
286       //------------------------------------------------------------------------------
GetType()287       ETypeCode GetType() const
288       {
289         if (m_pCallback.get())
290         {
291           return m_pCallback->GetType();
292         }
293         else
294         {
295           return m_iType;
296         }
297       }
298 
299       //------------------------------------------------------------------------------
GetPri()300       int GetPri() const
301       {
302         if ( !m_pCallback.get())
303 	        throw ParserError(ecINTERNAL_ERROR);
304 
305         if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)
306 	        throw ParserError(ecINTERNAL_ERROR);
307 
308         return m_pCallback->GetPri();
309       }
310 
311       //------------------------------------------------------------------------------
GetAssociativity()312       EOprtAssociativity GetAssociativity() const
313       {
314         if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN)
315 	        throw ParserError(ecINTERNAL_ERROR);
316 
317         return m_pCallback->GetAssociativity();
318       }
319 
320       //------------------------------------------------------------------------------
321       /** \brief Return the address of the callback function assoziated with
322                  function and operator tokens.
323 
324           \return The pointer stored in #m_pTok.
325           \throw exception_type if token type is non of:
326                  <ul>
327                    <li>cmFUNC</li>
328                    <li>cmSTRFUNC</li>
329                    <li>cmPOSTOP</li>
330                    <li>cmINFIXOP</li>
331                    <li>cmOPRT_BIN</li>
332                  </ul>
333           \sa ECmdCode
334       */
GetFuncAddr()335       generic_fun_type GetFuncAddr() const
336       {
337         return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0;
338       }
339 
340       //------------------------------------------------------------------------------
341       /** \biref Get value of the token.
342 
343           Only applicable to variable and value tokens.
344           \throw exception_type if token is no value/variable token.
345       */
GetVal()346       TBase GetVal() const
347       {
348         switch (m_iCode)
349         {
350           case cmVAL:  return m_fVal;
351           case cmVAR:  return *((TBase*)m_pTok);
352           default:     throw ParserError(ecVAL_EXPECTED);
353         }
354       }
355 
356       //------------------------------------------------------------------------------
357       /** \brief Get address of a variable token.
358 
359         Valid only if m_iType==CmdVar.
360         \throw exception_type if token is no variable token.
361       */
GetVar()362       TBase* GetVar() const
363       {
364         if (m_iCode!=cmVAR)
365 	        throw ParserError(ecINTERNAL_ERROR);
366 
367         return (TBase*)m_pTok;
368       }
369 
370       //------------------------------------------------------------------------------
371       /** \brief Return the number of function arguments.
372 
373         Valid only if m_iType==CmdFUNC.
374       */
GetArgCount()375       int GetArgCount() const
376       {
377         assert(m_pCallback.get());
378 
379         if (!m_pCallback->GetAddr())
380 	        throw ParserError(ecINTERNAL_ERROR);
381 
382         return m_pCallback->GetArgc();
383       }
384 
385       //------------------------------------------------------------------------------
386       /** \brief Return the token identifier.
387 
388           If #m_iType is cmSTRING the token identifier is the value of the string argument
389           for a string function.
390           \return #m_strTok
391           \throw nothrow
392           \sa m_strTok
393       */
GetAsString()394       const TString& GetAsString() const
395       {
396         return m_strTok;
397       }
398   };
399 } // namespace mu
400 
401 #endif
402