muParser API -  1.35
muParserBase.cpp
Go to the documentation of this file.
1 /*
2 
3  _____ __ _____________ _______ ______ ___________
4  / \| | \____ \__ \\_ __ \/ ___// __ \_ __ \
5  | Y Y \ | / |_> > __ \| | \/\___ \\ ___/| | \/
6  |__|_| /____/| __(____ /__| /____ >\___ >__|
7  \/ |__| \/ \/ \/
8  Copyright (C) 2004 - 2020 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 #include "muParserBase.h"
30 #include "muParserTemplateMagic.h"
31 
32 //--- Standard includes ------------------------------------------------------------------------
33 #include <algorithm>
34 #include <cmath>
35 #include <memory>
36 #include <vector>
37 #include <deque>
38 #include <sstream>
39 #include <locale>
40 #include <cassert>
41 #include <cctype>
42 
43 #ifdef MUP_USE_OPENMP
44 #include <omp.h>
45 #endif
46 
47 #if defined(_MSC_VER)
48  #pragma warning(push)
49  #pragma warning(disable : 26812)
50 #endif
51 
52 using namespace std;
53 
54 /** \file
55  \brief This file contains the basic implementation of the muparser engine.
56 */
57 
58 namespace mu
59 {
60  std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));
61 
62  bool ParserBase::g_DbgDumpCmdCode = false;
63  bool ParserBase::g_DbgDumpStack = false;
64 
65  //------------------------------------------------------------------------------
66  /** \brief Identifiers for built in binary operators.
67 
68  When defining custom binary operators with #AddOprt(...) make sure not to choose
69  names conflicting with these definitions.
70  */
71  const char_type* ParserBase::c_DefaultOprt[] =
72  {
73  _T("<="), _T(">="), _T("!="),
74  _T("=="), _T("<"), _T(">"),
75  _T("+"), _T("-"), _T("*"),
76  _T("/"), _T("^"), _T("&&"),
77  _T("||"), _T("="), _T("("),
78  _T(")"), _T("?"), _T(":"), 0
79  };
80 
81  const int ParserBase::s_MaxNumOpenMPThreads = 16;
82 
83  //------------------------------------------------------------------------------
84  /** \brief Constructor.
85  \param a_szFormula the formula to interpret.
86  \throw ParserException if a_szFormula is nullptr.
87  */
88  ParserBase::ParserBase()
89  : m_pParseFormula(&ParserBase::ParseString)
90  , m_vRPN()
91  , m_vStringBuf()
92  , m_pTokenReader()
93  , m_FunDef()
94  , m_PostOprtDef()
95  , m_InfixOprtDef()
96  , m_OprtDef()
97  , m_ConstDef()
98  , m_StrVarDef()
99  , m_VarDef()
100  , m_bBuiltInOp(true)
101  , m_sNameChars()
102  , m_sOprtChars()
103  , m_sInfixOprtChars()
104  , m_vStackBuffer()
105  , m_nFinalResultIdx(0)
106  {
107  InitTokenReader();
108  }
109 
110  //---------------------------------------------------------------------------
111  /** \brief Copy constructor.
112 
113  The parser can be safely copy constructed but the bytecode is reset during
114  copy construction.
115  */
117  : m_pParseFormula(&ParserBase::ParseString)
118  , m_vRPN()
119  , m_vStringBuf()
120  , m_pTokenReader()
121  , m_FunDef()
122  , m_PostOprtDef()
123  , m_InfixOprtDef()
124  , m_OprtDef()
125  , m_ConstDef()
126  , m_StrVarDef()
127  , m_VarDef()
128  , m_bBuiltInOp(true)
129  , m_sNameChars()
130  , m_sOprtChars()
131  , m_sInfixOprtChars()
132  {
133  m_pTokenReader.reset(new token_reader_type(this));
134  Assign(a_Parser);
135  }
136 
137  //---------------------------------------------------------------------------
138  ParserBase::~ParserBase()
139  {}
140 
141  //---------------------------------------------------------------------------
142  /** \brief Assignment operator.
143 
144  Implemented by calling Assign(a_Parser). Self assignment is suppressed.
145  \param a_Parser Object to copy to this.
146  \return *this
147  \throw nothrow
148  */
150  {
151  Assign(a_Parser);
152  return *this;
153  }
154 
155  //---------------------------------------------------------------------------
156  /** \brief Copy state of a parser object to this.
157 
158  Clears Variables and Functions of this parser.
159  Copies the states of all internal variables.
160  Resets parse function to string parse mode.
161 
162  \param a_Parser the source object.
163  */
164  void ParserBase::Assign(const ParserBase& a_Parser)
165  {
166  if (&a_Parser == this)
167  return;
168 
169  // Don't copy bytecode instead cause the parser to create new bytecode
170  // by resetting the parse function.
171  ReInit();
172 
173  m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants
174  m_VarDef = a_Parser.m_VarDef; // Copy user defined variables
175  m_bBuiltInOp = a_Parser.m_bBuiltInOp;
176  m_vStringBuf = a_Parser.m_vStringBuf;
177  m_vStackBuffer = a_Parser.m_vStackBuffer;
178  m_nFinalResultIdx = a_Parser.m_nFinalResultIdx;
179  m_StrVarDef = a_Parser.m_StrVarDef;
180  m_vStringVarBuf = a_Parser.m_vStringVarBuf;
181  m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));
182 
183  // Copy function and operator callbacks
184  m_FunDef = a_Parser.m_FunDef; // Copy function definitions
185  m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators
186  m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation
187  m_OprtDef = a_Parser.m_OprtDef; // binary operators
188 
189  m_sNameChars = a_Parser.m_sNameChars;
190  m_sOprtChars = a_Parser.m_sOprtChars;
191  m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
192  }
193 
194  //---------------------------------------------------------------------------
195  /** \brief Set the decimal separator.
196  \param cDecSep Decimal separator as a character value.
197  \sa SetThousandsSep
198 
199  By default muparser uses the "C" locale. The decimal separator of this
200  locale is overwritten by the one provided here.
201  */
203  {
204  char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();
205  s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
206  }
207 
208  //---------------------------------------------------------------------------
209  /** \brief Sets the thousands operator.
210  \param cThousandsSep The thousands separator as a character
211  \sa SetDecSep
212 
213  By default muparser uses the "C" locale. The thousands separator of this
214  locale is overwritten by the one provided here.
215  */
217  {
218  char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();
219  s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
220  }
221 
222  //---------------------------------------------------------------------------
223  /** \brief Resets the locale.
224 
225  The default locale used "." as decimal separator, no thousands separator and
226  "," as function argument separator.
227  */
229  {
230  s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));
231  SetArgSep(',');
232  }
233 
234  //---------------------------------------------------------------------------
235  /** \brief Initialize the token reader.
236 
237  Create new token reader object and submit pointers to function, operator,
238  constant and variable definitions.
239 
240  \post m_pTokenReader.get()!=0
241  \throw nothrow
242  */
243  void ParserBase::InitTokenReader()
244  {
245  m_pTokenReader.reset(new token_reader_type(this));
246  }
247 
248  //---------------------------------------------------------------------------
249  /** \brief Reset parser to string parsing mode and clear internal buffers.
250 
251  Clear bytecode, reset the token reader.
252  \throw nothrow
253  */
254  void ParserBase::ReInit() const
255  {
256  m_pParseFormula = &ParserBase::ParseString;
257  m_vStringBuf.clear();
258  m_vRPN.clear();
259  m_pTokenReader->ReInit();
260  }
261 
262  //---------------------------------------------------------------------------
263  void ParserBase::OnDetectVar(string_type* /*pExpr*/, int& /*nStart*/, int& /*nEnd*/)
264  {}
265 
266  //---------------------------------------------------------------------------
267  /** \brief Returns the version of muparser.
268  \param eInfo A flag indicating whether the full version info should be
269  returned or not.
270 
271  Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS
272  are returned only if eInfo==pviFULL.
273  */
274  string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const
275  {
277 
278  ss << ParserVersion;
279 
280  if (eInfo == pviFULL)
281  {
282  ss << _T(" (") << ParserVersionDate;
283  ss << std::dec << _T("; ") << sizeof(void*) * 8 << _T("BIT");
284 
285 #ifdef _DEBUG
286  ss << _T("; DEBUG");
287 #else
288  ss << _T("; RELEASE");
289 #endif
290 
291 #ifdef _UNICODE
292  ss << _T("; UNICODE");
293 #else
294 #ifdef _MBCS
295  ss << _T("; MBCS");
296 #else
297  ss << _T("; ASCII");
298 #endif
299 #endif
300 
301 #ifdef MUP_USE_OPENMP
302  ss << _T("; OPENMP");
303 #endif
304 
305  ss << _T(")");
306  }
307 
308  return ss.str();
309  }
310 
311  //---------------------------------------------------------------------------
312  /** \brief Add a value parsing function.
313 
314  When parsing an expression muParser tries to detect values in the expression
315  string using different valident callbacks. Thus it's possible to parse
316  for hex values, binary values and floating point values.
317  */
319  {
320  m_pTokenReader->AddValIdent(a_pCallback);
321  }
322 
323  //---------------------------------------------------------------------------
324  /** \brief Set a function that can create variable pointer for unknown expression variables.
325  \param a_pFactory A pointer to the variable factory.
326  \param pUserData A user defined context pointer.
327  */
328  void ParserBase::SetVarFactory(facfun_type a_pFactory, void* pUserData)
329  {
330  m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
331  }
332 
333  //---------------------------------------------------------------------------
334  /** \brief Add a function or operator callback to the parser. */
335  void ParserBase::AddCallback(const string_type& a_strName,
336  const ParserCallback& a_Callback,
337  funmap_type& a_Storage,
338  const char_type* a_szCharSet)
339  {
340  if (a_Callback.GetAddr() == 0)
342 
343  const funmap_type* pFunMap = &a_Storage;
344 
345  // Check for conflicting operator or function names
346  if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end())
347  Error(ecNAME_CONFLICT, -1, a_strName);
348 
349  if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end())
350  Error(ecNAME_CONFLICT, -1, a_strName);
351 
352  if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end())
353  Error(ecNAME_CONFLICT, -1, a_strName);
354 
355  if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end())
356  Error(ecNAME_CONFLICT, -1, a_strName);
357 
358  CheckOprt(a_strName, a_Callback, a_szCharSet);
359  a_Storage[a_strName] = a_Callback;
360  ReInit();
361  }
362 
363  //---------------------------------------------------------------------------
364  /** \brief Check if a name contains invalid characters.
365 
366  \throw ParserException if the name contains invalid characters.
367  */
368  void ParserBase::CheckOprt(const string_type& a_sName,
369  const ParserCallback& a_Callback,
370  const string_type& a_szCharSet) const
371  {
372  if (!a_sName.length() ||
373  (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
374  (a_sName[0] >= '0' && a_sName[0] <= '9'))
375  {
376  switch (a_Callback.GetCode())
377  {
378  case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); break;
379  case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); break;
380  default: Error(ecINVALID_NAME, -1, a_sName);
381  }
382  }
383  }
384 
385  //---------------------------------------------------------------------------
386  /** \brief Check if a name contains invalid characters.
387 
388  \throw ParserException if the name contains invalid characters.
389  */
390  void ParserBase::CheckName(const string_type& a_sName,
391  const string_type& a_szCharSet) const
392  {
393  if (!a_sName.length() ||
394  (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
395  (a_sName[0] >= '0' && a_sName[0] <= '9'))
396  {
398  }
399  }
400 
401  //---------------------------------------------------------------------------
402  /** \brief Set the formula.
403  \param a_strFormula Formula as string_type
404  \throw ParserException in case of syntax errors.
405 
406  Triggers first time calculation thus the creation of the bytecode and
407  scanning of used variables.
408  */
409  void ParserBase::SetExpr(const string_type& a_sExpr)
410  {
411  if (std::all_of(a_sExpr.begin(), a_sExpr.end(), [](char c) { return !std::isgraph(c); }))
412  {
414  }
415 
416  // Check locale compatibility
417  if (m_pTokenReader->GetArgSep() == std::use_facet<numpunct<char_type> >(s_locale).decimal_point())
418  Error(ecLOCALE);
419 
420  // Check maximum allowed expression length. An arbitrary value small enough so i can debug expressions sent to me
421  if (a_sExpr.length() >= MaxLenExpression)
422  Error(ecEXPRESSION_TOO_LONG, 0, a_sExpr);
423 
424  m_pTokenReader->SetFormula(a_sExpr + _T(" "));
425  ReInit();
426  }
427 
428  //---------------------------------------------------------------------------
429  /** \brief Get the default symbols used for the built in operators.
430  \sa c_DefaultOprt
431  */
433  {
434  return (const char_type**)(&c_DefaultOprt[0]);
435  }
436 
437  //---------------------------------------------------------------------------
438  /** \brief Define the set of valid characters to be used in names of
439  functions, variables, constants.
440  */
441  void ParserBase::DefineNameChars(const char_type* a_szCharset)
442  {
443  m_sNameChars = a_szCharset;
444  }
445 
446  //---------------------------------------------------------------------------
447  /** \brief Define the set of valid characters to be used in names of
448  binary operators and postfix operators.
449  */
450  void ParserBase::DefineOprtChars(const char_type* a_szCharset)
451  {
452  m_sOprtChars = a_szCharset;
453  }
454 
455  //---------------------------------------------------------------------------
456  /** \brief Define the set of valid characters to be used in names of
457  infix operators.
458  */
460  {
461  m_sInfixOprtChars = a_szCharset;
462  }
463 
464  //---------------------------------------------------------------------------
465  /** \brief Virtual function that defines the characters allowed in name identifiers.
466  \sa #ValidOprtChars, #ValidPrefixOprtChars
467  */
469  {
470  MUP_ASSERT(m_sNameChars.size());
471  return m_sNameChars.c_str();
472  }
473 
474  //---------------------------------------------------------------------------
475  /** \brief Virtual function that defines the characters allowed in operator definitions.
476  \sa #ValidNameChars, #ValidPrefixOprtChars
477  */
479  {
480  MUP_ASSERT(m_sOprtChars.size());
481  return m_sOprtChars.c_str();
482  }
483 
484  //---------------------------------------------------------------------------
485  /** \brief Virtual function that defines the characters allowed in infix operator definitions.
486  \sa #ValidNameChars, #ValidOprtChars
487  */
489  {
490  MUP_ASSERT(m_sInfixOprtChars.size());
491  return m_sInfixOprtChars.c_str();
492  }
493 
494  //---------------------------------------------------------------------------
495  /** \brief Add a user defined operator.
496  \post Will reset the Parser to string parsing mode.
497  */
498  void ParserBase::DefinePostfixOprt(const string_type& a_sName, fun_type1 a_pFun, bool a_bAllowOpt)
499  {
500  if (a_sName.length() > MaxLenIdentifier)
502 
503  AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), m_PostOprtDef, ValidOprtChars());
504  }
505 
506  //---------------------------------------------------------------------------
507  /** \brief Initialize user defined functions.
508 
509  Calls the virtual functions InitFun(), InitConst() and InitOprt().
510  */
512  {
513  InitCharSets();
514  InitFun();
515  InitConst();
516  InitOprt();
517  }
518 
519  //---------------------------------------------------------------------------
520  /** \brief Add a user defined operator.
521  \post Will reset the Parser to string parsing mode.
522  \param [in] a_sName operator Identifier
523  \param [in] a_pFun Operator callback function
524  \param [in] a_iPrec Operator Precedence (default=prSIGN)
525  \param [in] a_bAllowOpt True if operator is volatile (default=false)
526  \sa EPrec
527  */
528  void ParserBase::DefineInfixOprt(const string_type& a_sName, fun_type1 a_pFun, int a_iPrec, bool a_bAllowOpt)
529  {
530  if (a_sName.length() > MaxLenIdentifier)
532 
533  AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, ValidInfixOprtChars());
534  }
535 
536 
537  //---------------------------------------------------------------------------
538  /** \brief Define a binary operator.
539  \param [in] a_sName The identifier of the operator.
540  \param [in] a_pFun Pointer to the callback function.
541  \param [in] a_iPrec Precedence of the operator.
542  \param [in] a_eAssociativity The associativity of the operator.
543  \param [in] a_bAllowOpt If this is true the operator may be optimized away.
544 
545  Adds a new Binary operator the the parser instance.
546  */
547  void ParserBase::DefineOprt(const string_type& a_sName, fun_type2 a_pFun, unsigned a_iPrec, EOprtAssociativity a_eAssociativity, bool a_bAllowOpt)
548  {
549  if (a_sName.length() > MaxLenIdentifier)
551 
552  // Check for conflicts with built in operator names
553  for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i)
554  {
555  if (a_sName == string_type(c_DefaultOprt[i]))
556  {
557  Error(ecBUILTIN_OVERLOAD, -1, a_sName);
558  }
559  }
560 
561  AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), m_OprtDef, ValidOprtChars());
562  }
563 
564  //---------------------------------------------------------------------------
565  /** \brief Define a new string constant.
566  \param [in] a_strName The name of the constant.
567  \param [in] a_strVal the value of the constant.
568  */
569  void ParserBase::DefineStrConst(const string_type& a_strName, const string_type& a_strVal)
570  {
571  // Test if a constant with that names already exists
572  if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
574 
575  CheckName(a_strName, ValidNameChars());
576 
577  m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer
578  m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1; // bind buffer index to variable name
579 
580  ReInit();
581  }
582 
583  //---------------------------------------------------------------------------
584  /** \brief Add a user defined variable.
585  \param [in] a_sName the variable name
586  \param [in] a_pVar A pointer to the variable value.
587  \post Will reset the Parser to string parsing mode.
588  \throw ParserException in case the name contains invalid signs or a_pVar is nullptr.
589  */
590  void ParserBase::DefineVar(const string_type& a_sName, value_type* a_pVar)
591  {
592  if (a_pVar == 0)
594 
595  if (a_sName.length() > MaxLenIdentifier)
597 
598  // Test if a constant with that names already exists
599  if (m_ConstDef.find(a_sName) != m_ConstDef.end())
601 
602  CheckName(a_sName, ValidNameChars());
603  m_VarDef[a_sName] = a_pVar;
604  ReInit();
605  }
606 
607  //---------------------------------------------------------------------------
608  /** \brief Add a user defined constant.
609  \param [in] a_sName The name of the constant.
610  \param [in] a_fVal the value of the constant.
611  \post Will reset the Parser to string parsing mode.
612  \throw ParserException in case the name contains invalid signs.
613  */
614  void ParserBase::DefineConst(const string_type& a_sName, value_type a_fVal)
615  {
616  if (a_sName.length() > MaxLenIdentifier)
618 
619  CheckName(a_sName, ValidNameChars());
620  m_ConstDef[a_sName] = a_fVal;
621  ReInit();
622  }
623 
624  //---------------------------------------------------------------------------
625  /** \brief Get operator priority.
626  \throw ParserException if a_Oprt is no operator code
627  */
628  int ParserBase::GetOprtPrecedence(const token_type& a_Tok) const
629  {
630  switch (a_Tok.GetCode())
631  {
632  // built in operators
633  case cmEND: return -5;
634  case cmARG_SEP: return -4;
635  case cmASSIGN: return -1;
636  case cmELSE:
637  case cmIF: return 0;
638  case cmLAND: return prLAND;
639  case cmLOR: return prLOR;
640  case cmLT:
641  case cmGT:
642  case cmLE:
643  case cmGE:
644  case cmNEQ:
645  case cmEQ: return prCMP;
646  case cmADD:
647  case cmSUB: return prADD_SUB;
648  case cmMUL:
649  case cmDIV: return prMUL_DIV;
650  case cmPOW: return prPOW;
651 
652  // user defined binary operators
653  case cmOPRT_INFIX:
654  case cmOPRT_BIN: return a_Tok.GetPri();
655  default: Error(ecINTERNAL_ERROR, 5);
656  return 999;
657  }
658  }
659 
660  //---------------------------------------------------------------------------
661  /** \brief Get operator priority.
662  \throw ParserException if a_Oprt is no operator code
663  */
664  EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type& a_Tok) const
665  {
666  switch (a_Tok.GetCode())
667  {
668  case cmASSIGN:
669  case cmLAND:
670  case cmLOR:
671  case cmLT:
672  case cmGT:
673  case cmLE:
674  case cmGE:
675  case cmNEQ:
676  case cmEQ:
677  case cmADD:
678  case cmSUB:
679  case cmMUL:
680  case cmDIV: return oaLEFT;
681  case cmPOW: return oaRIGHT;
682  case cmOPRT_BIN: return a_Tok.GetAssociativity();
683  default: return oaNONE;
684  }
685  }
686 
687  //---------------------------------------------------------------------------
688  /** \brief Return a map containing the used variables only. */
690  {
691  try
692  {
693  m_pTokenReader->IgnoreUndefVar(true);
694  CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it
695  // may contain references to nonexisting variables.
696  m_pParseFormula = &ParserBase::ParseString;
697  m_pTokenReader->IgnoreUndefVar(false);
698  }
699  catch (exception_type& /*e*/)
700  {
701  // Make sure to stay in string parse mode, don't call ReInit()
702  // because it deletes the array with the used variables
703  m_pParseFormula = &ParserBase::ParseString;
704  m_pTokenReader->IgnoreUndefVar(false);
705  throw;
706  }
707 
708  return m_pTokenReader->GetUsedVar();
709  }
710 
711  //---------------------------------------------------------------------------
712  /** \brief Return a map containing the used variables only. */
714  {
715  return m_VarDef;
716  }
717 
718  //---------------------------------------------------------------------------
719  /** \brief Return a map containing all parser constants. */
721  {
722  return m_ConstDef;
723  }
724 
725  //---------------------------------------------------------------------------
726  /** \brief Return prototypes of all parser functions.
727  \return #m_FunDef
728  \sa FunProt
729  \throw nothrow
730 
731  The return type is a map of the public type #funmap_type containing the prototype
732  definitions for all numerical parser functions. String functions are not part of
733  this map. The Prototype definition is encapsulated in objects of the class FunProt
734  one per parser function each associated with function names via a map construct.
735  */
737  {
738  return m_FunDef;
739  }
740 
741  //---------------------------------------------------------------------------
742  /** \brief Retrieve the formula. */
744  {
745  return m_pTokenReader->GetExpr();
746  }
747 
748  //---------------------------------------------------------------------------
749  /** \brief Execute a function that takes a single string argument.
750  \param a_FunTok Function token.
751  \throw exception_type If the function token is not a string function
752  */
753  ParserBase::token_type ParserBase::ApplyStrFunc(const token_type& a_FunTok,
754  const std::vector<token_type>& a_vArg) const
755  {
756  if (a_vArg.back().GetCode() != cmSTRING)
757  Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
758 
759  token_type valTok;
760  generic_fun_type pFunc = a_FunTok.GetFuncAddr();
761  MUP_ASSERT(pFunc);
762 
763  try
764  {
765  // Check function arguments; write dummy value into valtok to represent the result
766  switch (a_FunTok.GetArgCount())
767  {
768  case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break;
769  case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break;
770  case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break;
771  case 3: valTok.SetVal(1); a_vArg[3].GetAsString(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break;
772  case 4: valTok.SetVal(1); a_vArg[4].GetAsString(); a_vArg[3].GetVal(); a_vArg[2].GetVal(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break;
773  default: Error(ecINTERNAL_ERROR);
774  }
775  }
776  catch (ParserError&)
777  {
778  Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
779  }
780 
781  // string functions won't be optimized
782  m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
783 
784  // Push dummy value representing the function result to the stack
785  return valTok;
786  }
787 
788  //---------------------------------------------------------------------------
789  /** \brief Apply a function token.
790  \param iArgCount Number of Arguments actually gathered used only for multiarg functions.
791  \post The result is pushed to the value stack
792  \post The function token is removed from the stack
793  \throw exception_type if Argument count does not match function requirements.
794  */
795  void ParserBase::ApplyFunc(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal, int a_iArgCount) const
796  {
797  MUP_ASSERT(m_pTokenReader.get());
798 
799  // Operator stack empty or does not contain tokens with callback functions
800  if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0)
801  return;
802 
803  token_type funTok = a_stOpt.top();
804  a_stOpt.pop();
805  MUP_ASSERT(funTok.GetFuncAddr() != nullptr);
806 
807  // Binary operators must rely on their internal operator number
808  // since counting of operators relies on commas for function arguments
809  // binary operators do not have commas in their expression
810  int iArgCount = (funTok.GetCode() == cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
811 
812  // determine how many parameters the function needs. To remember iArgCount includes the
813  // string parameter whilst GetArgCount() counts only numeric parameters.
814  int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() == tpSTR) ? 1 : 0);
815 
816  // That's the number of numerical parameters
817  int iArgNumerical = iArgCount - ((funTok.GetType() == tpSTR) ? 1 : 0);
818 
819  if (funTok.GetCode() == cmFUNC_STR && iArgCount - iArgNumerical > 1)
821 
822  if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
823  Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
824 
825  if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired)
826  Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
827 
828  if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired)
829  Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
830 
831  // Collect the numeric function arguments from the value stack and store them
832  // in a vector
833  std::vector<token_type> stArg;
834  for (int i = 0; i < iArgNumerical; ++i)
835  {
836  if (a_stVal.empty())
837  Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString());
838 
839  stArg.push_back(a_stVal.top());
840  a_stVal.pop();
841 
842  if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR)
843  Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
844  }
845 
846  switch (funTok.GetCode())
847  {
848  case cmFUNC_STR:
849  if (a_stVal.empty())
850  Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), funTok.GetAsString());
851 
852  stArg.push_back(a_stVal.top());
853  a_stVal.pop();
854 
855  if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR)
856  Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
857 
858  ApplyStrFunc(funTok, stArg);
859  break;
860 
861  case cmFUNC_BULK:
862  m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
863  break;
864 
865  case cmOPRT_BIN:
866  case cmOPRT_POSTFIX:
867  case cmOPRT_INFIX:
868  case cmFUNC:
869  if (funTok.GetArgCount() == -1 && iArgCount == 0)
870  Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());
871 
872  m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical);
873  break;
874  default:
875  break;
876  }
877 
878  // Push dummy value representing the function result to the stack
879  token_type token;
880  token.SetVal(1);
881  a_stVal.push(token);
882  }
883 
884  //---------------------------------------------------------------------------
885  void ParserBase::ApplyIfElse(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const
886  {
887  // Check if there is an if Else clause to be calculated
888  while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE)
889  {
890  MUP_ASSERT(!a_stOpt.empty())
891  token_type opElse = a_stOpt.top();
892  a_stOpt.pop();
893 
894  // Take the value associated with the else branch from the value stack
895  MUP_ASSERT(!a_stVal.empty());
896  token_type vVal2 = a_stVal.top();
897  a_stVal.pop();
898 
899  // it then else is a ternary operator Pop all three values from the value s
900  // tack and just return the right value
901  MUP_ASSERT(!a_stVal.empty());
902  token_type vVal1 = a_stVal.top();
903  a_stVal.pop();
904 
905  MUP_ASSERT(!a_stVal.empty());
906  token_type vExpr = a_stVal.top();
907  a_stVal.pop();
908 
909  a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2);
910 
911  token_type opIf = a_stOpt.top();
912  a_stOpt.pop();
913 
914  MUP_ASSERT(opElse.GetCode() == cmELSE);
915 
916  if (opIf.GetCode() != cmIF)
917  Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
918 
919  m_vRPN.AddIfElse(cmENDIF);
920  } // while pending if-else-clause found
921  }
922 
923  //---------------------------------------------------------------------------
924  /** \brief Performs the necessary steps to write code for
925  the execution of binary operators into the bytecode.
926  */
927  void ParserBase::ApplyBinOprt(std::stack<token_type>& a_stOpt, std::stack<token_type>& a_stVal) const
928  {
929  // is it a user defined binary operator?
930  if (a_stOpt.top().GetCode() == cmOPRT_BIN)
931  {
932  ApplyFunc(a_stOpt, a_stVal, 2);
933  }
934  else
935  {
936  if (a_stVal.size() < 2)
937  Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos(), _T("ApplyBinOprt: not enough values in value stack!"));
938 
939  token_type valTok1 = a_stVal.top();
940  a_stVal.pop();
941 
942  token_type valTok2 = a_stVal.top();
943  a_stVal.pop();
944 
945  token_type optTok = a_stOpt.top();
946  a_stOpt.pop();
947 
948  token_type resTok;
949 
950  if (valTok1.GetType() != valTok2.GetType() ||
951  (valTok1.GetType() == tpSTR && valTok2.GetType() == tpSTR))
952  Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());
953 
954  if (optTok.GetCode() == cmASSIGN)
955  {
956  if (valTok2.GetCode() != cmVAR)
957  Error(ecUNEXPECTED_OPERATOR, -1, _T("="));
958 
959  m_vRPN.AddAssignOp(valTok2.GetVar());
960  }
961  else
962  m_vRPN.AddOp(optTok.GetCode());
963 
964  resTok.SetVal(1);
965  a_stVal.push(resTok);
966  }
967  }
968 
969  //---------------------------------------------------------------------------
970  /** \brief Apply a binary operator.
971  \param a_stOpt The operator stack
972  \param a_stVal The value stack
973  */
974  void ParserBase::ApplyRemainingOprt(std::stack<token_type>& stOpt, std::stack<token_type>& stVal) const
975  {
976  while (stOpt.size() &&
977  stOpt.top().GetCode() != cmBO &&
978  stOpt.top().GetCode() != cmIF)
979  {
980  token_type tok = stOpt.top();
981  switch (tok.GetCode())
982  {
983  case cmOPRT_INFIX:
984  case cmOPRT_BIN:
985  case cmLE:
986  case cmGE:
987  case cmNEQ:
988  case cmEQ:
989  case cmLT:
990  case cmGT:
991  case cmADD:
992  case cmSUB:
993  case cmMUL:
994  case cmDIV:
995  case cmPOW:
996  case cmLAND:
997  case cmLOR:
998  case cmASSIGN:
999  if (stOpt.top().GetCode() == cmOPRT_INFIX)
1000  ApplyFunc(stOpt, stVal, 1);
1001  else
1002  ApplyBinOprt(stOpt, stVal);
1003  break;
1004 
1005  case cmELSE:
1006  ApplyIfElse(stOpt, stVal);
1007  break;
1008 
1009  default:
1011  }
1012  }
1013  }
1014 
1015  //---------------------------------------------------------------------------
1016  /** \brief Parse the command code.
1017  \sa ParseString(...)
1018 
1019  Command code contains precalculated stack positions of the values and the
1020  associated operators. The Stack is filled beginning from index one the
1021  value at index zero is not used at all.
1022  */
1023  value_type ParserBase::ParseCmdCode() const
1024  {
1025  return ParseCmdCodeBulk(0, 0);
1026  }
1027 
1028  value_type ParserBase::ParseCmdCodeShort() const
1029  {
1030  const SToken *const tok = m_vRPN.GetBase();
1031  value_type buf;
1032 
1033  switch (tok->Cmd)
1034  {
1035  case cmVAL:
1036  return tok->Val.data2;
1037 
1038  case cmVAR:
1039  return *tok->Val.ptr;
1040 
1041  case cmVARMUL:
1042  return *tok->Val.ptr * tok->Val.data + tok->Val.data2;
1043 
1044  case cmVARPOW2:
1045  buf = *(tok->Val.ptr);
1046  return buf * buf;
1047 
1048  case cmVARPOW3:
1049  buf = *(tok->Val.ptr);
1050  return buf * buf * buf;
1051 
1052  case cmVARPOW4:
1053  buf = *(tok->Val.ptr);
1054  return buf * buf * buf * buf;
1055 
1056  // numerical function without any argument
1057  case cmFUNC:
1058  return (*(fun_type0)tok->Fun.ptr)();
1059 
1060  // String function without a numerical argument
1061  case cmFUNC_STR:
1062  return (*(strfun_type1)tok->Fun.ptr)(m_vStringBuf[0].c_str());
1063 
1064  default:
1065  throw ParserError(ecINTERNAL_ERROR);
1066  }
1067  }
1068 
1069  //---------------------------------------------------------------------------
1070  /** \brief Evaluate the RPN.
1071  \param nOffset The offset added to variable addresses (for bulk mode)
1072  \param nThreadID OpenMP Thread id of the calling thread
1073  */
1074  value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const
1075  {
1076  assert(nThreadID <= s_MaxNumOpenMPThreads);
1077 
1078  // Note: The check for nOffset==0 and nThreadID here is not necessary but
1079  // brings a minor performance gain when not in bulk mode.
1080  value_type* Stack = ((nOffset == 0) && (nThreadID == 0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)];
1081  value_type buf;
1082  int sidx(0);
1083  for (const SToken* pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok)
1084  {
1085  switch (pTok->Cmd)
1086  {
1087  // built in binary operators
1088  case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx + 1]; continue;
1089  case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx + 1]; continue;
1090  case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx + 1]; continue;
1091  case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx + 1]; continue;
1092  case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx + 1]; continue;
1093  case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx + 1]; continue;
1094  case cmADD: --sidx; Stack[sidx] += Stack[1 + sidx]; continue;
1095  case cmSUB: --sidx; Stack[sidx] -= Stack[1 + sidx]; continue;
1096  case cmMUL: --sidx; Stack[sidx] *= Stack[1 + sidx]; continue;
1097  case cmDIV: --sidx;
1098  Stack[sidx] /= Stack[1 + sidx];
1099  continue;
1100 
1101  case cmPOW:
1102  --sidx; Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1 + sidx]);
1103  continue;
1104 
1105  case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx + 1]; continue;
1106  case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx + 1]; continue;
1107 
1108  case cmASSIGN:
1109  // Bugfix for Bulkmode:
1110  // for details see:
1111  // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws
1112  --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue;
1113  // original code:
1114  //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue;
1115 
1116  case cmIF:
1117  if (Stack[sidx--] == 0)
1118  {
1119  MUP_ASSERT(sidx >= 0);
1120  pTok += pTok->Oprt.offset;
1121  }
1122  continue;
1123 
1124  case cmELSE:
1125  pTok += pTok->Oprt.offset;
1126  continue;
1127 
1128  case cmENDIF:
1129  continue;
1130 
1131  // value and variable tokens
1132  case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset); continue;
1133  case cmVAL: Stack[++sidx] = pTok->Val.data2; continue;
1134 
1135  case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset);
1136  Stack[++sidx] = buf * buf;
1137  continue;
1138 
1139  case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset);
1140  Stack[++sidx] = buf * buf * buf;
1141  continue;
1142 
1143  case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset);
1144  Stack[++sidx] = buf * buf * buf * buf;
1145  continue;
1146 
1147  case cmVARMUL:
1148  Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2;
1149  continue;
1150 
1151  // Next is treatment of numeric functions
1152  case cmFUNC:
1153  {
1154  int iArgCount = pTok->Fun.argc;
1155 
1156  // switch according to argument count
1157  switch (iArgCount)
1158  {
1159  case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); continue;
1160  case 1: Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); continue;
1161  case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1]); continue;
1162  case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]); continue;
1163  case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3]); continue;
1164  case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4]); continue;
1165  case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5]); continue;
1166  case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]); continue;
1167  case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7]); continue;
1168  case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], Stack[sidx + 8]); continue;
1169  case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], Stack[sidx + 8], Stack[sidx + 9]); continue;
1170  default:
1171  // function with variable arguments store the number as a negative value
1172  if (iArgCount > 0)
1173  Error(ecINTERNAL_ERROR, -1);
1174 
1175  sidx -= -iArgCount - 1;
1176 
1177  // <ibg 2020-06-08/> From oss-fuzz. Happend when Multiarg functions and if-then-else are used incorrectly "sum(0?1,2,3,4,5:6)"
1178  // The final result normally lieas at position 1. If sixd is smaller there is something wrong.
1179  if (sidx <= 0)
1180  Error(ecINTERNAL_ERROR, -1);
1181 
1182  Stack[sidx] = (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
1183  continue;
1184  }
1185  }
1186 
1187  // Next is treatment of string functions
1188  case cmFUNC_STR:
1189  {
1190  sidx -= pTok->Fun.argc - 1;
1191 
1192  // The index of the string argument in the string table
1193  int iIdxStack = pTok->Fun.idx;
1194  if (iIdxStack < 0 || iIdxStack >= (int)m_vStringBuf.size())
1195  Error(ecINTERNAL_ERROR, m_pTokenReader->GetPos());
1196 
1197  switch (pTok->Fun.argc) // switch according to argument count
1198  {
1199  case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue;
1200  case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue;
1201  case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1]); continue;
1202  case 3: Stack[sidx] = (*(strfun_type4)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]); continue;
1203  case 4: Stack[sidx] = (*(strfun_type5)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3]); continue;
1204  }
1205 
1206  continue;
1207  }
1208 
1209  case cmFUNC_BULK:
1210  {
1211  int iArgCount = pTok->Fun.argc;
1212 
1213  // switch according to argument count
1214  switch (iArgCount)
1215  {
1216  case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0)pTok->Fun.ptr)(nOffset, nThreadID); continue;
1217  case 1: Stack[sidx] = (*(bulkfun_type1)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue;
1218  case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1]); continue;
1219  case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]); continue;
1220  case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3]); continue;
1221  case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4]); continue;
1222  case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5]); continue;
1223  case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]); continue;
1224  case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7]); continue;
1225  case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], Stack[sidx + 8]); continue;
1226  case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], Stack[sidx + 8], Stack[sidx + 9]); continue;
1227  default:
1228  Error(ecINTERNAL_ERROR, 2);
1229  continue;
1230  }
1231  }
1232 
1233  default:
1234  Error(ecINTERNAL_ERROR, 3);
1235  return 0;
1236  } // switch CmdCode
1237  } // for all bytecode tokens
1238 
1239  return Stack[m_nFinalResultIdx];
1240  }
1241 
1242  //---------------------------------------------------------------------------
1243  void ParserBase::CreateRPN() const
1244  {
1245  if (!m_pTokenReader->GetExpr().length())
1246  Error(ecUNEXPECTED_EOF, 0);
1247 
1248  std::stack<token_type> stOpt, stVal;
1249  std::stack<int> stArgCount;
1250  token_type opta, opt; // for storing operators
1251  token_type val, tval; // for storing value
1252  int ifElseCounter = 0;
1253 
1254  ReInit();
1255 
1256  // The outermost counter counts the number of separated items
1257  // such as in "a=10,b=20,c=c+a"
1258  stArgCount.push(1);
1259 
1260  for (;;)
1261  {
1262  opt = m_pTokenReader->ReadNextToken();
1263 
1264  switch (opt.GetCode())
1265  {
1266  //
1267  // Next three are different kind of value entries
1268  //
1269  case cmSTRING:
1270  if (stOpt.empty())
1271  Error(ecSTR_RESULT, m_pTokenReader->GetPos(), opt.GetAsString());
1272 
1273  opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token
1274  stVal.push(opt);
1275  m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer
1276  break;
1277 
1278  case cmVAR:
1279  stVal.push(opt);
1280  m_vRPN.AddVar(static_cast<value_type*>(opt.GetVar()));
1281  break;
1282 
1283  case cmVAL:
1284  stVal.push(opt);
1285  m_vRPN.AddVal(opt.GetVal());
1286  break;
1287 
1288  case cmELSE:
1289  if (stArgCount.empty())
1290  Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1291 
1292  if (stArgCount.top() > 1)
1293  Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
1294 
1295  stArgCount.pop();
1296 
1297  ifElseCounter--;
1298  if (ifElseCounter < 0)
1299  Error(ecMISPLACED_COLON, m_pTokenReader->GetPos());
1300 
1301  ApplyRemainingOprt(stOpt, stVal);
1302  m_vRPN.AddIfElse(cmELSE);
1303  stOpt.push(opt);
1304  break;
1305 
1306  case cmARG_SEP:
1307  if (!stOpt.empty() && stOpt.top().GetCode() == cmIF)
1308  Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
1309 
1310  if (stArgCount.empty())
1311  Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos());
1312 
1313  ++stArgCount.top();
1314  // Falls through.
1315  // intentional (no break!)
1316 
1317  case cmEND:
1318  ApplyRemainingOprt(stOpt, stVal);
1319  break;
1320 
1321  case cmBC:
1322  {
1323  // The argument count for parameterless functions is zero
1324  // by default an opening bracket sets parameter count to 1
1325  // in preparation of arguments to come. If the last token
1326  // was an opening bracket we know better...
1327  if (opta.GetCode() == cmBO)
1328  --stArgCount.top();
1329 
1330  ApplyRemainingOprt(stOpt, stVal);
1331 
1332  // Check if the bracket content has been evaluated completely
1333  if (stOpt.size() && stOpt.top().GetCode() == cmBO)
1334  {
1335  // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check
1336  // if there is either a function or a sign pending
1337  // neither the opening nor the closing bracket will be pushed back to
1338  // the operator stack
1339  // Check if a function is standing in front of the opening bracket,
1340  // if yes evaluate it afterwards check for infix operators
1341  MUP_ASSERT(stArgCount.size());
1342  int iArgCount = stArgCount.top();
1343  stArgCount.pop();
1344 
1345  stOpt.pop(); // Take opening bracket from stack
1346 
1347  if (iArgCount > 1 && (stOpt.size() == 0 ||
1348  (stOpt.top().GetCode() != cmFUNC &&
1349  stOpt.top().GetCode() != cmFUNC_BULK &&
1350  stOpt.top().GetCode() != cmFUNC_STR)))
1351  Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());
1352 
1353  // The opening bracket was popped from the stack now check if there
1354  // was a function before this bracket
1355  if (stOpt.size() &&
1356  stOpt.top().GetCode() != cmOPRT_INFIX &&
1357  stOpt.top().GetCode() != cmOPRT_BIN &&
1358  stOpt.top().GetFuncAddr() != 0)
1359  {
1360  ApplyFunc(stOpt, stVal, iArgCount);
1361  }
1362  }
1363  } // if bracket content is evaluated
1364  break;
1365 
1366  //
1367  // Next are the binary operator entries
1368  //
1369  case cmIF:
1370  ifElseCounter++;
1371  stArgCount.push(1);
1372  // Falls through.
1373  // intentional (no break!)
1374 
1375  case cmLAND:
1376  case cmLOR:
1377  case cmLT:
1378  case cmGT:
1379  case cmLE:
1380  case cmGE:
1381  case cmNEQ:
1382  case cmEQ:
1383  case cmADD:
1384  case cmSUB:
1385  case cmMUL:
1386  case cmDIV:
1387  case cmPOW:
1388  case cmASSIGN:
1389  case cmOPRT_BIN:
1390 
1391  // A binary operator (user defined or built in) has been found.
1392  while (
1393  stOpt.size() &&
1394  stOpt.top().GetCode() != cmBO &&
1395  stOpt.top().GetCode() != cmELSE &&
1396  stOpt.top().GetCode() != cmIF)
1397  {
1398  int nPrec1 = GetOprtPrecedence(stOpt.top()),
1399  nPrec2 = GetOprtPrecedence(opt);
1400 
1401  if (stOpt.top().GetCode() == opt.GetCode())
1402  {
1403 
1404  // Deal with operator associativity
1405  EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt);
1406  if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
1407  (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)))
1408  {
1409  break;
1410  }
1411  }
1412  else if (nPrec1 < nPrec2)
1413  {
1414  // In case the operators are not equal the precedence decides alone...
1415  break;
1416  }
1417 
1418  if (stOpt.top().GetCode() == cmOPRT_INFIX)
1419  ApplyFunc(stOpt, stVal, 1);
1420  else
1421  ApplyBinOprt(stOpt, stVal);
1422  } // while ( ... )
1423 
1424  if (opt.GetCode() == cmIF)
1425  m_vRPN.AddIfElse(opt.GetCode());
1426 
1427  // The operator can't be evaluated right now, push back to the operator stack
1428  stOpt.push(opt);
1429  break;
1430 
1431  //
1432  // Last section contains functions and operators implicitly mapped to functions
1433  //
1434  case cmBO:
1435  stArgCount.push(1);
1436  stOpt.push(opt);
1437  break;
1438 
1439  case cmOPRT_INFIX:
1440  case cmFUNC:
1441  case cmFUNC_BULK:
1442  case cmFUNC_STR:
1443  stOpt.push(opt);
1444  break;
1445 
1446  case cmOPRT_POSTFIX:
1447  stOpt.push(opt);
1448  ApplyFunc(stOpt, stVal, 1); // this is the postfix operator
1449  break;
1450 
1451  default: Error(ecINTERNAL_ERROR, 3);
1452  } // end of switch operator-token
1453 
1454  opta = opt;
1455 
1456  if (opt.GetCode() == cmEND)
1457  {
1458  m_vRPN.Finalize();
1459  break;
1460  }
1461 
1462  if (ParserBase::g_DbgDumpStack)
1463  {
1464  StackDump(stVal, stOpt);
1465  m_vRPN.AsciiDump();
1466  }
1467 
1468 // if (ParserBase::g_DbgDumpCmdCode)
1469  //m_vRPN.AsciiDump();
1470  } // while (true)
1471 
1472  if (ParserBase::g_DbgDumpCmdCode)
1473  m_vRPN.AsciiDump();
1474 
1475  if (ifElseCounter > 0)
1476  Error(ecMISSING_ELSE_CLAUSE);
1477 
1478  // get the last value (= final result) from the stack
1479  MUP_ASSERT(stArgCount.size() == 1);
1480  m_nFinalResultIdx = stArgCount.top();
1481  if (m_nFinalResultIdx == 0)
1482  Error(ecINTERNAL_ERROR, 9);
1483 
1484  if (stVal.size() == 0)
1485  Error(ecEMPTY_EXPRESSION);
1486 
1487  if (stVal.top().GetType() != tpDBL)
1488  Error(ecSTR_RESULT);
1489 
1490  m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads);
1491  }
1492 
1493  //---------------------------------------------------------------------------
1494  /** \brief One of the two main parse functions.
1495  \sa ParseCmdCode(...)
1496 
1497  Parse expression from input string. Perform syntax checking and create
1498  bytecode. After parsing the string and creating the bytecode the function
1499  pointer #m_pParseFormula will be changed to the second parse routine the
1500  uses bytecode instead of string parsing.
1501  */
1502  value_type ParserBase::ParseString() const
1503  {
1504  try
1505  {
1506  CreateRPN();
1507 
1508  if (m_vRPN.GetSize() == 2)
1509  {
1510  m_pParseFormula = &ParserBase::ParseCmdCodeShort;
1511  }
1512  else
1513  {
1514  m_pParseFormula = &ParserBase::ParseCmdCode;
1515  }
1516 
1517  return (this->*m_pParseFormula)();
1518  }
1519  catch (ParserError& exc)
1520  {
1521  exc.SetFormula(m_pTokenReader->GetExpr());
1522  throw;
1523  }
1524  }
1525 
1526  //---------------------------------------------------------------------------
1527  /** \brief Create an error containing the parse error position.
1528 
1529  This function will create an Parser Exception object containing the error text and
1530  its position.
1531 
1532  \param a_iErrc [in] The error code of type #EErrorCodes.
1533  \param a_iPos [in] The position where the error was detected.
1534  \param a_strTok [in] The token string representation associated with the error.
1535  \throw ParserException always throws that's the only purpose of this function.
1536  */
1537  void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type& a_sTok) const
1538  {
1539  throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
1540  }
1541 
1542  //------------------------------------------------------------------------------
1543  /** \brief Clear all user defined variables.
1544  \throw nothrow
1545 
1546  Resets the parser to string parsing mode by calling #ReInit.
1547  */
1548  void ParserBase::ClearVar()
1549  {
1550  m_VarDef.clear();
1551  ReInit();
1552  }
1553 
1554  //------------------------------------------------------------------------------
1555  /** \brief Remove a variable from internal storage.
1556  \throw nothrow
1557 
1558  Removes a variable if it exists. If the Variable does not exist nothing will be done.
1559  */
1560  void ParserBase::RemoveVar(const string_type& a_strVarName)
1561  {
1562  varmap_type::iterator item = m_VarDef.find(a_strVarName);
1563  if (item != m_VarDef.end())
1564  {
1565  m_VarDef.erase(item);
1566  ReInit();
1567  }
1568  }
1569 
1570  //------------------------------------------------------------------------------
1571  /** \brief Clear all functions.
1572  \post Resets the parser to string parsing mode.
1573  \throw nothrow
1574  */
1575  void ParserBase::ClearFun()
1576  {
1577  m_FunDef.clear();
1578  ReInit();
1579  }
1580 
1581  //------------------------------------------------------------------------------
1582  /** \brief Clear all user defined constants.
1583 
1584  Both numeric and string constants will be removed from the internal storage.
1585  \post Resets the parser to string parsing mode.
1586  \throw nothrow
1587  */
1588  void ParserBase::ClearConst()
1589  {
1590  m_ConstDef.clear();
1591  m_StrVarDef.clear();
1592  ReInit();
1593  }
1594 
1595  //------------------------------------------------------------------------------
1596  /** \brief Clear all user defined postfix operators.
1597  \post Resets the parser to string parsing mode.
1598  \throw nothrow
1599  */
1600  void ParserBase::ClearPostfixOprt()
1601  {
1602  m_PostOprtDef.clear();
1603  ReInit();
1604  }
1605 
1606  //------------------------------------------------------------------------------
1607  /** \brief Clear all user defined binary operators.
1608  \post Resets the parser to string parsing mode.
1609  \throw nothrow
1610  */
1611  void ParserBase::ClearOprt()
1612  {
1613  m_OprtDef.clear();
1614  ReInit();
1615  }
1616 
1617  //------------------------------------------------------------------------------
1618  /** \brief Clear the user defined Prefix operators.
1619  \post Resets the parser to string parser mode.
1620  \throw nothrow
1621  */
1622  void ParserBase::ClearInfixOprt()
1623  {
1624  m_InfixOprtDef.clear();
1625  ReInit();
1626  }
1627 
1628  //------------------------------------------------------------------------------
1629  /** \brief Enable or disable the formula optimization feature.
1630  \post Resets the parser to string parser mode.
1631  \throw nothrow
1632  */
1633  void ParserBase::EnableOptimizer(bool a_bIsOn)
1634  {
1635  m_vRPN.EnableOptimizer(a_bIsOn);
1636  ReInit();
1637  }
1638 
1639  //---------------------------------------------------------------------------
1640  /** \brief Enable the dumping of bytecode and stack content on the console.
1641  \param bDumpCmd Flag to enable dumping of the current bytecode to the console.
1642  \param bDumpStack Flag to enable dumping of the stack content is written to the console.
1643 
1644  This function is for debug purposes only!
1645  */
1646  void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)
1647  {
1648  ParserBase::g_DbgDumpCmdCode = bDumpCmd;
1649  ParserBase::g_DbgDumpStack = bDumpStack;
1650  }
1651 
1652  //------------------------------------------------------------------------------
1653  /** \brief Enable or disable the built in binary operators.
1654  \throw nothrow
1655  \sa m_bBuiltInOp, ReInit()
1656 
1657  If you disable the built in binary operators there will be no binary operators
1658  defined. Thus you must add them manually one by one. It is not possible to
1659  disable built in operators selectively. This function will Reinitialize the
1660  parser by calling ReInit().
1661  */
1662  void ParserBase::EnableBuiltInOprt(bool a_bIsOn)
1663  {
1664  m_bBuiltInOp = a_bIsOn;
1665  ReInit();
1666  }
1667 
1668  //------------------------------------------------------------------------------
1669  /** \brief Query status of built in variables.
1670  \return #m_bBuiltInOp; true if built in operators are enabled.
1671  \throw nothrow
1672  */
1673  bool ParserBase::HasBuiltInOprt() const
1674  {
1675  return m_bBuiltInOp;
1676  }
1677 
1678  //------------------------------------------------------------------------------
1679  /** \brief Get the argument separator character.
1680  */
1681  char_type ParserBase::GetArgSep() const
1682  {
1683  return m_pTokenReader->GetArgSep();
1684  }
1685 
1686  //------------------------------------------------------------------------------
1687  /** \brief Set argument separator.
1688  \param cArgSep the argument separator character.
1689  */
1690  void ParserBase::SetArgSep(char_type cArgSep)
1691  {
1692  m_pTokenReader->SetArgSep(cArgSep);
1693  }
1694 
1695  //------------------------------------------------------------------------------
1696  /** \brief Dump stack content.
1697 
1698  This function is used for debugging only.
1699  */
1700  void ParserBase::StackDump(const std::stack<token_type>& a_stVal, const std::stack<token_type>& a_stOprt) const
1701  {
1702  std::stack<token_type> stOprt(a_stOprt);
1703  std::stack<token_type> stVal(a_stVal);
1704 
1705  mu::console() << _T("\nValue stack:\n");
1706  while (!stVal.empty())
1707  {
1708  token_type val = stVal.top();
1709  stVal.pop();
1710 
1711  if (val.GetType() == tpSTR)
1712  mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");
1713  else
1714  mu::console() << _T(" ") << val.GetVal() << _T(" ");
1715  }
1716  mu::console() << "\nOperator stack:\n";
1717 
1718  while (!stOprt.empty())
1719  {
1720  if (stOprt.top().GetCode() <= cmASSIGN)
1721  {
1722  mu::console() << _T("OPRT_INTRNL \"")
1723  << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
1724  << _T("\" \n");
1725  }
1726  else
1727  {
1728  switch (stOprt.top().GetCode())
1729  {
1730  case cmVAR: mu::console() << _T("VAR\n"); break;
1731  case cmVAL: mu::console() << _T("VAL\n"); break;
1732  case cmFUNC:
1733  mu::console()
1734  << _T("FUNC \"")
1735  << stOprt.top().GetAsString()
1736  << _T("\"\n");
1737  break;
1738 
1739  case cmFUNC_BULK:
1740  mu::console()
1741  << _T("FUNC_BULK \"")
1742  << stOprt.top().GetAsString()
1743  << _T("\"\n");
1744  break;
1745 
1746  case cmOPRT_INFIX:
1747  mu::console() << _T("OPRT_INFIX \"")
1748  << stOprt.top().GetAsString()
1749  << _T("\"\n");
1750  break;
1751 
1752  case cmOPRT_BIN:
1753  mu::console() << _T("OPRT_BIN \"")
1754  << stOprt.top().GetAsString()
1755  << _T("\"\n");
1756  break;
1757 
1758  case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break;
1759  case cmEND: mu::console() << _T("END\n"); break;
1760  case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break;
1761  case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break;
1762  case cmBC: mu::console() << _T("BRACKET \")\"\n"); break;
1763  case cmIF: mu::console() << _T("IF\n"); break;
1764  case cmELSE: mu::console() << _T("ELSE\n"); break;
1765  case cmENDIF: mu::console() << _T("ENDIF\n"); break;
1766  default: mu::console() << stOprt.top().GetCode() << _T(" "); break;
1767  }
1768  }
1769  stOprt.pop();
1770  }
1771 
1772  mu::console() << dec << endl;
1773  }
1774 
1775  /** \brief Calculate the result.
1776 
1777  A note on const correctness:
1778  I consider it important that Calc is a const function.
1779  Due to caching operations Calc changes only the state of internal variables with one exception
1780  m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
1781  Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update.
1782 
1783  \pre A formula must be set.
1784  \pre Variables must have been set (if needed)
1785 
1786  \sa #m_pParseFormula
1787  \return The evaluation result
1788  \throw ParseException if no Formula is set or in case of any other error related to the formula.
1789  */
1790  value_type ParserBase::Eval() const
1791  {
1792  return (this->*m_pParseFormula)();
1793  }
1794 
1795  //------------------------------------------------------------------------------
1796  /** \brief Evaluate an expression containing comma separated subexpressions
1797  \param [out] nStackSize The total number of results available
1798  \return Pointer to the array containing all expression results
1799 
1800  This member function can be used to retrieve all results of an expression
1801  made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)")
1802  */
1803  value_type* ParserBase::Eval(int& nStackSize) const
1804  {
1805  if (m_vRPN.GetSize() > 0)
1806  {
1807  ParseCmdCode();
1808  }
1809  else
1810  {
1811  ParseString();
1812  }
1813 
1814  nStackSize = m_nFinalResultIdx;
1815 
1816  // (for historic reasons the stack starts at position 1)
1817  return &m_vStackBuffer[1];
1818  }
1819 
1820  //---------------------------------------------------------------------------
1821  /** \brief Return the number of results on the calculation stack.
1822 
1823  If the expression contains comma separated subexpressions (i.e. "sin(y), x+y").
1824  There may be more than one return value. This function returns the number of
1825  available results.
1826  */
1827  int ParserBase::GetNumResults() const
1828  {
1829  return m_nFinalResultIdx;
1830  }
1831 
1832  //---------------------------------------------------------------------------
1833  void ParserBase::Eval(value_type* results, int nBulkSize)
1834  {
1835  CreateRPN();
1836 
1837  int i = 0;
1838 
1839 #ifdef MUP_USE_OPENMP
1840  //#define DEBUG_OMP_STUFF
1841 #ifdef DEBUG_OMP_STUFF
1842  int* pThread = new int[nBulkSize];
1843  int* pIdx = new int[nBulkSize];
1844 #endif
1845 
1846  int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
1847  int nThreadID = 0;
1848 
1849 #ifdef DEBUG_OMP_STUFF
1850  int ct = 0;
1851 #endif
1852  omp_set_num_threads(nMaxThreads);
1853 
1854 #pragma omp parallel for schedule(static, std::max(nBulkSize/nMaxThreads, 1)) private(nThreadID)
1855  for (i = 0; i < nBulkSize; ++i)
1856  {
1857  nThreadID = omp_get_thread_num();
1858  results[i] = ParseCmdCodeBulk(i, nThreadID);
1859 
1860 #ifdef DEBUG_OMP_STUFF
1861 #pragma omp critical
1862  {
1863  pThread[ct] = nThreadID;
1864  pIdx[ct] = i;
1865  ct++;
1866  }
1867 #endif
1868  }
1869 
1870 #ifdef DEBUG_OMP_STUFF
1871  FILE* pFile = fopen("bulk_dbg.txt", "w");
1872  for (i = 0; i < nBulkSize; ++i)
1873  {
1874  fprintf(pFile, "idx: %d thread: %d \n", pIdx[i], pThread[i]);
1875  }
1876 
1877  delete[] pIdx;
1878  delete[] pThread;
1879 
1880  fclose(pFile);
1881 #endif
1882 
1883 #else
1884  for (i = 0; i < nBulkSize; ++i)
1885  {
1886  results[i] = ParseCmdCodeBulk(i, 0);
1887  }
1888 #endif
1889 
1890  }
1891 } // namespace mu
1892 
1893 #if defined(_MSC_VER)
1894  #pragma warning(pop)
1895 #endif
1896 
void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true)
Add a user defined operator.
Operator item: closing bracket.
Definition: muParserDef.h:155
code for infix operators
Definition: muParserDef.h:176
void DefineInfixOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of infix operators.
value_type(* strfun_type1)(const char_type *)
Callback type used for functions taking a string as an argument.
Definition: muParserDef.h:397
multiplication/division
Definition: muParserDef.h:216
user defined binary operator
Definition: muParserDef.h:174
#define _T(x)
Activate this option in order to compile with OpenMP support.
Definition: muParserDef.h:69
value_type(* bulkfun_type1)(int, int, value_type)
Callback type used for functions with a single arguments.
Definition: muParserDef.h:364
binary operators may only be applied to value items of the same type
Definition: muParserDef.h:245
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
Definition: muParserDef.h:415
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
void DefineNameChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of functions, variables, constants.
An unexpected comma has been found. (Example: "1,23")
Definition: muParserDef.h:232
void DefineVar(const string_type &a_sName, value_type *a_fVar)
Add a user defined variable.
std::ostream & console()
Encapsulate cout.
Definition: muParserDef.h:115
result is a string
Definition: muParserDef.h:246
An unexpected argument has been found.
Definition: muParserDef.h:233
const funmap_type & GetFunDef() const
Return prototypes of all parser functions.
Throw an exception if the expression has more than 10000 characters. (an arbitrary limit) ...
Definition: muParserDef.h:274
static std::locale s_locale
The locale used by the parser.
Definition: muParserBase.h:187
Postfix operator priority (currently unused)
Definition: muParserDef.h:221
Name conflict.
Definition: muParserDef.h:258
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Definition: muParserDef.h:314
Operator item: y to the power of ...
Definition: muParserDef.h:150
function argument separator
Definition: muParserDef.h:159
Internal error of any kind.
Definition: muParserDef.h:279
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
code for postfix operators
Definition: muParserDef.h:175
Trying to overload builtin operator.
Definition: muParserDef.h:254
static const char_type * c_DefaultOprt[]
Identifiers for built in binary operators.
Definition: muParserBase.h:186
void AddAssignOp(value_type *a_pVar)
Add an assignment operator.
value_type(* bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with eight arguments.
Definition: muParserDef.h:385
Operator item: not equal.
Definition: muParserDef.h:142
void SetVarFactory(facfun_type a_pFactory, void *pUserData=nullptr)
Set a function that can create variable pointer for unknown expression variables. ...
For use in the ternary if-then-else operator.
Definition: muParserDef.h:156
value_type(* fun_type5)(value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
Definition: muParserDef.h:343
value_type(* bulkfun_type2)(int, int, value_type, value_type)
Callback type used for functions with two arguments.
Definition: muParserDef.h:367
value_type(* fun_type1)(value_type)
Callback type used for functions with a single arguments.
Definition: muParserDef.h:331
const char_type * ValidInfixOprtChars() const
Virtual function that defines the characters allowed in infix operator definitions.
void SetArgSep(char_type cArgSep)
Set argument separator.
const char_type * ValidOprtChars() const
Virtual function that defines the characters allowed in operator definitions.
void AddValIdent(identfun_type a_pCallback)
Add a value parsing function.
ParserToken & SetVal(TBase a_fVal, const TString &a_strTok=TString())
Make this token a value token.
STL namespace.
value_type(* strfun_type4)(const char_type *, value_type, value_type, value_type)
Callback type used for functions taking a string and a value as arguments.
Definition: muParserDef.h:406
value_type(* bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with nine arguments.
Definition: muParserDef.h:388
void AddFun(generic_fun_type a_pFun, int a_iArgc)
Add function to bytecode.
end of formula
Definition: muParserDef.h:177
power operator priority (highest)
Definition: muParserDef.h:217
void SetDecSep(char_type cDecSep)
Set the decimal separator.
void ResetLocale()
Resets the locale.
std::basic_stringstream< char_type, std::char_traits< char_type >, std::allocator< char_type > > stringstream_type
Typedef for easily using stringstream that respect the parser stringtype.
Definition: muParserDef.h:309
std::map< string_type, ParserCallback > funmap_type
Container for Callback objects.
value_type(* strfun_type3)(const char_type *, value_type, value_type)
Callback type used for functions taking a string and two values as arguments.
Definition: muParserDef.h:403
void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true)
Add a user defined operator.
void Error(EErrorCodes a_iErrc, int a_iPos=(int) mu::string_type::npos, const string_type &a_strTok=string_type()) const
Create an error containing the parse error position.
value_type(* multfun_type)(const value_type *, int)
Callback type used for functions with a variable argument list.
Definition: muParserDef.h:394
const string_type & GetExpr() const
Retrieve the formula.
Code for a generic function item.
Definition: muParserDef.h:170
EOprtAssociativity
Parser operator precedence values.
Definition: muParserDef.h:199
value_type(* fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with eight arguments.
Definition: muParserDef.h:352
void DefineOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of binary operators and postfix operators...
value_type(* bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with five arguments.
Definition: muParserDef.h:376
value_type(* bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with six arguments.
Definition: muParserDef.h:379
const char_type * ValidNameChars() const
Virtual function that defines the characters allowed in name identifiers.
value_type(* strfun_type5)(const char_type *, value_type, value_type, value_type, value_type)
Callback type used for functions taking a string and two values as arguments.
Definition: muParserDef.h:409
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
Conflict with current locale.
Definition: muParserDef.h:264
void SetThousandsSep(char_type cThousandsSep=0)
Sets the thousands operator.
comparsion operators
Definition: muParserDef.h:214
std::map< string_type, value_type > valmap_type
Type used for storing constants.
Definition: muParserDef.h:317
For use in the ternary if-then-else operator.
Definition: muParserDef.h:157
value_type(* fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with ten arguments.
Definition: muParserDef.h:358
value_type(* fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with nine arguments.
Definition: muParserDef.h:355
const valmap_type & GetConst() const
Return a map containing all parser constants.
Invalid variable pointer.
Definition: muParserDef.h:256
Invalid function, variable or constant name.
Definition: muParserDef.h:249
Operator item: subtract.
Definition: muParserDef.h:147
value_type(* fun_type2)(value_type, value_type)
Callback type used for functions with two arguments.
Definition: muParserDef.h:334
addition
Definition: muParserDef.h:215
void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri=0, EOprtAssociativity a_eAssociativity=oaLEFT, bool a_bAllowOpt=false)
Define a binary operator.
Error class of the parser.
Definition: muParserError.h:68
For use in the ternary if-then-else operator.
Definition: muParserDef.h:158
const varmap_type & GetVar() const
Return a map containing the used variables only.
This file contains the class definition of the muparser engine.
Operator item: multiply.
Definition: muParserDef.h:148
#define MUP_ASSERT(COND)
An assertion that does not kill the program.
Definition: muParserDef.h:77
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:294
A facet class used to change decimal and thousands separator.
Definition: muParserBase.h:193
String type (Function arguments and constants only, no string variables)
Definition: muParserDef.h:185
Operator item: division.
Definition: muParserDef.h:149
void SetExpr(const string_type &a_sExpr)
Set the formula.
The Expression is empty.
Definition: muParserDef.h:257
value_type(* strfun_type2)(const char_type *, value_type)
Callback type used for functions taking a string and a value as arguments.
Definition: muParserDef.h:400
Too many function parameters.
Definition: muParserDef.h:243
Operator item: add.
Definition: muParserDef.h:146
A numerical function has been called with a non value type of argument.
Definition: muParserDef.h:239
Namespace for mathematical applications.
Definition: muParser.cpp:46
Unexpected end of formula. (Example: "2+sin(")
Definition: muParserDef.h:231
Operator item: less than.
Definition: muParserDef.h:144
int(* identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal)
Callback used for functions that identify values in a string.
Definition: muParserDef.h:412
Too few function parameters. (Example: "ite(1<2,2)")
Definition: muParserDef.h:244
string_type GetVersion(EParserVersionInfo eInfo=pviFULL) const
Returns the version of muparser.
A string function has been called with a different type of argument.
Definition: muParserDef.h:238
value item
Definition: muParserDef.h:161
value_type(* fun_type3)(value_type, value_type, value_type)
Callback type used for functions with three arguments.
Definition: muParserDef.h:337
value_type(* fun_type0)()
Callback type used for functions without arguments.
Definition: muParserDef.h:328
Operator item: greater than.
Definition: muParserDef.h:145
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
Definition: muParserDef.h:325
const char_type ** GetOprtDef() const
Get the default symbols used for the built in operators.
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Definition: muParserDef.h:172
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:306
Code for a function with a string parameter.
Definition: muParserDef.h:171
Token reader for the ParserBase class.
Thrown when an identifier with more then 255 characters is used.
Definition: muParserDef.h:272
void * GetAddr() const
Get the callback address for the parser function.
value_type(* bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with seven arguments.
Definition: muParserDef.h:382
ParserBase & operator=(const ParserBase &a_Parser)
Assignment operator.
void DefineConst(const string_type &a_sName, value_type a_fVal)
Add a user defined constant.
Operator item: equals.
Definition: muParserDef.h:143
uninitialized item
Definition: muParserDef.h:178
Operator item: Assignment operator.
Definition: muParserDef.h:153
value_type(* fun_type4)(value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
Definition: muParserDef.h:340
Unexpected binary operator found.
Definition: muParserDef.h:229
MUP_STRING_TYPE string_type
The stringtype used by the parser.
Definition: muParserDef.h:300
ParserBase()
Constructor.
value_type(* fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with seven arguments.
Definition: muParserDef.h:349
void clear()
Delete the bytecode.
Code for a string token.
Definition: muParserDef.h:173
Operator item: less or equal.
Definition: muParserDef.h:140
value_type(* bulkfun_type4)(int, int, value_type, value_type, value_type, value_type)
Callback type used for functions with four arguments.
Definition: muParserDef.h:373
variable item
Definition: muParserDef.h:160
void DefineStrConst(const string_type &a_sName, const string_type &a_strVal)
Define a new string constant.
Invalid function, variable or constant name.
Definition: muParserDef.h:252
Operator item: greater or equal.
Definition: muParserDef.h:141
Invalid callback function pointer.
Definition: muParserDef.h:255
The expression or identifier contains invalid non printable characters.
Definition: muParserDef.h:276
value_type(* bulkfun_type0)(int, int)
Callback type used for functions without arguments.
Definition: muParserDef.h:361
Floating point variables.
Definition: muParserDef.h:186
value_type(* bulkfun_type3)(int, int, value_type, value_type, value_type)
Callback type used for functions with three arguments.
Definition: muParserDef.h:370
EErrorCodes
Error codes.
Definition: muParserDef.h:226
void Init()
Initialize user defined functions.
Encapsulation of prototypes for a numerical parser function.
value_type(* fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with six arguments.
Definition: muParserDef.h:346
Invalid function, variable or constant name.
Definition: muParserDef.h:251
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:63
Operator item: opening bracket.
Definition: muParserDef.h:154
const varmap_type & GetUsedVar() const
Return a map containing the used variables only.
value_type(* bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type)
Callback type used for functions with ten arguments.
Definition: muParserDef.h:391