Seamly2D
Code documentation
qmuparsertoken.h
Go to the documentation of this file.
1 /***************************************************************************************************
2  **
3  ** Copyright (C) 2013 Ingo Berg
4  **
5  ** Permission is hereby granted, free of charge, to any person obtaining a copy of this
6  ** software and associated documentation files (the "Software"), to deal in the Software
7  ** without restriction, including without limitation the rights to use, copy, modify,
8  ** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9  ** permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  **
11  ** The above copyright notice and this permission notice shall be included in all copies or
12  ** substantial portions of the Software.
13  **
14  ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15  ** NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16  ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17  ** DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  **
20  ******************************************************************************************************/
21 
22 #ifndef QMUPARSERTOKEN_H
23 #define QMUPARSERTOKEN_H
24 
25 #include <cassert>
26 #include <string>
27 #include <stack>
28 #include <memory>
29 #include <QtGlobal>
30 
31 #include "qmuparsererror.h"
32 #include "qmuparsercallback.h"
33 
34 /** @file
35  @brief This file contains the parser token definition.
36 */
37 
38 namespace qmu
39 {
40 /**
41  * @brief Encapsulation of the data for a single formula token.
42  *
43  * Formula token implementation. Part of the Math Parser Package.
44  * Formula tokens can be either one of the following:
45  * <ul>
46  * <li>value</li>
47  * <li>variable</li>
48  * <li>function with numerical arguments</li>
49  * <li>functions with a string as argument</li>
50  * <li>prefix operators</li>
51  * <li>infix operators</li>
52  * <li>binary operator</li>
53  * </ul>
54  *
55  * @author (C) 2004-2013 Ingo Berg
56  */
57 template<typename TBase, typename TString>
59 {
60 public:
61  //---------------------------------------------------------------------------
62  /**
63  * @brief Constructor (default).
64  *
65  * Sets token to an neutral state of type cmUNKNOWN.
66  * @throw nothrow
67  * @sa ECmdCode
68  */
70  : m_iCode ( cmUNKNOWN ), m_iType ( tpVOID ), m_pTok ( nullptr ), m_iIdx ( -1 ), m_strTok(), m_strVal(),
71  m_fVal(), m_pCallback()
72  {}
73 
74  //------------------------------------------------------------------------------
75  /**
76  * @brief Create token from another one.
77  *
78  * Implemented by calling Assign(...)
79  * @throw nothrow
80  * @post m_iType==cmUNKNOWN
81  * @sa #Assign
82  */
83  QmuParserToken ( const QmuParserToken &a_Tok )
84  : m_iCode ( a_Tok.m_iCode ), m_iType ( a_Tok.m_iType ), m_pTok ( a_Tok.m_pTok ), m_iIdx ( a_Tok.m_iIdx ),
85  m_strTok( a_Tok.m_strTok ), m_strVal(a_Tok.m_strVal), m_fVal(a_Tok.m_fVal), m_pCallback()
86  {
87  Assign ( a_Tok );
88  }
89 
90  //------------------------------------------------------------------------------
91  /**
92  * @brief Assignement operator.
93  *
94  * Copy token state from another token and return this.
95  * Implemented by calling Assign(...).
96  * @throw nothrow
97  */
99  {
100  if ( &a_Tok == this )
101  {
102  return *this;
103  }
104  Assign ( a_Tok );
105  return *this;
106  }
107 
108  //------------------------------------------------------------------------------
109  /**
110  * @brief Copy token information from argument.
111  *
112  * @throw nothrow
113  */
114  void Assign ( const QmuParserToken &a_Tok )
115  {
116  m_iCode = a_Tok.m_iCode;
117  m_pTok = a_Tok.m_pTok;
118  m_strTok = a_Tok.m_strTok;
119  m_iIdx = a_Tok.m_iIdx;
120  m_strVal = a_Tok.m_strVal;
121  m_iType = a_Tok.m_iType;
122  m_fVal = a_Tok.m_fVal;
123  // create new callback object if a_Tok has one
124  m_pCallback.reset ( a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : nullptr );
125  }
126 
127  //------------------------------------------------------------------------------
128  /**
129  * @brief Assign a token type.
130  *
131  * Token may not be of type value, variable or function. Those have seperate set functions.
132  *
133  * @pre [assert] a_iType!=cmVAR
134  * @pre [assert] a_iType!=cmVAL
135  * @pre [assert] a_iType!=cmFUNC
136  * @post m_fVal = 0
137  * @post m_pTok = 0
138  */
139  QmuParserToken& Set ( ECmdCode a_iType, const TString &a_strTok = TString() )
140  {
141  // The following types cant be set this way, they have special Set functions
142  assert ( a_iType != cmVAR );
143  assert ( a_iType != cmVAL );
144  assert ( a_iType != cmFUNC );
145 
146  m_iCode = a_iType;
147  m_iType = tpVOID;
148  m_pTok = nullptr;
149  m_strTok = a_strTok;
150  m_iIdx = -1;
151 
152  return *this;
153  }
154 
155  //------------------------------------------------------------------------------
156  /**
157  * @brief Set Callback type.
158  */
159  QmuParserToken& Set ( const QmuParserCallback &a_pCallback, const TString &a_sTok )
160  {
161  assert ( a_pCallback.GetAddr() );
162 
163  m_iCode = a_pCallback.GetCode();
164  m_iType = tpVOID;
165  m_strTok = a_sTok;
166  m_pCallback.reset ( new QmuParserCallback ( a_pCallback ) );
167 
168  m_pTok = nullptr;
169  m_iIdx = -1;
170 
171  return *this;
172  }
173 
174  //------------------------------------------------------------------------------
175  /**
176  * @brief Make this token a value token.
177  *
178  * Member variables not necessary for value tokens will be invalidated.
179  * @throw nothrow
180  */
181  QmuParserToken& SetVal ( TBase a_fVal, const TString &a_strTok = TString() )
182  {
183  m_iCode = cmVAL;
184  m_iType = tpDBL;
185  m_fVal = a_fVal;
186  m_strTok = a_strTok;
187  m_iIdx = -1;
188 
189  m_pTok = nullptr;
190  m_pCallback.reset ( nullptr );
191 
192  return *this;
193  }
194 
195  //------------------------------------------------------------------------------
196  /**
197  * @brief make this token a variable token.
198  *
199  * Member variables not necessary for variable tokens will be invalidated.
200  * @throw nothrow
201  */
202  QmuParserToken& SetVar ( TBase *a_pVar, const TString &a_strTok )
203  {
204  m_iCode = cmVAR;
205  m_iType = tpDBL;
206  m_strTok = a_strTok;
207  m_iIdx = -1;
208  m_pTok = reinterpret_cast<void*> ( a_pVar );
209  m_pCallback.reset ( nullptr );
210  return *this;
211  }
212 
213  //------------------------------------------------------------------------------
214  /**
215  * @brief Make this token a variable token.
216  *
217  * Member variables not necessary for variable tokens will be invalidated.
218  * @throw nothrow
219  */
220  QmuParserToken& SetString ( const TString &a_strTok, int a_iSize )
221  {
222  m_iCode = cmSTRING;
223  m_iType = tpSTR;
224  m_strTok = a_strTok;
225  m_iIdx = a_iSize;
226 
227  m_pTok = nullptr;
228  m_pCallback.reset ( nullptr );
229  return *this;
230  }
231 
232  //------------------------------------------------------------------------------
233  /**
234  * @brief Set an index associated with the token related data.
235  *
236  * In cmSTRFUNC - This is the index to a string table in the main parser.
237  * @param a_iIdx The index the string function result will take in the bytecode parser.
238  * @throw QmuParserError if #a_iIdx<0 or #m_iType!=cmSTRING
239  */
240  void SetIdx ( int a_iIdx )
241  {
242  if ( m_iCode != cmSTRING || a_iIdx < 0 )
243  {
245  }
246 
247  m_iIdx = a_iIdx;
248  }
249 
250  //------------------------------------------------------------------------------
251  /**
252  * @brief Return Index associated with the token related data.
253  *
254  * In cmSTRFUNC - This is the index to a string table in the main parser.
255  *
256  * @throw QmuParserError if #m_iIdx<0 or #m_iType!=cmSTRING
257  * @return The index the result will take in the Bytecode calculatin array (#m_iIdx).
258  */
259  int GetIdx() const
260  {
261  if ( m_iIdx < 0 || m_iCode != cmSTRING )
262  {
264  }
265 
266  return m_iIdx;
267  }
268 
269  //------------------------------------------------------------------------------
270  /**
271  * @brief Return the token type.
272  *
273  * @return #m_iType
274  * @throw nothrow
275  */
277  {
278  if ( m_pCallback.get() )
279  {
280  return m_pCallback->GetCode();
281  }
282  else
283  {
284  return m_iCode;
285  }
286  }
287 
288  //------------------------------------------------------------------------------
290  {
291  if ( m_pCallback.get() )
292  {
293  return m_pCallback->GetType();
294  }
295  else
296  {
297  return m_iType;
298  }
299  }
300 
301  //------------------------------------------------------------------------------
302  int GetPri() const
303  {
304  if ( m_pCallback.get() == nullptr)
305  {
307  }
308 
309  if ( m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX )
310  {
312  }
313 
314  return m_pCallback->GetPri();
315  }
316 
317  //------------------------------------------------------------------------------
319  {
320  if ( m_pCallback.get() == nullptr || m_pCallback->GetCode() != cmOPRT_BIN )
321  {
323  }
324 
325  return m_pCallback->GetAssociativity();
326  }
327 
328  //------------------------------------------------------------------------------
329  template < class FunctionPtr >
330  static FunctionPtr union_cast( void* objectPtr )
331  {
332  union
333  {
334  void* obj;
335  FunctionPtr func;
336  } var;
337 
338  // cppcheck-suppress duplicateExpression
339  Q_STATIC_ASSERT_X(sizeof(void *) == sizeof(void (*)(void)),
340  "object pointer and function pointer sizes must equal");
341 
342  var.obj = objectPtr;
343  return var.func;
344  }
345 
346  //------------------------------------------------------------------------------
347  /**
348  * @brief Return the address of the callback function assoziated with function and operator tokens.
349  *
350  * @return The pointer stored in #m_pTok.
351  * @throw QmuParserError if token type is non of:
352  * <ul>
353  * <li>cmFUNC</li>
354  * <li>cmSTRFUNC</li>
355  * <li>cmPOSTOP</li>
356  * <li>cmINFIXOP</li>
357  * <li>cmOPRT_BIN</li>
358  * </ul>
359  * @sa ECmdCode
360  */
362  {
363  return ( union_cast<generic_fun_type>( m_pCallback.get() ) ) ?
364  union_cast<generic_fun_type>( m_pCallback->GetAddr() ) : union_cast<generic_fun_type>(nullptr);
365  }
366 
367  //------------------------------------------------------------------------------
368  /**
369  * @brief Get value of the token.
370  *
371  * Only applicable to variable and value tokens.
372  * @throw QmuParserError if token is no value/variable token.
373  */
374  TBase GetVal() const
375  {
376  switch ( m_iCode )
377  {
378  case cmVAL:
379  return m_fVal;
380  case cmVAR:
381  return * ( reinterpret_cast<TBase*>(m_pTok) );
382  case cmLE:
383  case cmGE:
384  case cmNEQ:
385  case cmEQ:
386  case cmLT:
387  case cmGT:
388  case cmADD:
389  case cmSUB:
390  case cmMUL:
391  case cmDIV:
392  case cmPOW:
393  case cmLAND:
394  case cmLOR:
395  case cmASSIGN:
396  case cmBO:
397  case cmBC:
398  case cmIF:
399  case cmELSE:
400  case cmENDIF:
401  case cmARG_SEP:
402  case cmVARPOW2:
403  case cmVARPOW3:
404  case cmVARPOW4:
405  case cmVARMUL:
406  case cmPOW2:
407  case cmFUNC:
408  case cmFUNC_STR:
409  case cmFUNC_BULK:
410  case cmOPRT_BIN:
411  case cmOPRT_POSTFIX:
412  case cmOPRT_INFIX:
413  case cmEND:
414  case cmUNKNOWN:
415  case cmSTRING:
416  default:
417  throw QmuParserError ( ecVAL_EXPECTED );
418  }
419  }
420 
421  //------------------------------------------------------------------------------
422  /**
423  * @brief Get address of a variable token.
424  *
425  * Valid only if m_iType==CmdVar.
426  * @throw QmuParserError if token is no variable token.
427  */
428  TBase* GetVar() const
429  {
430  if ( m_iCode != cmVAR )
431  {
433  }
434 
435  return reinterpret_cast<TBase*>( m_pTok );
436  }
437 
438  //------------------------------------------------------------------------------
439  /**
440  * @brief Return the number of function arguments.
441  *
442  * Valid only if m_iType==CmdFUNC.
443  */
444  int GetArgCount() const
445  {
446  assert ( m_pCallback.get() );
447 
448  if ( m_pCallback->GetAddr() == nullptr)
449  {
451  }
452 
453  return m_pCallback->GetArgc();
454  }
455 
456  //------------------------------------------------------------------------------
457  /**
458  * @brief Return the token identifier.
459  *
460  * If #m_iType is cmSTRING the token identifier is the value of the string argument
461  * for a string function.
462  * @return #m_strTok
463  * @throw nothrow
464  * @sa m_strTok
465  */
466  const TString& GetAsString() const
467  {
468  return m_strTok;
469  }
470 private:
471  ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode.
473  void *m_pTok; ///< Stores Token pointer; not applicable for all tokens
474  int m_iIdx; ///< An otional index to an external buffer storing the token data
475  TString m_strTok; ///< Token string
476  TString m_strVal; ///< Value for string variables
477  qreal m_fVal; ///< the value
478  std::unique_ptr<QmuParserCallback> m_pCallback;
479 };
480 } // namespace qmu
481 
482 #endif
Encapsulation of prototypes for a numerical parser function.
ECmdCode GetCode() const
Return the callback code.
void * GetAddr() const
Get the callback address for the parser function.
Error class of the parser.
Encapsulation of the data for a single formula token.
ETypeCode GetType() const
QmuParserToken & Set(const QmuParserCallback &a_pCallback, const TString &a_sTok)
Set Callback type.
void * m_pTok
Stores Token pointer; not applicable for all tokens.
EOprtAssociativity GetAssociativity() const
ECmdCode m_iCode
Type of the token; The token type is a constant of type ECmdCode.
generic_fun_type GetFuncAddr() const
Return the address of the callback function assoziated with function and operator tokens.
void SetIdx(int a_iIdx)
Set an index associated with the token related data.
ECmdCode GetCode() const
Return the token type.
static FunctionPtr union_cast(void *objectPtr)
qreal m_fVal
the value
int GetIdx() const
Return Index associated with the token related data.
QmuParserToken & operator=(const QmuParserToken &a_Tok)
Assignement operator.
int m_iIdx
An otional index to an external buffer storing the token data.
std::unique_ptr< QmuParserCallback > m_pCallback
QmuParserToken & SetVal(TBase a_fVal, const TString &a_strTok=TString())
Make this token a value token.
TString m_strTok
Token string.
int GetArgCount() const
Return the number of function arguments.
QmuParserToken & SetVar(TBase *a_pVar, const TString &a_strTok)
make this token a variable token.
QmuParserToken()
Constructor (default).
TString m_strVal
Value for string variables.
QmuParserToken & Set(ECmdCode a_iType, const TString &a_strTok=TString())
Assign a token type.
QmuParserToken & SetString(const TString &a_strTok, int a_iSize)
Make this token a variable token.
const TString & GetAsString() const
Return the token identifier.
QmuParserToken(const QmuParserToken &a_Tok)
Create token from another one.
void Assign(const QmuParserToken &a_Tok)
Copy token information from argument.
TBase GetVal() const
Get value of the token.
TBase * GetVar() const
Get address of a variable token.
Namespace for mathematical applications.
@ ecVAL_EXPECTED
A numerical function has been called with a non value type of argument.
@ ecINTERNAL_ERROR
Internal error of any kind.
ECmdCode
Bytecode values.
Definition: qmuparserdef.h:99
@ cmVARPOW4
Definition: qmuparserdef.h:129
@ cmOPRT_INFIX
code for infix operators
Definition: qmuparserdef.h:140
@ cmBC
Operator item: closing bracket.
Definition: qmuparserdef.h:118
@ cmLE
Operator item: less or equal.
Definition: qmuparserdef.h:103
@ cmUNKNOWN
uninitialized item
Definition: qmuparserdef.h:142
@ cmSUB
Operator item: subtract.
Definition: qmuparserdef.h:110
@ cmLAND
Definition: qmuparserdef.h:114
@ cmGT
Operator item: greater than.
Definition: qmuparserdef.h:108
@ cmSTRING
Code for a string token.
Definition: qmuparserdef.h:137
@ cmFUNC
Code for a generic function item.
Definition: qmuparserdef.h:134
@ cmVARMUL
Definition: qmuparserdef.h:130
@ cmEND
end of formula
Definition: qmuparserdef.h:141
@ cmFUNC_STR
Code for a function with a string parameter.
Definition: qmuparserdef.h:135
@ cmLT
Operator item: less than.
Definition: qmuparserdef.h:107
@ cmMUL
Operator item: multiply.
Definition: qmuparserdef.h:111
@ cmVARPOW3
Definition: qmuparserdef.h:128
@ cmGE
Operator item: greater or equal.
Definition: qmuparserdef.h:104
@ cmADD
Operator item: add.
Definition: qmuparserdef.h:109
@ cmASSIGN
Operator item: Assignment operator.
Definition: qmuparserdef.h:116
@ cmENDIF
For use in the ternary if-then-else operator.
Definition: qmuparserdef.h:121
@ cmELSE
For use in the ternary if-then-else operator.
Definition: qmuparserdef.h:120
@ cmEQ
Operator item: equals.
Definition: qmuparserdef.h:106
@ cmFUNC_BULK
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Definition: qmuparserdef.h:136
@ cmPOW2
Definition: qmuparserdef.h:131
@ cmARG_SEP
function argument separator
Definition: qmuparserdef.h:122
@ cmPOW
Operator item: y to the power of ...
Definition: qmuparserdef.h:113
@ cmLOR
Definition: qmuparserdef.h:115
@ cmNEQ
Operator item: not equal.
Definition: qmuparserdef.h:105
@ cmVARPOW2
Definition: qmuparserdef.h:127
@ cmOPRT_BIN
user defined binary operator
Definition: qmuparserdef.h:138
@ cmIF
For use in the ternary if-then-else operator.
Definition: qmuparserdef.h:119
@ cmVAL
value item
Definition: qmuparserdef.h:124
@ cmOPRT_POSTFIX
code for postfix operators
Definition: qmuparserdef.h:139
@ cmDIV
Operator item: division.
Definition: qmuparserdef.h:112
@ cmVAR
variable item
Definition: qmuparserdef.h:123
@ cmBO
Operator item: opening bracket.
Definition: qmuparserdef.h:117
qreal(* generic_fun_type)()
Callback type used for functions without arguments.
Definition: qmuparserdef.h:221
EOprtAssociativity
Parser operator precedence values.
Definition: qmuparserdef.h:165
ETypeCode
Types internally used by the parser.
Definition: qmuparserdef.h:149
@ tpVOID
Undefined type.
Definition: qmuparserdef.h:152
@ tpDBL
Floating point variables.
Definition: qmuparserdef.h:151
@ tpSTR
String type (Function arguments and constants only, no string variables)
Definition: qmuparserdef.h:150
Definition of the parser callback class.
This file defines the error class used by the parser.