NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
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"
28#include "../../kernel.hpp"
29#include "../utils/stringtools.hpp"
30#include "../structures.hpp"
31
32//--- Standard includes ------------------------------------------------------------------------
33#include <cassert>
34#include <cmath>
35#include <memory>
36#include <vector>
37#include <deque>
38#include <sstream>
39#include <locale>
40#include <omp.h>
41
42using namespace std;
43
44unsigned int getMatchingParenthesis(const StringView&);
59
60
61
62
70namespace mu
71{
72 std::vector<double> real(const std::vector<value_type>& vVec)
73 {
74 std::vector<double> vReal;
75
76 for (const auto& val : vVec)
77 vReal.push_back(val.real());
78
79 return vReal;
80 }
81
82
83 std::vector<double> imag(const std::vector<value_type>& vVec)
84 {
85 std::vector<double> vImag;
86
87 for (const auto& val : vVec)
88 vImag.push_back(val.imag());
89
90 return vImag;
91 }
92
93
95 {
96 return value_type(std::rint(v.real()), std::rint(v.imag()));
97 }
98
99
109 std::vector<value_type> parser_logtoidx(const value_type* v, int n)
110 {
111 std::vector<value_type> vIdx;
112
113 for (int i = 0; i < n; i++)
114 {
115 if (v[i] != 0.0)
116 vIdx.push_back(i+1);
117 }
118
119 if (!vIdx.size())
120 vIdx.push_back(0.0);
121
122 return vIdx;
123 }
124
125
135 std::vector<value_type> parser_idxtolog(const value_type* v, int n)
136 {
137 if (!n)
138 return std::vector<value_type>(1, 0.0);
139
140 value_type maxIdx = parser_Max(v, n);
141
142 if (std::isnan(maxIdx.real()))
143 return std::vector<value_type>(1, 0.0);
144
145 std::vector<value_type> vLogical(maxIdx.real(), 0.0);
146
147 for (int i = 0; i < n; i++)
148 {
149 if (v[i].real() > 0)
150 vLogical[v[i].real()-1] = 1.0;
151 }
152
153 return vLogical;
154 }
155
156
157
168 inline value_type operator*(const value_type& __x, const value_type& __y)
169 {
170 if (__x.imag() == 0.0)
171 return value_type(__y.real()*__x.real(), __y.imag()*__x.real());
172 else if (__y.imag() == 0.0)
173 return value_type(__x.real()*__y.real(), __x.imag()*__y.real());
174
175 value_type __r = __x;
176 __r *= __y;
177 return __r;
178 }
179
180
190 inline value_type operator/(const value_type& __x, const value_type& __y)
191 {
192 if (__y.imag() == 0.0)
193 return value_type(__x.real() / __y.real(), __x.imag() / __y.real());
194
195 value_type __r = __x;
196 __r /= __y;
197 return __r;
198 }
199
200
201
202 std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep<char_type>('.'));
203
204 bool ParserBase::g_DbgDumpCmdCode = false;
205 bool ParserBase::g_DbgDumpStack = false;
206
207 //------------------------------------------------------------------------------
214 {
215 _nrT("<="), _nrT(">="), _nrT("!="),
216 _nrT("=="), _nrT("<"), _nrT(">"),
217 _nrT("+"), _nrT("-"), _nrT("*"),
218 _nrT("/"), _nrT("^"), _nrT("&&"),
219 _nrT("||"), _nrT("="), _nrT("("),
220 _nrT(")"), _nrT("?"), _nrT(":"), 0
221 };
222
223 //------------------------------------------------------------------------------
228 : m_pParseFormula(&ParserBase::ParseString)
229 , m_compilingState()
230 , m_vStringBuf()
231 , m_pTokenReader()
232 , m_FunDef()
233 , m_PostOprtDef()
234 , m_InfixOprtDef()
235 , m_OprtDef()
236 , m_ConstDef()
237 , m_StrVarDef()
238 , m_VarDef()
239 , m_bBuiltInOp(true)
240 , m_sNameChars()
241 , m_sOprtChars()
242 , m_sInfixOprtChars()
243 , m_nIfElseCounter(0)
244 {
246 nthLoopElement = 0;
249 bMakeLoopByteCode = false;
250 bPauseLoopByteCode = false;
251 bPauseLock = false;
253 nMaxThreads = omp_get_max_threads();// std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
254
255 mVarMapPntr = nullptr;
256 }
257
258 //---------------------------------------------------------------------------
265 : m_pParseFormula(&ParserBase::ParseString)
266 , m_compilingState()
267 , m_vStringBuf()
268 , m_pTokenReader()
269 , m_FunDef()
270 , m_PostOprtDef()
271 , m_InfixOprtDef()
272 , m_OprtDef()
273 , m_ConstDef()
274 , m_StrVarDef()
275 , m_VarDef()
276 , m_bBuiltInOp(true)
277 , m_sNameChars()
278 , m_sOprtChars()
279 , m_sInfixOprtChars()
280 , m_nIfElseCounter(0)
281 {
282 m_pTokenReader.reset(new token_reader_type(this));
283 nthLoopElement = 0;
284 bMakeLoopByteCode = false;
285 bPauseLoopByteCode = false;
286 bPauseLock = false;
288 nMaxThreads = omp_get_max_threads(); //std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
289
290 mVarMapPntr = nullptr;
291
292 Assign(a_Parser);
293 }
294
295 //---------------------------------------------------------------------------
297 {
298 for (auto iter = m_lDataStorage.begin(); iter != m_lDataStorage.end(); ++iter)
299 delete *iter;
300 }
301
302 //---------------------------------------------------------------------------
311 {
312 Assign(a_Parser);
313 return *this;
314 }
315
316 //---------------------------------------------------------------------------
325 void ParserBase::Assign(const ParserBase& a_Parser)
326 {
327 if (&a_Parser == this)
328 return;
329
330 // Don't copy bytecode instead cause the parser to create new bytecode
331 // by resetting the parse function.
332 ReInit();
333
334 m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants
335 m_VarDef = a_Parser.m_VarDef; // Copy user defined variables
336 m_bBuiltInOp = a_Parser.m_bBuiltInOp;
337 m_vStringBuf = a_Parser.m_vStringBuf;
339 m_StrVarDef = a_Parser.m_StrVarDef;
342 m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));
343
344 // Copy function and operator callbacks
345 m_FunDef = a_Parser.m_FunDef; // Copy function definitions
346 m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators
347 m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation
348 m_OprtDef = a_Parser.m_OprtDef; // binary operators
349
350 m_sNameChars = a_Parser.m_sNameChars;
351 m_sOprtChars = a_Parser.m_sOprtChars;
353 }
354
355 //---------------------------------------------------------------------------
364 {
365 char_type cThousandsSep = std::use_facet< change_dec_sep<char_type> >(s_locale).thousands_sep();
366 s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
367 }
368
369 //---------------------------------------------------------------------------
378 {
379 char_type cDecSep = std::use_facet< change_dec_sep<char_type> >(s_locale).decimal_point();
380 s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>(cDecSep, cThousandsSep));
381 }
382
383 //---------------------------------------------------------------------------
390 {
391 s_locale = std::locale(std::locale("C"), new change_dec_sep<char_type>('.'));
392 SetArgSep(',');
393 }
394
395 //---------------------------------------------------------------------------
405 {
406 m_pTokenReader.reset(new token_reader_type(this));
407 }
408
409 //---------------------------------------------------------------------------
416 {
418 m_vStringBuf.clear();
420 m_pTokenReader->ReInit();
422 }
423
432 {
434 return m_stateStacks[nthLoopElement].m_target;
435
436 return m_compilingTarget;
437 }
438
439 //---------------------------------------------------------------------------
440 void ParserBase::OnDetectVar(string_type* pExpr, int& nStart, int& nEnd)
441 {
442 if (mVectorVars.size())
443 {
444 if (mVectorVars.find(pExpr->substr(nStart, nEnd - nStart)) != mVectorVars.end())
445 return;
446
447 std::vector<mu::value_type> vVar;
448
449 if (GetVar().find(pExpr->substr(nStart, nEnd - nStart)) != GetVar().end())
450 vVar.push_back(*(GetVar().find(pExpr->substr(nStart, nEnd - nStart))->second));
451 else
452 vVar.push_back(0.0);
453
454 SetVectorVar(pExpr->substr(nStart, nEnd - nStart), vVar);
455 }
456 }
457
458 //---------------------------------------------------------------------------
467 {
468 string_type sCompileTimeSettings;
469
471
472 ss << MUP_VERSION;
473
474 if (eInfo == pviFULL)
475 {
476 ss << _nrT(" (") << MUP_VERSION_DATE;
477 ss << std::dec << _nrT("; ") << sizeof(void*) * 8 << _nrT("BIT");
478
479#ifdef _DEBUG
480 ss << _nrT("; DEBUG");
481#else
482 ss << _nrT("; RELEASE");
483#endif
484
485#ifdef _UNICODE
486 ss << _nrT("; UNICODE");
487#else
488#ifdef _MBCS
489 ss << _nrT("; MBCS");
490#else
491 ss << _nrT("; ASCII");
492#endif
493#endif
494
495#ifdef MUP_USE_OPENMP
496 ss << _nrT("; OPENMP");
497//#else
498// ss << _nrT("; NO_OPENMP");
499#endif
500
501#if defined(MUP_MATH_EXCEPTIONS)
502 ss << _nrT("; MATHEXC");
503//#else
504// ss << _nrT("; NO_MATHEXC");
505#endif
506
507 ss << _nrT(")");
508 }
509
510 return ss.str();
511 }
512
513 //---------------------------------------------------------------------------
521 {
522 m_pTokenReader->AddValIdent(a_pCallback);
523 }
524
525 //---------------------------------------------------------------------------
530 void ParserBase::SetVarFactory(facfun_type a_pFactory, void* pUserData)
531 {
532 m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
533 }
534
535 //---------------------------------------------------------------------------
537 void ParserBase::AddCallback( const string_type& a_strName,
538 const ParserCallback& a_Callback,
539 funmap_type& a_Storage,
540 const char_type* a_szCharSet )
541 {
542 if (a_Callback.GetAddr() == 0)
544
545 const funmap_type* pFunMap = &a_Storage;
546
547 // Check for conflicting operator or function names
548 if ( pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end() )
549 Error(ecNAME_CONFLICT, -1, a_strName);
550
551 if ( pFunMap != &m_PostOprtDef && pFunMap != &m_InfixOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end() )
552 Error(ecNAME_CONFLICT, -1, a_strName);
553
554 if ( pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && pFunMap != &m_PostOprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end() )
555 Error(ecNAME_CONFLICT, -1, a_strName);
556
557 if ( pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end() )
558 Error(ecNAME_CONFLICT, -1, a_strName);
559
560 CheckOprt(a_strName, a_Callback, a_szCharSet);
561 a_Storage[a_strName] = a_Callback;
562 ReInit();
563 }
564
565 //---------------------------------------------------------------------------
571 const ParserCallback& a_Callback,
572 const string_type& a_szCharSet) const
573 {
574 if ( !a_sName.length() ||
575 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
576 (a_sName[0] >= '0' && a_sName[0] <= '9'))
577 {
578 switch (a_Callback.GetCode())
579 {
580 case cmOPRT_POSTFIX:
581 Error(ecINVALID_POSTFIX_IDENT, -1, a_sName);
582 case cmOPRT_INFIX:
583 Error(ecINVALID_INFIX_IDENT, -1, a_sName);
584 default:
585 Error(ecINVALID_NAME, -1, a_sName);
586 }
587 }
588 }
589
590 //---------------------------------------------------------------------------
596 const string_type& a_szCharSet) const
597 {
598 if ( !a_sName.length() ||
599 (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) ||
600 (a_sName[0] >= '0' && a_sName[0] <= '9'))
601 {
603 }
604 }
605
606
617 {
618 string_type st;
619
620 // Perform the pre-evaluation of the vectors first
621 if (a_sExpr.find_first_of("{}") != string::npos || ContainsVectorVars(a_sExpr, true))
622 {
623 st = a_sExpr.to_string();
624 a_sExpr = compileVectors(st);
625
626 if (a_sExpr.find_first_of("{}") != string::npos)
627 Error(ecMISSING_PARENS, a_sExpr.to_string(), a_sExpr.find_first_of("{}"), "{}");
628 }
629
630 // Now check, whether the pre-evaluated formula was already parsed into the bytecode
631 // -> Return, if that is true
632 // -> Invalidate the bytecode for this formula, if necessary
633 if (IsAlreadyParsed(a_sExpr))
634 return;
635 else if (bMakeLoopByteCode
637 && this->GetExpr().length()
638 && m_state->m_valid)
639 m_state->m_valid = 0;
640
641 string_type sBuf(a_sExpr.to_string() + " ");
642
643 if (mVarMapPntr)
644 replaceLocalVars(sBuf);
645
646 // Pass the formula to the token reader
647 m_pTokenReader->SetFormula(sBuf);
648
649 // Re-initialize the parser
650 ReInit();
651 }
652
653
665 {
666 std::vector<mu::value_type> vResults;
667
668 // Resolve vectors, which are part of a multi-argument
669 // function's parentheses
670 for (auto iter = mVectorVars.begin(); iter != mVectorVars.end(); ++iter)
671 {
672 size_t match = 0;
673
674 if (iter->second.size() == 1)
675 continue;
676
677 while ((match = sExpr.find(iter->first, match)) != string::npos)
678 {
679 if (!match || checkDelimiter(sExpr.subview(match-1, iter->first.length()+2)))
680 compileVectorsInMultiArgFunc(sExpr, match);
681
682 match++;
683 }
684 }
685
686 // Walk through the whole expression
687 for (size_t i = 0; i < sExpr.length(); i++)
688 {
689 // search for vector parentheses
690 if (sExpr[i] == '{' && (!i || isDelimiter(sExpr[i-1])) && sExpr.find('}', i) != string::npos)
691 {
692 if (compileVectorsInMultiArgFunc(sExpr, i))
693 continue;
694
695 vResults.clear();
696
697 // Find the matching brace for the current vector brace
698 size_t j = getMatchingParenthesis(sExpr.subview(i));
699
700 if (j != std::string::npos)
701 j += i; // if one is found, add the current position
702
703 if (i+1 == j) // This is an empty brace
704 sExpr.replace(i, 2, "nan");
705 else if (j != std::string::npos && sExpr.subview(i, j - i).find(':') != std::string::npos)
706 {
707 // This is vector expansion: e.g. "{1:10}"
708 // Store the result in a new temporary vector
709 string sVectorVarName = CreateTempVectorVar(vResults);
710
711 // Get the expression and evaluate the expansion
712 compileVectorExpansion(sExpr.subview(i + 1, j - i - 1), sVectorVarName);
713
714 sExpr.replace(i, j + 1 - i, sVectorVarName + " "); // Whitespace for constructs like {a:b}i
715 }
716 else
717 {
718 if (j != std::string::npos)
719 {
720 // This is a normal vector, e.g. "{1,2,3}"
721 // Set the sub expression and evaluate it
722 SetExpr(sExpr.subview(i + 1, j - i - 1));
723
724 // Determine, whether the current vector is a target vector or not
725 if (sExpr.find_first_not_of(' ') == i
726 && sExpr.find('=', j) != std::string::npos
727 && sExpr.find('=', j) < sExpr.length() - 1
728 && sExpr.find('!', j) != sExpr.find('=', j) - 1
729 && sExpr.find('<', j) != sExpr.find('=', j) - 1
730 && sExpr.find('>', j) != sExpr.find('=', j) - 1
731 && sExpr[sExpr.find('=', j) + 1] != '=')
732 {
733 // This is a target vector
734 int nResults;
735 value_type* v = Eval(nResults);
736 // Store the results in the target vector
737 vResults.insert(vResults.end(), v, v+nResults);
738 // Store the variable names
739 getTarget().create(sExpr.subview(i + 1, j - i - 1), m_pTokenReader->GetUsedVar());
740 SetVectorVar("_~TRGTVCT[~]", vResults);
741 sExpr.replace(i, j + 1 - i, "_~TRGTVCT[~]");
742 }
743 else
744 {
745 // This is a usual vector
746 // Create a new temporary vector name
747 std::string sVectorVarName = CreateTempVectorVar(vResults);
748 m_compilingState.m_vectEval.create(sVectorVarName);
749 int nResults;
750 // Calculate and store the results in the target vector
751 Eval(nResults);
752 // Update the expression
753 sExpr.replace(i, j + 1 - i, sVectorVarName + " "); // Whitespace for constructs like {a,b}i
754 }
755 }
756 }
757 }
758
759 if (sExpr.subview(i, 9) == "logtoidx(" || sExpr.subview(i, 9) == "idxtolog(")
760 {
761 i += 8;
763 }
764 }
765
766 return sExpr;
767 }
768
769
779 void ParserBase::compileVectorExpansion(MutableStringView sSubExpr, const std::string& sVectorVarName)
780 {
781 int nResults = 0;
782
784 std::vector<int> vComponentType;
785 std::string sCompiledExpression;
786 const int SINGLETON = 1;
787
788 // Determine the type of every part of the vector brace
789 for (size_t n = 0; n < args.size(); n++)
790 {
791 if (args[n].find(':') == std::string::npos)
792 {
793 vComponentType.push_back(SINGLETON);
794
795 if (sCompiledExpression.length())
796 sCompiledExpression += ",";
797
798 sCompiledExpression += args[n].to_string();
799 }
800 else
801 {
802 int isExpansion = -1;
803 MutableStringView sExpansion = args[n].make_mutable();
804
805 // Replace the colons with commas. But ensure that this is not a conditional statement
806 for (size_t i = 0; i < sExpansion.length(); i++)
807 {
808 if (sExpansion[i] == '(' || sExpansion[i] == '[' || sExpansion[i] == '{')
809 i += getMatchingParenthesis(sSubExpr.subview(i));
810
811 if (sExpansion[i] == ':')
812 {
813 if (isExpansion == -1)
814 isExpansion = 1;
815
816 // This is a conditional operator
817 if (isExpansion == 0)
818 continue;
819
820 sExpansion[i] = ',';
821 }
822
823 // This is a conditional operator
824 if (sExpansion[i] == '?')
825 {
826 if (isExpansion == -1)
827 isExpansion = 0;
828
829 if (isExpansion == 1)
830 throw ParserError(ecUNEXPECTED_CONDITIONAL, "?", sExpansion.to_string(), i);
831 }
832 }
833
834 if (sCompiledExpression.length())
835 sCompiledExpression += ",";
836
837 sCompiledExpression += sExpansion.to_string();
838 vComponentType.push_back(getAllArguments(sExpansion).size());
839 }
840 }
841
842 // Evaluate
843 SetExpr(sCompiledExpression);
844 m_compilingState.m_vectEval.create(sVectorVarName, vComponentType);
845 Eval(nResults);
846 }
847
848
860 static bool stepIsStillPossible(const mu::value_type& current, const mu::value_type& last, const mu::value_type& d)
861 {
862 mu::value_type fact(d.real() >= 0.0 ? 1.0 : -1.0, d.imag() >= 0.0 ? 1.0 : -1.0);
863
864 return (current.real() * fact.real()) <= (last.real() * fact.real())
865 && (current.imag() * fact.imag()) <= (last.imag() * fact.imag());
866 }
867
868
881 void ParserBase::expandVector(mu::value_type dFirst, const mu::value_type& dLast, const mu::value_type& dIncrement, vector<mu::value_type>& vResults)
882 {
883 // ignore impossible combinations. Store only
884 // the accessible value
885 if ((dFirst.real() < dLast.real() && dIncrement.real() < 0)
886 || (dFirst.imag() < dLast.imag() && dIncrement.imag() < 0)
887 || (dFirst.real() > dLast.real() && dIncrement.real() > 0)
888 || (dFirst.imag() > dLast.imag() && dIncrement.imag() > 0)
889 || dIncrement == 0.0)
890 {
891 vResults.push_back(dFirst);
892 return;
893 }
894
895 // Store the first value
896 vResults.push_back(dFirst);
897
898 // As long as the next step is possible, add the increment
899 while (stepIsStillPossible(dFirst+dIncrement, dLast+1e-10*dIncrement, dIncrement))
900 {
901 dFirst += dIncrement;
902 vResults.push_back(dFirst);
903 }
904 }
905
906
919 {
920 string sMultiArgFunc;
921 // Try to find a multi-argument function. The size_t will store the start position of the function name
922 size_t nMultiArgParens = FindMultiArgFunc(sExpr, nPos, sMultiArgFunc);
923
924 if (nMultiArgParens != std::string::npos)
925 {
926 // This is part of a multi-argument function
927 // Find the matching parenthesis for the multi-argument function
928 size_t nClosingParens = getMatchingParenthesis(sExpr.subview(nMultiArgParens)) + nMultiArgParens;
929
930 // Set the argument of the function as expression and evaluate it recursively
931 vector<mu::value_type> vResults;
932 int nResults;
933 string sVectorVarName = CreateTempVectorVar(vResults);
934 SetExpr(sExpr.subview(nMultiArgParens + 1, nClosingParens - nMultiArgParens - 1));
935 m_compilingState.m_vectEval.create(sVectorVarName, sMultiArgFunc);
936 Eval(nResults);
937
938 // Store the result in a new temporary vector
939 sExpr.replace(nMultiArgParens - sMultiArgFunc.length(),
940 nClosingParens - nMultiArgParens + 1 + sMultiArgFunc.length(),
941 sVectorVarName);
942
943 // Set the position to the start of the multi-argument
944 // function to avoid jumping over consecutive vectors
945 nPos = nMultiArgParens-sMultiArgFunc.length();
946
947 return true;
948 }
949
950 return false;
951 }
952
953
967 size_t ParserBase::FindMultiArgFunc(StringView sExpr, size_t nPos, std::string& sMultArgFunc)
968 {
969 // Walk through the expression
970 for (int i = nPos; i >= 2; i--)
971 {
972 // If there's a parenthesis and the character before is alphabetic
973 if (sExpr[i] == '(' && isalpha(sExpr[i - 1]))
974 {
975 // Get the matching parenthesis
976 size_t nParPos = getMatchingParenthesis(sExpr.subview(i));
977
978 if (nParPos == string::npos)
979 return std::string::npos;
980 else
981 nParPos += i;
982
983 // Ignore all results before nPos
984 if (nParPos < nPos)
985 continue;
986
987 // Find the last character before the alphabetic part
988 size_t nSep = sExpr.find_last_of(" +-*/(=:?&|<>!%{^", i - 1) + 1;
989 // Extract the function
990 std::string sFunc = sExpr.subview(nSep, i - nSep).to_string();
991
992 // Exclude the following functions
993 if (sFunc == "polynomial" || sFunc == "perlin")
994 continue;
995 else if (sFunc == "logtoidx" || sFunc == "idxtolog")
996 {
997 sMultArgFunc = sFunc;
998 return i;
999 }
1000
1001 // Compare the function with the set of known multi-argument functions
1002 auto iter = m_FunDef.find(sFunc);
1003
1004 if (iter != m_FunDef.end() && iter->second.GetArgc() == -1)
1005 {
1006 // If the function is a multi-argument function, store it and return the position
1007 sMultArgFunc = sFunc;
1008 return i;
1009 }
1010 }
1011 }
1012
1013 // Return string::npos if nothing was found
1014 return std::string::npos;
1015 }
1016
1017 //---------------------------------------------------------------------------
1022 {
1023 return (const char_type**)(&c_DefaultOprt[0]);
1024 }
1025
1026 //---------------------------------------------------------------------------
1031 {
1032 m_sNameChars = a_szCharset;
1033 }
1034
1035 //---------------------------------------------------------------------------
1040 {
1041 m_sOprtChars = a_szCharset;
1042 }
1043
1044 //---------------------------------------------------------------------------
1049 {
1050 m_sInfixOprtChars = a_szCharset;
1051 }
1052
1053 //---------------------------------------------------------------------------
1058 {
1059 assert(m_sNameChars.size());
1060 return m_sNameChars.c_str();
1061 }
1062
1063 //---------------------------------------------------------------------------
1068 {
1069 assert(m_sOprtChars.size());
1070 return m_sOprtChars.c_str();
1071 }
1072
1073 //---------------------------------------------------------------------------
1078 {
1079 assert(m_sInfixOprtChars.size());
1080 return m_sInfixOprtChars.c_str();
1081 }
1082
1083 //---------------------------------------------------------------------------
1088 fun_type1 a_pFun,
1089 bool optimizeAway)
1090 {
1091 AddCallback(a_sName,
1092 ParserCallback(a_pFun, optimizeAway, prPOSTFIX, cmOPRT_POSTFIX),
1094 ValidOprtChars() );
1095 }
1096
1097 //---------------------------------------------------------------------------
1103 {
1104 InitCharSets();
1105 InitFun();
1106 InitConst();
1107 InitOprt();
1108 }
1109
1110 //---------------------------------------------------------------------------
1120 fun_type1 a_pFun,
1121 int a_iPrec,
1122 bool optimizeAway)
1123 {
1124 AddCallback(a_sName,
1125 ParserCallback(a_pFun, optimizeAway, a_iPrec, cmOPRT_INFIX),
1128 }
1129
1130
1131 //---------------------------------------------------------------------------
1142 fun_type2 a_pFun,
1143 unsigned a_iPrec,
1144 EOprtAssociativity a_eAssociativity,
1145 bool optimizeAway )
1146 {
1147 // Check for conflicts with built in operator names
1148 for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i)
1149 if (a_sName == string_type(c_DefaultOprt[i]))
1150 Error(ecBUILTIN_OVERLOAD, -1, a_sName);
1151
1152 AddCallback(a_sName,
1153 ParserCallback(a_pFun, optimizeAway, a_iPrec, a_eAssociativity),
1154 m_OprtDef,
1155 ValidOprtChars() );
1156 }
1157
1158 //---------------------------------------------------------------------------
1163 void ParserBase::DefineStrConst(const string_type& a_strName, const string_type& a_strVal)
1164 {
1165 // Test if a constant with that names already exists
1166 if (m_StrVarDef.find(a_strName) != m_StrVarDef.end())
1168
1169 CheckName(a_strName, ValidNameChars());
1170
1171 m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer
1172 m_StrVarDef[a_strName] = m_vStringBuf.size(); // bind buffer index to variable name
1173
1174 ReInit();
1175 }
1176
1177 //---------------------------------------------------------------------------
1184 void ParserBase::DefineVar(const string_type& a_sName, value_type* a_pVar)
1185 {
1186 if (a_pVar == 0)
1188
1189 // Test if a constant with that names already exists
1190 if (m_ConstDef.find(a_sName) != m_ConstDef.end())
1192
1193 CheckName(a_sName, ValidNameChars());
1194
1195 bool makeReInit = false;
1196
1197 if (m_VarDef.find(a_sName) != m_VarDef.end())
1198 makeReInit = true;
1199
1200 m_VarDef[a_sName] = a_pVar;
1201
1202 if (makeReInit)
1203 ReInit();
1204 }
1205
1206 //---------------------------------------------------------------------------
1214 {
1215 CheckName(a_sName, ValidNameChars());
1216 m_ConstDef[a_sName] = a_fVal;
1217 ReInit();
1218 }
1219
1220 //---------------------------------------------------------------------------
1225 {
1226 switch (a_Tok.GetCode())
1227 {
1228 // built in operators
1229 case cmEND:
1230 return -5;
1231 case cmARG_SEP:
1232 return -4;
1233 case cmASSIGN:
1234 return -1;
1235 case cmELSE:
1236 case cmIF:
1237 return 0;
1238 case cmLAND:
1239 return prLAND;
1240 case cmLOR:
1241 return prLOR;
1242 case cmLT:
1243 case cmGT:
1244 case cmLE:
1245 case cmGE:
1246 case cmNEQ:
1247 case cmEQ:
1248 return prCMP;
1249 case cmADD:
1250 case cmSUB:
1251 return prADD_SUB;
1252 case cmMUL:
1253 case cmDIV:
1254 return prMUL_DIV;
1255 case cmPOW:
1256 return prPOW;
1257
1258 // user defined binary operators
1259 case cmOPRT_INFIX:
1260 case cmOPRT_BIN:
1261 return a_Tok.GetPri();
1262 default:
1264 return 999;
1265 }
1266 }
1267
1268 //---------------------------------------------------------------------------
1273 {
1274 switch (a_Tok.GetCode())
1275 {
1276 case cmASSIGN:
1277 case cmLAND:
1278 case cmLOR:
1279 case cmLT:
1280 case cmGT:
1281 case cmLE:
1282 case cmGE:
1283 case cmNEQ:
1284 case cmEQ:
1285 case cmADD:
1286 case cmSUB:
1287 case cmMUL:
1288 case cmDIV:
1289 return oaLEFT;
1290 case cmPOW:
1291 return oaRIGHT;
1292 case cmOPRT_BIN:
1293 return a_Tok.GetAssociativity();
1294 default:
1295 return oaNONE;
1296 }
1297 }
1298
1299 //---------------------------------------------------------------------------
1302 {
1303 /*try
1304 {
1305 m_pTokenReader->IgnoreUndefVar(true);
1306 CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it
1307 // may contain references to nonexisting variables.
1308 m_pParseFormula = &ParserBase::ParseString;
1309 m_pTokenReader->IgnoreUndefVar(false);
1310 }
1311 catch (exception_type& e)
1312 {
1313 // Make sure to stay in string parse mode, dont call ReInit()
1314 // because it deletes the array with the used variables
1315 m_pParseFormula = &ParserBase::ParseString;
1316 m_pTokenReader->IgnoreUndefVar(false);
1317 throw;
1318 }*/
1319
1320 return m_pTokenReader->GetUsedVar();
1321 }
1322
1323 //---------------------------------------------------------------------------
1326 {
1327 return m_VarDef;
1328 }
1329
1330 //---------------------------------------------------------------------------
1333 {
1334 return m_ConstDef;
1335 }
1336
1337 //---------------------------------------------------------------------------
1349 {
1350 return m_FunDef;
1351 }
1352
1353 const std::map<std::string, std::vector<mu::value_type> >& ParserBase::GetVectors() const
1354 {
1355 for (auto iter = mVectorVars.begin(); iter != mVectorVars.end(); ++iter)
1356 {
1357 if (m_VarDef.find(iter->first) != m_VarDef.end()) // FIX needed because both maps do not have to be identical
1358 iter->second[0] = *(m_VarDef.find(iter->first)->second);
1359 }
1360
1361 return mVectorVars;
1362 }
1363
1364 //---------------------------------------------------------------------------
1367 {
1368 if (g_DbgDumpStack)
1369 NumeReKernel::print("Current Eq: \"" + m_state->m_expr + "\"");
1370
1371 return m_state->m_expr;
1372 }
1373
1374 //---------------------------------------------------------------------------
1380 const std::vector<token_type>& a_vArg) const
1381 {
1382 if (a_vArg.back().GetCode() != cmSTRING)
1383 Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
1384
1385 token_type valTok;
1386 generic_fun_type pFunc = a_FunTok.GetFuncAddr();
1387 assert(pFunc);
1388
1389 try
1390 {
1391 // Collect the function arguments from the value stack
1392 switch (a_FunTok.GetArgCount())
1393 {
1394 case 0:
1395 valTok.SetVal( ((strfun_type1)pFunc)(a_vArg[0].GetAsString().c_str()) );
1396 break;
1397 case 1:
1398 valTok.SetVal( ((strfun_type2)pFunc)(a_vArg[1].GetAsString().c_str(),
1399 a_vArg[0].GetVal()) );
1400 break;
1401 case 2:
1402 valTok.SetVal( ((strfun_type3)pFunc)(a_vArg[2].GetAsString().c_str(),
1403 a_vArg[1].GetVal(),
1404 a_vArg[0].GetVal()) );
1405 break;
1406 default:
1408 }
1409 }
1410 catch (ParserError& /*e*/)
1411 {
1412 Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
1413 }
1414
1415 // string functions won't be optimized
1416 m_compilingState.m_byteCode.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
1417
1418 return valTok;
1419 }
1420
1421 //---------------------------------------------------------------------------
1429 ParserStack<token_type>& a_stVal,
1430 int a_iArgCount) const
1431 {
1432 assert(m_pTokenReader.get());
1433
1434 // Operator stack empty or does not contain tokens with callback functions
1435 if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0 )
1436 return;
1437
1438 token_type funTok = a_stOpt.pop();
1439 assert(funTok.GetFuncAddr());
1440
1441 // Binary operators must rely on their internal operator number
1442 // since counting of operators relies on commas for function arguments
1443 // binary operators do not have commas in their expression
1444 int iArgCount = (funTok.GetCode() == cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount;
1445
1446 // determine how many parameters the function needs. To remember iArgCount includes the
1447 // string parameter whilst GetArgCount() counts only numeric parameters.
1448 int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() == tpSTR) ? 1 : 0);
1449
1450 // Thats the number of numerical parameters
1451 int iArgNumerical = iArgCount - ((funTok.GetType() == tpSTR) ? 1 : 0);
1452
1453 if (funTok.GetCode() == cmFUNC_STR && iArgCount - iArgNumerical > 1)
1455
1456 if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired)
1457 Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
1458
1459 if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired )
1460 Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
1461
1462 if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired )
1463 Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString());
1464
1465 // Collect the numeric function arguments from the value stack and store them
1466 // in a vector
1467 std::vector<token_type> stArg;
1468 for (int i = 0; i < iArgNumerical; ++i)
1469 {
1470 stArg.push_back( a_stVal.pop() );
1471 if ( stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR )
1472 Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
1473 }
1474
1475 switch (funTok.GetCode())
1476 {
1477 case cmFUNC_STR:
1478 stArg.push_back(a_stVal.pop());
1479
1480 if ( stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR )
1481 Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
1482
1483 ApplyStrFunc(funTok, stArg);
1484 break;
1485
1486 case cmFUNC_BULK:
1487 m_compilingState.m_byteCode.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size());
1488 break;
1489
1490 case cmOPRT_BIN:
1491 case cmOPRT_POSTFIX:
1492 case cmOPRT_INFIX:
1493 case cmFUNC:
1494 if (funTok.GetArgCount() == -1 && iArgCount == 0)
1495 Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString());
1496
1498 (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical,
1499 funTok.IsOptimizable());
1500 break;
1501 default:
1502 break;
1503 // nothing, just avoiding warnings
1504 }
1505
1506 // Push dummy value representing the function result to the stack
1507 token_type token;
1508 token.SetVal(1);
1509 a_stVal.push(token);
1510 }
1511
1512 //---------------------------------------------------------------------------
1514 ParserStack<token_type>& a_stVal) const
1515 {
1516 // Check if there is an if Else clause to be calculated
1517 while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE)
1518 {
1519 token_type opElse = a_stOpt.pop();
1520 MUP_ASSERT(a_stOpt.size() > 0);
1521
1522 // Take the value associated with the else branch from the value stack
1523 token_type vVal2 = a_stVal.pop();
1524
1525 MUP_ASSERT(a_stOpt.size() > 0);
1526 MUP_ASSERT(a_stVal.size() >= 2);
1527
1528 // it then else is a ternary operator Pop all three values from the value s
1529 // tack and just return the right value
1530 token_type vVal1 = a_stVal.pop();
1531 token_type vExpr = a_stVal.pop();
1532
1533 a_stVal.push( (vExpr.GetVal() != 0.0) ? vVal1 : vVal2);
1534
1535 token_type opIf = a_stOpt.pop();
1536 MUP_ASSERT(opElse.GetCode() == cmELSE);
1537 MUP_ASSERT(opIf.GetCode() == cmIF);
1538
1540 } // while pending if-else-clause found
1541 }
1542
1543 //---------------------------------------------------------------------------
1548 ParserStack<token_type>& a_stVal) const
1549 {
1550 // is it a user defined binary operator?
1551 if (a_stOpt.top().GetCode() == cmOPRT_BIN)
1552 {
1553 ApplyFunc(a_stOpt, a_stVal, 2);
1554 }
1555 else
1556 {
1557 MUP_ASSERT(a_stVal.size() >= 2);
1558 token_type valTok1 = a_stVal.pop(),
1559 valTok2 = a_stVal.pop(),
1560 optTok = a_stOpt.pop(),
1561 resTok;
1562
1563 if ( valTok1.GetType() != valTok2.GetType() ||
1564 (valTok1.GetType() == tpSTR && valTok2.GetType() == tpSTR) )
1565 Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());
1566
1567 if (optTok.GetCode() == cmASSIGN)
1568 {
1569 if (valTok2.GetCode() != cmVAR)
1570 Error(ecUNEXPECTED_OPERATOR, -1, _nrT("="));
1571
1572 m_compilingState.m_byteCode.AddAssignOp(valTok2.GetVar());
1573 }
1574 else
1575 m_compilingState.m_byteCode.AddOp(optTok.GetCode());
1576
1577 resTok.SetVal(1);
1578 a_stVal.push(resTok);
1579 }
1580 }
1581
1582 //---------------------------------------------------------------------------
1588 ParserStack<token_type>& stVal) const
1589 {
1590 while (stOpt.size() &&
1591 stOpt.top().GetCode() != cmBO &&
1592 stOpt.top().GetCode() != cmIF)
1593 {
1594 token_type tok = stOpt.top();
1595 switch (tok.GetCode())
1596 {
1597 case cmOPRT_INFIX:
1598 case cmOPRT_BIN:
1599 case cmLE:
1600 case cmGE:
1601 case cmNEQ:
1602 case cmEQ:
1603 case cmLT:
1604 case cmGT:
1605 case cmADD:
1606 case cmSUB:
1607 case cmMUL:
1608 case cmDIV:
1609 case cmPOW:
1610 case cmLAND:
1611 case cmLOR:
1612 case cmASSIGN:
1613 if (stOpt.top().GetCode() == cmOPRT_INFIX)
1614 ApplyFunc(stOpt, stVal, 1);
1615 else
1616 ApplyBinOprt(stOpt, stVal);
1617 break;
1618
1619 case cmELSE:
1620 ApplyIfElse(stOpt, stVal);
1621 break;
1622
1623 default:
1625 }
1626 }
1627 }
1628
1629 //---------------------------------------------------------------------------
1638 {
1639 ParseCmdCodeBulk(0, 0);
1640 }
1641
1642 //---------------------------------------------------------------------------
1647 void ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID)
1648 {
1649 assert(nThreadID <= nMaxThreads);
1650
1651 // Note: The check for nOffset==0 and nThreadID here is not necessary but
1652 // brings a minor performance gain when not in bulk mode.
1653 value_type* Stack = nullptr;
1654
1655 Stack = ((nOffset == 0) && (nThreadID == 0))
1656 ? &m_state->m_stackBuffer[0]
1657 : &m_state->m_stackBuffer[nThreadID * (m_state->m_stackBuffer.size() / nMaxThreads)];
1658
1659 value_type buf;
1660 int sidx(0);
1661
1662 for (const SToken* pTok = m_state->m_byteCode.GetBase(); pTok->Cmd != cmEND ; ++pTok)
1663 {
1664 switch (pTok->Cmd)
1665 {
1666 // built in binary operators
1667 case cmLE:
1668 --sidx;
1669 Stack[sidx] = Stack[sidx].real() <= Stack[sidx + 1].real();
1670 continue;
1671 case cmGE:
1672 --sidx;
1673 Stack[sidx] = Stack[sidx].real() >= Stack[sidx + 1].real();
1674 continue;
1675 case cmNEQ:
1676 --sidx;
1677 Stack[sidx] = Stack[sidx] != Stack[sidx + 1];
1678 continue;
1679 case cmEQ:
1680 --sidx;
1681 Stack[sidx] = Stack[sidx] == Stack[sidx + 1];
1682 continue;
1683 case cmLT:
1684 --sidx;
1685 Stack[sidx] = Stack[sidx].real() < Stack[sidx + 1].real();
1686 continue;
1687 case cmGT:
1688 --sidx;
1689 Stack[sidx] = Stack[sidx].real() > Stack[sidx + 1].real();
1690 continue;
1691 case cmADD:
1692 --sidx;
1693 Stack[sidx] += Stack[1 + sidx];
1694 continue;
1695 case cmSUB:
1696 --sidx;
1697 Stack[sidx] -= Stack[1 + sidx];
1698 continue;
1699 case cmMUL:
1700 --sidx;
1701 Stack[sidx] = Stack[sidx] * Stack[1 + sidx]; // Uses the optimized version
1702 continue;
1703 case cmDIV:
1704 --sidx;
1705 Stack[sidx] = Stack[sidx] / Stack[1 + sidx]; // Uses the optimized version
1706 continue;
1707
1708 case cmPOW:
1709 --sidx;
1710 Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1 + sidx]);
1711 continue;
1712
1713 case cmLAND:
1714 --sidx;
1715 Stack[sidx] = Stack[sidx] != 0.0 && Stack[sidx + 1] != 0.0;
1716 continue;
1717 case cmLOR:
1718 --sidx;
1719 Stack[sidx] = Stack[sidx] != 0.0 || Stack[sidx + 1] != 0.0;
1720 continue;
1721
1722 case cmASSIGN:
1723 --sidx;
1724 Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx + 1];
1725 continue;
1726
1727 case cmIF:
1728 if (Stack[sidx--] == 0.0)
1729 pTok += pTok->Oprt.offset;
1730 continue;
1731
1732 case cmELSE:
1733 pTok += pTok->Oprt.offset;
1734 continue;
1735
1736 case cmENDIF:
1737 continue;
1738
1739 // value and variable tokens
1740 case cmVAL:
1741 Stack[++sidx] = pTok->Val.data2;
1742 continue;
1743
1744 case cmVAR:
1745 Stack[++sidx] = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
1746 continue;
1747
1748 case cmVARPOW2:
1749 buf = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
1750 Stack[++sidx] = buf * buf;
1751 continue;
1752
1753 case cmVARPOW3:
1754 buf = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
1755 Stack[++sidx] = buf * buf * buf;
1756 continue;
1757
1758 case cmVARPOW4:
1759 buf = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
1760 Stack[++sidx] = buf * buf * buf * buf;
1761 continue;
1762
1763 case cmVARPOWN:
1764 Stack[++sidx] = intPower(*(pTok->Val.ptr + pTok->Val.isVect*nOffset), pTok->Val.data.real());
1765 continue;
1766
1767 case cmVARMUL:
1768 Stack[++sidx] = *(pTok->Val.ptr + pTok->Val.isVect*nOffset) * pTok->Val.data + pTok->Val.data2;
1769 continue;
1770
1771 // Next is treatment of numeric functions
1772 case cmFUNC:
1773 {
1774 int iArgCount = pTok->Fun.argc;
1775
1776 // switch according to argument count
1777 switch (iArgCount)
1778 {
1779 case 0:
1780 sidx += 1;
1781 Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)();
1782 continue;
1783 case 1:
1784 Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]);
1785 continue;
1786 case 2:
1787 sidx -= 1;
1788 Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx],
1789 Stack[sidx + 1]);
1790 continue;
1791 case 3:
1792 sidx -= 2;
1793 Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx],
1794 Stack[sidx + 1],
1795 Stack[sidx + 2]);
1796 continue;
1797 case 4:
1798 sidx -= 3;
1799 Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx],
1800 Stack[sidx + 1],
1801 Stack[sidx + 2],
1802 Stack[sidx + 3]);
1803 continue;
1804 case 5:
1805 sidx -= 4;
1806 Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx],
1807 Stack[sidx + 1],
1808 Stack[sidx + 2],
1809 Stack[sidx + 3],
1810 Stack[sidx + 4]);
1811 continue;
1812 case 6:
1813 sidx -= 5;
1814 Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx],
1815 Stack[sidx + 1],
1816 Stack[sidx + 2],
1817 Stack[sidx + 3],
1818 Stack[sidx + 4],
1819 Stack[sidx + 5]);
1820 continue;
1821 case 7:
1822 sidx -= 6;
1823 Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx],
1824 Stack[sidx + 1],
1825 Stack[sidx + 2],
1826 Stack[sidx + 3],
1827 Stack[sidx + 4],
1828 Stack[sidx + 5],
1829 Stack[sidx + 6]);
1830 continue;
1831 case 8:
1832 sidx -= 7;
1833 Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx],
1834 Stack[sidx + 1],
1835 Stack[sidx + 2],
1836 Stack[sidx + 3],
1837 Stack[sidx + 4],
1838 Stack[sidx + 5],
1839 Stack[sidx + 6],
1840 Stack[sidx + 7]);
1841 continue;
1842 case 9:
1843 sidx -= 8;
1844 Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx],
1845 Stack[sidx + 1],
1846 Stack[sidx + 2],
1847 Stack[sidx + 3],
1848 Stack[sidx + 4],
1849 Stack[sidx + 5],
1850 Stack[sidx + 6],
1851 Stack[sidx + 7],
1852 Stack[sidx + 8]);
1853 continue;
1854 case 10:
1855 sidx -= 9;
1856 Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx],
1857 Stack[sidx + 1],
1858 Stack[sidx + 2],
1859 Stack[sidx + 3],
1860 Stack[sidx + 4],
1861 Stack[sidx + 5],
1862 Stack[sidx + 6],
1863 Stack[sidx + 7],
1864 Stack[sidx + 8],
1865 Stack[sidx + 9]);
1866 continue;
1867 default:
1868 if (iArgCount > 0) // function with variable arguments store the number as a negative value
1870
1871 sidx -= -iArgCount - 1;
1872 Stack[sidx] = (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
1873 continue;
1874 }
1875 }
1876
1877 default:
1879 } // switch CmdCode
1880 } // for all bytecode tokens
1881 }
1882
1883
1892 void ParserBase::ParseCmdCodeBulkParallel(size_t nVectorLength)
1893 {
1894 size_t nBufferOffset = m_state->m_stackBuffer.size() / nMaxThreads;
1895 int nStackSize = m_state->m_numResults;
1896
1897 #pragma omp parallel for //schedule(static, (nVectorLength-1)/nMaxThreads)
1898 for (size_t nOffset = 1; nOffset < nVectorLength; ++nOffset)
1899 {
1900 int nThreadID = omp_get_thread_num();
1901 value_type* Stack = &m_state->m_stackBuffer[nThreadID * nBufferOffset];
1902 value_type buf;
1903 int sidx(0);
1904
1905 // Run the bytecode
1906 for (const SToken* pTok = m_state->m_byteCode.GetBase(); pTok->Cmd != cmEND ; ++pTok)
1907 {
1908 switch (pTok->Cmd)
1909 {
1910 // built in binary operators
1911 case cmLE:
1912 --sidx;
1913 Stack[sidx] = Stack[sidx].real() <= Stack[sidx + 1].real();
1914 continue;
1915 case cmGE:
1916 --sidx;
1917 Stack[sidx] = Stack[sidx].real() >= Stack[sidx + 1].real();
1918 continue;
1919 case cmNEQ:
1920 --sidx;
1921 Stack[sidx] = Stack[sidx] != Stack[sidx + 1];
1922 continue;
1923 case cmEQ:
1924 --sidx;
1925 Stack[sidx] = Stack[sidx] == Stack[sidx + 1];
1926 continue;
1927 case cmLT:
1928 --sidx;
1929 Stack[sidx] = Stack[sidx].real() < Stack[sidx + 1].real();
1930 continue;
1931 case cmGT:
1932 --sidx;
1933 Stack[sidx] = Stack[sidx].real() > Stack[sidx + 1].real();
1934 continue;
1935 case cmADD:
1936 --sidx;
1937 Stack[sidx] += Stack[1 + sidx];
1938 continue;
1939 case cmSUB:
1940 --sidx;
1941 Stack[sidx] -= Stack[1 + sidx];
1942 continue;
1943 case cmMUL:
1944 --sidx;
1945 Stack[sidx] = Stack[sidx] * Stack[1 + sidx]; // Uses the optimized version
1946 continue;
1947 case cmDIV:
1948 --sidx;
1949 Stack[sidx] = Stack[sidx] / Stack[1 + sidx]; // Uses the optimized version
1950 continue;
1951
1952 case cmPOW:
1953 --sidx;
1954 Stack[sidx] = MathImpl<value_type>::Pow(Stack[sidx], Stack[1 + sidx]);
1955 continue;
1956
1957 case cmLAND:
1958 --sidx;
1959 Stack[sidx] = Stack[sidx] != 0.0 && Stack[sidx + 1] != 0.0;
1960 continue;
1961 case cmLOR:
1962 --sidx;
1963 Stack[sidx] = Stack[sidx] != 0.0 || Stack[sidx + 1] != 0.0;
1964 continue;
1965
1966 case cmASSIGN:
1967 --sidx;
1968 Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx + 1];
1969 continue;
1970
1971 case cmIF:
1972 if (Stack[sidx--] == 0.0)
1973 pTok += pTok->Oprt.offset;
1974 continue;
1975
1976 case cmELSE:
1977 pTok += pTok->Oprt.offset;
1978 continue;
1979
1980 case cmENDIF:
1981 continue;
1982
1983 // value and variable tokens
1984 case cmVAL:
1985 Stack[++sidx] = pTok->Val.data2;
1986 continue;
1987
1988 case cmVAR:
1989 Stack[++sidx] = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
1990 //NumeReKernel::print(toString(*(pTok->Val.ptr + pTok->Val.isVect*nOffset), 14));
1991 continue;
1992
1993 case cmVARPOW2:
1994 buf = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
1995 Stack[++sidx] = buf * buf;
1996 continue;
1997
1998 case cmVARPOW3:
1999 buf = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
2000 Stack[++sidx] = buf * buf * buf;
2001 continue;
2002
2003 case cmVARPOW4:
2004 buf = *(pTok->Val.ptr + pTok->Val.isVect*nOffset);
2005 Stack[++sidx] = buf * buf * buf * buf;
2006 continue;
2007
2008 case cmVARPOWN:
2009 Stack[++sidx] = intPower(*(pTok->Val.ptr + pTok->Val.isVect*nOffset), pTok->Val.data.real());
2010 continue;
2011
2012 case cmVARMUL:
2013 Stack[++sidx] = *(pTok->Val.ptr + pTok->Val.isVect*nOffset) * pTok->Val.data + pTok->Val.data2;
2014 continue;
2015
2016 // Next is treatment of numeric functions
2017 case cmFUNC:
2018 {
2019 int iArgCount = pTok->Fun.argc;
2020
2021 // switch according to argument count
2022 switch (iArgCount)
2023 {
2024 case 0:
2025 sidx += 1;
2026 Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)();
2027 continue;
2028 case 1:
2029 Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]);
2030 continue;
2031 case 2:
2032 sidx -= 1;
2033 Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx],
2034 Stack[sidx + 1]);
2035 continue;
2036 case 3:
2037 sidx -= 2;
2038 Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx],
2039 Stack[sidx + 1],
2040 Stack[sidx + 2]);
2041 continue;
2042 case 4:
2043 sidx -= 3;
2044 Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx],
2045 Stack[sidx + 1],
2046 Stack[sidx + 2],
2047 Stack[sidx + 3]);
2048 continue;
2049 case 5:
2050 sidx -= 4;
2051 Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx],
2052 Stack[sidx + 1],
2053 Stack[sidx + 2],
2054 Stack[sidx + 3],
2055 Stack[sidx + 4]);
2056 continue;
2057 case 6:
2058 sidx -= 5;
2059 Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx],
2060 Stack[sidx + 1],
2061 Stack[sidx + 2],
2062 Stack[sidx + 3],
2063 Stack[sidx + 4],
2064 Stack[sidx + 5]);
2065 continue;
2066 case 7:
2067 sidx -= 6;
2068 Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx],
2069 Stack[sidx + 1],
2070 Stack[sidx + 2],
2071 Stack[sidx + 3],
2072 Stack[sidx + 4],
2073 Stack[sidx + 5],
2074 Stack[sidx + 6]);
2075 continue;
2076 case 8:
2077 sidx -= 7;
2078 Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx],
2079 Stack[sidx + 1],
2080 Stack[sidx + 2],
2081 Stack[sidx + 3],
2082 Stack[sidx + 4],
2083 Stack[sidx + 5],
2084 Stack[sidx + 6],
2085 Stack[sidx + 7]);
2086 continue;
2087 case 9:
2088 sidx -= 8;
2089 Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx],
2090 Stack[sidx + 1],
2091 Stack[sidx + 2],
2092 Stack[sidx + 3],
2093 Stack[sidx + 4],
2094 Stack[sidx + 5],
2095 Stack[sidx + 6],
2096 Stack[sidx + 7],
2097 Stack[sidx + 8]);
2098 continue;
2099 case 10:
2100 sidx -= 9;
2101 Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx],
2102 Stack[sidx + 1],
2103 Stack[sidx + 2],
2104 Stack[sidx + 3],
2105 Stack[sidx + 4],
2106 Stack[sidx + 5],
2107 Stack[sidx + 6],
2108 Stack[sidx + 7],
2109 Stack[sidx + 8],
2110 Stack[sidx + 9]);
2111 continue;
2112 default:
2113 if (iArgCount > 0) // function with variable arguments store the number as a negative value
2115
2116 sidx -= -iArgCount - 1;
2117 Stack[sidx] = (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount);
2118 continue;
2119 }
2120 }
2121
2122 default:
2124 } // switch CmdCode
2125 } // for all bytecode tokens
2126
2127 // Copy the results
2128 for (int j = 0; j < nStackSize; j++)
2129 {
2130 m_buffer[nOffset*nStackSize + j] = m_state->m_stackBuffer[nThreadID*nBufferOffset + j + 1];
2131 }
2132 }
2133
2134 }
2135
2136 //---------------------------------------------------------------------------
2138 {
2139 if (g_DbgDumpStack)
2140 NumeReKernel::print("Parsing: \"" + m_pTokenReader->GetExpr() + "\"");
2141
2142 if (!m_pTokenReader->GetExpr().length())
2144
2145 ParserStack<token_type> stOpt, stVal;
2146 ParserStack<int> stArgCount;
2147 token_type opta, opt; // for storing operators
2148 token_type val, tval; // for storing value
2149 string_type strBuf; // buffer for string function arguments
2150
2151 //ReInit();
2152
2153 // The outermost counter counts the number of seperated items
2154 // such as in "a=10,b=20,c=c+a"
2155 stArgCount.push(1);
2156
2157 for (;;)
2158 {
2159 opt = m_pTokenReader->ReadNextToken();
2160
2161 switch (opt.GetCode())
2162 {
2163 //
2164 // Next three are different kind of value entries
2165 //
2166 case cmSTRING:
2167 opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token
2168 stVal.push(opt);
2169 m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer
2170 break;
2171
2172 case cmVAR:
2173 stVal.push(opt);
2174 m_compilingState.m_byteCode.AddVar( static_cast<value_type*>(opt.GetVar()) );
2175
2176 if (mVectorVars.size())
2177 {
2178 if (mVectorVars.find(opt.GetAsString()) != mVectorVars.end())
2179 {
2180 mVectorVars[opt.GetAsString()][0] = *opt.GetVar();
2181 break;
2182 }
2183
2184 std::vector<mu::value_type> vVar;
2185 vVar.push_back(*(opt.GetVar()));
2186 SetVectorVar(opt.GetAsString(), vVar, true);
2187 }
2188
2189 break;
2190
2191 case cmVAL:
2192 stVal.push(opt);
2194 break;
2195
2196 case cmELSE:
2198
2199 if (m_nIfElseCounter < 0)
2201
2202 ApplyRemainingOprt(stOpt, stVal);
2204 stOpt.push(opt);
2205 break;
2206
2207
2208 case cmARG_SEP:
2209 if (stArgCount.empty())
2211
2212 ++stArgCount.top();
2213 // fallthrough intentional (no break!)
2214
2215 case cmEND:
2216 ApplyRemainingOprt(stOpt, stVal);
2217 break;
2218
2219 case cmBC:
2220 {
2221 // The argument count for parameterless functions is zero
2222 // by default an opening bracket sets parameter count to 1
2223 // in preparation of arguments to come. If the last token
2224 // was an opening bracket we know better...
2225 if (opta.GetCode() == cmBO)
2226 --stArgCount.top();
2227
2228 ApplyRemainingOprt(stOpt, stVal);
2229
2230 // Check if the bracket content has been evaluated completely
2231 if (stOpt.size() && stOpt.top().GetCode() == cmBO)
2232 {
2233 // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check
2234 // if there is either a function or a sign pending
2235 // neither the opening nor the closing bracket will be pushed back to
2236 // the operator stack
2237 // Check if a function is standing in front of the opening bracket,
2238 // if yes evaluate it afterwards check for infix operators
2239 assert(stArgCount.size());
2240 int iArgCount = stArgCount.pop();
2241
2242 stOpt.pop(); // Take opening bracket from stack
2243
2244 if (iArgCount > 1 && ( stOpt.size() == 0 ||
2245 (stOpt.top().GetCode() != cmFUNC &&
2246 stOpt.top().GetCode() != cmFUNC_BULK &&
2247 stOpt.top().GetCode() != cmFUNC_STR) ) )
2249
2250 // The opening bracket was popped from the stack now check if there
2251 // was a function before this bracket
2252 if (stOpt.size() &&
2253 stOpt.top().GetCode() != cmOPRT_INFIX &&
2254 stOpt.top().GetCode() != cmOPRT_BIN &&
2255 stOpt.top().GetFuncAddr() != 0)
2256 {
2257 ApplyFunc(stOpt, stVal, iArgCount);
2258 }
2259 }
2260 } // if bracket content is evaluated
2261 break;
2262
2263 //
2264 // Next are the binary operator entries
2265 //
2266 //case cmAND: // built in binary operators
2267 //case cmOR:
2268 //case cmXOR:
2269 case cmIF:
2271 // fallthrough intentional (no break!)
2272
2273 case cmLAND:
2274 case cmLOR:
2275 case cmLT:
2276 case cmGT:
2277 case cmLE:
2278 case cmGE:
2279 case cmNEQ:
2280 case cmEQ:
2281 case cmADD:
2282 case cmSUB:
2283 case cmMUL:
2284 case cmDIV:
2285 case cmPOW:
2286 case cmASSIGN:
2287 case cmOPRT_BIN:
2288
2289 // A binary operator (user defined or built in) has been found.
2290 while ( stOpt.size() &&
2291 stOpt.top().GetCode() != cmBO &&
2292 stOpt.top().GetCode() != cmELSE &&
2293 stOpt.top().GetCode() != cmIF)
2294 {
2295 int nPrec1 = GetOprtPrecedence(stOpt.top()),
2296 nPrec2 = GetOprtPrecedence(opt);
2297
2298 if (stOpt.top().GetCode() == opt.GetCode())
2299 {
2300
2301 // Deal with operator associativity
2303 if ( (eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) ||
2304 (eOprtAsct == oaLEFT && (nPrec1 < nPrec2)) )
2305 {
2306 break;
2307 }
2308 }
2309 else if (nPrec1 < nPrec2)
2310 {
2311 // In case the operators are not equal the precedence decides alone...
2312 break;
2313 }
2314
2315 if (stOpt.top().GetCode() == cmOPRT_INFIX)
2316 ApplyFunc(stOpt, stVal, 1);
2317 else
2318 ApplyBinOprt(stOpt, stVal);
2319 } // while ( ... )
2320
2321 if (opt.GetCode() == cmIF)
2323
2324 // The operator can't be evaluated right now, push back to the operator stack
2325 stOpt.push(opt);
2326 break;
2327
2328 //
2329 // Last section contains functions and operators implicitely mapped to functions
2330 //
2331 case cmBO:
2332 stArgCount.push(1);
2333 stOpt.push(opt);
2334 break;
2335
2336 case cmOPRT_INFIX:
2337 case cmFUNC:
2338 case cmFUNC_BULK:
2339 case cmFUNC_STR:
2340 stOpt.push(opt);
2341 break;
2342
2343 case cmOPRT_POSTFIX:
2344 stOpt.push(opt);
2345 ApplyFunc(stOpt, stVal, 1); // this is the postfix operator
2346 break;
2347
2348 default:
2350 } // end of switch operator-token
2351
2352 opta = opt;
2353
2354 if ( opt.GetCode() == cmEND )
2355 {
2357 break;
2358 }
2359
2360 // Commented out - might be necessary for deep debugging stuff
2361 //if (ParserBase::g_DbgDumpStack)
2362 //{
2363 // StackDump(stVal, stOpt);
2364 // m_compilingState.m_byteCode.AsciiDump();
2365 //}
2366 } // while (true)
2367
2370
2371 if (m_nIfElseCounter > 0)
2373
2374 // get the last value (= final result) from the stack
2375 MUP_ASSERT(stArgCount.size() == 1);
2376
2377 m_compilingState.m_numResults = stArgCount.top();
2378
2381
2382 if (stVal.size() == 0)
2384
2385 if (stVal.top().GetType() != tpDBL)
2387
2389 }
2390
2391 //---------------------------------------------------------------------------
2401 {
2402 CreateRPN();
2406
2410 {
2412 state = m_compilingState;
2413 m_state = &state;
2414 }
2415 else
2417
2419 (this->*m_pParseFormula)();
2420 }
2421
2422 //---------------------------------------------------------------------------
2433 void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type& a_sTok) const
2434 {
2435 throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
2436 }
2437
2438 //---------------------------------------------------------------------------
2450 void ParserBase::Error(EErrorCodes a_iErrc, const string_type& a_Expr, int a_iPos, const string_type& a_sTok) const
2451 {
2452 throw exception_type(a_iErrc, a_sTok, a_Expr, a_iPos);
2453 }
2454
2455 //------------------------------------------------------------------------------
2462 {
2463 m_VarDef.clear();
2464 ReInit();
2465 }
2466
2467 //------------------------------------------------------------------------------
2473 void ParserBase::RemoveVar(const string_type& a_strVarName)
2474 {
2475 varmap_type::iterator item = m_VarDef.find(a_strVarName);
2476 //g_logger.debug("Trying to delete " + a_strVarName);
2477
2478 if (item != m_VarDef.end())
2479 {
2480 // Search for the variable in the internal storage and
2481 // remove it
2482 for (auto iter = m_lDataStorage.begin(); iter != m_lDataStorage.end(); ++iter)
2483 {
2484 if (item->second == *iter)
2485 {
2486 delete *iter;
2487 m_lDataStorage.erase(iter);
2488 break;
2489 }
2490 }
2491
2492 m_VarDef.erase(item);
2493 ReInit();
2494 }
2495 }
2496
2497 //------------------------------------------------------------------------------
2503 {
2504 m_FunDef.clear();
2505 ReInit();
2506 }
2507
2508 //------------------------------------------------------------------------------
2516 {
2517 m_ConstDef.clear();
2518 m_StrVarDef.clear();
2519 ReInit();
2520 }
2521
2522 //------------------------------------------------------------------------------
2528 {
2529 m_PostOprtDef.clear();
2530 ReInit();
2531 }
2532
2533 //------------------------------------------------------------------------------
2539 {
2540 m_OprtDef.clear();
2541 ReInit();
2542 }
2543
2544 //------------------------------------------------------------------------------
2550 {
2551 m_InfixOprtDef.clear();
2552 ReInit();
2553 }
2554
2555 //------------------------------------------------------------------------------
2561 {
2563 ReInit();
2564 }
2565
2566 //---------------------------------------------------------------------------
2573 void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack)
2574 {
2576 ParserBase::g_DbgDumpStack = bDumpStack;
2577 }
2578
2579 //------------------------------------------------------------------------------
2590 {
2591 m_bBuiltInOp = a_bIsOn;
2592 ReInit();
2593 }
2594
2595 //------------------------------------------------------------------------------
2601 {
2602 return m_bBuiltInOp;
2603 }
2604
2605 //------------------------------------------------------------------------------
2609 {
2610 return m_pTokenReader->GetArgSep();
2611 }
2612
2613 //------------------------------------------------------------------------------
2618 {
2619 m_pTokenReader->SetArgSep(cArgSep);
2620 }
2621
2622 //------------------------------------------------------------------------------
2628 const ParserStack<token_type>& a_stOprt) const
2629 {
2630 ParserStack<token_type> stOprt(a_stOprt),
2631 stVal(a_stVal);
2632
2633 NumeReKernel::print("Value stack:");
2635
2636 while ( !stVal.empty() )
2637 {
2638 token_type val = stVal.pop();
2639
2640 if (val.GetType() == tpSTR)
2641 NumeReKernel::printPreFmt(" \"" + val.GetAsString() + "\" ");
2642 else
2643 NumeReKernel::printPreFmt(" " + toString(val.GetVal(), 7) + " ");
2644 }
2645
2647 NumeReKernel::printPreFmt("|-> Operator stack:\n");
2648
2649 while ( !stOprt.empty() )
2650 {
2651 if (stOprt.top().GetCode() <= cmASSIGN)
2652 {
2653 NumeReKernel::printPreFmt("| OPRT_INTRNL \"" + string(ParserBase::c_DefaultOprt[stOprt.top().GetCode()]) + "\"\n");
2654 }
2655 else
2656 {
2657 switch (stOprt.top().GetCode())
2658 {
2659 case cmVAR:
2660 NumeReKernel::printPreFmt("| VAR\n");
2661 break;
2662 case cmVAL:
2663 NumeReKernel::printPreFmt("| VAL\n");
2664 break;
2665 case cmFUNC:
2666 NumeReKernel::printPreFmt("| FUNC \"" + stOprt.top().GetAsString() + "\"\n");
2667 break;
2668 case cmFUNC_BULK:
2669 NumeReKernel::printPreFmt("| FUNC_BULK \"" + stOprt.top().GetAsString() + "\"\n");
2670 break;
2671 case cmOPRT_INFIX:
2672 NumeReKernel::printPreFmt("| OPRT_INF \"" + stOprt.top().GetAsString() + "\"\n");
2673 break;
2674 case cmOPRT_BIN:
2675 NumeReKernel::printPreFmt("| OPRT_BIN \"" + stOprt.top().GetAsString() + "\"\n");
2676 break;
2677 case cmFUNC_STR:
2678 NumeReKernel::printPreFmt("| FUNC_STR\n");
2679 break;
2680 case cmEND:
2681 NumeReKernel::printPreFmt("| END\n");
2682 break;
2683 case cmUNKNOWN:
2684 NumeReKernel::printPreFmt("| UNKNOWN\n");
2685 break;
2686 case cmBO:
2687 NumeReKernel::printPreFmt("| BRACKET \"(\"\n");
2688 break;
2689 case cmBC:
2690 NumeReKernel::printPreFmt("| BRACKET \")\"\n");
2691 break;
2692 case cmIF:
2693 NumeReKernel::printPreFmt("| IF\n");
2694 break;
2695 case cmELSE:
2696 NumeReKernel::printPreFmt("| ELSE\n");
2697 break;
2698 case cmENDIF:
2699 NumeReKernel::printPreFmt("| ENDIF\n");
2700 break;
2701 default:
2702 NumeReKernel::printPreFmt("| " + toString(stOprt.top().GetCode()) + "\n");
2703 break;
2704 }
2705 }
2706
2707 stOprt.pop();
2708 }
2709
2710 }
2711
2712
2723 string_type ParserBase::getNextVarObject(std::string& sArgList, bool bCut)
2724 {
2725 int nParenthesis = 0;
2726 int nVektorbrace = 0;
2727 unsigned int nPos = 0;
2728
2729 // Find the next "top-level" expression object, which
2730 // is separated by a comma
2731 for (unsigned int i = 0; i < sArgList.length(); i++)
2732 {
2733 if (sArgList[i] == '(')
2734 nParenthesis++;
2735
2736 if (sArgList[i] == ')')
2737 nParenthesis--;
2738
2739 if (sArgList[i] == '{')
2740 {
2741 nVektorbrace++;
2742 i++;
2743 }
2744
2745 if (sArgList[i] == '}')
2746 {
2747 nVektorbrace--;
2748 i++;
2749 }
2750
2751 if (sArgList[i] == ',' && !nParenthesis && !nVektorbrace)
2752 {
2753 nPos = i;
2754 break;
2755 }
2756 }
2757
2758 // Nothing found: use everything
2759 if (!nPos && sArgList[0] != ',')
2760 nPos = sArgList.length();
2761
2762 // First position: remove the comma
2763 // and return an empty string
2764 if (!nPos)
2765 {
2766 if (bCut && sArgList[0] == ',')
2767 sArgList.erase(0, 1);
2768
2769 return "";
2770 }
2771
2772 // Extract the argument
2773 std::string sArg = sArgList.substr(0, nPos);
2774
2775 // Strip whitespaces from front and back
2776 while (sArg.front() == ' ' || sArg.front() == '\t')
2777 sArg.erase(0, 1);
2778
2779 while (sArg.back() == ' ' || sArg.back() == '\t')
2780 sArg.erase(sArg.length() - 1);
2781
2782 // Remove the argument and the trailing comma
2783 // from the argument list
2784 if (bCut && sArgList.length() > nPos + 1)
2785 sArgList = sArgList.substr(nPos + 1);
2786 else if (bCut)
2787 sArgList = "";
2788
2789 return sArg;
2790 }
2791
2792
2805 {
2807 {
2810 return sIndex;
2811 }
2812 else
2813 return toString(m_lDataStorage.size()); //nVectorIndex);
2814 }
2815
2816
2828 void ParserBase::evaluateTemporaryVectors(const VectorEvaluation& vectEval, int nStackSize)
2829 {
2830 //g_logger.debug("Accessing " + vectEval.m_targetVect);
2831 std::vector<mu::value_type>* vTgt = GetVectorVar(vectEval.m_targetVect);
2832
2833 switch (vectEval.m_type)
2834 {
2836 {
2837 vTgt->clear();
2838
2839 for (size_t i = 0, n = 0; i < m_state->m_vectEval.m_componentDefs.size(); i++, n++)
2840 {
2841 if (m_state->m_vectEval.m_componentDefs[i] == 1)
2842 vTgt->push_back(m_buffer[n]);
2843 else
2844 {
2845 int nComps = m_state->m_vectEval.m_componentDefs[i];
2846
2847 // This is an expansion. There are two possible cases
2848 if (nComps == 2)
2849 {
2850 mu::value_type diff = m_buffer[n+1] - m_buffer[n];
2851 diff.real(diff.real() > 0.0 ? 1.0 : (diff.real() < 0.0 ? -1.0 : 0.0));
2852 diff.imag(diff.imag() > 0.0 ? 1.0 : (diff.imag() < 0.0 ? -1.0 : 0.0));
2853 expandVector(m_buffer[n], m_buffer[n+1], diff, *vTgt);
2854 }
2855 else if (nComps == 3)
2856 expandVector(m_buffer[n], m_buffer[n+2], m_buffer[n+1], *vTgt);
2857
2858 n += nComps-1;
2859 }
2860 }
2861
2862 break;
2863 }
2864
2866 vTgt->assign(m_buffer.begin(), m_buffer.begin() + nStackSize);
2867 break;
2868
2870 {
2871 // Apply the needed multi-argument function
2872 if (m_FunDef.find(m_state->m_vectEval.m_mafunc) != m_FunDef.end())
2873 {
2875 vTgt->assign(1, multfun_type(pCallback.GetAddr())(&m_buffer[0], nStackSize));
2876 }
2877 else if (m_state->m_vectEval.m_mafunc == "logtoidx")
2878 *vTgt = parser_logtoidx(&m_buffer[0], nStackSize);
2879 else if (m_state->m_vectEval.m_mafunc == "idxtolog")
2880 *vTgt = parser_idxtolog(&m_buffer[0], nStackSize);
2881
2882 break;
2883 }
2884
2885 }
2886
2888 }
2889
2890
2900 static std::string printVector(const valbuf_type& buffer, int nElems)
2901 {
2902 std::string s;
2903
2904 for (int i = 0; i < nElems; i++)
2905 s += toString(buffer[i], 5) + ",";
2906
2907 s.pop_back();
2908
2909 return s;
2910 }
2911
2912
2927 {
2928 // Run the evaluation
2929 (this->*m_pParseFormula)();
2930
2931 nStackSize = m_state->m_numResults;
2932
2933 // Copy the actual results (ignore the 0-th term)
2934 m_buffer.assign(m_state->m_stackBuffer.begin()+1,
2935 m_state->m_stackBuffer.begin()+nStackSize+1);
2936
2937 if (mVectorVars.size())
2938 {
2939 std::vector<std::vector<value_type>*> vUsedVectorVars;
2940 std::vector<value_type*> vUsedVectorVarAddresses;
2941 varmap_type& vars = m_state->m_usedVar;
2942 size_t nVectorLength = 0;
2943
2944 // Get the maximal size of the used vectors
2945 auto iterVector = mVectorVars.begin();
2946 auto iterVar = vars.begin();
2947
2948 for ( ; iterVector != mVectorVars.end() && iterVar != vars.end(); )
2949 {
2950 if (iterVector->first == iterVar->first)
2951 {
2952 if (iterVector->second.size() > 1 && iterVector->first != "_~TRGTVCT[~]")
2953 {
2954 vUsedVectorVarAddresses.push_back(iterVar->second);
2955 vUsedVectorVars.push_back(&(iterVector->second));
2956 nVectorLength = std::max(nVectorLength, iterVector->second.size());
2957 }
2958
2959 ++iterVector;
2960 ++iterVar;
2961 }
2962 else
2963 {
2964 if (iterVector->first < iterVar->first)
2965 ++iterVector;
2966 else
2967 ++iterVar;
2968 }
2969 }
2970
2971 // Any vectors larger than 1 element in this equation?
2972 if (vUsedVectorVarAddresses.size())
2973 {
2974 // Replace all addresses and resize all vectors to fit
2975 for (size_t i = 0; i < vUsedVectorVarAddresses.size(); i++)
2976 {
2977 vUsedVectorVars[i]->resize(nVectorLength);
2978 m_state->m_byteCode.ChangeVar(vUsedVectorVarAddresses[i], vUsedVectorVars[i]->data(), true);
2979 }
2980
2981 // Resize the target buffer correspondingly
2982 m_buffer.resize(nStackSize * nVectorLength);
2983
2984 if (nVectorLength < 500)
2985 {
2986 // Too few components -> run sequentially
2987 for (size_t i = 1; i < nVectorLength; ++i)
2988 {
2989 ParseCmdCodeBulk(i, 0);
2990
2991 for (int j = 0; j < nStackSize; j++)
2992 {
2993 m_buffer[i*nStackSize + j] = m_state->m_stackBuffer[j + 1];
2994 }
2995 }
2996 }
2997 else
2998 {
2999 //g_logger.info("Start parallel run");
3000 // Run parallel
3001
3002 ParseCmdCodeBulkParallel(nVectorLength);
3003
3004 /*size_t nBufferOffset = m_state->m_stackBuffer.size() / nMaxThreads;
3005
3006 #pragma omp parallel for //schedule(static, (nVectorLength-1)/nMaxThreads)
3007 for (size_t i = 1; i < nVectorLength; ++i)
3008 {
3009 int nThreadID = omp_get_thread_num();
3010 ParseCmdCodeBulk(i, nThreadID);
3011
3012 for (int j = 0; j < nStackSize; j++)
3013 {
3014 m_buffer[i*nStackSize + j] = m_state->m_stackBuffer[nThreadID*nBufferOffset + j + 1];
3015 }
3016 }*/
3017 //g_logger.info("Ran parallel");
3018 }
3019
3020
3021 // Update the external variable
3022 nStackSize *= nVectorLength;
3023
3024 // Replace all addresses (they are temporary!)
3025 for (size_t i = 0; i < vUsedVectorVarAddresses.size(); i++)
3026 {
3027 m_state->m_byteCode.ChangeVar(vUsedVectorVars[i]->data(), vUsedVectorVarAddresses[i], false);
3028 }
3029
3030 // Repeat the first component to resolve possible overwrites (needs additional time)
3031 (this->*m_pParseFormula)();
3032 }
3033 }
3034
3035 // assign the results of the calculation to a possible
3036 // temporary vector
3037 ExpressionTarget& target = getTarget();
3038
3039 if (target.isValid() && m_state->m_usedVar.find("_~TRGTVCT[~]") != m_state->m_usedVar.end())
3040 target.assign(m_buffer, nStackSize);
3041
3042 // Temporary target vector
3045
3046 if (g_DbgDumpStack)
3047 NumeReKernel::print("ParserBase::Eval() @ ["
3049 + "] m_buffer[:] = {" + printVector(m_buffer, nStackSize) + "}");
3050
3052 {
3054 nCurrVectorIndex = 0;
3055
3057 m_stateStacks[nthLoopElement].m_states.push_back(State());
3058
3060 }
3061
3062 return &m_buffer[0];
3063 }
3064
3065
3073 value_type ParserBase::Eval() // declared as deprecated
3074 {
3075 value_type* v;
3076 int nResults;
3077
3078 v = Eval(nResults);
3079
3080 if (!nResults)
3081 return NAN;
3082
3083 return v[0];
3084 }
3085
3086
3096 void ParserBase::ActivateLoopMode(unsigned int _nLoopLength)
3097 {
3098 if (!bMakeLoopByteCode)
3099 {
3100 if (g_DbgDumpStack)
3101 NumeReKernel::print("DEBUG: Activated loop mode");
3102
3103 nthLoopElement = 0;
3104 nCurrVectorIndex = 0;
3106 bMakeLoopByteCode = true;
3108 bMakeLoopByteCode = true;
3109 bCompiling = false;
3110 m_stateStacks.resize(_nLoopLength);
3111 }
3112 }
3113
3114
3123 {
3125 {
3126 if (g_DbgDumpStack)
3127 NumeReKernel::print("DEBUG: Deactivated loop mode");
3128 nthLoopElement = 0;
3130 nCurrVectorIndex = 0;
3131 bMakeLoopByteCode = false;
3132 bCompiling = false;
3135 }
3136 }
3137
3138
3147 void ParserBase::SetIndex(unsigned int _nLoopElement)
3148 {
3149 nthLoopElement = _nLoopElement;
3150 nCurrVectorIndex = 0;
3153 }
3154
3155
3164 void ParserBase::SetCompiling(bool _bCompiling)
3165 {
3166 bCompiling = _bCompiling;
3167 }
3168
3169
3178 {
3179 return bCompiling;
3180 }
3181
3182
3192 {
3194 m_stateStacks[nthLoopElement].m_cache.m_accesses.push_back(_access);
3195 }
3196
3197
3206 {
3208 return m_stateStacks[nthLoopElement].m_cache.m_accesses.size();
3209
3210 return 0;
3211 }
3212
3213
3222 {
3224 {
3225 m_stateStacks[nthLoopElement].m_cache.m_enabled = false;
3226 m_stateStacks[nthLoopElement].m_cache.m_accesses.clear();
3227 }
3228 }
3229
3230
3239 {
3241 return m_stateStacks[nthLoopElement].m_cache.m_enabled;
3242
3243 return false;
3244 }
3245
3246
3256 {
3257 if (bMakeLoopByteCode && !bPauseLoopByteCode && m_stateStacks[nthLoopElement].m_cache.m_accesses.size() > nthAccess)
3258 return m_stateStacks[nthLoopElement].m_cache.m_accesses[nthAccess];
3259
3260 return CachedDataAccess();
3261 }
3262
3263
3272 void ParserBase::CacheCurrentEquation(const string& sEquation)
3273 {
3275 m_stateStacks[nthLoopElement].m_cache.m_expr = sEquation;
3276 }
3277
3278
3286 const std::string& ParserBase::GetCachedEquation() const
3287 {
3289 return m_stateStacks[nthLoopElement].m_cache.m_expr;
3290
3291 return EMPTYSTRING;
3292 }
3293
3294
3303 void ParserBase::CacheCurrentTarget(const string& sEquation)
3304 {
3306 m_stateStacks[nthLoopElement].m_cache.m_target = sEquation;
3307 }
3308
3309
3317 const std::string& ParserBase::GetCachedTarget() const
3318 {
3320 return m_stateStacks[nthLoopElement].m_cache.m_target;
3321
3322 return EMPTYSTRING;
3323 }
3324
3325
3336 int ParserBase::IsValidByteCode(unsigned int _nthLoopElement, unsigned int _nthPartEquation)
3337 {
3338 if (!bMakeLoopByteCode)
3339 return 0;
3340
3341 if (_nthLoopElement < m_stateStacks.size())
3342 return m_stateStacks(_nthLoopElement, _nthPartEquation).m_valid;
3343 else
3344 return m_stateStacks(nthLoopElement, _nthPartEquation).m_valid;
3345 }
3346
3347
3357 {
3358 return bMakeLoopByteCode;
3359 }
3360
3361
3370 {
3371 return bPauseLock;
3372 }
3373
3374
3384 void ParserBase::LockPause(bool _bLock)
3385 {
3386 bPauseLock = _bLock;
3387 }
3388
3389
3399 void ParserBase::PauseLoopMode(bool _bPause)
3400 {
3402 {
3403 if (g_DbgDumpStack)
3404 NumeReKernel::print("DEBUG: Set loop pause mode to: " + toString(_bPause));
3405
3406 bPauseLoopByteCode = _bPause;
3407
3408 if (!_bPause)
3409 {
3412 }
3413 else
3415 }
3416 }
3417
3418
3429 {
3430 StringView sCurrentEquation(GetExpr());
3431 sNewEquation.strip();
3432
3433 if (sNewEquation == sCurrentEquation
3435 return true;
3436
3437 return false;
3438 }
3439
3440
3449 {
3452
3453 return false;
3454 }
3455
3456
3467 void ParserBase::Eval(value_type* results, int nBulkSize)
3468 {
3469 CreateRPN();
3470
3471#ifdef MUP_USE_OPENMP
3472//#define DEBUG_OMP_STUFF
3473#ifdef DEBUG_OMP_STUFF
3474 int* pThread = new int[nBulkSize];
3475 int* pIdx = new int[nBulkSize];
3476#endif
3477
3478 int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads);
3479 int nThreadID, ct = 0;
3480 omp_set_num_threads(nMaxThreads);
3481
3482 #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID)
3483 for (int i = 0; i < nBulkSize; ++i)
3484 {
3485 nThreadID = omp_get_thread_num();
3486 results[i] = ParseCmdCodeBulk(i, nThreadID);
3487
3488#ifdef DEBUG_OMP_STUFF
3489 #pragma omp critical
3490 {
3491 pThread[ct] = nThreadID;
3492 pIdx[ct] = i;
3493 ct++;
3494 }
3495#endif
3496 }
3497
3498#ifdef DEBUG_OMP_STUFF
3499 FILE* pFile = fopen("bulk_dbg.txt", "w");
3500 for (int i = 0; i < nBulkSize; ++i)
3501 {
3502 fprintf(pFile, "idx: %d thread: %d \n", pIdx[i], pThread[i]);
3503 }
3504
3505 delete [] pIdx;
3506 delete [] pThread;
3507
3508 fclose(pFile);
3509#endif
3510#endif
3511
3512 }
3513
3514
3524 string_type ParserBase::CreateTempVectorVar(const std::vector<mu::value_type>& vVar)
3525 {
3526 string_type sTempVarName = "_~TV[" + getNextVectorVarIndex() + "]";
3527
3528 if (!vVar.size())
3529 SetVectorVar(sTempVarName, std::vector<mu::value_type>(1, 0.0), false);
3530 else
3531 SetVectorVar(sTempVarName, vVar, false);
3532
3533 return sTempVarName;
3534 }
3535
3536
3548 void ParserBase::SetVectorVar(const std::string& sVarName, const std::vector<mu::value_type>& vVar, bool bAddVectorType)
3549 {
3550 if (!vVar.size())
3551 return;
3552
3553 //g_logger.debug("Declaring " + sVarName);
3554
3555 if (!bAddVectorType && mVectorVars.find(sVarName) == mVectorVars.end() && m_VarDef.find(sVarName) == m_VarDef.end())
3556 {
3557 // Create the storage for a new variable
3558 m_lDataStorage.push_back(new mu::value_type);
3559
3560 // Assign the first element of the vector
3561 // to this storage
3562 *m_lDataStorage.back() = vVar[0];
3563
3564 // Define a new variable
3565 DefineVar(sVarName, m_lDataStorage.back());
3566 }
3567 else if (!bAddVectorType && m_VarDef.find(sVarName) != m_VarDef.end())
3568 *(m_VarDef.find(sVarName)->second) = vVar[0];
3569
3570 mVectorVars[sVarName] = vVar;
3571 }
3572
3573
3582 std::vector<mu::value_type>* ParserBase::GetVectorVar(const std::string& sVarName)
3583 {
3584 if (mVectorVars.find(sVarName) == mVectorVars.end())
3585 return nullptr;
3586
3587 return &mVectorVars[sVarName];
3588 }
3589
3590
3600 void ParserBase::UpdateVectorVar(const std::string& sVarName)
3601 {
3602 if (mVectorVars.find(sVarName) == mVectorVars.end())
3603 return;
3604
3605 //g_logger.debug("Updating " + sVarName + " Exists: " + toString(GetVar().find(sVarName) != GetVar().end()));
3606
3607 *(GetVar().find(sVarName)->second) = mVectorVars[sVarName][0];
3608 }
3609
3610
3619 void ParserBase::ClearVectorVars(bool bIgnoreProcedureVects)
3620 {
3621 if (!mVectorVars.size())
3622 return;
3623
3624 auto iter = mVectorVars.begin();
3625
3626 while (iter != mVectorVars.end())
3627 {
3628 string siter = iter->first;
3629
3630 if ((iter->first).find('[') != string::npos && (iter->first).find(']') != string::npos)
3631 {
3632 if (bIgnoreProcedureVects && (iter->first).substr(0, 8) == "_~PROC~[")
3633 {
3634 iter++;
3635 continue;
3636 }
3637
3638 RemoveVar(iter->first);
3639 iter = mVectorVars.erase(iter);
3640 }
3641 else
3642 iter = mVectorVars.erase(iter); //iter++;
3643 }
3644
3645 if (!bIgnoreProcedureVects || !mVectorVars.size())
3646 {
3647 //g_logger.debug("Clearing vector vars and target.");
3648 mVectorVars.clear();
3650 }
3651 }
3652
3653
3663 bool ParserBase::ContainsVectorVars(StringView sExpr, bool ignoreSingletons)
3664 {
3665 for (auto iter = mVectorVars.begin(); iter != mVectorVars.end(); ++iter)
3666 {
3667 if (ignoreSingletons && iter->second.size() == 1)
3668 continue;
3669
3670 size_t nPos = sExpr.find(iter->first);
3671
3672 if (nPos != string::npos && (!nPos || checkDelimiter(sExpr.subview(nPos-1, iter->first.length()+2))))
3673 return true;
3674 }
3675
3676 static std::vector<std::string> vNDVECTFUNCS = {"logtoidx", "idxtolog"};
3677
3678 for (const auto& func : vNDVECTFUNCS)
3679 {
3680 size_t nPos = sExpr.find(func);
3681
3682 if (nPos != string::npos && (!nPos || checkDelimiter(sExpr.subview(nPos-1, func.length()+2))))
3683 return true;
3684 }
3685
3686
3687 return false;
3688 }
3689
3690 static bool isDelim(char c)
3691 {
3692 // Characters converted to a single logical expression
3693 return c >= 32 && c <= 126 && c != 36 && c != 39 && c != 46 && (c < 48 || c > 57) && (c < 64 || c > 90) && (c < 95 || c > 122);
3694 }
3695
3705 {
3706 return isDelim(sLine.front()) && isDelim(sLine.back());
3707 //static std::string sDelimiter = "+-*/ ()={}^&|!<>,\\%#~[]:";
3708 //
3710 //return sDelimiter.find(sLine.front()) != std::string::npos && sDelimiter.find(sLine.back()) != std::string::npos;
3711 }
3712
3713
3722 void ParserBase::replaceLocalVars(std::string& sLine)
3723 {
3724 if (!mVarMapPntr || !mVarMapPntr->size())
3725 return;
3726
3727 for (auto iter = mVarMapPntr->begin(); iter != mVarMapPntr->end(); ++iter)
3728 {
3729 for (unsigned int i = 0; i < sLine.length(); i++)
3730 {
3731 if (sLine.substr(i, (iter->first).length()) == iter->first)
3732 {
3733 if ((i && checkDelimiter(sLine.substr(i - 1, (iter->first).length() + 2)))
3734 || (!i && checkDelimiter(" " + sLine.substr(i, (iter->first).length() + 1))))
3735 {
3736 sLine.replace(i, (iter->first).length(), iter->second);
3737 }
3738 }
3739 }
3740 }
3741 }
3742
3743} // namespace mu
3744
This class extends the std::vector for endlessness.
Definition: structures.hpp:838
This class is a mutable version of a string view. It can be used to replace single characters or enti...
MutableStringView subview(size_t pos=0, size_t len=std::string::npos) const
This member function creates a new MutableStringView class instance using the selected position and l...
MutableStringView & replace(size_t pos, size_t len, const std::string &s)
This member function replaces a range in the internal viewed string with the passed string.
static void printPreFmt(const std::string &__sLine, bool printingEnabled=true)
This member function appends the pre- formatted string to the buffer and informs the terminal that we...
Definition: kernel.cpp:2683
static void print(const std::string &__sLine, bool printingEnabled=true)
This member function appends the passed string as a new output line to the buffer and informs the ter...
Definition: kernel.cpp:2636
void strip()
This member function shrinks the viewed section to remove all leading or trailing whitespace characte...
size_t find_first_of(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find_first_of()
const char & back() const
This member function provides a const char reference to the last character in the viewed section.
size_t find_last_of(const std::string &findstr, size_t pos=std::string::npos) const
Wrapper member function for std::string::find_last_of()
const char & front() const
This member function provides a const char reference to the first character in the viewed section.
std::string to_string() const
This member function returns a copy of the viewed section of the string (via std::string::substr)....
size_t find(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find()
size_t length() const
This member function simply returns the length of the viewed section.
size_t find_first_not_of(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find_first_not_of()
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
StringView subview(size_t pos=0, size_t len=std::string::npos) const
This member function creates a new StringView class instance using the selected position and length a...
A facet class used to change decimal and thousands separator.
Definition: muParserBase.h:235
Mathematical expressions parser (base parser engine).
Definition: muParserBase.h:69
varmap_type m_VarDef
user defind variables.
Definition: muParserBase.h:362
ParserTokenReader token_reader_type
Typedef for the token reader.
Definition: muParserBase.h:85
const string_type & GetExpr() const
Retrieve the formula.
const char_type * ValidInfixOprtChars() const
Virtual function that defines the characters allowed in infix operator definitions.
bool checkDelimiter(StringView sLine)
This member function checks, whether the passed string is delimited on both sides.
void CacheCurrentAccess(const CachedDataAccess &_access)
Store the passed data access for this position internally.
void StackDump(const ParserStack< token_type > &a_stVal, const ParserStack< token_type > &a_stOprt) const
Dump stack content.
void Assign(const ParserBase &a_Parser)
Copy state of a parser object to this.
void AddValIdent(identfun_type a_pCallback)
Add a value parsing function.
static const char_type * c_DefaultOprt[]
Identifiers for built in binary operators.
Definition: muParserBase.h:227
void CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, const string_type &a_szCharSet) const
Check if a name contains invalid characters.
ParseFunction m_pParseFormula
Pointer to the parser function.
Definition: muParserBase.h:330
void SetDecSep(char_type cDecSep)
Set the decimal separator.
size_t FindMultiArgFunc(StringView sExpr, size_t nPos, std::string &sMultArgFunc)
This function searches for the first multi-argument function found in the passed expression.
unsigned int nthLoopPartEquation
Definition: muParserBase.h:343
void ApplyBinOprt(ParserStack< token_type > &a_stOpt, ParserStack< token_type > &a_stVal) const
Performs the necessary steps to write code for the execution of binary operators into the bytecode.
MutableStringView compileVectors(MutableStringView sExpr)
This function pre-evaluates all vectors, which are contained in the expression passed through sExpr.
virtual void InitFun()=0
void SetExpr(StringView a_sExpr)
Set the expression. Triggers first time calculation thus the creation of the bytecode and scanning of...
value_type Eval()
Single-value wrapper around the vectorized overload of this member function.
void CheckName(const string_type &a_strName, const string_type &a_CharSet) const
Check if a name contains invalid characters.
const varmap_type & GetVar() const
Return a map containing the used variables only.
void CacheCurrentTarget(const std::string &sEquation)
Caches the passed target equation for this position.
void Init()
Initialize user defined functions.
stringbuf_type m_vStringBuf
String buffer, used for storing string function arguments.
Definition: muParserBase.h:351
void AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, funmap_type &a_Storage, const char_type *a_szCharSet)
Add a function or operator callback to the parser.
void ApplyIfElse(ParserStack< token_type > &a_stOpt, ParserStack< token_type > &a_stVal) const
const CachedDataAccess & GetCachedAccess(size_t nthAccess)
Returns the cached data access for the passed position.
int IsValidByteCode(unsigned int _nthLoopElement=-1, unsigned int _nthPartEquation=0)
This member function returns, whether the current equation is already parsed and there's a valid byte...
static bool g_DbgDumpStack
Definition: muParserBase.h:230
bool HasBuiltInOprt() const
Query status of built in variables.
void ResetLocale()
Resets the locale.
const std::string & GetCachedEquation() const
Returns the stored equation for this position.
const char_type ** GetOprtDef() const
Get the default symbols used for the built in operators.
void SetIndex(unsigned int _nLoopElement)
Activates the selected position in the internally stored bytecode.
void ParseCmdCodeBulkParallel(size_t nVectorLength)
OpenMP optimized parallel bytecode executor.
StateStacks m_stateStacks
Definition: muParserBase.h:333
string_type GetVersion(EParserVersionInfo eInfo=pviFULL) const
Returns the version of muparser.
void PauseLoopMode(bool _bPause=true)
This member function pauses the loop mode, so that the new assigned equation does not invalidate alre...
virtual void InitCharSets()=0
bool IsLockedPause() const
Check, whether the pause mode is locked.
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.
ParserBase()
Constructor.
void EnableOptimizer(bool a_bIsOn=true)
Enable or disable the formula optimization feature.
vectormap_type mVectorVars
Maximum number of threads spawned by OpenMP when using the bulk mode.
Definition: muParserBase.h:340
funmap_type m_InfixOprtDef
unary infix operator.
Definition: muParserBase.h:358
void ApplyFunc(ParserStack< token_type > &a_stOpt, ParserStack< token_type > &a_stVal, int iArgCount) const
Apply a function token.
const std::string & GetCachedTarget() const
Returns the stored target equation for this position.
unsigned int nCurrVectorIndex
Definition: muParserBase.h:344
virtual void InitOprt()=0
const valmap_type & GetConst() const
Return a map containing all parser constants.
void DeactivateLoopMode()
Deactivates the loop mode and resets the internal arrays.
void ClearVectorVars(bool bIgnoreProcedureVects=false)
This member function cleares the internal vector storage.
const std::map< std::string, std::vector< mu::value_type > > & GetVectors() const
int m_nIfElseCounter
Internal counter for keeping track of nested if-then-else clauses.
Definition: muParserBase.h:370
const varmap_type & GetUsedVar()
Return a map containing the used variables only.
void DefineStrConst(const string_type &a_sName, const string_type &a_strVal)
Define a new string constant.
valmap_type m_ConstDef
user constants.
Definition: muParserBase.h:360
bool compileVectorsInMultiArgFunc(MutableStringView &sExpr, size_t &nPos)
This private function will try to find a surrounding multi-argument function, resolve the arguments,...
bool ActiveLoopMode() const
Check, whether the loop mode is active. This function returns true even if the loop mode is paused.
void SetVarFactory(facfun_type a_pFactory, void *pUserData=NULL)
Set a function that can create variable pointer for unknown expression variables.
const funmap_type & GetFunDef() const
Return prototypes of all parser functions.
void ClearInfixOprt()
Clear the user defined Prefix operators.
std::vector< mu::value_type > * GetVectorVar(const std::string &sVarName)
This member function returns a pointer to the vector stored internally.
const char_type * ValidNameChars() const
Virtual function that defines the characters allowed in name identifiers.
void ParseString()
One of the two main parse functions.
void DefineVar(const string_type &a_sName, value_type *a_fVar)
Add a user defined variable.
void evaluateTemporaryVectors(const VectorEvaluation &vectEval, int nStackSize)
This member function evaluates the temporary vector expressions and assigns their results to their co...
bool bPauseLoopByteCode
Definition: muParserBase.h:346
void DefineConst(const string_type &a_sName, value_type a_fVal)
Add a user defined constant.
void RemoveVar(const string_type &a_strVarName)
Remove a variable from internal storage.
funmap_type m_FunDef
Map of function names and pointers.
Definition: muParserBase.h:356
virtual ~ParserBase()
void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool optimizeAway=true)
Add a user defined operator.
funmap_type m_PostOprtDef
Postfix operator callbacks.
Definition: muParserBase.h:357
bool CanCacheAccess()
Check, whether the current position can cache any data accesses.
funmap_type m_OprtDef
Binary operator callbacks.
Definition: muParserBase.h:359
void ApplyRemainingOprt(ParserStack< token_type > &a_stOpt, ParserStack< token_type > &a_stVal) const
Apply a binary operator.
bool IsAlreadyParsed(StringView sNewEquation)
This member function checks, whether the passed expression is already parsed, so that the parsing ste...
void ClearOprt()
Clear all user defined binary operators.
int GetOprtPrecedence(const token_type &a_Tok) const
Get operator priority.
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd)
void replaceLocalVars(std::string &sLine)
This member function replaces var occurences with the names of local variables.
void compileVectorExpansion(MutableStringView sSubExpr, const std::string &sVectorVarName)
This function evaluates the vector expansion, e.g. "{1:4}" = {1, 2, 3, 4}.
bool IsCompiling()
Returns true, if the parser is currently in compiling step.
bool IsNotLastStackItem() const
Check, whether there are more elements on the parsing stack remaining.
virtual void InitConst()=0
State m_compilingState
Definition: muParserBase.h:331
string_type m_sInfixOprtChars
Charset for infix operator tokens.
Definition: muParserBase.h:368
void DefineOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of binary operators and postfix operators.
void LockPause(bool _bLock=true)
This member function locks the pause mode so that it cannot be accidentally activated.
void ActivateLoopMode(unsigned int _nLoopLength)
Activates the loop mode and prepares the internal arrays for storing the necessary data.
ExpressionTarget m_compilingTarget
Definition: muParserBase.h:332
void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool optimizeAway=true)
Add a user defined operator.
ParserError exception_type
Type of the error class.
Definition: muParserBase.h:96
void SetThousandsSep(char_type cThousandsSep=0)
Sets the thousands operator.
EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const
Get operator priority.
string_type CreateTempVectorVar(const std::vector< mu::value_type > &vVar)
This member function copies the passed vector into the internal storage referencing it with a auto-ge...
void ClearPostfixOprt()
Clear all user defined postfix operators.
void CacheCurrentEquation(const std::string &sEquation)
Caches the passed equation for this position.
void ClearFun()
Clear all functions.
void ParseCmdCode()
Parse the command code.
token_type ApplyStrFunc(const token_type &a_FunTok, const std::vector< token_type > &a_vArg) const
Execute a function that takes a single string argument.
static bool g_DbgDumpCmdCode
Definition: muParserBase.h:229
void ReInit()
Reset parser to string parsing mode and clear internal buffers.
valbuf_type m_buffer
Definition: muParserBase.h:335
void DefineInfixOprtChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of infix operators.
ParserBase & operator=(const ParserBase &a_Parser)
Assignement operator.
void UpdateVectorVar(const std::string &sVarName)
This member function updates the corresponding variable of a vector with the previously newly assigne...
size_t HasCachedAccess()
Evaluate, whether there are any cached data accesses for this position.
std::map< std::string, std::string > * mVarMapPntr
Definition: muParserBase.h:98
void ParseCmdCodeBulk(int nOffset, int nThreadID)
Evaluate the RPN.
void DisableAccessCaching()
Disable the data access caching for this position.
static std::locale s_locale
The locale used by the parser.
Definition: muParserBase.h:228
const std::string EMPTYSTRING
Definition: muParserBase.h:373
bool ContainsVectorVars(StringView sExpr, bool ignoreSingletons)
This member function checks, whether the passed expression contains a vector.
unsigned int nthLoopElement
Definition: muParserBase.h:342
void ClearConst()
Clear all user defined constants.
const char_type * ValidOprtChars() const
Virtual function that defines the characters allowed in operator definitions.
void ClearVar()
Clear all user defined variables.
void expandVector(mu::value_type dFirst, const mu::value_type &dLast, const mu::value_type &dIncrement, std::vector< mu::value_type > &vResults)
This function expands the vector. Private member used by ParserBase::compileVectorExpansion().
void SetArgSep(char_type cArgSep)
Set argument separator.
std::unique_ptr< token_reader_type > m_pTokenReader
Managed pointer to the token reader object.
Definition: muParserBase.h:354
void DefineNameChars(const char_type *a_szCharset)
Define the set of valid characters to be used in names of functions, variables, constants.
void EnableBuiltInOprt(bool a_bIsOn=true)
Enable or disable the built in binary operators.
void SetCompiling(bool _bCompiling=true)
Activate the compiling step for the parser.
strmap_type m_StrVarDef
user defined string constants
Definition: muParserBase.h:361
static void EnableDebugDump(bool bDumpCmd, bool bDumpStack)
Enable the dumping of bytecode amd stack content on the console.
string_type getNextVectorVarIndex()
This member function returns the next free vector index, which can be used to create a new temporary ...
void InitTokenReader()
Initialize the token reader.
char_type GetArgSep() const
Get the argument separator character.
ExpressionTarget & getTarget() const
Simple state-considering wrapper around the ExpressionTarget structure.
string_type m_sNameChars
Charset for names.
Definition: muParserBase.h:366
bool m_bBuiltInOp
Flag that can be used for switching built in operators on and off.
Definition: muParserBase.h:364
string_type getNextVarObject(std::string &sArgList, bool bCut)
This member function returns the next comma-separated expression object from the passed argument list...
string_type m_sOprtChars
Charset for postfix/ binary operator tokens.
Definition: muParserBase.h:367
bool bMakeLoopByteCode
Definition: muParserBase.h:345
stringbuf_type m_vStringVarBuf
Definition: muParserBase.h:352
std::list< mu::value_type * > m_lDataStorage
Definition: muParserBase.h:99
void SetVectorVar(const std::string &sVarName, const std::vector< mu::value_type > &vVar, bool bAddVectorType=false)
This member function copies the passed vector into the internal storage referencing it with the passe...
void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri=0, EOprtAssociativity a_eAssociativity=oaLEFT, bool optimizeAway=true)
Define a binary operator.
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
Add Strung function entry to the parser bytecode.
void EnableOptimizer(bool bStat)
std::size_t GetMaxStackSize() const
void AddOp(ECmdCode a_Oprt)
Add an operator identifier to bytecode.
const SToken * GetBase() const
void ChangeVar(value_type *a_pOldVar, value_type *a_pNewVar, bool isVect)
Changes all old variable pointers to the new addresses. Will be used to compensate for different loca...
void AddVal(value_type a_fVal)
Add a Variable pointer to bytecode.
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
Add a bulk function to bytecode.
void AddFun(generic_fun_type a_pFun, int a_iArgc, bool optimizeAway)
Add a function to the bytecode.
void AsciiDump()
Dump bytecode (for debugging only!).
void AddVar(value_type *a_pVar)
Add a Variable pointer to bytecode.
void Finalize()
Add end marker to bytecode.
void AddAssignOp(value_type *a_pVar)
Add an assignement operator.
void AddIfElse(ECmdCode a_Oprt)
Encapsulation of prototypes for a numerical parser function.
void * GetAddr() const
Get the callback address for the parser function.
ECmdCode GetCode() const
Return the callback code.
Error class of the parser.
Parser stack implementation.
Definition: muParserStack.h:54
TValueType & top()
Return reference to the top object in the stack.
void push(const TValueType &a_Val)
Push an object into the stack.
Definition: muParserStack.h:97
TValueType pop()
Pop a value from the stack.
Definition: muParserStack.h:82
unsigned size() const
Return the number of stored elements.
bool empty() const
Returns true if stack is empty false otherwise.
ECmdCode GetCode() const
Return the token type.
bool IsOptimizable() const
TBase * GetVar() const
Get address of a variable token.
int GetArgCount() const
Return the number of function arguments.
generic_fun_type GetFuncAddr() const
Return the address of the callback function assoziated with function and operator tokens.
ParserToken & SetVal(TBase a_fVal, const TString &a_strTok=TString())
Make this token a value token.
ETypeCode GetType() const
TBase GetVal() const
void SetIdx(int a_iIdx)
Set an index associated with the token related data.
const TString & GetAsString() const
Return the token identifier.
EOprtAssociativity GetAssociativity() const
int GetPri() const
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
mu::value_type parser_Sum(const mu::value_type *, int)
This function summarizes all elements in the passed array.
mu::value_type parser_Med(const mu::value_type *, int)
This function calculates the median of the elements in the passed array.
mu::value_type parser_Std(const mu::value_type *, int)
This function calculates the standard deviation of the elements in the passed array.
mu::value_type parser_compare(const mu::value_type *, int)
This function searches for elements of a specified type in the passed array.
mu::value_type parser_product(const mu::value_type *, int)
This function calculates the product of all elements in the passed array.
mu::value_type parser_Pct(const mu::value_type *, int)
This function calculates the selected percentile of the passed array.
mu::value_type parser_Norm(const mu::value_type *, int)
This function calculates the vector norm of the elements in the passed array.
mu::value_type parser_or(const mu::value_type *, int)
This function calculates the logical OR operation between all elements in the passed array.
mu::value_type parser_Max(const mu::value_type *, int)
This function calculates the maximal value of all elements in the passed array.
mu::value_type parser_Cnt(const mu::value_type *, int)
This functioon simply returns the number of elements in its array (even the invalid ones).
mu::value_type parser_Min(const mu::value_type *, int)
This function calculates the minimal value of all elements in the passed array.
mu::value_type parser_and(const mu::value_type *, int)
This function calculates the logical AND operation between all elements in the passed array.
mu::value_type parser_Num(const mu::value_type *, int)
This function returns the number of valid elements in its array.
mu::value_type parser_Avg(const mu::value_type *, int)
This function calculates the average of all elements in passed array.
This file contains the class definition of the muparser engine.
#define MUP_VERSION_DATE
Definition: muParserDef.h:42
#define MUP_ASSERT(COND)
Definition: muParserDef.h:104
#define MUP_VERSION
Definition: muParserDef.h:41
#define _nrT(x)
Activate this option in order to compile with OpenMP support.
Definition: muParserDef.h:62
std::complex< double > intPower(const std::complex< double > &, int)
This function calculates the power of a value with the specialization that the exponent is an integer...
Definition: tools.cpp:3640
CONSTDATA date::last_spec last
Definition: date.h:1989
CONSTDATA date::month dec
Definition: date.h:2002
Namespace for mathematical applications.
Definition: muParser.cpp:53
value_type(* multfun_type)(const value_type *, int)
Callback type used for functions with a variable argument list.
Definition: muParserDef.h:356
value_type(* fun_type9)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:317
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
value_type(* fun_type6)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:308
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:362
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
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:365
value_type *(* facfun_type)(const char_type *, void *)
Callback used for variable creation factory functions.
Definition: muParserDef.h:371
bool isnan(const value_type &v)
Definition: muParserDef.h:379
std::vector< value_type > parser_logtoidx(const value_type *v, int n)
Adaption of the logtoidx() function for 1D data arrays.
value_type operator/(const value_type &__x, const value_type &__y)
Custom implementation for the complex division operator with a scalar optimization.
value_type(* fun_type10)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:320
static std::string printVector(const valbuf_type &buffer, int nElems)
Simple helper function to print the buffer's contents.
value_type(* strfun_type1)(const char_type *)
Callback type used for functions taking a string as an argument.
Definition: muParserDef.h:359
std::map< string_type, value_type > valmap_type
Type used for storing constants.
Definition: muParserDef.h:276
std::vector< double > real(const std::vector< value_type > &vVec)
static bool isDelim(char c)
value_type(* fun_type2)(const value_type &, const value_type &)
Callback type used for functions with two arguments.
Definition: muParserDef.h:296
string_type::value_type char_type
The character type used by the parser.
Definition: muParserDef.h:263
std::vector< double > imag(const std::vector< value_type > &vVec)
static bool stepIsStillPossible(const mu::value_type &current, const mu::value_type &last, const mu::value_type &d)
Determines, whether the passed step is still in valid range and therefore can be done to expand the v...
value_type(* fun_type7)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:311
std::vector< value_type > valbuf_type
Type used for storing an array of values.
Definition: muParserDef.h:282
value_type(* fun_type5)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:305
std::map< string_type, ParserCallback > funmap_type
Container for Callback objects.
value_type(* fun_type1)(const value_type &)
Callback type used for functions with a single arguments.
Definition: muParserDef.h:293
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:268
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Definition: muParserDef.h:273
@ cmVARMUL
Definition: muParserDef.h:185
@ cmVARPOW2
Definition: muParserDef.h:181
@ cmFUNC_BULK
Special callbacks for Bulk mode with an additional parameter for the bulk index.
Definition: muParserDef.h:191
@ 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
@ cmSTRING
Code for a string token.
Definition: muParserDef.h:192
@ cmDIV
Operator item: division.
Definition: muParserDef.h:166
@ cmLOR
Definition: muParserDef.h:169
@ cmENDIF
For use in the ternary if-then-else operator.
Definition: muParserDef.h:175
@ cmOPRT_INFIX
code for infix operators
Definition: muParserDef.h:195
@ cmBC
Operator item: closing bracket.
Definition: muParserDef.h:172
@ cmOPRT_BIN
user defined binary operator
Definition: muParserDef.h:193
@ cmVAL
value item
Definition: muParserDef.h:177
@ cmIF
For use in the ternary if-then-else operator.
Definition: muParserDef.h:173
@ cmUNKNOWN
uninitialized item
Definition: muParserDef.h:197
@ 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
@ cmVARPOWN
Definition: muParserDef.h:184
@ cmSUB
Operator item: subtract.
Definition: muParserDef.h:164
@ cmVARPOW3
Definition: muParserDef.h:182
@ cmFUNC_STR
Code for a function with a string parameter.
Definition: muParserDef.h:190
@ cmFUNC
Code for a generic function item.
Definition: muParserDef.h:189
@ cmVARPOW4
Definition: muParserDef.h:183
@ cmOPRT_POSTFIX
code for postfix operators
Definition: muParserDef.h:194
@ cmELSE
For use in the ternary if-then-else operator.
Definition: muParserDef.h:174
@ cmVAR
variable item
Definition: muParserDef.h:180
value_type operator*(const value_type &__x, const value_type &__y)
Custom implementation for the complex multiplication operator with a scalar optimization.
EParserVersionInfo
Definition: muParserDef.h:212
@ pviFULL
Definition: muParserDef.h:214
value_type rint(value_type v)
@ tpDBL
Floating point variables.
Definition: muParserDef.h:206
@ tpSTR
String type (Function arguments and constants only, no string variables)
Definition: muParserDef.h:205
EErrorCodes
Error codes.
Definition: muParserError.h:50
@ ecINVALID_NAME
Invalid function, variable or constant name.
Definition: muParserError.h:72
@ ecMISPLACED_COLON
Definition: muParserError.h:91
@ ecMISSING_PARENS
Missing parens. (Example: "3*sin(3")
Definition: muParserError.h:63
@ ecBUILTIN_OVERLOAD
Trying to overload builtin operator.
Definition: muParserError.h:77
@ ecUNEXPECTED_EOF
Unexpected end of formula. (Example: "2+sin(")
Definition: muParserError.h:54
@ ecNAME_CONFLICT
Name conflict.
Definition: muParserError.h:81
@ ecSTRING_EXPECTED
A string function has been called with a different type of argument.
Definition: muParserError.h:61
@ ecTOO_MANY_PARAMS
Too many function parameters.
Definition: muParserError.h:66
@ ecVAL_EXPECTED
A numerical function has been called with a non value type of argument.
Definition: muParserError.h:62
@ ecSTR_RESULT
result is a string
Definition: muParserError.h:69
@ ecUNEXPECTED_ARG
An unexpected argument has been found.
Definition: muParserError.h:56
@ ecUNEXPECTED_OPERATOR
Unexpected binary operator found.
Definition: muParserError.h:52
@ ecINVALID_INFIX_IDENT
Invalid function, variable or constant name.
Definition: muParserError.h:74
@ ecOPRT_TYPE_CONFLICT
binary operators may only be applied to value items of the same type
Definition: muParserError.h:68
@ ecINTERNAL_ERROR
Internal error of any kind.
Definition: muParserError.h:94
@ ecINVALID_VAR_PTR
Invalid variable pointer.
Definition: muParserError.h:79
@ ecUNEXPECTED_ARG_SEP
An unexpected comma has been found. (Example: "1,23")
Definition: muParserError.h:55
@ ecMISSING_ELSE_CLAUSE
Definition: muParserError.h:90
@ ecUNEXPECTED_CONDITIONAL
Definition: muParserError.h:89
@ ecINVALID_FUN_PTR
Invalid callback function pointer.
Definition: muParserError.h:78
@ ecTOO_FEW_PARAMS
Too few function parameters. (Example: "ite(1<2,2)")
Definition: muParserError.h:67
@ ecINVALID_POSTFIX_IDENT
Invalid function, variable or constant name.
Definition: muParserError.h:75
@ ecEMPTY_EXPRESSION
The Expression is empty.
Definition: muParserError.h:80
value_type(* fun_type8)(const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with five arguments.
Definition: muParserDef.h:314
std::vector< value_type > parser_idxtolog(const value_type *v, int n)
Adaption of the idxtolog() function for 1D data arrays.
value_type(* generic_fun_type)()
Callback type used for functions without arguments.
Definition: muParserDef.h:287
std::string string_type
The stringtype used by the parser.
Definition: muParserDef.h:257
value_type(* fun_type4)(const value_type &, const value_type &, const value_type &, const value_type &)
Callback type used for functions with four arguments.
Definition: muParserDef.h:302
@ prPOSTFIX
Postfix operator priority (currently unused)
Definition: muParserDef.h:241
@ prLOR
Definition: muParserDef.h:231
@ prCMP
comparsion operators
Definition: muParserDef.h:234
@ prPOW
power operator priority (highest)
Definition: muParserDef.h:237
@ prADD_SUB
addition
Definition: muParserDef.h:235
@ prMUL_DIV
multiplication/division
Definition: muParserDef.h:236
@ prLAND
Definition: muParserDef.h:232
value_type(* fun_type0)()
Callback type used for functions without arguments.
Definition: muParserDef.h:290
value_type(* fun_type3)(const value_type &, const value_type &, const value_type &)
Callback type used for functions with three arguments.
Definition: muParserDef.h:299
EOprtAssociativity
Parser operator precedence values.
Definition: muParserDef.h:220
@ oaLEFT
Definition: muParserDef.h:221
@ oaNONE
Definition: muParserDef.h:223
@ oaRIGHT
Definition: muParserDef.h:222
#define min(a, b)
Definition: resampler.cpp:34
Resample_Real(* func)(Resample_Real t)
Definition: resampler.cpp:372
#define max(a, b)
Definition: resampler.cpp:30
void StripSpaces(std::string &)
Removes leading and trailing white spaces and tabulator characters.
Describes an already evaluated data access, which can be reconstructed from the current parser state.
This structure defines the overall expression target, if it is composed out of a temporary vector lik...
void create(StringView sTargets, const varmap_type &usedVars)
Create a expression target made up from multiple variables.
void assign(const valbuf_type &buffer, int nResults)
Assign the calculated values to the target vector components.
static T Pow(const T &v1, const T &v2)
ECmdCode Cmd
Defines a single parser state, which contains all necessary information for evaluating a single expre...
VectorEvaluation m_vectEval
ParserByteCode m_byteCode
varmap_type m_usedVar
std::string m_expr
valbuf_type m_stackBuffer
size_t size() const
void resize(size_t s)
This structure contains the necessary data to resolve all preevaluated vectors.
std::string m_targetVect
void create(const std::string &sTargetVect)
Create a standard vector pre- evaluation.
std::vector< int > m_componentDefs
std::string toString(int)
Converts an integer to a string without the Settings bloat.
EndlessVector< StringView > getAllArguments(StringView sArgList)
Splits up the complete argument list and returns them as an EndlessVector.
Definition: tools.cpp:2346
bool isDelimiter(char c)
This function determines, if the passed character is a delimiter character.
Definition: tools.cpp:1852