muParser API -  1.35
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
muParserBytecode.cpp
1 /*
2  __________
3  _____ __ __\______ \_____ _______ ______ ____ _______
4  / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
5  | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
6  |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
7  \/ \/ \/ \/
8  Copyright (C) 2011 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 #include "muParserBytecode.h"
27 
28 #include <algorithm>
29 #include <cassert>
30 #include <string>
31 #include <stack>
32 #include <vector>
33 #include <iostream>
34 
35 #include "muParserDef.h"
36 #include "muParserError.h"
37 #include "muParserToken.h"
38 #include "muParserStack.h"
39 #include "muParserTemplateMagic.h"
40 
41 
42 namespace mu
43 {
44  //---------------------------------------------------------------------------
45  /** \brief Bytecode default constructor. */
47  :m_iStackPos(0)
48  ,m_iMaxStackSize(0)
49  ,m_vRPN()
50  ,m_bEnableOptimizer(true)
51  {
52  m_vRPN.reserve(50);
53  }
54 
55  //---------------------------------------------------------------------------
56  /** \brief Copy constructor.
57 
58  Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
59  */
61  {
62  Assign(a_ByteCode);
63  }
64 
65  //---------------------------------------------------------------------------
66  /** \brief Assignment operator.
67 
68  Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
69  */
71  {
72  Assign(a_ByteCode);
73  return *this;
74  }
75 
76  //---------------------------------------------------------------------------
77  void ParserByteCode::EnableOptimizer(bool bStat)
78  {
79  m_bEnableOptimizer = bStat;
80  }
81 
82  //---------------------------------------------------------------------------
83  /** \brief Copy state of another object to this.
84 
85  \throw nowthrow
86  */
87  void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)
88  {
89  if (this==&a_ByteCode)
90  return;
91 
92  m_iStackPos = a_ByteCode.m_iStackPos;
93  m_vRPN = a_ByteCode.m_vRPN;
94  m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
95  m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer;
96  }
97 
98  //---------------------------------------------------------------------------
99  /** \brief Add a Variable pointer to bytecode.
100  \param a_pVar Pointer to be added.
101  \throw nothrow
102  */
104  {
105  ++m_iStackPos;
106  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
107 
108  // optimization does not apply
109  SToken tok;
110  tok.Cmd = cmVAR;
111  tok.Val.ptr = a_pVar;
112  tok.Val.data = 1;
113  tok.Val.data2 = 0;
114  m_vRPN.push_back(tok);
115  }
116 
117  //---------------------------------------------------------------------------
118  /** \brief Add a Variable pointer to bytecode.
119 
120  Value entries in byte code consist of:
121  <ul>
122  <li>value array position of the value</li>
123  <li>the operator code according to ParserToken::cmVAL</li>
124  <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
125  </ul>
126 
127  \param a_pVal Value to be added.
128  \throw nothrow
129  */
131  {
132  ++m_iStackPos;
133  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
134 
135  // If optimization does not apply
136  SToken tok;
137  tok.Cmd = cmVAL;
138  tok.Val.ptr = NULL;
139  tok.Val.data = 0;
140  tok.Val.data2 = a_fVal;
141  m_vRPN.push_back(tok);
142  }
143 
144  //---------------------------------------------------------------------------
145  void ParserByteCode::ConstantFolding(ECmdCode a_Oprt)
146  {
147  std::size_t sz = m_vRPN.size();
148  value_type &x = m_vRPN[sz-2].Val.data2,
149  &y = m_vRPN[sz-1].Val.data2;
150  switch (a_Oprt)
151  {
152  case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;
153  case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break;
154  case cmLT: x = x < y; m_vRPN.pop_back(); break;
155  case cmGT: x = x > y; m_vRPN.pop_back(); break;
156  case cmLE: x = x <= y; m_vRPN.pop_back(); break;
157  case cmGE: x = x >= y; m_vRPN.pop_back(); break;
158  case cmNEQ: x = x != y; m_vRPN.pop_back(); break;
159  case cmEQ: x = x == y; m_vRPN.pop_back(); break;
160  case cmADD: x = x + y; m_vRPN.pop_back(); break;
161  case cmSUB: x = x - y; m_vRPN.pop_back(); break;
162  case cmMUL: x = x * y; m_vRPN.pop_back(); break;
163  case cmDIV:
164 
165 #if defined(MUP_MATH_EXCEPTIONS)
166  if (y==0)
167  throw ParserError(ecDIV_BY_ZERO, _T("0"));
168 #endif
169 
170  x = x / y;
171  m_vRPN.pop_back();
172  break;
173 
174  case cmPOW: x = MathImpl<value_type>::Pow(x, y);
175  m_vRPN.pop_back();
176  break;
177 
178  default:
179  break;
180  } // switch opcode
181  }
182 
183  //---------------------------------------------------------------------------
184  /** \brief Add an operator identifier to bytecode.
185 
186  Operator entries in byte code consist of:
187  <ul>
188  <li>value array position of the result</li>
189  <li>the operator code according to ParserToken::ECmdCode</li>
190  </ul>
191 
192  \sa ParserToken::ECmdCode
193  */
195  {
196  bool bOptimized = false;
197 
198  if (m_bEnableOptimizer)
199  {
200  std::size_t sz = m_vRPN.size();
201 
202  // Check for foldable constants like:
203  // cmVAL cmVAL cmADD
204  // where cmADD can stand fopr any binary operator applied to
205  // two constant values.
206  if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL)
207  {
208  ConstantFolding(a_Oprt);
209  bOptimized = true;
210  }
211  else
212  {
213  switch(a_Oprt)
214  {
215  case cmPOW:
216  // Optimization for polynomials of low order
217  if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)
218  {
219  if (m_vRPN[sz-1].Val.data2==2)
220  m_vRPN[sz-2].Cmd = cmVARPOW2;
221  else if (m_vRPN[sz-1].Val.data2==3)
222  m_vRPN[sz-2].Cmd = cmVARPOW3;
223  else if (m_vRPN[sz-1].Val.data2==4)
224  m_vRPN[sz-2].Cmd = cmVARPOW4;
225  else
226  break;
227 
228  m_vRPN.pop_back();
229  bOptimized = true;
230  }
231  break;
232 
233  case cmSUB:
234  case cmADD:
235  // Simple optimization based on pattern recognition for a shitload of different
236  // bytecode combinations of addition/subtraction
237  if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
238  (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ||
239  (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
240  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ||
241  (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
242  (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
243  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
244  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) )
245  {
246  assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) ||
247  (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) ||
248  (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) );
249 
250  m_vRPN[sz-2].Cmd = cmVARMUL;
251  m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable
252  m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset
253  m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand
254  m_vRPN.pop_back();
255  bOptimized = true;
256  }
257  break;
258 
259  case cmMUL:
260  if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
261  (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) )
262  {
263  m_vRPN[sz-2].Cmd = cmVARMUL;
264  m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
265  m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2;
266  m_vRPN[sz-2].Val.data2 = 0;
267  m_vRPN.pop_back();
268  bOptimized = true;
269  }
270  else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
271  (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) )
272  {
273  // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
274  m_vRPN[sz-2].Cmd = cmVARMUL;
275  m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr));
276  if (m_vRPN[sz-1].Cmd == cmVAL)
277  {
278  m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2;
279  m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2;
280  }
281  else
282  {
283  m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2;
284  m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2;
285  }
286  m_vRPN.pop_back();
287  bOptimized = true;
288  }
289  else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&
290  m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr)
291  {
292  // Optimization: a*a -> a^2
293  m_vRPN[sz-2].Cmd = cmVARPOW2;
294  m_vRPN.pop_back();
295  bOptimized = true;
296  }
297  break;
298 
299  case cmDIV:
300  if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
301  {
302  // Optimization: 4*a/2 -> 2*a
303  m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2;
304  m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2;
305  m_vRPN.pop_back();
306  bOptimized = true;
307  }
308  break;
309 
310  } // switch a_Oprt
311  }
312  }
313 
314  // If optimization can't be applied just write the value
315  if (!bOptimized)
316  {
317  --m_iStackPos;
318  SToken tok;
319  tok.Cmd = a_Oprt;
320  m_vRPN.push_back(tok);
321  }
322  }
323 
324  //---------------------------------------------------------------------------
325  void ParserByteCode::AddIfElse(ECmdCode a_Oprt)
326  {
327  SToken tok;
328  tok.Cmd = a_Oprt;
329  m_vRPN.push_back(tok);
330  }
331 
332  //---------------------------------------------------------------------------
333  /** \brief Add an assignment operator
334 
335  Operator entries in byte code consist of:
336  <ul>
337  <li>cmASSIGN code</li>
338  <li>the pointer of the destination variable</li>
339  </ul>
340 
341  \sa ParserToken::ECmdCode
342  */
344  {
345  --m_iStackPos;
346 
347  SToken tok;
348  tok.Cmd = cmASSIGN;
349  tok.Oprt.ptr = a_pVar;
350  m_vRPN.push_back(tok);
351  }
352 
353  //---------------------------------------------------------------------------
354  /** \brief Add function to bytecode.
355 
356  \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
357  \param a_pFun Pointer to function callback.
358  */
359  void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)
360  {
361  if (a_iArgc>=0)
362  {
363  m_iStackPos = m_iStackPos - a_iArgc + 1;
364  }
365  else
366  {
367  // function with unlimited number of arguments
368  m_iStackPos = m_iStackPos + a_iArgc + 1;
369  }
370  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
371 
372  SToken tok;
373  tok.Cmd = cmFUNC;
374  tok.Fun.argc = a_iArgc;
375  tok.Fun.ptr = a_pFun;
376  m_vRPN.push_back(tok);
377  }
378 
379  //---------------------------------------------------------------------------
380  /** \brief Add a bulk function to bytecode.
381 
382  \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
383  \param a_pFun Pointer to function callback.
384  */
386  {
387  m_iStackPos = m_iStackPos - a_iArgc + 1;
388  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
389 
390  SToken tok;
391  tok.Cmd = cmFUNC_BULK;
392  tok.Fun.argc = a_iArgc;
393  tok.Fun.ptr = a_pFun;
394  m_vRPN.push_back(tok);
395  }
396 
397  //---------------------------------------------------------------------------
398  /** \brief Add Strung function entry to the parser bytecode.
399  \throw nothrow
400 
401  A string function entry consists of the stack position of the return value,
402  followed by a cmSTRFUNC code, the function pointer and an index into the
403  string buffer maintained by the parser.
404  */
405  void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
406  {
407  m_iStackPos = m_iStackPos - a_iArgc + 1;
408 
409  SToken tok;
410  tok.Cmd = cmFUNC_STR;
411  tok.Fun.argc = a_iArgc;
412  tok.Fun.idx = a_iIdx;
413  tok.Fun.ptr = a_pFun;
414  m_vRPN.push_back(tok);
415 
416  m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
417  }
418 
419  //---------------------------------------------------------------------------
420  /** \brief Add end marker to bytecode.
421 
422  \throw nothrow
423  */
425  {
426  SToken tok;
427  tok.Cmd = cmEND;
428  m_vRPN.push_back(tok);
429  rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit
430 
431  // Determine the if-then-else jump offsets
432  ParserStack<int> stIf, stElse;
433  int idx;
434  for (int i=0; i<(int)m_vRPN.size(); ++i)
435  {
436  switch(m_vRPN[i].Cmd)
437  {
438  case cmIF:
439  stIf.push(i);
440  break;
441 
442  case cmELSE:
443  stElse.push(i);
444  idx = stIf.pop();
445  m_vRPN[idx].Oprt.offset = i - idx;
446  break;
447 
448  case cmENDIF:
449  idx = stElse.pop();
450  m_vRPN[idx].Oprt.offset = i - idx;
451  break;
452 
453  default:
454  break;
455  }
456  }
457  }
458 
459  //---------------------------------------------------------------------------
460  const SToken* ParserByteCode::GetBase() const
461  {
462  if (m_vRPN.size()==0)
464  else
465  return &m_vRPN[0];
466  }
467 
468  //---------------------------------------------------------------------------
469  std::size_t ParserByteCode::GetMaxStackSize() const
470  {
471  return m_iMaxStackSize+1;
472  }
473 
474  //---------------------------------------------------------------------------
475  /** \brief Returns the number of entries in the bytecode. */
476  std::size_t ParserByteCode::GetSize() const
477  {
478  return m_vRPN.size();
479  }
480 
481  //---------------------------------------------------------------------------
482  /** \brief Delete the bytecode.
483 
484  \throw nothrow
485 
486  The name of this function is a violation of my own coding guidelines
487  but this way it's more in line with the STL functions thus more
488  intuitive.
489  */
491  {
492  m_vRPN.clear();
493  m_iStackPos = 0;
494  m_iMaxStackSize = 0;
495  }
496 
497  //---------------------------------------------------------------------------
498  /** \brief Dump bytecode (for debugging only!). */
500  {
501  if (!m_vRPN.size())
502  {
503  mu::console() << _T("No bytecode available\n");
504  return;
505  }
506 
507  mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n");
508  for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)
509  {
510  mu::console() << std::dec << i << _T(" : \t");
511  switch (m_vRPN[i].Cmd)
512  {
513  case cmVAL: mu::console() << _T("VAL \t");
514  mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n");
515  break;
516 
517  case cmVAR: mu::console() << _T("VAR \t");
518  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
519  break;
520 
521  case cmVARPOW2: mu::console() << _T("VARPOW2 \t");
522  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
523  break;
524 
525  case cmVARPOW3: mu::console() << _T("VARPOW3 \t");
526  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
527  break;
528 
529  case cmVARPOW4: mu::console() << _T("VARPOW4 \t");
530  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n");
531  break;
532 
533  case cmVARMUL: mu::console() << _T("VARMUL \t");
534  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]");
535  mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]");
536  mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n");
537  break;
538 
539  case cmFUNC: mu::console() << _T("CALL\t");
540  mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
541  mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Fun.ptr << _T("]");
542  mu::console() << _T("\n");
543  break;
544 
545  case cmFUNC_STR:
546  mu::console() << _T("CALL STRFUNC\t");
547  mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]");
548  mu::console() << _T("[IDX:") << std::dec << m_vRPN[i].Fun.idx << _T("]");
549  mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Fun.ptr << _T("]\n");
550  break;
551 
552  case cmLT: mu::console() << _T("LT\n"); break;
553  case cmGT: mu::console() << _T("GT\n"); break;
554  case cmLE: mu::console() << _T("LE\n"); break;
555  case cmGE: mu::console() << _T("GE\n"); break;
556  case cmEQ: mu::console() << _T("EQ\n"); break;
557  case cmNEQ: mu::console() << _T("NEQ\n"); break;
558  case cmADD: mu::console() << _T("ADD\n"); break;
559  case cmLAND: mu::console() << _T("&&\n"); break;
560  case cmLOR: mu::console() << _T("||\n"); break;
561  case cmSUB: mu::console() << _T("SUB\n"); break;
562  case cmMUL: mu::console() << _T("MUL\n"); break;
563  case cmDIV: mu::console() << _T("DIV\n"); break;
564  case cmPOW: mu::console() << _T("POW\n"); break;
565 
566  case cmIF: mu::console() << _T("IF\t");
567  mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
568  break;
569 
570  case cmELSE: mu::console() << _T("ELSE\t");
571  mu::console() << _T("[OFFSET:") << std::dec << m_vRPN[i].Oprt.offset << _T("]\n");
572  break;
573 
574  case cmENDIF: mu::console() << _T("ENDIF\n"); break;
575 
576  case cmASSIGN:
577  mu::console() << _T("ASSIGN\t");
578  mu::console() << _T("[ADDR: 0x") << m_vRPN[i].Oprt.ptr << _T("]\n");
579  break;
580 
581  default: mu::console() << _T("(unknown code: ") << m_vRPN[i].Cmd << _T(")\n");
582  break;
583  } // switch cmdCode
584  } // while bytecode
585 
586  mu::console() << _T("END") << std::endl;
587  }
588 } // namespace mu
Definition of the parser bytecode class.
#define _T(x)
Activate this option in order to compile with OpenMP support.
Definition: muParserDef.h:69
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
std::ostream & console()
Encapsulate cout.
Definition: muParserDef.h:128
void push(const TValueType &a_Val)
Push an object into the stack.
Definition: muParserStack.h:97
Division by zero (currently unused)
Definition: muParserError.h:82
Operator item: y to the power of ...
Definition: muParserDef.h:164
Internal error of any kind.
Definition: muParserError.h:93
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
void AddAssignOp(value_type *a_pVar)
Add an assignment operator.
Operator item: not equal.
Definition: muParserDef.h:156
For use in the ternary if-then-else operator.
Definition: muParserDef.h:170
TValueType pop()
Pop a value from the stack.
Definition: muParserStack.h:82
void AddFun(generic_fun_type a_pFun, int a_iArgc)
Add function to bytecode.
end of formula
Definition: muParserDef.h:192
Parser stack implementation.
Definition: muParserStack.h:53
void Assign(const ParserByteCode &a_ByteCode)
Copy state of another object to this.
std::size_t GetSize() const
Returns the number of entries in the bytecode.
Code for a generic function item.
Definition: muParserDef.h:185
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
void AsciiDump()
Dump bytecode (for debugging only!).
ParserByteCode()
Bytecode default constructor.
For use in the ternary if-then-else operator.
Definition: muParserDef.h:171
Operator item: subtract.
Definition: muParserDef.h:161
void AddVal(value_type a_fVal)
Add a Variable pointer to bytecode.
Error class of the parser.
For use in the ternary if-then-else operator.
Definition: muParserDef.h:172
ECmdCode
Bytecode values.
Definition: muParserDef.h:149
Operator item: multiply.
Definition: muParserDef.h:162
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:247
Operator item: division.
Definition: muParserDef.h:163
Operator item: add.
Definition: muParserDef.h:160
A template class for providing wrappers for essential math functions.
Namespace for mathematical applications.
Definition: muParser.cpp:49
Operator item: less than.
Definition: muParserDef.h:158
value item
Definition: muParserDef.h:175
Operator item: greater than.
Definition: muParserDef.h:159
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
Definition: muParserDef.h:280
This file defines the stack used by muparser.
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Definition: muParserDef.h:187
Code for a function with a string parameter.
Definition: muParserDef.h:186
Operator item: equals.
Definition: muParserDef.h:157
Operator item: Assignment operator.
Definition: muParserDef.h:167
Bytecode implementation of the Math Parser.
This file contains the parser token definition.
void clear()
Delete the bytecode.
void AddVar(value_type *a_pVar)
Add a Variable pointer to bytecode.
Operator item: less or equal.
Definition: muParserDef.h:154
variable item
Definition: muParserDef.h:174
Operator item: greater or equal.
Definition: muParserDef.h:155
ParserByteCode & operator=(const ParserByteCode &a_ByteCode)
Assignment operator.
void Finalize()
Add end marker to bytecode.
This file defines the error class used by the parser.
This file contains standard definitions used by the parser.