NCBI C++ ToolKit
muParserTokenReader.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /*
2  __________
3  _____ __ __\______ \_____ _______ ______ ____ _______
4  / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
5  | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
6  |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
7  \/ \/ \/ \/
8  Copyright (C) 2004-2008 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 #include <ncbi_pch.hpp>
26 #include <cassert>
27 #include <cstdio>
28 #include <cstring>
29 #include <map>
30 #include <stack>
31 #include <string>
32 
35 
36 #define wxT(x) MUP_T(x)
37 
38 /** \file
39  \brief This file contains the parser token reader implementation.
40 */
41 
42 
43 namespace mu
44 {
45 
46  // Forward declaration
47  class ParserBase;
48 
49  //---------------------------------------------------------------------------
50  /** \brief Copy constructor.
51 
52  \sa Assign
53  \throw nothrow
54  */
56  {
57  Assign(a_Reader);
58  }
59 
60  //---------------------------------------------------------------------------
61  /** \brief Assignement operator.
62 
63  Self assignement will be suppressed otherwise #Assign is called.
64 
65  \param a_Reader Object to copy to this token reader.
66  \throw nothrow
67  */
69  {
70  if (&a_Reader!=this)
71  Assign(a_Reader);
72 
73  return *this;
74  }
75 
76  //---------------------------------------------------------------------------
77  /** \brief Assign state of a token reader to this token reader.
78 
79  \param a_Reader Object from which the state should be copied.
80  \throw nothrow
81  */
83  {
84  m_pParser = a_Reader.m_pParser;
85  m_strFormula = a_Reader.m_strFormula;
86  m_iPos = a_Reader.m_iPos;
87  m_iSynFlags = a_Reader.m_iSynFlags;
88 
89  m_UsedVar = a_Reader.m_UsedVar;
90  m_pFunDef = a_Reader.m_pFunDef;
91  m_pConstDef = a_Reader.m_pConstDef;
92  m_pVarDef = a_Reader.m_pVarDef;
93  m_pStrVarDef = a_Reader.m_pStrVarDef;
94  m_pPostOprtDef = a_Reader.m_pPostOprtDef;
96  m_pOprtDef = a_Reader.m_pOprtDef;
98  m_vIdentFun = a_Reader.m_vIdentFun;
99  m_pFactory = a_Reader.m_pFactory;
100  m_pFactoryData = a_Reader.m_pFactoryData;
101  m_iBrackets = a_Reader.m_iBrackets;
102  m_cArgSep = a_Reader.m_cArgSep;
103  }
104 
105  //---------------------------------------------------------------------------
106  /** \brief Constructor.
107 
108  Create a Token reader and bind it to a parser object.
109 
110  \pre [assert] a_pParser may not be NULL
111  \post #m_pParser==a_pParser
112  \param a_pParent Parent parser object of the token reader.
113  */
115  :m_pParser(a_pParent)
116  ,m_strFormula()
117  ,m_iPos(0)
118  ,m_iSynFlags(0)
119  ,m_bIgnoreUndefVar(false)
120  ,m_pFunDef(NULL)
121  ,m_pPostOprtDef(NULL)
122  ,m_pInfixOprtDef(NULL)
123  ,m_pOprtDef(NULL)
124  ,m_pConstDef(NULL)
125  ,m_pStrVarDef(NULL)
126  ,m_pVarDef(NULL)
127  ,m_pFactory(NULL)
128  ,m_pFactoryData(NULL)
129  ,m_vIdentFun()
130  ,m_UsedVar()
131  ,m_fZero(0)
132  ,m_iBrackets(0)
133  ,m_lastTok()
134  ,m_cArgSep(',')
135  {
136  assert(m_pParser);
138  }
139 
140  //---------------------------------------------------------------------------
141  /** \brief Create instance of a ParserTokenReader identical with this
142  and return its pointer.
143 
144  This is a factory method the calling function must take care of the object destruction.
145 
146  \return A new ParserTokenReader object.
147  \throw nothrow
148  */
150  {
151  std::unique_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));
152  ptr->SetParent(a_pParent);
153  return ptr.release();
154  }
155 
156  //---------------------------------------------------------------------------
158  {
159  m_lastTok = tok;
160  return m_lastTok;
161  }
162 
163  //---------------------------------------------------------------------------
165  {
166  m_vIdentFun.push_back(a_pCallback);
167  }
168 
169  //---------------------------------------------------------------------------
170  void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)
171  {
172  m_pFactory = a_pFactory;
173  m_pFactoryData = pUserData;
174  }
175 
176  //---------------------------------------------------------------------------
177  /** \brief Return the current position of the token reader in the formula string.
178 
179  \return #m_iPos
180  \throw nothrow
181  */
183  {
184  return m_iPos;
185  }
186 
187  //---------------------------------------------------------------------------
188  /** \brief Return a reference to the formula.
189 
190  \return #m_strFormula
191  \throw nothrow
192  */
194  {
195  return m_strFormula;
196  }
197 
198  //---------------------------------------------------------------------------
199  /** \brief Return a map containing the used variables only. */
201  {
202  return m_UsedVar;
203  }
204 
205  //---------------------------------------------------------------------------
206  /** \brief Initialize the token Reader.
207 
208  Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
209  \pre [assert] triggered if a_szFormula==0
210  */
211  void ParserTokenReader::SetFormula(const string_type &a_strFormula)
212  {
213  m_strFormula = a_strFormula;
214  ReInit();
215  }
216 
217  //---------------------------------------------------------------------------
218  /** \brief Set Flag that contronls behaviour in case of undefined variables beeing found.
219 
220  If true, the parser does not throw an exception if an undefined variable is found.
221  otherwise it does. This variable is used internally only!
222  It supresses a "undefined variable" exception in GetUsedVar().
223  Those function should return a complete list of variables including
224  those the are not defined by the time of it's call.
225  */
227  {
228  m_bIgnoreUndefVar = bIgnore;
229  }
230 
231  //---------------------------------------------------------------------------
232  /** \brief Reset the token reader to the start of the formula.
233 
234  The syntax flags will be reset to a value appropriate for the
235  start of a formula.
236  \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR
237  \throw nothrow
238  \sa ESynCodes
239  */
241  {
242  m_iPos = 0;
244  m_iBrackets = 0;
245  m_UsedVar.clear();
246  m_lastTok = token_type();
247  }
248 
249  //---------------------------------------------------------------------------
250  /** \brief Read the next token from the string. */
252  {
253  assert(m_pParser);
254 
255  std::stack<int> FunArgs;
256  const char_type *szFormula = m_strFormula.c_str();
257  token_type tok;
258 
259  while (szFormula[m_iPos]==' ')
260  ++m_iPos;
261 
262  if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula
263  if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator
264  if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token
265  if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens
266  if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators
267  if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens
268  if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens
269  if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables
270  if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens
271  if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators
272  if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators
273 
274  // Check String for undefined variable token. Done only if a
275  // flag is set indicating to ignore undefined variables.
276  // This is a way to conditionally avoid an error if
277  // undefined variables occur.
278  // The GetUsedVar function must supress the error for
279  // undefined variables in order to collect all variable
280  // names including the undefined ones.
281  if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )
282  return SaveBeforeReturn(tok);
283 
284  // Check for unknown token
285  //
286  // !!! From this point on there is no exit without an exception possible...
287  //
288  string_type strTok;
289  int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
290  if (iEnd!=m_iPos)
292 
294  return token_type(); // never reached
295  }
296 
297  //---------------------------------------------------------------------------
299  {
300  m_pParser = a_pParent;
301  m_pFunDef = &a_pParent->m_FunDef;
302  m_pOprtDef = &a_pParent->m_OprtDef;
303  m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
304  m_pPostOprtDef = &a_pParent->m_PostOprtDef;
305  m_pVarDef = &a_pParent->m_VarDef;
306  m_pStrVarDef = &a_pParent->m_StrVarDef;
307  m_pConstDef = &a_pParent->m_ConstDef;
308  }
309 
310  //---------------------------------------------------------------------------
311  /** \brief Extract all characters that belong to a certain charset.
312 
313  \param a_szCharSet [in] Const char array of the characters allowed in the token.
314  \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.
315  \param a_iPos [in] Position in the string from where to start reading.
316  \return The Position of the first character not listed in a_szCharSet.
317  \throw nothrow
318  */
319  int ParserTokenReader::ExtractToken( const char_type *a_szCharSet,
320  string_type &a_sTok,
321  int a_iPos ) const
322  {
323  int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
324 
325  if (iEnd==(int)string_type::npos)
326  iEnd = (int)m_strFormula.length();
327 
328  a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);
329  a_iPos = iEnd;
330  return iEnd;
331  }
332 
333  //---------------------------------------------------------------------------
334  /** \brief Check if a built in operator or other token can be found
335  \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
336  \return true if an operator token has been found.
337  */
339  {
340  const char_type **const pOprtDef = m_pParser->GetOprtDef(),
341  *const szFormula = m_strFormula.c_str();
342 
343  // Compare token with function and operator strings
344  // check string for operator/function
345  for (int i=0; pOprtDef[i]; i++)
346  {
347  std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
348  if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
349  {
350  switch(i)
351  {
352  case cmAND:
353  case cmOR:
354  case cmXOR:
355  case cmLT:
356  case cmGT:
357  case cmLE:
358  case cmGE:
359  case cmNEQ:
360  case cmEQ:
361  case cmADD:
362  case cmSUB:
363  case cmMUL:
364  case cmDIV:
365  case cmPOW:
366  case cmASSIGN:
367  //if (len!=sTok.length())
368  // continue;
369 
370  // The assignement operator need special treatment
371  if (i==cmASSIGN && m_iSynFlags & noASSIGN)
372  Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
373 
374  if (!m_pParser->HasBuiltInOprt()) continue;
375  if (m_iSynFlags & noOPT)
376  {
377  // Maybe its an infix operator not an operator
378  // Both operator types can share characters in
379  // their identifiers
380  if ( IsInfixOpTok(a_Tok) )
381  return true;
382 
383  Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
384  }
385 
387  m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;
388  break;
389 
390  case cmBO:
391  if (m_iSynFlags & noBO)
392  Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
393 
394  if (m_lastTok.GetCode()==cmFUNC)
396  else
398 
399  ++m_iBrackets;
400  break;
401 
402  case cmBC:
403  if (m_iSynFlags & noBC)
404  Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
405 
407 
408  if (--m_iBrackets<0)
409  Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
410  break;
411 
412  default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
414  } // switch operator id
415 
416  m_iPos += (int)len;
417  a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
418  return true;
419  } // if operator string found
420  } // end of for all operator strings
421 
422  return false;
423  }
424 
425  //---------------------------------------------------------------------------
427  {
428  const char_type* szFormula = m_strFormula.c_str();
429 
430  if (szFormula[m_iPos]==m_cArgSep)
431  {
432  // copy the separator into null terminated string
433  char_type szSep[2];
434  szSep[0] = m_cArgSep;
435  szSep[1] = 0;
436 
437  if (m_iSynFlags & noARG_SEP)
439 
441  m_iPos++;
442  a_Tok.Set(cmARG_SEP, szSep);
443  return true;
444  }
445 
446  return false;
447  }
448 
449  //---------------------------------------------------------------------------
450  /** \brief Check for End of Formula.
451 
452  \return true if an end of formula is found false otherwise.
453  \param a_Tok [out] If an eof is found the corresponding token will be stored there.
454  \throw nothrow
455  \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok
456  */
458  {
459  const char_type* szFormula = m_strFormula.c_str();
460 
461  // check for EOF
462  if ( !szFormula[m_iPos] || szFormula[m_iPos] == '\n')
463  {
464  if ( m_iSynFlags & noEND )
466 
467  if (m_iBrackets>0)
469 
470  m_iSynFlags = 0;
471  a_Tok.Set(cmEND);
472  return true;
473  }
474 
475  return false;
476  }
477 
478  //---------------------------------------------------------------------------
479  /** \brief Check if a string position contains a unary infix operator.
480  \return true if a function token has been found false otherwise.
481  */
483  {
484  string_type sTok;
485  int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);
486  if (iEnd==m_iPos)
487  return false;
488 
489  funmap_type::const_iterator item = m_pInfixOprtDef->find(sTok);
490  if (item==m_pInfixOprtDef->end())
491  return false;
492 
493  a_Tok.Set(item->second, sTok);
494  m_iPos = (int)iEnd;
495 
496  if (m_iSynFlags & noINFIXOP)
498 
500  return true;
501  }
502 
503  //---------------------------------------------------------------------------
504  /** \brief Check whether the token at a given position is a function token.
505  \param a_Tok [out] If a value token is found it will be placed here.
506  \throw ParserException if Syntaxflags do not allow a function at a_iPos
507  \return true if a function token has been found false otherwise.
508  \pre [assert] m_pParser!=0
509  */
511  {
512  string_type strTok;
513  int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
514  if (iEnd==m_iPos)
515  return false;
516 
517  funmap_type::const_iterator item = m_pFunDef->find(strTok);
518  if (item==m_pFunDef->end())
519  return false;
520 
521  a_Tok.Set(item->second, strTok);
522 
523  m_iPos = (int)iEnd;
524  if (m_iSynFlags & noFUN)
525  Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
526 
527  m_iSynFlags = noANY ^ noBO;
528  return true;
529  }
530 
531  //---------------------------------------------------------------------------
532  /** \brief Check if a string position contains a binary operator.
533  \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
534  \return true if an operator token has been found.
535  */
537  {
538  string_type strTok;
539  int iEnd = ExtractToken(m_pParser->ValidOprtChars(), strTok, m_iPos);
540  if (iEnd==m_iPos)
541  return false;
542 
543  funmap_type::const_iterator item = m_pOprtDef->find(strTok);
544  if (item==m_pOprtDef->end())
545  return false;
546 
547  a_Tok.Set(item->second, strTok);
548 
549  if (m_iSynFlags & noOPT)
550  {
551  // An operator was found but is not expected to occur at
552  // this position of the formula, maybe it is an infix
553  // operator, not a binary operator. Both operator types
554  // can share characters in their identifiers.
555  if ( IsInfixOpTok(a_Tok) ) return true;
556  // nope, no infix operator
558  }
559 
560  m_iPos = (int)iEnd;
562  return true;
563  }
564 
565  //---------------------------------------------------------------------------
566  /** \brief Check if a string position contains a unary post value operator. */
568  {
569  // Tricky problem with equations like "3m+5":
570  // m is a postfix operator, + is a valid sign for postfix operators and
571  // for binary operators parser detects "m+" as operator string and
572  // finds no matching postfix operator.
573  //
574  // This is a special case so this routine slightly differs from the other
575  // token readers.
576 
577  // Test if there could be a postfix operator
578  string_type sTok;
579  int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);
580  if (iEnd==m_iPos)
581  return false;
582 
583  // iteraterate over all postfix operator strings
584  funmap_type::const_iterator item = m_pPostOprtDef->begin();
585  for (item=m_pPostOprtDef->begin(); item!=m_pPostOprtDef->end(); ++item)
586  {
587  if (sTok.find(item->first)!=0)
588  continue;
589 
590  a_Tok.Set(item->second, sTok);
591  m_iPos += (int)item->first.length();
592 
593  if (m_iSynFlags & noPOSTOP)
594  Error(ecUNEXPECTED_OPERATOR, m_iPos-(int)item->first.length(), item->first);
595 
597  return true;
598  }
599 
600  return false;
601  }
602 
603  //---------------------------------------------------------------------------
604  /** \brief Check whether the token at a given position is a value token.
605 
606  Value tokens are either values or constants.
607 
608  \param a_Tok [out] If a value token is found it will be placed here.
609  \return true if a value token has been found.
610  */
612  {
614  assert(m_pParser);
615 
616  #if defined(_MSC_VER)
617  #pragma warning( disable : 4244 )
618  #endif
619 
620  string_type strTok;
621  value_type fVal(0);
622  int iEnd(0);
623 
624  // 2.) Check for user defined constant
625  // Read everything that could be a constant name
626  iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
627  if (iEnd!=m_iPos)
628  {
629  valmap_type::const_iterator item = m_pConstDef->find(strTok);
630  if (item!=m_pConstDef->end())
631  {
632  m_iPos = iEnd;
633  a_Tok.SetVal(item->second, strTok);
634 
635  if (m_iSynFlags & noVAL)
636  Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
637 
639  return true;
640  }
641  }
642 
643  // 3.call the value recognition functions provided by the user
644  // Call user defined value recognition functions
645  std::vector<identfun_type>::const_iterator item = m_vIdentFun.begin();
646  for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)
647  {
648  int iStart = m_iPos;
649  if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )
650  {
651  strTok.assign(m_strFormula.c_str(), iStart, m_iPos);
652  if (m_iSynFlags & noVAL)
653  Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
654 
655  a_Tok.SetVal(fVal, strTok);
657  return true;
658  }
659  }
660 
661  return false;
662 
663  #if defined(_MSC_VER)
664  #pragma warning( default : 4244 )
665  #endif
666  }
667 
668  //---------------------------------------------------------------------------
669  /** \brief Check wheter a token at a given position is a variable token.
670  \param a_Tok [out] If a variable token has been found it will be placed here.
671  \return true if a variable token has been found.
672  */
674  {
675  if (!m_pVarDef->size())
676  return false;
677 
678  string_type strTok;
679  int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
680  if (iEnd==m_iPos)
681  return false;
682 
683  varmap_type::const_iterator item = m_pVarDef->find(strTok);
684  if (item==m_pVarDef->end())
685  return false;
686 
687  if (m_iSynFlags & noVAR)
688  Error(ecUNEXPECTED_VAR, m_iPos, strTok);
689 
690  m_iPos = iEnd;
691  a_Tok.SetVar(item->second, strTok);
692  m_UsedVar[item->first] = item->second; // Add variable to used-var-list
693 
695  return true;
696  }
697 
698  //---------------------------------------------------------------------------
700  {
701  if (!m_pStrVarDef || !m_pStrVarDef->size())
702  return false;
703 
704  string_type strTok;
705  int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
706  if (iEnd==m_iPos)
707  return false;
708 
709  strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
710  if (item==m_pStrVarDef->end())
711  return false;
712 
713  if (m_iSynFlags & noSTR)
714  Error(ecUNEXPECTED_VAR, m_iPos, strTok);
715 
716  m_iPos = iEnd;
717  if (!m_pParser->m_vStringVarBuf.size())
719 
720  a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );
721 
723  return true;
724  }
725 
726 
727  //---------------------------------------------------------------------------
728  /** \brief Check wheter a token at a given position is an undefined variable.
729 
730  \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.
731  \return true if a variable token has been found.
732  \throw nothrow
733  */
735  {
736  string_type strTok;
737  int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );
738  if ( iEnd==m_iPos )
739  return false;
740 
741  if (m_iSynFlags & noVAR)
742  {
743  // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the
744  // token identifier.
745  // related bug report:
746  // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979
747  Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
748  }
749 
750  // If a factory is available implicitely create new variables
751  if (m_pFactory)
752  {
753  value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
754  a_Tok.SetVar(fVar, strTok );
755 
756  // Do not use m_pParser->DefineVar( strTok, fVar );
757  // in order to define the new variable, it will clear the
758  // m_UsedVar array which will kill previousely defined variables
759  // from the list
760  // This is safe because the new variable can never override an existing one
761  // because they are checked first!
762  (*m_pVarDef)[strTok] = fVar;
763  m_UsedVar[strTok] = fVar; // Add variable to used-var-list
764  }
765  else
766  {
767  a_Tok.SetVar((value_type*)&m_fZero, strTok);
768  m_UsedVar[strTok] = 0; // Add variable to used-var-list
769  }
770 
771  m_iPos = iEnd;
772 
773  // Call the variable factory in order to let it define a new parser variable
775  return true;
776  }
777 
778 
779  //---------------------------------------------------------------------------
780  /** \brief Check wheter a token at a given position is a string.
781  \param a_Tok [out] If a variable token has been found it will be placed here.
782  \return true if a string token has been found.
783  \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok
784  \throw nothrow
785  */
787  {
788  if (m_strFormula[m_iPos]!='"')
789  return false;
790 
791  string_type strBuf(&m_strFormula[m_iPos+1]);
792  std::size_t iEnd(0), iSkip(0);
793 
794  // parser over escaped '\"' end replace them with '"'
795  for(iEnd=(int)strBuf.find( wxT("\"") ); iEnd!=string_type::npos; iEnd=(int)strBuf.find( wxT("\""), iEnd))
796  {
797  if (strBuf[iEnd-1]!='\\') break;
798  strBuf.replace(iEnd-1, 2, wxT("\"") );
799  iSkip++;
800  }
801 
802  if (iEnd==string_type::npos)
804 
805  string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);
806 
807  if (m_iSynFlags & noSTR)
808  Error(ecUNEXPECTED_STR, m_iPos, strTok);
809 
810  m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
811  a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
812 
813  m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen
815 
816  return true;
817  }
818 
819  //---------------------------------------------------------------------------
820  /** \brief Create an error containing the parse error position.
821 
822  This function will create an Parser Exception object containing the error text and its position.
823 
824  \param a_iErrc [in] The error code of type #EErrorCodes.
825  \param a_iPos [in] The position where the error was detected.
826  \param a_strTok [in] The token string representation associated with the error.
827  \throw ParserException always throws thats the only purpose of this function.
828  */
830  int a_iPos,
831  const string_type &a_sTok) const
832  {
833  m_pParser->Error(a_iErrc, a_iPos, a_sTok);
834  }
835 
836  //---------------------------------------------------------------------------
838  {
839  m_cArgSep = cArgSep;
840  }
841 
842  //---------------------------------------------------------------------------
844  {
845  return m_cArgSep;
846  }
847 } // namespace mu
848 
#define false
Definition: bool.h:36
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:64
varmap_type m_VarDef
user defind variables.
Definition: muParserBase.h:255
const char_type * ValidInfixOprtChars() const
Virtual function that defines the characters allowed in infix operator definitions.
stringbuf_type m_vStringBuf
String buffer, used for storing string function arguments.
Definition: muParserBase.h:244
bool HasBuiltInOprt() const
Query status of built in variables.
const char_type ** GetOprtDef() const
Get the default symbols used for the built in operators.
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.
funmap_type m_InfixOprtDef
unary infix operator.
Definition: muParserBase.h:251
valmap_type m_ConstDef
user constants.
Definition: muParserBase.h:253
const char_type * ValidNameChars() const
Virtual function that defines the characters allowed in name identifiers.
funmap_type m_FunDef
Map of function names and pointers.
Definition: muParserBase.h:249
funmap_type m_PostOprtDef
Postfix operator callbacks.
Definition: muParserBase.h:250
funmap_type m_OprtDef
Binary operator callbacks.
Definition: muParserBase.h:252
const char_type * ValidOprtChars() const
Virtual function that defines the characters allowed in operator definitions.
strmap_type m_StrVarDef
user defined string constants
Definition: muParserBase.h:254
stringbuf_type m_vStringVarBuf
Definition: muParserBase.h:245
Token reader for the ParserBase class.
bool IsArgSep(token_type &a_Tok)
bool IsPostOpTok(token_type &a_Tok)
Check if a string position contains a unary post value operator.
const funmap_type * m_pPostOprtDef
const funmap_type * m_pInfixOprtDef
ParserTokenReader(ParserBase *a_pParent)
Constructor.
bool IsFunTok(token_type &a_Tok)
Check whether the token at a given position is a function token.
bool IsValTok(token_type &a_Tok)
Check whether the token at a given position is a value token.
std::vector< identfun_type > m_vIdentFun
Value token identification function.
token_type ReadNextToken()
Read the next token from the string.
const varmap_type & GetUsedVar() const
Return a map containing the used variables only.
@ noASSIGN
to block assignement to constant i.e. "4=7"
@ noEND
to avoid unexpected end of formula
@ noSTR
to block numeric arguments on string functions
@ noINFIXOP
to avoid i.e. "++4" "!!4"
@ noVAR
to avoid i.e. "sin a" or "sin(8)a"
@ noBO
to avoid i.e. "cos(7)("
@ noOPT
to avoid i.e. "(+)"
@ noANY
All of he above flags set.
@ noVAL
to avoid i.e. "tan 2" or "sin(8)3.14"
@ noPOSTOP
to avoid i.e. "(5!!)" "sin!"
@ noARG_SEP
to avoid i.e. ",," or "+," ...
@ noBC
to avoid i.e. "sin)" or "()"
@ noFUN
to avoid i.e. "sqrt cos" or "(1)sin"
void SetParent(ParserBase *a_pParent)
char_type m_cArgSep
The character used for separating function arguments.
void Assign(const ParserTokenReader &a_Reader)
Assign state of a token reader to this token reader.
bool IsOprt(token_type &a_Tok)
Check if a string position contains a binary operator.
int ExtractToken(const char_type *a_szCharSet, string_type &a_strTok, int a_iPos) const
Extract all characters that belong to a certain charset.
value_type m_fZero
Dummy value of zero, referenced by undefined variables.
void SetArgSep(char_type cArgSep)
const funmap_type * m_pFunDef
ParserTokenReader & operator=(const ParserTokenReader &a_Reader)
Assignement operator.
void Error(EErrorCodes a_iErrc, int a_iPos=-1, const string_type &a_sTok=string_type()) const
Create an error containing the parse error position.
void SetVarCreator(facfun_type a_pFactory, void *pUserData)
void IgnoreUndefVar(bool bIgnore)
Set Flag that contronls behaviour in case of undefined variables beeing found.
const funmap_type * m_pOprtDef
ParserTokenReader * Clone(ParserBase *a_pParent) const
Create instance of a ParserTokenReader identical with this and return its pointer.
bool IsVarTok(token_type &a_Tok)
Check wheter a token at a given position is a variable token.
void SetFormula(const string_type &a_strFormula)
Initialize the token Reader.
bool IsString(token_type &a_Tok)
Check wheter a token at a given position is a string.
int GetPos() const
Return the current position of the token reader in the formula string.
bool IsInfixOpTok(token_type &a_Tok)
Check if a string position contains a unary infix operator.
ParserToken< value_type, string_type > token_type
varmap_type * m_pVarDef
The only non const pointer to parser internals.
const strmap_type * m_pStrVarDef
bool IsEOF(token_type &a_Tok)
Check for End of Formula.
bool IsBuiltIn(token_type &a_Tok)
Check if a built in operator or other token can be found.
void ReInit()
Reset the token reader to the start of the formula.
token_type & SaveBeforeReturn(const token_type &tok)
void AddValIdent(identfun_type a_pCallback)
const string_type & GetFormula() const
Return a reference to the formula.
bool IsStrVarTok(token_type &a_Tok)
bool IsUndefVarTok(token_type &a_Tok)
Check wheter a token at a given position is an undefined variable.
const valmap_type * m_pConstDef
ECmdCode GetCode() const
Return the token type.
ParserToken & SetVal(TBase a_fVal, const TString &a_strTok=TString())
Make this token a value token.
const TString & GetAsString() const
Return the token identifier.
ParserToken & SetVar(TBase *a_pVar, const TString &a_strTok)
make this token a variable token.
ParserToken & Set(ECmdCode a_iType, const TString &a_strTok=TString())
Assign a token type.
ParserToken & SetString(const TString &a_strTok, std::size_t a_iSize)
Make this token a variable token.
#define NULL
Definition: ncbistd.hpp:225
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
int i
int len
This file contains the class definition of the muparser engine.
#define wxT(x)
This file contains the parser token reader definition.
Namespace for mathematical applications.
Definition: muParser.h:41
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:297
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:246
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
Definition: muParserDef.h:300
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Definition: muParserDef.h:256
ECmdCode
Bytecode values.
Definition: muParserDef.h:161
@ cmADD
Operator item: add.
Definition: muParserDef.h:171
@ cmGE
Operator item: greater or equal.
Definition: muParserDef.h:166
@ cmLT
Operator item: less than.
Definition: muParserDef.h:169
@ cmPOW
Operator item: y to the power of ...
Definition: muParserDef.h:175
@ cmASSIGN
Operator item: Assignment operator.
Definition: muParserDef.h:179
@ cmARG_SEP
function argument separator
Definition: muParserDef.h:182
@ cmLE
Operator item: less or equal.
Definition: muParserDef.h:165
@ cmBO
Operator item: opening bracket.
Definition: muParserDef.h:180
@ cmMUL
Operator item: multiply.
Definition: muParserDef.h:173
@ cmEND
end of formula
Definition: muParserDef.h:191
@ cmXOR
Operator item: logical xor.
Definition: muParserDef.h:178
@ cmDIV
Operator item: division.
Definition: muParserDef.h:174
@ cmAND
Operator item: logical and.
Definition: muParserDef.h:176
@ cmBC
Operator item: closing bracket.
Definition: muParserDef.h:181
@ cmOR
Operator item: logical or.
Definition: muParserDef.h:177
@ cmNEQ
Operator item: not equal.
Definition: muParserDef.h:167
@ cmGT
Operator item: greater than.
Definition: muParserDef.h:170
@ cmEQ
Operator item: equals.
Definition: muParserDef.h:168
@ cmSUB
Operator item: subtract.
Definition: muParserDef.h:172
@ cmFUNC
Code for a function item.
Definition: muParserDef.h:185
EErrorCodes
Error codes.
Definition: muParserError.h:47
@ ecUNASSIGNABLE_TOKEN
Token cant be identified.
Definition: muParserError.h:50
@ ecMISSING_PARENS
Missing parens. (Example: "3*sin(3")
Definition: muParserError.h:60
@ ecUNEXPECTED_EOF
Unexpected end of formula. (Example: "2+sin(")
Definition: muParserError.h:51
@ ecUNEXPECTED_VAR
An unexpected variable token has been found.
Definition: muParserError.h:55
@ ecUNEXPECTED_FUN
Unexpected function found. (Example: "sin(8)cos(9)")
Definition: muParserError.h:61
@ ecUNEXPECTED_OPERATOR
Unexpected binary operator found.
Definition: muParserError.h:49
@ ecUNEXPECTED_STR
A string has been found at an inapropriate position.
Definition: muParserError.h:57
@ ecUNEXPECTED_PARENS
Unexpected Parenthesis, opening or closing.
Definition: muParserError.h:56
@ ecINTERNAL_ERROR
Internal error of any kind.
Definition: muParserError.h:83
@ ecUNEXPECTED_ARG_SEP
An unexpected comma has been found. (Example: "1,23")
Definition: muParserError.h:52
@ ecUNTERMINATED_STRING
unterminated string constant. (Example: "3*valueof("hello)")
Definition: muParserError.h:62
@ ecUNEXPECTED_VAL
An unexpected value token has been found.
Definition: muParserError.h:54
double value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:228
std::string string_type
The stringtype used by the parser.
Definition: muParserDef.h:234
#define assert(x)
Definition: srv_diag.hpp:58
Modified on Wed Dec 06 07:15:21 2023 by modify_doxy.py rev. 669887