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