NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
muParserTokenReader.cpp
Go to the documentation of this file.
1/*
2 __________
3 _____ __ __\______ \_____ _______ ______ ____ _______
4 / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
5 | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
6 |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
7 \/ \/ \/ \/
8 Copyright (C) 2012 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 <cassert>
26#include <cstdio>
27#include <cstring>
28#include <map>
29#include <stack>
30#include <string>
31
32#include "muParserTokenReader.h"
33#include "muParserBase.h"
34
40namespace mu
41{
42
43 // Forward declaration
44 class ParserBase;
45
46 //---------------------------------------------------------------------------
53 {
54 Assign(a_Reader);
55 }
56
57 //---------------------------------------------------------------------------
66 {
67 if (&a_Reader != this)
68 Assign(a_Reader);
69
70 return *this;
71 }
72
73 //---------------------------------------------------------------------------
80 {
81 m_pParser = a_Reader.m_pParser;
82 m_strFormula = a_Reader.m_strFormula;
83 m_iPos = a_Reader.m_iPos;
84 m_iSynFlags = a_Reader.m_iSynFlags;
85
86 m_UsedVar = a_Reader.m_UsedVar;
87 m_pFunDef = a_Reader.m_pFunDef;
88 m_pConstDef = a_Reader.m_pConstDef;
89 m_pVarDef = a_Reader.m_pVarDef;
90 m_pStrVarDef = a_Reader.m_pStrVarDef;
93 m_pOprtDef = a_Reader.m_pOprtDef;
95 m_vIdentFun = a_Reader.m_vIdentFun;
96 m_pFactory = a_Reader.m_pFactory;
98 m_iBrackets = a_Reader.m_iBrackets;
99 m_cArgSep = a_Reader.m_cArgSep;
100 }
101
102 //---------------------------------------------------------------------------
112 : m_pParser(a_pParent)
113 , m_strFormula()
114 , m_iPos(0)
115 , m_iSynFlags(0)
116 , m_bIgnoreUndefVar(false)
117 , m_pFunDef(NULL)
118 , m_pPostOprtDef(NULL)
119 , m_pInfixOprtDef(NULL)
120 , m_pOprtDef(NULL)
121 , m_pConstDef(NULL)
122 , m_pStrVarDef(NULL)
123 , m_pVarDef(NULL)
124 , m_pFactory(NULL)
125 , m_pFactoryData(NULL)
126 , m_vIdentFun()
127 , m_UsedVar()
128 , m_fZero(0)
129 , m_iBrackets(0)
130 , m_lastTok()
131 , m_cArgSep(',')
132 {
133 assert(m_pParser);
135 }
136
137 //---------------------------------------------------------------------------
147 {
148 std::unique_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));
149 ptr->SetParent(a_pParent);
150 return ptr.release();
151 }
152
153 //---------------------------------------------------------------------------
155 {
156 m_lastTok = tok;
157 return m_lastTok;
158 }
159
160 //---------------------------------------------------------------------------
162 {
163 // Use push_front is used to give user defined callbacks a higher priority than
164 // the built in ones. Otherwise reading hex numbers would not work
165 // since the "0" in "0xff" would always be read first making parsing of
166 // the rest impossible.
167 // reference:
168 // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956
169 m_vIdentFun.push_front(a_pCallback);
170 }
171
172 //---------------------------------------------------------------------------
173 void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void* pUserData)
174 {
175 m_pFactory = a_pFactory;
176 m_pFactoryData = pUserData;
177 }
178
179 //---------------------------------------------------------------------------
186 {
187 return m_iPos;
188 }
189
190 //---------------------------------------------------------------------------
197 {
198 return m_strFormula;
199 }
200
201 //---------------------------------------------------------------------------
204 {
205 return m_UsedVar;
206 }
207
208 //---------------------------------------------------------------------------
215 {
216 m_strFormula = a_strFormula;
217 ReInit();
218 }
219
220 //---------------------------------------------------------------------------
230 {
231 m_bIgnoreUndefVar = bIgnore;
232 }
233
234 //---------------------------------------------------------------------------
244 {
245 m_iPos = 0;
247 m_iBrackets = 0;
248 m_UsedVar.clear();
250 }
251
252 //---------------------------------------------------------------------------
255 {
256 assert(m_pParser);
257
258 std::stack<int> FunArgs;
259 const char_type* szFormula = m_strFormula.c_str();
260 token_type tok;
262
263 // Ignore all non printable characters when reading the expression
264 while (szFormula[m_iPos] > 0 && szFormula[m_iPos] <= 0x20)
265 ++m_iPos;
266
267 if ( IsEOF(tok) )
268 return SaveBeforeReturn(tok); // Check for end of formula
269 if ( IsOprt(tok) )
270 return SaveBeforeReturn(tok); // Check for user defined binary operator
271 if ( IsFunTok(tok) )
272 return SaveBeforeReturn(tok); // Check for function token
273 if ( IsBuiltIn(tok) )
274 return SaveBeforeReturn(tok); // Check built in operators / tokens
275 if ( IsArgSep(tok) )
276 return SaveBeforeReturn(tok); // Check for function argument separators
277 if ( IsValTok(tok) )
278 return SaveBeforeReturn(tok); // Check for values / constant tokens
279 if ( IsVarTok(tok) )
280 return SaveBeforeReturn(tok); // Check for variable tokens
281 if ( IsStrVarTok(tok) )
282 return SaveBeforeReturn(tok); // Check for string variables
283 if ( IsString(tok) )
284 return SaveBeforeReturn(tok); // Check for String tokens
285 if (IsInfixOpTok(tok))
286 return SaveBeforeReturn(tok); // Check for unary operators
287 if ( IsPostOpTok(tok) )
288 return SaveBeforeReturn(tok); // Check for unary operators
289
290 // Check String for undefined variable token. Done only if a
291 // flag is set indicating to ignore undefined variables.
292 // This is a way to conditionally avoid an error if
293 // undefined variables occur.
294 // (The GetUsedVar function must suppress the error for
295 // undefined variables in order to collect all variable
296 // names including the undefined ones.)
297 if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )
298 return SaveBeforeReturn(tok);
299
300 // Check for unknown token
301 //
302 // !!! From this point on there is no exit without an exception possible...
303 //
304 string_type strTok;
305 int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
306 if (iEnd != m_iPos)
308
310 return token_type(); // never reached
311 }
312
313 //---------------------------------------------------------------------------
315 {
316 m_pParser = a_pParent;
317 m_pFunDef = &a_pParent->m_FunDef;
318 m_pOprtDef = &a_pParent->m_OprtDef;
319 m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
320 m_pPostOprtDef = &a_pParent->m_PostOprtDef;
321 m_pVarDef = &a_pParent->m_VarDef;
322 m_pStrVarDef = &a_pParent->m_StrVarDef;
323 m_pConstDef = &a_pParent->m_ConstDef;
324 }
325
326 //---------------------------------------------------------------------------
336 string_type& a_sTok,
337 int a_iPos) const
338 {
339 int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
340
341 if (iEnd == (int)string_type::npos)
342 iEnd = (int)m_strFormula.length();
343
344 // Assign token string if there was something found
345 if (a_iPos != iEnd)
346 a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
347
348 return iEnd;
349 }
350
351 //---------------------------------------------------------------------------
360 int a_iPos) const
361 {
362 int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidInfixOprtChars(), a_iPos);
363 if (iEnd == (int)string_type::npos)
364 iEnd = (int)m_strFormula.length();
365
366 // Assign token string if there was something found
367 if (a_iPos != iEnd)
368 {
369 a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
370 return iEnd;
371 }
372 else
373 {
374 // There is still the chance of having to deal with an operator consisting exclusively
375 // of alphabetic characters.
376 return ExtractToken(MUP_CHARS, a_sTok, a_iPos);
377 }
378 }
379
380 //---------------------------------------------------------------------------
386 {
387 const char_type** const pOprtDef = m_pParser->GetOprtDef(),
388 *const szFormula = m_strFormula.c_str();
389
390 // Compare token with function and operator strings
391 // check string for operator/function
392 for (int i = 0; pOprtDef[i]; i++)
393 {
394 std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
395 if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
396 {
397 switch (i)
398 {
399 //case cmAND:
400 //case cmOR:
401 //case cmXOR:
402 case cmLAND:
403 case cmLOR:
404 case cmLT:
405 case cmGT:
406 case cmLE:
407 case cmGE:
408 case cmNEQ:
409 case cmEQ:
410 case cmADD:
411 case cmSUB:
412 case cmMUL:
413 case cmDIV:
414 case cmPOW:
415 case cmASSIGN:
416 //if (len!=sTok.length())
417 // continue;
418
419 // The assignement operator need special treatment
420 if (i == cmASSIGN && m_iSynFlags & noASSIGN)
421 Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
422
424 continue;
425 if (m_iSynFlags & noOPT)
426 {
427 // Maybe its an infix operator not an operator
428 // Both operator types can share characters in
429 // their identifiers
430 if ( IsInfixOpTok(a_Tok) )
431 return true;
432
433 Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
434 }
435
437 m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;
438 break;
439
440 case cmBO:
441 if (m_iSynFlags & noBO)
442 Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
443
444 if (m_lastTok.GetCode() == cmFUNC)
446 else
448
449 ++m_iBrackets;
450 break;
451
452 case cmBC:
453 if (m_iSynFlags & noBC)
454 Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
455
457
458 if (--m_iBrackets < 0)
459 Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
460 break;
461
462 case cmELSE:
463 if (m_iSynFlags & noELSE)
465
467 break;
468
469 case cmIF:
470 if (m_iSynFlags & noIF)
472
474 break;
475
476 default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
478 } // switch operator id
479
480 m_iPos += (int)len;
481 a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
482 return true;
483 } // if operator string found
484 } // end of for all operator strings
485
486 return false;
487 }
488
489 //---------------------------------------------------------------------------
491 {
492 const char_type* szFormula = m_strFormula.c_str();
493
494 if (szFormula[m_iPos] == m_cArgSep)
495 {
496 // copy the separator into null terminated string
497 char_type szSep[2];
498 szSep[0] = m_cArgSep;
499 szSep[1] = 0;
500
503
505 m_iPos++;
506 a_Tok.Set(cmARG_SEP, szSep);
507 return true;
508 }
509
510 return false;
511 }
512
513 //---------------------------------------------------------------------------
522 {
523 const char_type* szFormula = m_strFormula.c_str();
524
525 // check for EOF
526 if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)
527 {
528 if ( m_iSynFlags & noEND )
530
531 if (m_iBrackets > 0)
533
534 m_iSynFlags = 0;
535 a_Tok.Set(cmEND);
536 return true;
537 }
538
539 return false;
540 }
541
542 //---------------------------------------------------------------------------
547 {
549 return false;
550
551 string_type sTok;
552 int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);
553 if (iEnd == m_iPos)
554 return false;
555
556 // iteraterate over all postfix operator strings
557 funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();
558 for ( ; it != m_pInfixOprtDef->rend(); ++it)
559 {
560 if (sTok.find(it->first) != 0)
561 continue;
562
563 a_Tok.Set(it->second, it->first);
564 m_iPos += (int)it->first.length();
565
568
570 return true;
571 }
572
573 return false;
574
575 /*
576 a_Tok.Set(item->second, sTok);
577 m_iPos = (int)iEnd;
578
579 if (m_iSynFlags & noINFIXOP)
580 Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
581
582 m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
583 return true;
584 */
585 }
586
587 //---------------------------------------------------------------------------
595 {
596 string_type strTok;
597 int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
598 if (iEnd == m_iPos)
599 return false;
600
601 funmap_type::const_iterator item = m_pFunDef->find(strTok);
602 if (item == m_pFunDef->end())
603 return false;
604
605 // Check if the next sign is an opening bracket
606 const char_type* szFormula = m_strFormula.c_str();
607 if (szFormula[iEnd] != '(')
608 return false;
609
610 a_Tok.Set(item->second, strTok);
611
612 m_iPos = (int)iEnd;
613 if (m_iSynFlags & noFUN)
614 Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
615
617 return true;
618 }
619
620 //---------------------------------------------------------------------------
626 {
627 const char_type* const szExpr = m_strFormula.c_str();
628 string_type strTok;
629
630 int iEnd = ExtractOperatorToken(strTok, m_iPos);
631 if (iEnd == m_iPos)
632 return false;
633
634 // Check if the operator is a built in operator, if so ignore it here
635 const char_type** const pOprtDef = m_pParser->GetOprtDef();
636 for (int i = 0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)
637 {
638 if (string_type(pOprtDef[i]) == strTok)
639 return false;
640 }
641
642 // Note:
643 // All tokens in oprt_bin_maptype are have been sorted by their length
644 // Long operators must come first! Otherwise short names (like: "add") that
645 // are part of long token names (like: "add123") will be found instead
646 // of the long ones.
647 // Length sorting is done with ascending length so we use a reverse iterator here.
648 funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
649 for ( ; it != m_pOprtDef->rend(); ++it)
650 {
651 const string_type& sID = it->first;
652 if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )
653 {
654 a_Tok.Set(it->second, strTok);
655
656 // operator was found
657 if (m_iSynFlags & noOPT)
658 {
659 // An operator was found but is not expected to occur at
660 // this position of the formula, maybe it is an infix
661 // operator, not a binary operator. Both operator types
662 // can share characters in their identifiers.
663 if ( IsInfixOpTok(a_Tok) )
664 return true;
665 else
666 {
667 // nope, no infix operator
668 return false;
669 //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
670 }
671
672 }
673
674 m_iPos += (int)sID.length();
676 return true;
677 }
678 }
679
680 return false;
681 }
682
683 //---------------------------------------------------------------------------
686 {
687 // <ibg 20110629> Do not check for postfix operators if they are not allowed at
688 // the current expression index.
689 //
690 // This will fix the bug reported here:
691 //
692 // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979
693 //
694 if (m_iSynFlags & noPOSTOP)
695 return false;
696 // </ibg>
697
698 // Tricky problem with equations like "3m+5":
699 // m is a postfix operator, + is a valid sign for postfix operators and
700 // for binary operators parser detects "m+" as operator string and
701 // finds no matching postfix operator.
702 //
703 // This is a special case so this routine slightly differs from the other
704 // token readers.
705
706 // Test if there could be a postfix operator
707 string_type sTok;
708 int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);
709 if (iEnd == m_iPos)
710 return false;
711
712 // iteraterate over all postfix operator strings
713 funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();
714 for ( ; it != m_pPostOprtDef->rend(); ++it)
715 {
716 if (sTok.find(it->first) != 0)
717 continue;
718
719 a_Tok.Set(it->second, sTok);
720 m_iPos += (int)it->first.length();
721
723 return true;
724 }
725
726 return false;
727 }
728
729 //---------------------------------------------------------------------------
738 {
739 assert(m_pConstDef);
740 assert(m_pParser);
741
742 string_type strTok;
743 value_type fVal(0);
744 int iEnd(0);
745
746 // 2.) Check for user defined constant
747 // Read everything that could be a constant name
748 iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
749 if (iEnd != m_iPos)
750 {
751 valmap_type::const_iterator item = m_pConstDef->find(strTok);
752 if (item != m_pConstDef->end())
753 {
754 m_iPos = iEnd;
755 a_Tok.SetVal(item->second, strTok);
756
757 if (m_iSynFlags & noVAL)
758 Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
759
761 return true;
762 }
763 }
764
765 // 3.call the value recognition functions provided by the user
766 // Call user defined value recognition functions
767 std::list<identfun_type>::const_iterator item = m_vIdentFun.begin();
768 for (item = m_vIdentFun.begin(); item != m_vIdentFun.end(); ++item)
769 {
770 int iStart = m_iPos;
771 if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal) == 1 )
772 {
773 strTok.assign(m_strFormula.c_str(), iStart, m_iPos);
774 if (m_iSynFlags & noVAL)
775 Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
776
777 a_Tok.SetVal(fVal, strTok);
779 return true;
780 }
781 }
782
783 return false;
784 }
785
786 //---------------------------------------------------------------------------
792 {
793 if (!m_pVarDef->size())
794 return false;
795
796 string_type strTok;
797 int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
798 if (iEnd == m_iPos)
799 return false;
800
801 varmap_type::const_iterator item = m_pVarDef->find(strTok);
802 if (item == m_pVarDef->end())
803 return false;
804
805 if (m_iSynFlags & noVAR)
806 {
807 if (m_pPostOprtDef->find(strTok) != m_pPostOprtDef->end())
808 return false;
809
810 Error(ecUNEXPECTED_VAR, m_iPos, strTok);
811 }
812
814
815 m_iPos = iEnd;
816 a_Tok.SetVar(item->second, strTok);
817 m_UsedVar[item->first] = item->second; // Add variable to used-var-list
818
820
821// Zur Info hier die SynFlags von IsVal():
822// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
823 return true;
824 }
825
826 //---------------------------------------------------------------------------
828 {
829 if (!m_pStrVarDef || !m_pStrVarDef->size())
830 return false;
831
832 string_type strTok;
833 int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
834 if (iEnd == m_iPos)
835 return false;
836
837 strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
838 if (item == m_pStrVarDef->end())
839 return false;
840
841 if (m_iSynFlags & noSTR)
842 Error(ecUNEXPECTED_VAR, m_iPos, strTok);
843
844 m_iPos = iEnd;
845 if (!m_pParser->m_vStringVarBuf.size())
847
848 a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );
849
851 return true;
852 }
853
854
855 //---------------------------------------------------------------------------
863 {
864 string_type strTok;
865 int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );
866 if ( iEnd == m_iPos )
867 return false;
868
869 if (m_iSynFlags & noVAR)
870 {
871 // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the
872 // token identifier.
873 // related bug report:
874 // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979
875 Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
876 }
877
878 // If a factory is available implicitely create new variables
879 if (m_pFactory)
880 {
881 value_type* fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
882 a_Tok.SetVar(fVar, strTok );
883
884 // Do not use m_pParser->DefineVar( strTok, fVar );
885 // in order to define the new variable, it will clear the
886 // m_UsedVar array which will kill previousely defined variables
887 // from the list
888 // This is safe because the new variable can never override an existing one
889 // because they are checked first!
890 (*m_pVarDef)[strTok] = fVar;
891 m_UsedVar[strTok] = fVar; // Add variable to used-var-list
892 }
893 else
894 {
895 a_Tok.SetVar((value_type*)&m_fZero, strTok);
896 m_UsedVar[strTok] = 0; // Add variable to used-var-list
897 }
898
899 m_iPos = iEnd;
900
901 // Call the variable factory in order to let it define a new parser variable
903 return true;
904 }
905
906
907 //---------------------------------------------------------------------------
915 {
916 if (m_strFormula[m_iPos] != '"')
917 return false;
918
919 string_type strBuf(&m_strFormula[m_iPos + 1]);
920 std::size_t iEnd(0), iSkip(0);
921
922 // parser over escaped '\"' end replace them with '"'
923 for (iEnd = (int)strBuf.find( _nrT("\"") ); iEnd != 0 && iEnd != string_type::npos; iEnd = (int)strBuf.find( _nrT("\""), iEnd))
924 {
925 if (strBuf[iEnd - 1] != '\\')
926 break;
927 strBuf.replace(iEnd - 1, 2, _nrT("\"") );
928 iSkip++;
929 }
930
931 if (iEnd == string_type::npos)
933
934 string_type strTok(strBuf.begin(), strBuf.begin() + iEnd);
935
936 if (m_iSynFlags & noSTR)
937 Error(ecUNEXPECTED_STR, m_iPos, strTok);
938
939 m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
940 a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
941
942 m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen
944
945 return true;
946 }
947
948 //---------------------------------------------------------------------------
959 int a_iPos,
960 const string_type& a_sTok) const
961 {
962 m_pParser->Error(a_iErrc, a_iPos, a_sTok);
963 }
964
965 //---------------------------------------------------------------------------
967 {
968 m_cArgSep = cArgSep;
969 }
970
971 //---------------------------------------------------------------------------
973 {
974 return m_cArgSep;
975 }
976} // namespace mu
977
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:69
varmap_type m_VarDef
user defind variables.
Definition: muParserBase.h:362
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:351
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:358
valmap_type m_ConstDef
user constants.
Definition: muParserBase.h:360
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:356
funmap_type m_PostOprtDef
Postfix operator callbacks.
Definition: muParserBase.h:357
funmap_type m_OprtDef
Binary operator callbacks.
Definition: muParserBase.h:359
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd)
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:361
stringbuf_type m_vStringVarBuf
Definition: muParserBase.h:352
ECmdCode GetCode() const
Return the token type.
ParserToken & SetString(const TString &a_strTok, std::size_t a_iSize)
Make this token a variable token.
ParserToken & SetVar(TBase *a_pVar, const TString &a_strTok)
make this token a variable token.
ParserToken & SetVal(TBase a_fVal, const TString &a_strTok=TString())
Make this token a value token.
ParserToken & Set(ECmdCode a_iType, const TString &a_strTok=TString())
Assign a token type.
const TString & GetAsString() const
Return the token identifier.
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
std::list< identfun_type > m_vIdentFun
Value token identification function.
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.
token_type ReadNextToken()
Read the next token from the string.
@ 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
int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const
Check Expression for the presence of a binary operator token.
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)
varmap_type & GetUsedVar()
Return a map containing the used variables only.
void AddValIdent(identfun_type a_pCallback)
bool IsStrVarTok(token_type &a_Tok)
const string_type & GetExpr() const
Return a reference to the formula.
bool IsUndefVarTok(token_type &a_Tok)
Check wheter a token at a given position is an undefined variable.
const valmap_type * m_pConstDef
This file contains the class definition of the muparser engine.
#define _nrT(x)
Activate this option in order to compile with OpenMP support.
Definition: muParserDef.h:62
#define MUP_CHARS
Definition: muParserDef.h:44
This file contains the parser token reader definition.
Namespace for mathematical applications.
Definition: muParser.cpp:53
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:368
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
Definition: muParserDef.h:371
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:263
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Definition: muParserDef.h:273
ECmdCode
Bytecode values.
Definition: muParserDef.h:153
@ cmADD
Operator item: add.
Definition: muParserDef.h:163
@ cmGE
Operator item: greater or equal.
Definition: muParserDef.h:158
@ cmLT
Operator item: less than.
Definition: muParserDef.h:161
@ cmPOW
Operator item: y to the power of ...
Definition: muParserDef.h:167
@ cmASSIGN
Operator item: Assignment operator.
Definition: muParserDef.h:170
@ cmLAND
Definition: muParserDef.h:168
@ cmARG_SEP
function argument separator
Definition: muParserDef.h:176
@ cmLE
Operator item: less or equal.
Definition: muParserDef.h:157
@ cmBO
Operator item: opening bracket.
Definition: muParserDef.h:171
@ cmMUL
Operator item: multiply.
Definition: muParserDef.h:165
@ cmEND
end of formula
Definition: muParserDef.h:196
@ cmDIV
Operator item: division.
Definition: muParserDef.h:166
@ cmLOR
Definition: muParserDef.h:169
@ cmBC
Operator item: closing bracket.
Definition: muParserDef.h:172
@ cmVAL
value item
Definition: muParserDef.h:177
@ cmIF
For use in the ternary if-then-else operator.
Definition: muParserDef.h:173
@ cmNEQ
Operator item: not equal.
Definition: muParserDef.h:159
@ cmGT
Operator item: greater than.
Definition: muParserDef.h:162
@ cmEQ
Operator item: equals.
Definition: muParserDef.h:160
@ cmSUB
Operator item: subtract.
Definition: muParserDef.h:164
@ cmFUNC
Code for a generic function item.
Definition: muParserDef.h:189
@ cmELSE
For use in the ternary if-then-else operator.
Definition: muParserDef.h:174
@ cmVAR
variable item
Definition: muParserDef.h:180
EErrorCodes
Error codes.
Definition: muParserError.h:50
@ ecUNASSIGNABLE_TOKEN
Token cant be identified.
Definition: muParserError.h:53
@ ecMISSING_PARENS
Missing parens. (Example: "3*sin(3")
Definition: muParserError.h:63
@ ecUNEXPECTED_EOF
Unexpected end of formula. (Example: "2+sin(")
Definition: muParserError.h:54
@ ecUNEXPECTED_VAR
An unexpected variable token has been found.
Definition: muParserError.h:58
@ ecUNEXPECTED_FUN
Unexpected function found. (Example: "sin(8)cos(9)")
Definition: muParserError.h:64
@ ecUNEXPECTED_OPERATOR
Unexpected binary operator found.
Definition: muParserError.h:52
@ ecUNEXPECTED_STR
A string has been found at an inapropriate position.
Definition: muParserError.h:60
@ ecUNEXPECTED_PARENS
Unexpected Parenthesis, opening or closing.
Definition: muParserError.h:59
@ ecINTERNAL_ERROR
Internal error of any kind.
Definition: muParserError.h:94
@ ecUNEXPECTED_ARG_SEP
An unexpected comma has been found. (Example: "1,23")
Definition: muParserError.h:55
@ ecUNTERMINATED_STRING
unterminated string constant. (Example: "3*valueof("hello)")
Definition: muParserError.h:65
@ ecUNEXPECTED_CONDITIONAL
Definition: muParserError.h:89
@ ecUNEXPECTED_VAL
An unexpected value token has been found.
Definition: muParserError.h:57
std::string string_type
The stringtype used by the parser.
Definition: muParserDef.h:257