From 483930946bb516d3c30402b960ca05390005dab2 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Thu, 16 Nov 2017 12:46:01 -0800 Subject: [PATCH 01/62] [muParser] Remove ecINTERNAL_ERROR Internal errors should not be represented as exceptions, but instead as assertion failures. --- muparser-2.2.5/include/muParserError.h | 3 --- muparser-2.2.5/include/muParserToken.h | 14 +++++++------- muparser-2.2.5/src/muParserBase.cpp | 18 +++++++++--------- muparser-2.2.5/src/muParserBytecode.cpp | 5 ++--- muparser-2.2.5/src/muParserDLL.cpp | 1 - muparser-2.2.5/src/muParserError.cpp | 1 - muparser-2.2.5/src/muParserTokenReader.cpp | 4 ++-- 7 files changed, 20 insertions(+), 26 deletions(-) diff --git a/muparser-2.2.5/include/muParserError.h b/muparser-2.2.5/include/muParserError.h index 7be257608..5837df682 100644 --- a/muparser-2.2.5/include/muParserError.h +++ b/muparser-2.2.5/include/muParserError.h @@ -89,9 +89,6 @@ enum EErrorCodes ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, - // internal errors - ecINTERNAL_ERROR = 36, ///< Internal error of any kind. - // The last two are special entries ecCOUNT, ///< This is no error code, It just stores just the total number of error codes ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index ff48bce7f..78a66b733 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -244,7 +244,7 @@ namespace mu void SetIdx(int a_iIdx) { if (m_iCode!=cmSTRING || a_iIdx<0) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); m_iIdx = a_iIdx; } @@ -260,7 +260,7 @@ namespace mu int GetIdx() const { if (m_iIdx<0 || m_iCode!=cmSTRING ) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); return m_iIdx; } @@ -300,10 +300,10 @@ namespace mu int GetPri() const { if ( !m_pCallback.get()) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); return m_pCallback->GetPri(); } @@ -312,7 +312,7 @@ namespace mu EOprtAssociativity GetAssociativity() const { if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); return m_pCallback->GetAssociativity(); } @@ -362,7 +362,7 @@ namespace mu TBase* GetVar() const { if (m_iCode!=cmVAR) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); return (TBase*)m_pTok; } @@ -377,7 +377,7 @@ namespace mu assert(m_pCallback.get()); if (!m_pCallback->GetAddr()) - throw ParserError(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); return m_pCallback->GetArgc(); } diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index bdda6041d..76dcbdee6 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -650,7 +650,7 @@ namespace mu // user defined binary operators case cmOPRT_INFIX: case cmOPRT_BIN: return a_Tok.GetPri(); - default: Error(ecINTERNAL_ERROR, 5); + default: assert(0 && "Unexpected operator in muParser"); return 999; } } @@ -766,7 +766,7 @@ namespace mu case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break; case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break; case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; - default: Error(ecINTERNAL_ERROR); + default: assert(0 && "Unexpected arg count"); } } catch(ParserError& ) @@ -814,7 +814,7 @@ namespace mu int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0); if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1) - Error(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); @@ -979,7 +979,7 @@ namespace mu break; default: - Error(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); } } } @@ -1110,7 +1110,7 @@ namespace mu case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; default: if (iArgCount>0) // function with variable arguments store the number as a negative value - Error(ecINTERNAL_ERROR, 1); + assert(0 && "muParser internal error"); sidx -= -iArgCount - 1; Stack[sidx] =(*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); @@ -1156,13 +1156,13 @@ namespace mu case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; default: - Error(ecINTERNAL_ERROR, 2); + assert(0 && "muParser internal error"); continue; } } default: - Error(ecINTERNAL_ERROR, 3); + assert(0 && "muParser internal error"); return 0; } // switch CmdCode } // for all bytecode tokens @@ -1363,7 +1363,7 @@ namespace mu ApplyFunc(stOpt, stVal, 1); // this is the postfix operator break; - default: Error(ecINTERNAL_ERROR, 3); + default: assert(0 && "muParser internal error"); } // end of switch operator-token opta = opt; @@ -1391,7 +1391,7 @@ namespace mu MUP_ASSERT(stArgCount.size()==1); m_nFinalResultIdx = stArgCount.top(); if (m_nFinalResultIdx==0) - Error(ecINTERNAL_ERROR, 9); + assert(0 && "muParser internal error"); if (stVal.size()==0) Error(ecEMPTY_EXPRESSION); diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index 38ae3f933..f29f4aaa1 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -460,9 +460,8 @@ namespace mu const SToken* ParserByteCode::GetBase() const { if (m_vRPN.size()==0) - throw ParserError(ecINTERNAL_ERROR); - else - return &m_vRPN[0]; + assert(0 && "muParser internal error"); + return &m_vRPN[0]; } //--------------------------------------------------------------------------- diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index a05476655..142020a04 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -52,7 +52,6 @@ if (pTag->errHandler) \ catch (...) \ { \ ParserTag *pTag = static_cast(a_hParser); \ - pTag->exc = muError_t(mu::ecINTERNAL_ERROR); \ pTag->bError = true; \ if (pTag->errHandler) \ (pTag->errHandler)(a_hParser); \ diff --git a/muparser-2.2.5/src/muParserError.cpp b/muparser-2.2.5/src/muParserError.cpp index 30c464846..566c41d60 100644 --- a/muparser-2.2.5/src/muParserError.cpp +++ b/muparser-2.2.5/src/muParserError.cpp @@ -65,7 +65,6 @@ namespace mu m_vErrMsg.resize(ecCOUNT); m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$."); - m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error"); m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\"."); m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\"."); m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\"."); diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index de15ff043..4d49f5e52 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -462,7 +462,7 @@ namespace mu break; default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... - Error(ecINTERNAL_ERROR); + assert(0 && "missing operator in muParser"); } // switch operator id m_iPos += (int)len; @@ -825,7 +825,7 @@ namespace mu m_iPos = iEnd; if (!m_pParser->m_vStringVarBuf.size()) - Error(ecINTERNAL_ERROR); + assert(0 && "muParser internal error"); a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() ); From 8364e597093f9acab347158c9711a14e62af9c93 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 12:34:52 -0800 Subject: [PATCH 02/62] [muparser] Remove MUP_USE_OPENMP We are not using OpenMP in the fish shell. --- muparser-2.2.5/include/muParserDef.h | 6 --- muparser-2.2.5/src/muParserBase.cpp | 56 +--------------------------- 2 files changed, 1 insertion(+), 61 deletions(-) diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index c8e3f930b..213f1f3de 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -51,12 +51,6 @@ */ #define MUP_BASETYPE double -/** \brief Activate this option in order to compile with OpenMP support. - - OpenMP is used only in the bulk mode it may increase the performance a bit. -*/ -//#define MUP_USE_OPENMP - #if defined(_UNICODE) /** \brief Definition of the basic parser string type. */ #define MUP_STRING_TYPE std::wstring diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 76dcbdee6..0a58b1580 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -36,10 +36,6 @@ #include #include -#ifdef MUP_USE_OPENMP - #include -#endif - using namespace std; /** \file @@ -291,12 +287,6 @@ namespace mu #endif #endif -#ifdef MUP_USE_OPENMP - ss << _T("; OPENMP"); -//#else -// ss << _T("; NO_OPENMP"); -#endif - #if defined(MUP_MATH_EXCEPTIONS) ss << _T("; MATHEXC"); //#else @@ -1726,53 +1716,9 @@ namespace mu CreateRPN(); int i = 0; - -#ifdef MUP_USE_OPENMP -//#define DEBUG_OMP_STUFF - #ifdef DEBUG_OMP_STUFF - int *pThread = new int[nBulkSize]; - int *pIdx = new int[nBulkSize]; - #endif - - int nMaxThreads = std::min(omp_get_max_threads(), s_MaxNumOpenMPThreads); - int nThreadID = 0, ct = 0; - omp_set_num_threads(nMaxThreads); - - #pragma omp parallel for schedule(static, nBulkSize/nMaxThreads) private(nThreadID) for (i=0; i Date: Sat, 18 Nov 2017 13:48:16 -0800 Subject: [PATCH 03/62] Add muparser example executable to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5f98b18a4..f59a91d54 100644 --- a/.gitignore +++ b/.gitignore @@ -90,6 +90,7 @@ messages.pot /muparser-*/bk-deps /muparser-*/shared-ld-sh /muparser-*/build/autoconf/muparser.pc +/muparser-2.2.5/samples/example1/example1 /pcre2-*/configure.lineno # xcode From e2b798cda38e26b3e1f69a46ace6a4aa663f1934 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 13:49:52 -0800 Subject: [PATCH 04/62] [muparser] Restyle muparser sources to match fish Add muparser soruces to style.fish, and run it to make muparser match fish style guidelines. --- build_tools/style.fish | 2 +- muparser-2.2.5/include/muParser.h | 119 +- muparser-2.2.5/include/muParserBase.h | 280 +- muparser-2.2.5/include/muParserBytecode.h | 116 +- muparser-2.2.5/include/muParserCallback.h | 113 +- muparser-2.2.5/include/muParserDLL.h | 311 +- muparser-2.2.5/include/muParserDef.h | 464 ++- muparser-2.2.5/include/muParserError.h | 198 +- muparser-2.2.5/include/muParserFixes.h | 34 +- muparser-2.2.5/include/muParserInt.h | 174 +- muparser-2.2.5/include/muParserStack.h | 141 +- .../include/muParserTemplateMagic.h | 159 +- muparser-2.2.5/include/muParserTest.h | 306 +- muparser-2.2.5/include/muParserToken.h | 521 ++- muparser-2.2.5/include/muParserTokenReader.h | 210 +- muparser-2.2.5/src/muParser.cpp | 524 ++- muparser-2.2.5/src/muParserBase.cpp | 2872 +++++++++-------- muparser-2.2.5/src/muParserBytecode.cpp | 883 ++--- muparser-2.2.5/src/muParserCallback.cpp | 736 ++--- muparser-2.2.5/src/muParserDLL.cpp | 694 ++-- muparser-2.2.5/src/muParserError.cpp | 466 ++- muparser-2.2.5/src/muParserInt.cpp | 315 +- muparser-2.2.5/src/muParserTest.cpp | 2458 +++++++------- muparser-2.2.5/src/muParserTokenReader.cpp | 1181 +++---- 24 files changed, 6315 insertions(+), 6962 deletions(-) diff --git a/build_tools/style.fish b/build_tools/style.fish index 95213466d..a5889cb4e 100755 --- a/build_tools/style.fish +++ b/build_tools/style.fish @@ -29,7 +29,7 @@ if test $all = yes echo exit 1 end - set c_files src/*.h src/*.cpp + set c_files src/*.h src/*.cpp muparser-2.2.5/src/*.cpp muparser-2.2.5/include/*.h # For now we don't restyle all fish scripts other than completion scripts. That's because people # really like to vertically align the elements of the `complete` command and fish_indent # currently does not honor that whitespace. diff --git a/muparser-2.2.5/include/muParser.h b/muparser-2.2.5/include/muParser.h index 451cf7036..42e0cbe1c 100644 --- a/muparser-2.2.5/include/muParser.h +++ b/muparser-2.2.5/include/muParser.h @@ -1,26 +1,26 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_H #define MU_PARSER_H @@ -36,22 +36,19 @@ \brief Definition of the standard floating point parser. */ -namespace mu -{ - /** \brief Mathematical expressions parser. - - Standard implementation of the mathematical expressions parser. - Can be used as a reference implementation for subclassing the parser. +namespace mu { +/** \brief Mathematical expressions parser. - - (C) 2011 Ingo Berg
- muparser(at)beltoforion.de -
- */ - /* final */ class Parser : public ParserBase - { - public: + Standard implementation of the mathematical expressions parser. + Can be used as a reference implementation for subclassing the parser. + + (C) 2011 Ingo Berg
+ muparser(at)beltoforion.de +
+*/ +/* final */ class Parser : public ParserBase { + public: Parser(); virtual void InitCharSets(); @@ -60,56 +57,52 @@ namespace mu virtual void InitOprt(); virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - value_type Diff(value_type *a_Var, - value_type a_fPos, - value_type a_fEpsilon = 0) const; - - protected: + value_type Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon = 0) const; + protected: // Trigonometric functions - static value_type Sin(value_type); - static value_type Cos(value_type); - static value_type Tan(value_type); - static value_type Tan2(value_type, value_type); + static value_type Sin(value_type); + static value_type Cos(value_type); + static value_type Tan(value_type); + static value_type Tan2(value_type, value_type); // arcus functions - static value_type ASin(value_type); - static value_type ACos(value_type); - static value_type ATan(value_type); - static value_type ATan2(value_type, value_type); + static value_type ASin(value_type); + static value_type ACos(value_type); + static value_type ATan(value_type); + static value_type ATan2(value_type, value_type); // hyperbolic functions - static value_type Sinh(value_type); - static value_type Cosh(value_type); - static value_type Tanh(value_type); + static value_type Sinh(value_type); + static value_type Cosh(value_type); + static value_type Tanh(value_type); // arcus hyperbolic functions - static value_type ASinh(value_type); - static value_type ACosh(value_type); - static value_type ATanh(value_type); + static value_type ASinh(value_type); + static value_type ACosh(value_type); + static value_type ATanh(value_type); // Logarithm functions - static value_type Log2(value_type); // Logarithm Base 2 - static value_type Log10(value_type); // Logarithm Base 10 - static value_type Ln(value_type); // Logarithm Base e (natural logarithm) + static value_type Log2(value_type); // Logarithm Base 2 + static value_type Log10(value_type); // Logarithm Base 10 + static value_type Ln(value_type); // Logarithm Base e (natural logarithm) // misc - static value_type Exp(value_type); - static value_type Abs(value_type); - static value_type Sqrt(value_type); - static value_type Rint(value_type); - static value_type Sign(value_type); + static value_type Exp(value_type); + static value_type Abs(value_type); + static value_type Sqrt(value_type); + static value_type Rint(value_type); + static value_type Sign(value_type); // Prefix operators // !!! Unary Minus is a MUST if you want to use negative signs !!! - static value_type UnaryMinus(value_type); - static value_type UnaryPlus(value_type); + static value_type UnaryMinus(value_type); + static value_type UnaryPlus(value_type); // Functions with variable number of arguments - static value_type Sum(const value_type*, int); // sum - static value_type Avg(const value_type*, int); // mean value - static value_type Min(const value_type*, int); // minimum - static value_type Max(const value_type*, int); // maximum + static value_type Sum(const value_type *, int); // sum + static value_type Avg(const value_type *, int); // mean value + static value_type Min(const value_type *, int); // minimum + static value_type Max(const value_type *, int); // maximum - static int IsVal(const char_type* a_szExpr, int *a_iPos, value_type *a_fVal); - }; -} // namespace mu + static int IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal); +}; +} // namespace mu #endif - diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index a37927306..c02aa0547 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -1,49 +1,47 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_BASE_H #define MU_PARSER_BASE_H //--- Standard includes ------------------------------------------------------------------------ +#include #include -#include #include +#include #include #include -#include -#include +#include //--- Parser includes -------------------------------------------------------------------------- +#include "muParserBytecode.h" #include "muParserDef.h" +#include "muParserError.h" #include "muParserStack.h" #include "muParserTokenReader.h" -#include "muParserBytecode.h" -#include "muParserError.h" - -namespace mu -{ +namespace mu { /** \file \brief This file contains the class definition of the muparser engine. */ @@ -52,26 +50,24 @@ namespace mu /** \brief Mathematical expressions parser (base parser engine). \author (C) 2013 Ingo Berg - This is the implementation of a bytecode based mathematical expressions parser. - The formula will be parsed from string and converted into a bytecode. + This is the implementation of a bytecode based mathematical expressions parser. + The formula will be parsed from string and converted into a bytecode. Future calculations will be done with the bytecode instead the formula string - resulting in a significant performance increase. - Complementary to a set of internally implemented functions the parser is able to handle - user defined functions and variables. + resulting in a significant performance increase. + Complementary to a set of internally implemented functions the parser is able to handle + user defined functions and variables. */ -class ParserBase -{ -friend class ParserTokenReader; +class ParserBase { + friend class ParserTokenReader; -private: + private: + /** \brief Typedef for the parse functions. - /** \brief Typedef for the parse functions. - The parse function do the actual work. The parser exchanges - the function pointer to the parser function depending on + the function pointer to the parser function depending on which state it is in. (i.e. bytecode parser vs. string parser) */ - typedef value_type (ParserBase::*ParseFunction)() const; + typedef value_type (ParserBase::*ParseFunction)() const; /** \brief Type used for storing an array of values. */ typedef std::vector valbuf_type; @@ -81,31 +77,30 @@ private: /** \brief Typedef for the token reader. */ typedef ParserTokenReader token_reader_type; - + /** \brief Type used for parser tokens. */ typedef ParserToken token_type; /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ static const int s_MaxNumOpenMPThreads = 16; - public: + public: + /** \brief Type of the error class. - /** \brief Type of the error class. - Included for backwards compatibility. */ typedef ParserError exception_type; static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); - ParserBase(); + ParserBase(); ParserBase(const ParserBase &a_Parser); - ParserBase& operator=(const ParserBase &a_Parser); + ParserBase &operator=(const ParserBase &a_Parser); virtual ~ParserBase(); - - value_type Eval() const; - value_type* Eval(int &nStackSize) const; + + value_type Eval() const; + value_type *Eval(int &nStackSize) const; void Eval(value_type *results, int nBulkSize); int GetNumResults() const; @@ -117,34 +112,32 @@ private: void SetThousandsSep(char_type cThousandsSep = 0); void ResetLocale(); - void EnableOptimizer(bool a_bIsOn=true); - void EnableBuiltInOprt(bool a_bIsOn=true); + void EnableOptimizer(bool a_bIsOn = true); + void EnableBuiltInOprt(bool a_bIsOn = true); bool HasBuiltInOprt() const; void AddValIdent(identfun_type a_pCallback); - /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) + /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool + a_bAllowOpt = true) \brief Define a parser function without arguments. \param a_strName Name of the function \param a_pFun Pointer to the callback function \param a_bAllowOpt A flag indicating this function may be optimized */ - template - void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) - { - AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() ); + template + void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) { + AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars()); } - void DefineOprt(const string_type &a_strName, - fun_type2 a_pFun, - unsigned a_iPri=0, - EOprtAssociativity a_eAssociativity = oaLEFT, - bool a_bAllowOpt = false); + void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, + EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false); void DefineConst(const string_type &a_sName, value_type a_fVal); void DefineStrConst(const string_type &a_sName, const string_type &a_strVal); void DefineVar(const string_type &a_sName, value_type *a_fVar); - void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true); - void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true); + void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true); + void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, + bool a_bAllowOpt = true); // Clear user defined variables, constants or functions void ClearVar(); @@ -153,111 +146,91 @@ private: void ClearInfixOprt(); void ClearPostfixOprt(); void ClearOprt(); - + void RemoveVar(const string_type &a_strVarName); - const varmap_type& GetUsedVar() const; - const varmap_type& GetVar() const; - const valmap_type& GetConst() const; - const string_type& GetExpr() const; - const funmap_type& GetFunDef() const; + const varmap_type &GetUsedVar() const; + const varmap_type &GetVar() const; + const valmap_type &GetConst() const; + const string_type &GetExpr() const; + const funmap_type &GetFunDef() const; string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; - const char_type ** GetOprtDef() const; + const char_type **GetOprtDef() const; void DefineNameChars(const char_type *a_szCharset); void DefineOprtChars(const char_type *a_szCharset); void DefineInfixOprtChars(const char_type *a_szCharset); - const char_type* ValidNameChars() const; - const char_type* ValidOprtChars() const; - const char_type* ValidInfixOprtChars() const; + const char_type *ValidNameChars() const; + const char_type *ValidOprtChars() const; + const char_type *ValidInfixOprtChars() const; void SetArgSep(char_type cArgSep); char_type GetArgSep() const; - - void Error(EErrorCodes a_iErrc, - int a_iPos = (int)mu::string_type::npos, - const string_type &a_strTok = string_type() ) const; - protected: - + void Error(EErrorCodes a_iErrc, int a_iPos = (int)mu::string_type::npos, + const string_type &a_strTok = string_type()) const; + + protected: void Init(); virtual void InitCharSets() = 0; virtual void InitFun() = 0; virtual void InitConst() = 0; - virtual void InitOprt() = 0; + virtual void InitOprt() = 0; virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - static const char_type *c_DefaultOprt[]; + static const char_type *c_DefaultOprt[]; static std::locale s_locale; ///< The locale used by the parser static bool g_DbgDumpCmdCode; static bool g_DbgDumpStack; /** \brief A facet class used to change decimal and thousands separator. */ - template - class change_dec_sep : public std::numpunct - { - public: - - explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) - :std::numpunct() - ,m_nGroup(nGroup) - ,m_cDecPoint(cDecSep) - ,m_cThousandsSep(cThousandsSep) - {} - - protected: - - virtual char_type do_decimal_point() const - { - return m_cDecPoint; - } + template + class change_dec_sep : public std::numpunct { + public: + explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) + : std::numpunct(), + m_nGroup(nGroup), + m_cDecPoint(cDecSep), + m_cThousandsSep(cThousandsSep) {} - virtual char_type do_thousands_sep() const - { - return m_cThousandsSep; - } + protected: + virtual char_type do_decimal_point() const { return m_cDecPoint; } - virtual std::string do_grouping() const - { - // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 - // courtesy of Jens Bartsch - // original code: - // return std::string(1, (char)m_nGroup); - // new code: - return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); - } + virtual char_type do_thousands_sep() const { return m_cThousandsSep; } - private: + virtual std::string do_grouping() const { + // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 + // courtesy of Jens Bartsch + // original code: + // return std::string(1, (char)m_nGroup); + // new code: + return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); + } - int m_nGroup; - char_type m_cDecPoint; - char_type m_cThousandsSep; + private: + int m_nGroup; + char_type m_cDecPoint; + char_type m_cThousandsSep; }; - private: - + private: void Assign(const ParserBase &a_Parser); void InitTokenReader(); void ReInit() const; - void AddCallback( const string_type &a_strName, - const ParserCallback &a_Callback, - funmap_type &a_Storage, - const char_type *a_szCharSet ); + void AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, + funmap_type &a_Storage, const char_type *a_szCharSet); void ApplyRemainingOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; - void ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; + ParserStack &a_stVal) const; + void ApplyBinOprt(ParserStack &a_stOpt, ParserStack &a_stVal) const; - void ApplyIfElse(ParserStack &a_stOpt, - ParserStack &a_stVal) const; + void ApplyIfElse(ParserStack &a_stOpt, ParserStack &a_stVal) const; - void ApplyFunc(ParserStack &a_stOpt, - ParserStack &a_stVal, - int iArgCount) const; + void ApplyFunc(ParserStack &a_stOpt, ParserStack &a_stVal, + int iArgCount) const; token_type ApplyStrFunc(const token_type &a_FunTok, const std::vector &a_vArg) const; @@ -267,51 +240,52 @@ private: void CreateRPN() const; - value_type ParseString() const; + value_type ParseString() const; value_type ParseCmdCode() const; value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; - void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; - void CheckOprt(const string_type &a_sName, - const ParserCallback &a_Callback, - const string_type &a_szCharSet) const; + void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; + void CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, + const string_type &a_szCharSet) const; - void StackDump(const ParserStack &a_stVal, - const ParserStack &a_stOprt) const; + void StackDump(const ParserStack &a_stVal, + const ParserStack &a_stOprt) const; + + /** \brief Pointer to the parser function. - /** \brief Pointer to the parser function. - Eval() calls the function whose address is stored there. */ - mutable ParseFunction m_pParseFormula; - mutable ParserByteCode m_vRPN; ///< The Bytecode class. - mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments - stringbuf_type m_vStringVarBuf; + mutable ParseFunction m_pParseFormula; + mutable ParserByteCode m_vRPN; ///< The Bytecode class. + mutable stringbuf_type + m_vStringBuf; ///< String buffer, used for storing string function arguments + stringbuf_type m_vStringVarBuf; - std::auto_ptr m_pTokenReader; ///< Managed pointer to the token reader object. + std::auto_ptr + m_pTokenReader; ///< Managed pointer to the token reader object. - funmap_type m_FunDef; ///< Map of function names and pointers. - funmap_type m_PostOprtDef; ///< Postfix operator callbacks - funmap_type m_InfixOprtDef; ///< unary infix operator. - funmap_type m_OprtDef; ///< Binary operator callbacks - valmap_type m_ConstDef; ///< user constants. - strmap_type m_StrVarDef; ///< user defined string constants - varmap_type m_VarDef; ///< user defind variables. + funmap_type m_FunDef; ///< Map of function names and pointers. + funmap_type m_PostOprtDef; ///< Postfix operator callbacks + funmap_type m_InfixOprtDef; ///< unary infix operator. + funmap_type m_OprtDef; ///< Binary operator callbacks + valmap_type m_ConstDef; ///< user constants. + strmap_type m_StrVarDef; ///< user defined string constants + varmap_type m_VarDef; ///< user defind variables. - bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off + bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off - string_type m_sNameChars; ///< Charset for names - string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens - string_type m_sInfixOprtChars; ///< Charset for infix operator tokens - - mutable int m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses + string_type m_sNameChars; ///< Charset for names + string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens + string_type m_sInfixOprtChars; ///< Charset for infix operator tokens + + mutable int + m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses // items merely used for caching state information - mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine + mutable valbuf_type + m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine mutable int m_nFinalResultIdx; }; - } // namespace mu #endif - diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index 33e3c26c0..8544b17a2 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -1,33 +1,33 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_BYTECODE_H #define MU_PARSER_BYTECODE_H #include -#include #include +#include #include #include "muParserDef.h" @@ -38,56 +38,49 @@ \brief Definition of the parser bytecode class. */ - -namespace mu -{ - struct SToken - { +namespace mu { +struct SToken { ECmdCode Cmd; int StackPos; - union - { - struct //SValData - { - value_type *ptr; - value_type data; - value_type data2; - } Val; + union { + struct // SValData + { + value_type *ptr; + value_type data; + value_type data2; + } Val; - struct //SFunData - { - // Note: generic_fun_type is merely a placeholder. The real type could be - // anything between gun_type1 and fun_type9. I can't use a void - // pointer due to constraints in the ANSI standard which allows - // data pointers and function pointers to differ in size. - generic_fun_type ptr; - int argc; - int idx; - } Fun; + struct // SFunData + { + // Note: generic_fun_type is merely a placeholder. The real type could be + // anything between gun_type1 and fun_type9. I can't use a void + // pointer due to constraints in the ANSI standard which allows + // data pointers and function pointers to differ in size. + generic_fun_type ptr; + int argc; + int idx; + } Fun; - struct //SOprtData - { - value_type *ptr; - int offset; - } Oprt; + struct // SOprtData + { + value_type *ptr; + int offset; + } Oprt; }; - }; - - - /** \brief Bytecode implementation of the Math Parser. +}; - The bytecode contains the formula converted to revers polish notation stored in a continious - memory area. Associated with this data are operator codes, variable pointers, constant - values and function pointers. Those are necessary in order to calculate the result. - All those data items will be casted to the underlying datatype of the bytecode. +/** \brief Bytecode implementation of the Math Parser. - \author (C) 2004-2013 Ingo Berg +The bytecode contains the formula converted to revers polish notation stored in a continious +memory area. Associated with this data are operator codes, variable pointers, constant +values and function pointers. Those are necessary in order to calculate the result. +All those data items will be casted to the underlying datatype of the bytecode. + +\author (C) 2004-2013 Ingo Berg */ -class ParserByteCode -{ -private: - +class ParserByteCode { + private: /** \brief Token type for internal use only. */ typedef ParserToken token_type; @@ -99,19 +92,18 @@ private: /** \brief Maximum size needed for the stack. */ std::size_t m_iMaxStackSize; - + /** \brief The actual rpn storage. */ - rpn_type m_vRPN; + rpn_type m_vRPN; bool m_bEnableOptimizer; void ConstantFolding(ECmdCode a_Oprt); -public: - + public: ParserByteCode(); ParserByteCode(const ParserByteCode &a_ByteCode); - ParserByteCode& operator=(const ParserByteCode &a_ByteCode); + ParserByteCode &operator=(const ParserByteCode &a_ByteCode); void Assign(const ParserByteCode &a_ByteCode); void AddVar(value_type *a_pVar); @@ -130,12 +122,10 @@ public: std::size_t GetMaxStackSize() const; std::size_t GetSize() const; - const SToken* GetBase() const; + const SToken *GetBase() const; void AsciiDump(); }; -} // namespace mu +} // namespace mu #endif - - diff --git a/muparser-2.2.5/include/muParserCallback.h b/muparser-2.2.5/include/muParserCallback.h index 578bda041..ee48e734a 100644 --- a/muparser-2.2.5/include/muParserCallback.h +++ b/muparser-2.2.5/include/muParserCallback.h @@ -1,26 +1,26 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_CALLBACK_H @@ -32,47 +32,47 @@ \brief Definition of the parser callback class. */ -namespace mu -{ +namespace mu { /** \brief Encapsulation of prototypes for a numerical parser function. Encapsulates the prototyp for numerical parser functions. The class stores the number of arguments for parser functions as well as additional flags indication the function is non optimizeable. - The pointer to the callback function pointer is stored as void* + The pointer to the callback function pointer is stored as void* and needs to be casted according to the argument count. Negative argument counts indicate a parser function with a variable number - of arguments. + of arguments. \author (C) 2004-2011 Ingo Berg */ -class ParserCallback -{ -public: - ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eAssociativity); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); +class ParserCallback { + public: + ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, + ECmdCode a_iCode = cmFUNC); + ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, + EOprtAssociativity a_eAssociativity); + ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); + ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); + ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti); ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); @@ -80,39 +80,38 @@ public: ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti); ParserCallback(); - ParserCallback(const ParserCallback &a_Fun); - + ParserCallback(const ParserCallback& a_Fun); + ParserCallback* Clone() const; - bool IsOptimizable() const; + bool IsOptimizable() const; void* GetAddr() const; - ECmdCode GetCode() const; + ECmdCode GetCode() const; ETypeCode GetType() const; - int GetPri() const; + int GetPri() const; EOprtAssociativity GetAssociativity() const; int GetArgc() const; -private: - void *m_pFun; ///< Pointer to the callback function, casted to void - + private: + void* m_pFun; ///< Pointer to the callback function, casted to void + /** \brief Number of numeric function arguments - + This number is negative for functions with variable number of arguments. in this cases they represent the actual number of arguments found. */ - int m_iArgc; - int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. - EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators - ECmdCode m_iCode; + int m_iArgc; + int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. + EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators + ECmdCode m_iCode; ETypeCode m_iType; - bool m_bAllowOpti; ///< Flag indication optimizeability + bool m_bAllowOpti; ///< Flag indication optimizeability }; //------------------------------------------------------------------------------ /** \brief Container for Callback objects. */ -typedef std::map funmap_type; +typedef std::map funmap_type; -} // namespace mu +} // namespace mu #endif - diff --git a/muparser-2.2.5/include/muParserDLL.h b/muparser-2.2.5/include/muParserDLL.h index 180b4760e..1b8d60946 100644 --- a/muparser-2.2.5/include/muParserDLL.h +++ b/muparser-2.2.5/include/muParserDLL.h @@ -1,106 +1,116 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_DLL_H #define MU_PARSER_DLL_H #if defined(WIN32) || defined(_WIN32) - #ifdef MUPARSERLIB_EXPORTS - #define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl - #else - #define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl - #endif +#ifdef MUPARSERLIB_EXPORTS +#define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl #else - #define API_EXPORT(TYPE) TYPE +#define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl +#endif +#else +#define API_EXPORT(TYPE) TYPE #endif - #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif -/** \file +/** \file \brief This file contains the DLL interface of muparser. */ // Basic types -typedef void* muParserHandle_t; // parser handle +typedef void *muParserHandle_t; // parser handle #ifndef _UNICODE - typedef char muChar_t; // character type +typedef char muChar_t; // character type #else - typedef wchar_t muChar_t; // character type +typedef wchar_t muChar_t; // character type #endif -typedef int muBool_t; // boolean type -typedef int muInt_t; // integer type -typedef double muFloat_t; // floating point type +typedef int muBool_t; // boolean type +typedef int muInt_t; // integer type +typedef double muFloat_t; // floating point type // function types for calculation -typedef muFloat_t (*muFun0_t )(); -typedef muFloat_t (*muFun1_t )(muFloat_t); -typedef muFloat_t (*muFun2_t )(muFloat_t, muFloat_t); -typedef muFloat_t (*muFun3_t )(muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun4_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun5_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun6_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun7_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun8_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun9_t )(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun0_t)(); +typedef muFloat_t (*muFun1_t)(muFloat_t); +typedef muFloat_t (*muFun2_t)(muFloat_t, muFloat_t); +typedef muFloat_t (*muFun3_t)(muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun4_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun5_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun6_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun7_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t); +typedef muFloat_t (*muFun8_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t); +typedef muFloat_t (*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t, muFloat_t); // Function prototypes for bulkmode functions -typedef muFloat_t (*muBulkFun0_t )(int, int); -typedef muFloat_t (*muBulkFun1_t )(int, int, muFloat_t); -typedef muFloat_t (*muBulkFun2_t )(int, int, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun3_t )(int, int, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun4_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun5_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun6_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun7_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun8_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun9_t )(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun0_t)(int, int); +typedef muFloat_t (*muBulkFun1_t)(int, int, muFloat_t); +typedef muFloat_t (*muBulkFun2_t)(int, int, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun3_t)(int, int, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun4_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun5_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun6_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t); +typedef muFloat_t (*muBulkFun7_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun8_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun9_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muMultFun_t)(const muFloat_t*, muInt_t); -typedef muFloat_t (*muStrFun1_t)(const muChar_t*); -typedef muFloat_t (*muStrFun2_t)(const muChar_t*, muFloat_t); -typedef muFloat_t (*muStrFun3_t)(const muChar_t*, muFloat_t, muFloat_t); +typedef muFloat_t (*muMultFun_t)(const muFloat_t *, muInt_t); +typedef muFloat_t (*muStrFun1_t)(const muChar_t *); +typedef muFloat_t (*muStrFun2_t)(const muChar_t *, muFloat_t); +typedef muFloat_t (*muStrFun3_t)(const muChar_t *, muFloat_t, muFloat_t); // Functions for parser management -typedef void (*muErrorHandler_t)(muParserHandle_t a_hParser); // [optional] callback to an error handler -typedef muFloat_t* (*muFacFun_t)(const muChar_t*, void*); // [optional] callback for creating new variables -typedef muInt_t (*muIdentFun_t)(const muChar_t*, muInt_t*, muFloat_t*); // [optional] value identification callbacks +typedef void (*muErrorHandler_t)( + muParserHandle_t a_hParser); // [optional] callback to an error handler +typedef muFloat_t *(*muFacFun_t)(const muChar_t *, + void *); // [optional] callback for creating new variables +typedef muInt_t (*muIdentFun_t)(const muChar_t *, muInt_t *, + muFloat_t *); // [optional] value identification callbacks //----------------------------------------------------------------------------------------------------- // Constants -static const int muOPRT_ASCT_LEFT = 0; +static const int muOPRT_ASCT_LEFT = 0; static const int muOPRT_ASCT_RIGHT = 1; -static const int muBASETYPE_FLOAT = 0; -static const int muBASETYPE_INT = 1; +static const int muBASETYPE_FLOAT = 0; +static const int muBASETYPE_INT = 1; //----------------------------------------------------------------------------------------------------- // @@ -110,95 +120,120 @@ static const int muBASETYPE_INT = 1; // //----------------------------------------------------------------------------------------------------- - -// Basic operations / initialization +// Basic operations / initialization API_EXPORT(muParserHandle_t) mupCreate(int nBaseType); API_EXPORT(void) mupRelease(muParserHandle_t a_hParser); -API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser); +API_EXPORT(const muChar_t *) mupGetExpr(muParserHandle_t a_hParser); API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr); -API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData); -API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser); +API_EXPORT(void) +mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData); +API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser); API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); -API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum); +API_EXPORT(muFloat_t *) mupEvalMulti(muParserHandle_t a_hParser, int *nNum); API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize); // Defining callbacks / variables / constants -API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, + muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, + muBool_t a_bOptimize); // Defining bulkmode functions -API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun); -API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun); -API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun); -API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun); -API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun); -API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun); -API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun); -API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun); -API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun); -API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun); -API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun); +API_EXPORT(void) +mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun); // string functions -API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun); -API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun); -API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun); +API_EXPORT(void) +mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun); +API_EXPORT(void) +mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun); +API_EXPORT(void) +mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun); -API_EXPORT(void) mupDefineMultFun( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muMultFun_t a_pFun, - muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t *a_szName, muMultFun_t a_pFun, + muBool_t a_bOptimize); -API_EXPORT(void) mupDefineOprt( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun2_t a_pFun, - muInt_t a_nPrec, - muInt_t a_nOprtAsct, - muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, + muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bOptimize); -API_EXPORT(void) mupDefineConst( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFloat_t a_fVal ); +API_EXPORT(void) +mupDefineConst(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t a_fVal); -API_EXPORT(void) mupDefineStrConst( muParserHandle_t a_hParser, - const muChar_t* a_szName, - const muChar_t *a_sVal ); +API_EXPORT(void) +mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t *a_szName, const muChar_t *a_sVal); -API_EXPORT(void) mupDefineVar( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFloat_t *a_fVar); +API_EXPORT(void) +mupDefineVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar); -API_EXPORT(void) mupDefineBulkVar( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFloat_t *a_fVar); +API_EXPORT(void) +mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar); -API_EXPORT(void) mupDefinePostfixOprt( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bOptimize); +API_EXPORT(void) +mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pOprt, + muBool_t a_bOptimize); - -API_EXPORT(void) mupDefineInfixOprt( muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bOptimize); +API_EXPORT(void) +mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pOprt, + muBool_t a_bOptimize); // Define character sets for identifiers -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset); +API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t *a_szCharset); +API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t *a_szCharset); +API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t *a_szCharset); // Remove all / single variables -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName); +API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t *a_szName); API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser); API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser); API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser); @@ -208,9 +243,15 @@ API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser); API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser); API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser); -API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); -API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t** a_pVar); -API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, muFloat_t* a_pVar); +API_EXPORT(void) +mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, + muFloat_t **a_pVar); +API_EXPORT(void) +mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, + muFloat_t **a_pVar); +API_EXPORT(void) +mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, + muFloat_t *a_pVar); API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); @@ -223,19 +264,19 @@ API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t); API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser); API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser); API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler); -API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser); +API_EXPORT(const muChar_t *) mupGetErrorMsg(muParserHandle_t a_hParser); API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser); API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser); -API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser); -//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser); +API_EXPORT(const muChar_t *) mupGetErrorToken(muParserHandle_t a_hParser); +// API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser); // This is used for .NET only. It creates a new variable allowing the dll to // manage the variable rather than the .NET garbage collector. -API_EXPORT(muFloat_t*) mupCreateVar(); -API_EXPORT(void) mupReleaseVar(muFloat_t*); +API_EXPORT(muFloat_t *) mupCreateVar(); +API_EXPORT(void) mupReleaseVar(muFloat_t *); #ifdef __cplusplus } #endif -#endif // include guard +#endif // include guard diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 213f1f3de..7c2131438 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -1,34 +1,34 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2014 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MUP_DEF_H #define MUP_DEF_H #include -#include -#include #include +#include +#include #include "muParserFixes.h" @@ -41,7 +41,8 @@ #define MUP_CHARS _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") -/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */ +/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as + * exceptions. */ //#define MUP_MATH_EXCEPTIONS /** \brief Define the base datatype for values. @@ -52,121 +53,104 @@ #define MUP_BASETYPE double #if defined(_UNICODE) - /** \brief Definition of the basic parser string type. */ - #define MUP_STRING_TYPE std::wstring +/** \brief Definition of the basic parser string type. */ +#define MUP_STRING_TYPE std::wstring - #if !defined(_T) - #define _T(x) L##x - #endif // not defined _T +#if !defined(_T) +#define _T(x) L##x +#endif // not defined _T #else - #ifndef _T - #define _T(x) x - #endif - - /** \brief Definition of the basic parser string type. */ - #define MUP_STRING_TYPE std::string +#ifndef _T +#define _T(x) x +#endif + +/** \brief Definition of the basic parser string type. */ +#define MUP_STRING_TYPE std::string #endif #if defined(_DEBUG) - /** \brief Debug macro to force an abortion of the programm with a certain message. - */ - #define MUP_FAIL(MSG) \ - { \ - bool MSG=false; \ - assert(MSG); \ - } +/** \brief Debug macro to force an abortion of the programm with a certain message. +*/ +#define MUP_FAIL(MSG) \ + { \ + bool MSG = false; \ + assert(MSG); \ + } - /** \brief An assertion that does not kill the program. +/** \brief An assertion that does not kill the program. - This macro is neutralised in UNICODE builds. It's - too difficult to translate. - */ - #define MUP_ASSERT(COND) \ - if (!(COND)) \ - { \ - stringstream_type ss; \ - ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \ - << __FILE__ << _T(" line ") \ - << __LINE__ << _T("."); \ - throw ParserError( ss.str() ); \ - } + This macro is neutralised in UNICODE builds. It's + too difficult to translate. +*/ +#define MUP_ASSERT(COND) \ + if (!(COND)) { \ + stringstream_type ss; \ + ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") << __FILE__ << _T(" line ") \ + << __LINE__ << _T("."); \ + throw ParserError(ss.str()); \ + } #else - #define MUP_FAIL(MSG) - #define MUP_ASSERT(COND) +#define MUP_FAIL(MSG) +#define MUP_ASSERT(COND) #endif - -namespace mu -{ +namespace mu { #if defined(_UNICODE) - //------------------------------------------------------------------------------ - /** \brief Encapsulate wcout. */ - inline std::wostream& console() - { - return std::wcout; - } +//------------------------------------------------------------------------------ +/** \brief Encapsulate wcout. */ +inline std::wostream& console() { return std::wcout; } - /** \brief Encapsulate cin. */ - inline std::wistream& console_in() - { - return std::wcin; - } +/** \brief Encapsulate cin. */ +inline std::wistream& console_in() { return std::wcin; } #else - /** \brief Encapsulate cout. - - Used for supporting UNICODE more easily. - */ - inline std::ostream& console() - { - return std::cout; - } +/** \brief Encapsulate cout. - /** \brief Encapsulate cin. + Used for supporting UNICODE more easily. +*/ +inline std::ostream& console() { return std::cout; } - Used for supporting UNICODE more easily. - */ - inline std::istream& console_in() - { - return std::cin; - } +/** \brief Encapsulate cin. + + Used for supporting UNICODE more easily. +*/ +inline std::istream& console_in() { return std::cin; } #endif - //------------------------------------------------------------------------------ - /** \brief Bytecode values. +//------------------------------------------------------------------------------ +/** \brief Bytecode values. - \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! - */ - enum ECmdCode - { + \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! +*/ +enum ECmdCode { // The following are codes for built in binary operators // apart from built in operators the user has the opportunity to // add user defined operators. - cmLE = 0, ///< Operator item: less or equal - cmGE = 1, ///< Operator item: greater or equal - cmNEQ = 2, ///< Operator item: not equal - cmEQ = 3, ///< Operator item: equals - cmLT = 4, ///< Operator item: less than - cmGT = 5, ///< Operator item: greater than - cmADD = 6, ///< Operator item: add - cmSUB = 7, ///< Operator item: subtract - cmMUL = 8, ///< Operator item: multiply - cmDIV = 9, ///< Operator item: division - cmPOW = 10, ///< Operator item: y to the power of ... - cmLAND = 11, - cmLOR = 12, - cmASSIGN = 13, ///< Operator item: Assignment operator - cmBO = 14, ///< Operator item: opening bracket - cmBC = 15, ///< Operator item: closing bracket - cmIF = 16, ///< For use in the ternary if-then-else operator - cmELSE = 17, ///< For use in the ternary if-then-else operator - cmENDIF = 18, ///< For use in the ternary if-then-else operator - cmARG_SEP = 19, ///< function argument separator - cmVAR = 20, ///< variable item - cmVAL = 21, ///< value item + cmLE = 0, ///< Operator item: less or equal + cmGE = 1, ///< Operator item: greater or equal + cmNEQ = 2, ///< Operator item: not equal + cmEQ = 3, ///< Operator item: equals + cmLT = 4, ///< Operator item: less than + cmGT = 5, ///< Operator item: greater than + cmADD = 6, ///< Operator item: add + cmSUB = 7, ///< Operator item: subtract + cmMUL = 8, ///< Operator item: multiply + cmDIV = 9, ///< Operator item: division + cmPOW = 10, ///< Operator item: y to the power of ... + cmLAND = 11, + cmLOR = 12, + cmASSIGN = 13, ///< Operator item: Assignment operator + cmBO = 14, ///< Operator item: opening bracket + cmBC = 15, ///< Operator item: closing bracket + cmIF = 16, ///< For use in the ternary if-then-else operator + cmELSE = 17, ///< For use in the ternary if-then-else operator + cmENDIF = 18, ///< For use in the ternary if-then-else operator + cmARG_SEP = 19, ///< function argument separator + cmVAR = 20, ///< variable item + cmVAL = 21, ///< value item // For optimization purposes cmVARPOW2, @@ -176,187 +160,187 @@ namespace mu cmPOW2, // operators and functions - cmFUNC, ///< Code for a generic function item - cmFUNC_STR, ///< Code for a function with a string parameter - cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk index - cmSTRING, ///< Code for a string token - cmOPRT_BIN, ///< user defined binary operator - cmOPRT_POSTFIX, ///< code for postfix operators - cmOPRT_INFIX, ///< code for infix operators - cmEND, ///< end of formula - cmUNKNOWN ///< uninitialized item - }; + cmFUNC, ///< Code for a generic function item + cmFUNC_STR, ///< Code for a function with a string parameter + cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk + ///index + cmSTRING, ///< Code for a string token + cmOPRT_BIN, ///< user defined binary operator + cmOPRT_POSTFIX, ///< code for postfix operators + cmOPRT_INFIX, ///< code for infix operators + cmEND, ///< end of formula + cmUNKNOWN ///< uninitialized item +}; - //------------------------------------------------------------------------------ - /** \brief Types internally used by the parser. - */ - enum ETypeCode - { - tpSTR = 0, ///< String type (Function arguments and constants only, no string variables) - tpDBL = 1, ///< Floating point variables - tpVOID = 2 ///< Undefined type. - }; +//------------------------------------------------------------------------------ +/** \brief Types internally used by the parser. +*/ +enum ETypeCode { + tpSTR = 0, ///< String type (Function arguments and constants only, no string variables) + tpDBL = 1, ///< Floating point variables + tpVOID = 2 ///< Undefined type. +}; - //------------------------------------------------------------------------------ - enum EParserVersionInfo - { - pviBRIEF, - pviFULL - }; +//------------------------------------------------------------------------------ +enum EParserVersionInfo { pviBRIEF, pviFULL }; - //------------------------------------------------------------------------------ - /** \brief Parser operator precedence values. */ - enum EOprtAssociativity - { - oaLEFT = 0, - oaRIGHT = 1, - oaNONE = 2 - }; +//------------------------------------------------------------------------------ +/** \brief Parser operator precedence values. */ +enum EOprtAssociativity { oaLEFT = 0, oaRIGHT = 1, oaNONE = 2 }; - //------------------------------------------------------------------------------ - /** \brief Parser operator precedence values. */ - enum EOprtPrecedence - { +//------------------------------------------------------------------------------ +/** \brief Parser operator precedence values. */ +enum EOprtPrecedence { // binary operators - prLOR = 1, - prLAND = 2, - prLOGIC = 3, ///< logic operators - prCMP = 4, ///< comparsion operators + prLOR = 1, + prLAND = 2, + prLOGIC = 3, ///< logic operators + prCMP = 4, ///< comparsion operators prADD_SUB = 5, ///< addition prMUL_DIV = 6, ///< multiplication/division - prPOW = 7, ///< power operator priority (highest) + prPOW = 7, ///< power operator priority (highest) // infix operators - prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator + prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator prPOSTFIX = 6 ///< Postfix operator priority (currently unused) - }; +}; - //------------------------------------------------------------------------------ - // basic types +//------------------------------------------------------------------------------ +// basic types - /** \brief The numeric datatype used by the parser. - - Normally this is a floating point type either single or double precision. - */ - typedef MUP_BASETYPE value_type; +/** \brief The numeric datatype used by the parser. - /** \brief The stringtype used by the parser. + Normally this is a floating point type either single or double precision. +*/ +typedef MUP_BASETYPE value_type; - Depends on wether UNICODE is used or not. - */ - typedef MUP_STRING_TYPE string_type; +/** \brief The stringtype used by the parser. - /** \brief The character type used by the parser. - - Depends on wether UNICODE is used or not. - */ - typedef string_type::value_type char_type; + Depends on wether UNICODE is used or not. +*/ +typedef MUP_STRING_TYPE string_type; - /** \brief Typedef for easily using stringstream that respect the parser stringtype. */ - typedef std::basic_stringstream, - std::allocator > stringstream_type; +/** \brief The character type used by the parser. - // Data container types + Depends on wether UNICODE is used or not. +*/ +typedef string_type::value_type char_type; - /** \brief Type used for storing variables. */ - typedef std::map varmap_type; - - /** \brief Type used for storing constants. */ - typedef std::map valmap_type; - - /** \brief Type for assigning a string name to an index in the internal string table. */ - typedef std::map strmap_type; +/** \brief Typedef for easily using stringstream that respect the parser stringtype. */ +typedef std::basic_stringstream, std::allocator > + stringstream_type; - // Parser callbacks - - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*generic_fun_type)(); +// Data container types - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*fun_type0)(); +/** \brief Type used for storing variables. */ +typedef std::map varmap_type; - /** \brief Callback type used for functions with a single arguments. */ - typedef value_type (*fun_type1)(value_type); +/** \brief Type used for storing constants. */ +typedef std::map valmap_type; - /** \brief Callback type used for functions with two arguments. */ - typedef value_type (*fun_type2)(value_type, value_type); +/** \brief Type for assigning a string name to an index in the internal string table. */ +typedef std::map strmap_type; - /** \brief Callback type used for functions with three arguments. */ - typedef value_type (*fun_type3)(value_type, value_type, value_type); +// Parser callbacks - /** \brief Callback type used for functions with four arguments. */ - typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions without arguments. */ +typedef value_type (*generic_fun_type)(); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions without arguments. */ +typedef value_type (*fun_type0)(); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with a single arguments. */ +typedef value_type (*fun_type1)(value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with two arguments. */ +typedef value_type (*fun_type2)(value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with three arguments. */ +typedef value_type (*fun_type3)(value_type, value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with four arguments. */ +typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions without arguments. */ - typedef value_type (*bulkfun_type0)(int, int); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, + value_type); - /** \brief Callback type used for functions with a single arguments. */ - typedef value_type (*bulkfun_type1)(int, int, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type); - /** \brief Callback type used for functions with two arguments. */ - typedef value_type (*bulkfun_type2)(int, int, value_type, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type, value_type); - /** \brief Callback type used for functions with three arguments. */ - typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions with four arguments. */ - typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions without arguments. */ +typedef value_type (*bulkfun_type0)(int, int); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with a single arguments. */ +typedef value_type (*bulkfun_type1)(int, int, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with two arguments. */ +typedef value_type (*bulkfun_type2)(int, int, value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with three arguments. */ +typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with four arguments. */ +typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions with five arguments. */ - typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, + value_type); - /** \brief Callback type used for functions with a variable argument list. */ - typedef value_type (*multfun_type)(const value_type*, int); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, + value_type, value_type); - /** \brief Callback type used for functions taking a string as an argument. */ - typedef value_type (*strfun_type1)(const char_type*); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, + value_type, value_type, value_type); - /** \brief Callback type used for functions taking a string and a value as arguments. */ - typedef value_type (*strfun_type2)(const char_type*, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions taking a string and two values as arguments. */ - typedef value_type (*strfun_type3)(const char_type*, value_type, value_type); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type, value_type); - /** \brief Callback used for functions that identify values in a string. */ - typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal); +/** \brief Callback type used for functions with five arguments. */ +typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type, value_type, + value_type); - /** \brief Callback used for variable creation factory functions. */ - typedef value_type* (*facfun_type)(const char_type*, void*); -} // end of namespace +/** \brief Callback type used for functions with a variable argument list. */ +typedef value_type (*multfun_type)(const value_type*, int); + +/** \brief Callback type used for functions taking a string as an argument. */ +typedef value_type (*strfun_type1)(const char_type*); + +/** \brief Callback type used for functions taking a string and a value as arguments. */ +typedef value_type (*strfun_type2)(const char_type*, value_type); + +/** \brief Callback type used for functions taking a string and two values as arguments. */ +typedef value_type (*strfun_type3)(const char_type*, value_type, value_type); + +/** \brief Callback used for functions that identify values in a string. */ +typedef int (*identfun_type)(const char_type* sExpr, int* nPos, value_type* fVal); + +/** \brief Callback used for variable creation factory functions. */ +typedef value_type* (*facfun_type)(const char_type*, void*); +} // end of namespace #endif - diff --git a/muparser-2.2.5/include/muParserError.h b/muparser-2.2.5/include/muParserError.h index 5837df682..0bfb30437 100644 --- a/muparser-2.2.5/include/muParserError.h +++ b/muparser-2.2.5/include/muParserError.h @@ -1,173 +1,161 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_ERROR_H #define MU_PARSER_ERROR_H #include +#include +#include #include #include -#include #include -#include #include "muParserDef.h" -/** \file +/** \file \brief This file defines the error class used by the parser. */ -namespace mu -{ +namespace mu { /** \brief Error codes. */ -enum EErrorCodes -{ - // Formula syntax errors - ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found - ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. - ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") - ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") - ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found - ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found - ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found - ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing - ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position - ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument - ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument - ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") - ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") - ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") - ecTOO_MANY_PARAMS = 14, ///< Too many function parameters - ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") - ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type - ecSTR_RESULT = 17, ///< result is a string +enum EErrorCodes { + // Formula syntax errors + ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found + ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. + ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") + ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") + ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found + ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found + ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found + ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing + ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position + ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument + ecVAL_EXPECTED = + 10, ///< A numerical function has been called with a non value type of argument + ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") + ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") + ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") + ecTOO_MANY_PARAMS = 14, ///< Too many function parameters + ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") + ecOPRT_TYPE_CONFLICT = + 16, ///< binary operators may only be applied to value items of the same type + ecSTR_RESULT = 17, ///< result is a string - // Invalid Parser input Parameters - ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. - ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier - ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. - ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. + // Invalid Parser input Parameters + ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. + ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier + ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. + ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. - ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator - ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer - ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer - ecEMPTY_EXPRESSION = 25, ///< The Expression is empty - ecNAME_CONFLICT = 26, ///< Name conflict - ecOPT_PRI = 27, ///< Invalid operator priority - // - ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) - ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) - ecGENERIC = 30, ///< Generic error - ecLOCALE = 31, ///< Conflict with current locale + ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator + ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer + ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer + ecEMPTY_EXPRESSION = 25, ///< The Expression is empty + ecNAME_CONFLICT = 26, ///< Name conflict + ecOPT_PRI = 27, ///< Invalid operator priority + // + ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) + ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) + ecGENERIC = 30, ///< Generic error + ecLOCALE = 31, ///< Conflict with current locale - ecUNEXPECTED_CONDITIONAL = 32, - ecMISSING_ELSE_CLAUSE = 33, - ecMISPLACED_COLON = 34, + ecUNEXPECTED_CONDITIONAL = 32, + ecMISSING_ELSE_CLAUSE = 33, + ecMISPLACED_COLON = 34, - ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, + ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, - // The last two are special entries - ecCOUNT, ///< This is no error code, It just stores just the total number of error codes - ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages + // The last two are special entries + ecCOUNT, ///< This is no error code, It just stores just the total number of error codes + ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages }; //--------------------------------------------------------------------------- /** \brief A class that handles the error messages. */ -class ParserErrorMsg -{ -public: +class ParserErrorMsg { + public: typedef ParserErrorMsg self_type; - ParserErrorMsg& operator=(const ParserErrorMsg &); - ParserErrorMsg(const ParserErrorMsg&); + ParserErrorMsg &operator=(const ParserErrorMsg &); + ParserErrorMsg(const ParserErrorMsg &); ParserErrorMsg(); - ~ParserErrorMsg(); + ~ParserErrorMsg(); - static const ParserErrorMsg& Instance(); + static const ParserErrorMsg &Instance(); string_type operator[](unsigned a_iIdx) const; -private: - std::vector m_vErrMsg; ///< A vector with the predefined error messages - static const self_type m_Instance; ///< The instance pointer + private: + std::vector m_vErrMsg; ///< A vector with the predefined error messages + static const self_type m_Instance; ///< The instance pointer }; //--------------------------------------------------------------------------- -/** \brief Error class of the parser. +/** \brief Error class of the parser. \author Ingo Berg Part of the math parser package. */ -class ParserError -{ -private: - +class ParserError { + private: /** \brief Replace all ocuurences of a substring with another string. */ - void ReplaceSubString( string_type &strSource, - const string_type &strFind, - const string_type &strReplaceWith); + void ReplaceSubString(string_type &strSource, const string_type &strFind, + const string_type &strReplaceWith); void Reset(); -public: - + public: ParserError(); explicit ParserError(EErrorCodes a_iErrc); explicit ParserError(const string_type &sMsg); - ParserError( EErrorCodes a_iErrc, - const string_type &sTok, - const string_type &sFormula = string_type(), - int a_iPos = -1); - ParserError( EErrorCodes a_iErrc, - int a_iPos, - const string_type &sTok); - ParserError( const char_type *a_szMsg, - int a_iPos = -1, - const string_type &sTok = string_type()); + ParserError(EErrorCodes a_iErrc, const string_type &sTok, + const string_type &sFormula = string_type(), int a_iPos = -1); + ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type &sTok); + ParserError(const char_type *a_szMsg, int a_iPos = -1, const string_type &sTok = string_type()); ParserError(const ParserError &a_Obj); - ParserError& operator=(const ParserError &a_Obj); - ~ParserError(); + ParserError &operator=(const ParserError &a_Obj); + ~ParserError(); void SetFormula(const string_type &a_strFormula); - const string_type& GetExpr() const; - const string_type& GetMsg() const; + const string_type &GetExpr() const; + const string_type &GetMsg() const; int GetPos() const; - const string_type& GetToken() const; + const string_type &GetToken() const; EErrorCodes GetCode() const; -private: - string_type m_strMsg; ///< The message string - string_type m_strFormula; ///< Formula string - string_type m_strTok; ///< Token related with the error - int m_iPos; ///< Formula position related to the error - EErrorCodes m_iErrc; ///< Error code + private: + string_type m_strMsg; ///< The message string + string_type m_strFormula; ///< Formula string + string_type m_strTok; ///< Token related with the error + int m_iPos; ///< Formula position related to the error + EErrorCodes m_iErrc; ///< Error code const ParserErrorMsg &m_ErrMsg; -}; +}; -} // namespace mu +} // namespace mu #endif - diff --git a/muparser-2.2.5/include/muParserFixes.h b/muparser-2.2.5/include/muParserFixes.h index 0a07237c4..35bcdd80d 100644 --- a/muparser-2.2.5/include/muParserFixes.h +++ b/muparser-2.2.5/include/muParserFixes.h @@ -1,26 +1,26 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_FIXES_H @@ -45,18 +45,16 @@ // remark #981: operands are evaluated in unspecified order // disabled -> completely pointless if the functions do not have side effects // -#pragma warning(disable:981) +#pragma warning(disable : 981) // remark #383: value copied to temporary, reference to temporary used -#pragma warning(disable:383) +#pragma warning(disable : 383) // remark #1572: floating-point equality and inequality comparisons are unreliable // disabled -> everyone knows it, the parser passes this problem // deliberately to the user -#pragma warning(disable:1572) +#pragma warning(disable : 1572) #endif -#endif // include guard - - +#endif // include guard diff --git a/muparser-2.2.5/include/muParserInt.h b/muparser-2.2.5/include/muParserInt.h index 4db2be8b6..6869fd67e 100644 --- a/muparser-2.2.5/include/muParserInt.h +++ b/muparser-2.2.5/include/muParserInt.h @@ -1,131 +1,116 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_INT_H #define MU_PARSER_INT_H -#include "muParserBase.h" #include - +#include "muParserBase.h" /** \file \brief Definition of a parser using integer value. */ - -namespace mu -{ +namespace mu { /** \brief Mathematical expressions parser. - - This version of the parser handles only integer numbers. It disables the built in operators thus it is + + This version of the parser handles only integer numbers. It disables the built in operators thus + it is slower than muParser. Integer values are stored in the double value_type and converted if needed. */ -class ParserInt : public ParserBase -{ -private: - static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); }; - - static value_type Abs(value_type); - static value_type Sign(value_type); - static value_type Ite(value_type, value_type, value_type); - // !! The unary Minus is a MUST, otherwise you cant use negative signs !! - static value_type UnaryMinus(value_type); - // Functions with variable number of arguments - static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum - static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum - static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum - // binary operator callbacks - static value_type Add(value_type v1, value_type v2); - static value_type Sub(value_type v1, value_type v2); - static value_type Mul(value_type v1, value_type v2); - static value_type Div(value_type v1, value_type v2); - static value_type Mod(value_type v1, value_type v2); - static value_type Pow(value_type v1, value_type v2); - static value_type Shr(value_type v1, value_type v2); - static value_type Shl(value_type v1, value_type v2); - static value_type LogAnd(value_type v1, value_type v2); - static value_type LogOr(value_type v1, value_type v2); - static value_type And(value_type v1, value_type v2); - static value_type Or(value_type v1, value_type v2); - static value_type Xor(value_type v1, value_type v2); - static value_type Less(value_type v1, value_type v2); - static value_type Greater(value_type v1, value_type v2); - static value_type LessEq(value_type v1, value_type v2); - static value_type GreaterEq(value_type v1, value_type v2); - static value_type Equal(value_type v1, value_type v2); - static value_type NotEqual(value_type v1, value_type v2); - static value_type Not(value_type v1); +class ParserInt : public ParserBase { + private: + static int Round(value_type v) { return (int)(v + ((v >= 0) ? 0.5 : -0.5)); }; - static int IsHexVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); - static int IsBinVal(const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); - static int IsVal (const char_type* a_szExpr, int *a_iPos, value_type *a_iVal); + static value_type Abs(value_type); + static value_type Sign(value_type); + static value_type Ite(value_type, value_type, value_type); + // !! The unary Minus is a MUST, otherwise you cant use negative signs !! + static value_type UnaryMinus(value_type); + // Functions with variable number of arguments + static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum + static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum + static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum + // binary operator callbacks + static value_type Add(value_type v1, value_type v2); + static value_type Sub(value_type v1, value_type v2); + static value_type Mul(value_type v1, value_type v2); + static value_type Div(value_type v1, value_type v2); + static value_type Mod(value_type v1, value_type v2); + static value_type Pow(value_type v1, value_type v2); + static value_type Shr(value_type v1, value_type v2); + static value_type Shl(value_type v1, value_type v2); + static value_type LogAnd(value_type v1, value_type v2); + static value_type LogOr(value_type v1, value_type v2); + static value_type And(value_type v1, value_type v2); + static value_type Or(value_type v1, value_type v2); + static value_type Xor(value_type v1, value_type v2); + static value_type Less(value_type v1, value_type v2); + static value_type Greater(value_type v1, value_type v2); + static value_type LessEq(value_type v1, value_type v2); + static value_type GreaterEq(value_type v1, value_type v2); + static value_type Equal(value_type v1, value_type v2); + static value_type NotEqual(value_type v1, value_type v2); + static value_type Not(value_type v1); + + static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); + static int IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); + static int IsVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); /** \brief A facet class used to change decimal and thousands separator. */ - template - class change_dec_sep : public std::numpunct - { - public: - - explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) - :std::numpunct() - ,m_cDecPoint(cDecSep) - ,m_cThousandsSep(cThousandsSep) - ,m_nGroup(nGroup) - {} - - protected: - - virtual char_type do_decimal_point() const - { - return m_cDecPoint; - } + template + class change_dec_sep : public std::numpunct { + public: + explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) + : std::numpunct(), + m_cDecPoint(cDecSep), + m_cThousandsSep(cThousandsSep), + m_nGroup(nGroup) {} - virtual char_type do_thousands_sep() const - { - return m_cThousandsSep; - } + protected: + virtual char_type do_decimal_point() const { return m_cDecPoint; } - virtual std::string do_grouping() const - { - // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 - // courtesy of Jens Bartsch - // original code: - // return std::string(1, (char)m_nGroup); - // new code: - return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); - } + virtual char_type do_thousands_sep() const { return m_cThousandsSep; } - private: + virtual std::string do_grouping() const { + // fix for issue 4: https://code.google.com/p/muparser/issues/detail?id=4 + // courtesy of Jens Bartsch + // original code: + // return std::string(1, (char)m_nGroup); + // new code: + return std::string(1, (char)(m_cThousandsSep > 0 ? m_nGroup : CHAR_MAX)); + } - int m_nGroup; - char_type m_cDecPoint; - char_type m_cThousandsSep; + private: + int m_nGroup; + char_type m_cDecPoint; + char_type m_cThousandsSep; }; -public: + public: ParserInt(); virtual void InitFun(); @@ -134,7 +119,6 @@ public: virtual void InitCharSets(); }; -} // namespace mu +} // namespace mu #endif - diff --git a/muparser-2.2.5/include/muParserStack.h b/muparser-2.2.5/include/muParserStack.h index a4c20a5c8..af6a8a0fc 100644 --- a/muparser-2.2.5/include/muParserStack.h +++ b/muparser-2.2.5/include/muParserStack.h @@ -1,125 +1,104 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_STACK_H #define MU_PARSER_STACK_H #include -#include #include +#include #include #include "muParserError.h" #include "muParserToken.h" -/** \file +/** \file \brief This file defines the stack used by muparser. */ -namespace mu -{ +namespace mu { - /** \brief Parser stack implementation. +/** \brief Parser stack implementation. - Stack implementation based on a std::stack. The behaviour of pop() had been - slightly changed in order to get an error code if the stack is empty. - The stack is used within the Parser both as a value stack and as an operator stack. + Stack implementation based on a std::stack. The behaviour of pop() had been + slightly changed in order to get an error code if the stack is empty. + The stack is used within the Parser both as a value stack and as an operator stack. - \author (C) 2004-2011 Ingo Berg - */ - template - class ParserStack - { - private: + \author (C) 2004-2011 Ingo Berg +*/ +template +class ParserStack { + private: + /** \brief Type of the underlying stack implementation. */ + typedef std::stack > impl_type; - /** \brief Type of the underlying stack implementation. */ - typedef std::stack > impl_type; - - impl_type m_Stack; ///< This is the actual stack. + impl_type m_Stack; ///< This is the actual stack. - public: - - //--------------------------------------------------------------------------- - ParserStack() - :m_Stack() - {} + public: + //--------------------------------------------------------------------------- + ParserStack() : m_Stack() {} - //--------------------------------------------------------------------------- - virtual ~ParserStack() - {} + //--------------------------------------------------------------------------- + virtual ~ParserStack() {} - //--------------------------------------------------------------------------- - /** \brief Pop a value from the stack. - - Unlike the standard implementation this function will return the value that - is going to be taken from the stack. + //--------------------------------------------------------------------------- + /** \brief Pop a value from the stack. - \throw ParserException in case the stack is empty. - \sa pop(int &a_iErrc) - */ - TValueType pop() - { - if (empty()) - throw ParserError( _T("stack is empty.") ); + Unlike the standard implementation this function will return the value that + is going to be taken from the stack. + + \throw ParserException in case the stack is empty. + \sa pop(int &a_iErrc) + */ + TValueType pop() { + if (empty()) throw ParserError(_T("stack is empty.")); TValueType el = top(); m_Stack.pop(); return el; - } + } - /** \brief Push an object into the stack. + /** \brief Push an object into the stack. - \param a_Val object to push into the stack. - \throw nothrow - */ - void push(const TValueType& a_Val) - { - m_Stack.push(a_Val); - } + \param a_Val object to push into the stack. + \throw nothrow + */ + void push(const TValueType& a_Val) { m_Stack.push(a_Val); } - /** \brief Return the number of stored elements. */ - unsigned size() const - { - return (unsigned)m_Stack.size(); - } + /** \brief Return the number of stored elements. */ + unsigned size() const { return (unsigned)m_Stack.size(); } - /** \brief Returns true if stack is empty false otherwise. */ - bool empty() const - { - return m_Stack.empty(); - } - - /** \brief Return reference to the top object in the stack. - - The top object is the one pushed most recently. - */ - TValueType& top() - { - return m_Stack.top(); - } - }; -} // namespace MathUtils + /** \brief Returns true if stack is empty false otherwise. */ + bool empty() const { return m_Stack.empty(); } + + /** \brief Return reference to the top object in the stack. + + The top object is the one pushed most recently. + */ + TValueType& top() { return m_Stack.top(); } +}; +} // namespace MathUtils #endif diff --git a/muparser-2.2.5/include/muParserTemplateMagic.h b/muparser-2.2.5/include/muParserTemplateMagic.h index 1caeb4b6d..dc52ff763 100644 --- a/muparser-2.2.5/include/muParserTemplateMagic.h +++ b/muparser-2.2.5/include/muParserTemplateMagic.h @@ -4,110 +4,97 @@ #include #include "muParserError.h" +namespace mu { +//----------------------------------------------------------------------------------------------- +// +// Compile time type detection +// +//----------------------------------------------------------------------------------------------- -namespace mu -{ - //----------------------------------------------------------------------------------------------- - // - // Compile time type detection - // - //----------------------------------------------------------------------------------------------- - - /** \brief A class singling out integer types at compile time using - template meta programming. - */ - template - struct TypeInfo - { +/** \brief A class singling out integer types at compile time using + template meta programming. +*/ +template +struct TypeInfo { static bool IsInteger() { return false; } - }; +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; - template<> - struct TypeInfo - { - static bool IsInteger() { return true; } - }; +template <> +struct TypeInfo { + static bool IsInteger() { return true; } +}; +//----------------------------------------------------------------------------------------------- +// +// Standard math functions with dummy overload for integer types +// +//----------------------------------------------------------------------------------------------- - //----------------------------------------------------------------------------------------------- - // - // Standard math functions with dummy overload for integer types - // - //----------------------------------------------------------------------------------------------- +/** \brief A template class for providing wrappers for essential math functions. - /** \brief A template class for providing wrappers for essential math functions. - - This template is spezialized for several types in order to provide a unified interface - for parser internal math function calls regardless of the data type. - */ - template - struct MathImpl - { - static T Sin(T v) { return sin(v); } - static T Cos(T v) { return cos(v); } - static T Tan(T v) { return tan(v); } - static T ASin(T v) { return asin(v); } - static T ACos(T v) { return acos(v); } - static T ATan(T v) { return atan(v); } + This template is spezialized for several types in order to provide a unified interface + for parser internal math function calls regardless of the data type. +*/ +template +struct MathImpl { + static T Sin(T v) { return sin(v); } + static T Cos(T v) { return cos(v); } + static T Tan(T v) { return tan(v); } + static T ASin(T v) { return asin(v); } + static T ACos(T v) { return acos(v); } + static T ATan(T v) { return atan(v); } static T ATan2(T v1, T v2) { return atan2(v1, v2); } - static T Sinh(T v) { return sinh(v); } - static T Cosh(T v) { return cosh(v); } - static T Tanh(T v) { return tanh(v); } + static T Sinh(T v) { return sinh(v); } + static T Cosh(T v) { return cosh(v); } + static T Tanh(T v) { return tanh(v); } static T ASinh(T v) { return log(v + sqrt(v * v + 1)); } static T ACosh(T v) { return log(v + sqrt(v * v - 1)); } static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); } - static T Log(T v) { return log(v); } - static T Log2(T v) { return log(v)/log((T)2); } // Logarithm base 2 - static T Log10(T v) { return log10(v); } // Logarithm base 10 - static T Exp(T v) { return exp(v); } - static T Abs(T v) { return (v>=0) ? v : -v; } - static T Sqrt(T v) { return sqrt(v); } - static T Rint(T v) { return floor(v + (T)0.5); } - static T Sign(T v) { return (T)((v<0) ? -1 : (v>0) ? 1 : 0); } + static T Log(T v) { return log(v); } + static T Log2(T v) { return log(v) / log((T)2); } // Logarithm base 2 + static T Log10(T v) { return log10(v); } // Logarithm base 10 + static T Exp(T v) { return exp(v); } + static T Abs(T v) { return (v >= 0) ? v : -v; } + static T Sqrt(T v) { return sqrt(v); } + static T Rint(T v) { return floor(v + (T)0.5); } + static T Sign(T v) { return (T)((v < 0) ? -1 : (v > 0) ? 1 : 0); } static T Pow(T v1, T v2) { return std::pow(v1, v2); } - }; +}; } #endif diff --git a/muparser-2.2.5/include/muParserTest.h b/muparser-2.2.5/include/muParserTest.h index e8da872c5..5793a98b1 100644 --- a/muparser-2.2.5/include/muParserTest.h +++ b/muparser-2.2.5/include/muParserTest.h @@ -1,34 +1,34 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_TEST_H #define MU_PARSER_TEST_H -#include #include -#include // for accumulate +#include // for accumulate +#include #include "muParser.h" #include "muParserInt.h" @@ -36,179 +36,169 @@ \brief This file contains the parser test class. */ -namespace mu +namespace mu { +/** \brief Namespace for test cases. */ +namespace Test { +//------------------------------------------------------------------------------ +/** \brief Test cases for unit testing. + + (C) 2004-2011 Ingo Berg +*/ +class ParserTester // final { - /** \brief Namespace for test cases. */ - namespace Test - { - //------------------------------------------------------------------------------ - /** \brief Test cases for unit testing. + private: + static int c_iCount; - (C) 2004-2011 Ingo Berg - */ - class ParserTester // final - { - private: - static int c_iCount; + // Multiarg callbacks + static value_type f1of1(value_type v) { return v; }; - // Multiarg callbacks - static value_type f1of1(value_type v) { return v;}; - - static value_type f1of2(value_type v, value_type ) {return v;}; - static value_type f2of2(value_type , value_type v) {return v;}; + static value_type f1of2(value_type v, value_type) { return v; }; + static value_type f2of2(value_type, value_type v) { return v; }; - static value_type f1of3(value_type v, value_type , value_type ) {return v;}; - static value_type f2of3(value_type , value_type v, value_type ) {return v;}; - static value_type f3of3(value_type , value_type , value_type v) {return v;}; - - static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;} - static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;} - static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;} - static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;} + static value_type f1of3(value_type v, value_type, value_type) { return v; }; + static value_type f2of3(value_type, value_type v, value_type) { return v; }; + static value_type f3of3(value_type, value_type, value_type v) { return v; }; - static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; } - static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; } - static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; } - static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; } - static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; } + static value_type f1of4(value_type v, value_type, value_type, value_type) { return v; } + static value_type f2of4(value_type, value_type v, value_type, value_type) { return v; } + static value_type f3of4(value_type, value_type, value_type v, value_type) { return v; } + static value_type f4of4(value_type, value_type, value_type, value_type v) { return v; } - static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1a_fVal2) ? a_fVal1 : a_fVal2; } + static value_type f1of5(value_type v, value_type, value_type, value_type, value_type) { + return v; + } + static value_type f2of5(value_type, value_type v, value_type, value_type, value_type) { + return v; + } + static value_type f3of5(value_type, value_type, value_type v, value_type, value_type) { + return v; + } + static value_type f4of5(value_type, value_type, value_type, value_type v, value_type) { + return v; + } + static value_type f5of5(value_type, value_type, value_type, value_type, value_type v) { + return v; + } - static value_type plus2(value_type v1) { return v1+2; } - static value_type times3(value_type v1) { return v1*3; } - static value_type sqr(value_type v1) { return v1*v1; } - static value_type sign(value_type v) { return -v; } - static value_type add(value_type v1, value_type v2) { return v1+v2; } - static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } - + static value_type Min(value_type a_fVal1, value_type a_fVal2) { + return (a_fVal1 < a_fVal2) ? a_fVal1 : a_fVal2; + } + static value_type Max(value_type a_fVal1, value_type a_fVal2) { + return (a_fVal1 > a_fVal2) ? a_fVal1 : a_fVal2; + } - static value_type FirstArg(const value_type* a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw mu::Parser::exception_type( _T("too few arguments for function FirstArg.") ); + static value_type plus2(value_type v1) { return v1 + 2; } + static value_type times3(value_type v1) { return v1 * 3; } + static value_type sqr(value_type v1) { return v1 * v1; } + static value_type sign(value_type v) { return -v; } + static value_type add(value_type v1, value_type v2) { return v1 + v2; } + static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } - return a_afArg[0]; - } + static value_type FirstArg(const value_type* a_afArg, int a_iArgc) { + if (!a_iArgc) + throw mu::Parser::exception_type(_T("too few arguments for function FirstArg.")); - static value_type LastArg(const value_type* a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw mu::Parser::exception_type( _T("too few arguments for function LastArg.") ); + return a_afArg[0]; + } - return a_afArg[a_iArgc-1]; - } + static value_type LastArg(const value_type* a_afArg, int a_iArgc) { + if (!a_iArgc) + throw mu::Parser::exception_type(_T("too few arguments for function LastArg.")); - static value_type Sum(const value_type* a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw mu::Parser::exception_type( _T("too few arguments for function sum.") ); + return a_afArg[a_iArgc - 1]; + } - value_type fRes=0; - for (int i=0; i> val; - return (value_type)val; - } + static value_type ValueOf(const char_type*) { return 123; } - static value_type StrFun2(const char_type* v1, value_type v2) - { - int val(0); - stringstream_type(v1) >> val; - return (value_type)(val + v2); - } - - static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) - { - int val(0); - stringstream_type(v1) >> val; - return val + v2 + v3; - } + static value_type StrFun1(const char_type* v1) { + int val(0); + stringstream_type(v1) >> val; + return (value_type)val; + } - static value_type StrToFloat(const char_type* a_szMsg) - { - value_type val(0); - stringstream_type(a_szMsg) >> val; - return val; - } + static value_type StrFun2(const char_type* v1, value_type v2) { + int val(0); + stringstream_type(v1) >> val; + return (value_type)(val + v2); + } - // postfix operator callback - static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; } - static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; } - static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } + static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) { + int val(0); + stringstream_type(v1) >> val; + return val + v2 + v3; + } - // Custom value recognition - static int IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal); + static value_type StrToFloat(const char_type* a_szMsg) { + value_type val(0); + stringstream_type(a_szMsg) >> val; + return val; + } - int TestNames(); - int TestSyntax(); - int TestMultiArg(); - int TestPostFix(); - int TestExpression(); - int TestInfixOprt(); - int TestBinOprt(); - int TestVarConst(); - int TestInterface(); - int TestException(); - int TestStrArg(); - int TestIfThenElse(); - int TestBulkMode(); + // postfix operator callback + static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; } + static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; } + static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } - void Abort() const; + // Custom value recognition + static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal); - public: - typedef int (ParserTester::*testfun_type)(); + int TestNames(); + int TestSyntax(); + int TestMultiArg(); + int TestPostFix(); + int TestExpression(); + int TestInfixOprt(); + int TestBinOprt(); + int TestVarConst(); + int TestInterface(); + int TestException(); + int TestStrArg(); + int TestIfThenElse(); + int TestBulkMode(); - ParserTester(); - void Run(); + void Abort() const; - private: - std::vector m_vTestFun; - void AddTest(testfun_type a_pFun); + public: + typedef int (ParserTester::*testfun_type)(); - // Test Double Parser - int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass); - int EqnTestWithVarChange(const string_type& a_str, - double a_fRes1, - double a_fVar1, - double a_fRes2, - double a_fVar2); - int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true); + ParserTester(); + void Run(); - // Test Int Parser - int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass); + private: + std::vector m_vTestFun; + void AddTest(testfun_type a_pFun); - // Test Bulkmode - int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass); - }; - } // namespace Test -} // namespace mu + // Test Double Parser + int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass); + int EqnTestWithVarChange(const string_type& a_str, double a_fRes1, double a_fVar1, + double a_fRes2, double a_fVar2); + int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true); + + // Test Int Parser + int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass); + + // Test Bulkmode + int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass); +}; +} // namespace Test +} // namespace mu #endif - - diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index 78a66b733..b8ea6c133 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -1,129 +1,119 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_TOKEN_H #define MU_PARSER_TOKEN_H #include -#include -#include -#include #include +#include +#include +#include -#include "muParserError.h" #include "muParserCallback.h" +#include "muParserError.h" /** \file \brief This file contains the parser token definition. */ -namespace mu -{ - /** \brief Encapsulation of the data for a single formula token. +namespace mu { +/** \brief Encapsulation of the data for a single formula token. - Formula token implementation. Part of the Math Parser Package. - Formula tokens can be either one of the following: -
    -
  • value
  • -
  • variable
  • -
  • function with numerical arguments
  • -
  • functions with a string as argument
  • -
  • prefix operators
  • -
  • infix operators
  • -
  • binary operator
  • -
+ Formula token implementation. Part of the Math Parser Package. + Formula tokens can be either one of the following: +
    +
  • value
  • +
  • variable
  • +
  • function with numerical arguments
  • +
  • functions with a string as argument
  • +
  • prefix operators
  • +
  • infix operators
  • +
  • binary operator
  • +
- \author (C) 2004-2013 Ingo Berg - */ - template - class ParserToken - { - private: + \author (C) 2004-2013 Ingo Berg +*/ +template +class ParserToken { + private: + ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. + ETypeCode m_iType; + void *m_pTok; ///< Stores Token pointer; not applicable for all tokens + int m_iIdx; ///< An otional index to an external buffer storing the token data + TString m_strTok; ///< Token string + TString m_strVal; ///< Value for string variables + value_type m_fVal; ///< the value + std::auto_ptr m_pCallback; - ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode. - ETypeCode m_iType; - void *m_pTok; ///< Stores Token pointer; not applicable for all tokens - int m_iIdx; ///< An otional index to an external buffer storing the token data - TString m_strTok; ///< Token string - TString m_strVal; ///< Value for string variables - value_type m_fVal; ///< the value - std::auto_ptr m_pCallback; + public: + //--------------------------------------------------------------------------- + /** \brief Constructor (default). - public: + Sets token to an neutral state of type cmUNKNOWN. + \throw nothrow + \sa ECmdCode + */ + ParserToken() + : m_iCode(cmUNKNOWN), + m_iType(tpVOID), + m_pTok(0), + m_iIdx(-1), + m_strTok(), + m_strVal(), + m_fVal(0), + m_pCallback() {} - //--------------------------------------------------------------------------- - /** \brief Constructor (default). - - Sets token to an neutral state of type cmUNKNOWN. - \throw nothrow - \sa ECmdCode - */ - ParserToken() - :m_iCode(cmUNKNOWN) - ,m_iType(tpVOID) - ,m_pTok(0) - ,m_iIdx(-1) - ,m_strTok() - ,m_strVal() - ,m_fVal(0) - ,m_pCallback() - {} + //------------------------------------------------------------------------------ + /** \brief Create token from another one. - //------------------------------------------------------------------------------ - /** \brief Create token from another one. - - Implemented by calling Assign(...) - \throw nothrow - \post m_iType==cmUNKNOWN - \sa #Assign - */ - ParserToken(const ParserToken &a_Tok) - { - Assign(a_Tok); - } - - //------------------------------------------------------------------------------ - /** \brief Assignement operator. - - Copy token state from another token and return this. - Implemented by calling Assign(...). - \throw nothrow - */ - ParserToken& operator=(const ParserToken &a_Tok) - { + Implemented by calling Assign(...) + \throw nothrow + \post m_iType==cmUNKNOWN + \sa #Assign + */ + ParserToken(const ParserToken &a_Tok) { Assign(a_Tok); } + + //------------------------------------------------------------------------------ + /** \brief Assignement operator. + + Copy token state from another token and return this. + Implemented by calling Assign(...). + \throw nothrow + */ + ParserToken &operator=(const ParserToken &a_Tok) { Assign(a_Tok); return *this; - } + } - //------------------------------------------------------------------------------ - /** \brief Copy token information from argument. - - \throw nothrow - */ - void Assign(const ParserToken &a_Tok) - { + //------------------------------------------------------------------------------ + /** \brief Copy token information from argument. + + \throw nothrow + */ + void Assign(const ParserToken &a_Tok) { m_iCode = a_Tok.m_iCode; m_pTok = a_Tok.m_pTok; m_strTok = a_Tok.m_strTok; @@ -131,27 +121,26 @@ namespace mu m_strVal = a_Tok.m_strVal; m_iType = a_Tok.m_iType; m_fVal = a_Tok.m_fVal; - // create new callback object if a_Tok has one + // create new callback object if a_Tok has one m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); - } + } - //------------------------------------------------------------------------------ - /** \brief Assign a token type. + //------------------------------------------------------------------------------ + /** \brief Assign a token type. - Token may not be of type value, variable or function. Those have seperate set functions. + Token may not be of type value, variable or function. Those have seperate set functions. - \pre [assert] a_iType!=cmVAR - \pre [assert] a_iType!=cmVAL - \pre [assert] a_iType!=cmFUNC - \post m_fVal = 0 - \post m_pTok = 0 - */ - ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) - { + \pre [assert] a_iType!=cmVAR + \pre [assert] a_iType!=cmVAL + \pre [assert] a_iType!=cmFUNC + \post m_fVal = 0 + \post m_pTok = 0 + */ + ParserToken &Set(ECmdCode a_iType, const TString &a_strTok = TString()) { // The following types cant be set this way, they have special Set functions - assert(a_iType!=cmVAR); - assert(a_iType!=cmVAL); - assert(a_iType!=cmFUNC); + assert(a_iType != cmVAR); + assert(a_iType != cmVAL); + assert(a_iType != cmFUNC); m_iCode = a_iType; m_iType = tpVOID; @@ -160,12 +149,11 @@ namespace mu m_iIdx = -1; return *this; - } + } - //------------------------------------------------------------------------------ - /** \brief Set Callback type. */ - ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok) - { + //------------------------------------------------------------------------------ + /** \brief Set Callback type. */ + ParserToken &Set(const ParserCallback &a_pCallback, const TString &a_sTok) { assert(a_pCallback.GetAddr()); m_iCode = a_pCallback.GetCode(); @@ -175,55 +163,52 @@ namespace mu m_pTok = 0; m_iIdx = -1; - - return *this; - } - //------------------------------------------------------------------------------ - /** \brief Make this token a value token. - - Member variables not necessary for value tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) - { + return *this; + } + + //------------------------------------------------------------------------------ + /** \brief Make this token a value token. + + Member variables not necessary for value tokens will be invalidated. + \throw nothrow + */ + ParserToken &SetVal(TBase a_fVal, const TString &a_strTok = TString()) { m_iCode = cmVAL; m_iType = tpDBL; m_fVal = a_fVal; m_strTok = a_strTok; m_iIdx = -1; - + m_pTok = 0; m_pCallback.reset(0); return *this; - } + } - //------------------------------------------------------------------------------ - /** \brief make this token a variable token. - - Member variables not necessary for variable tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) - { + //------------------------------------------------------------------------------ + /** \brief make this token a variable token. + + Member variables not necessary for variable tokens will be invalidated. + \throw nothrow + */ + ParserToken &SetVar(TBase *a_pVar, const TString &a_strTok) { m_iCode = cmVAR; m_iType = tpDBL; m_strTok = a_strTok; m_iIdx = -1; - m_pTok = (void*)a_pVar; + m_pTok = (void *)a_pVar; m_pCallback.reset(0); return *this; - } + } - //------------------------------------------------------------------------------ - /** \brief Make this token a variable token. - - Member variables not necessary for variable tokens will be invalidated. - \throw nothrow - */ - ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) - { + //------------------------------------------------------------------------------ + /** \brief Make this token a variable token. + + Member variables not necessary for variable tokens will be invalidated. + \throw nothrow + */ + ParserToken &SetString(const TString &a_strTok, std::size_t a_iSize) { m_iCode = cmSTRING; m_iType = tpSTR; m_strTok = a_strTok; @@ -232,170 +217,148 @@ namespace mu m_pTok = 0; m_pCallback.reset(0); return *this; - } + } + + //------------------------------------------------------------------------------ + /** \brief Set an index associated with the token related data. + + In cmSTRFUNC - This is the index to a string table in the main parser. + \param a_iIdx The index the string function result will take in the bytecode parser. + \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING + */ + void SetIdx(int a_iIdx) { + if (m_iCode != cmSTRING || a_iIdx < 0) assert(0 && "muParser internal error"); - //------------------------------------------------------------------------------ - /** \brief Set an index associated with the token related data. - - In cmSTRFUNC - This is the index to a string table in the main parser. - \param a_iIdx The index the string function result will take in the bytecode parser. - \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING - */ - void SetIdx(int a_iIdx) - { - if (m_iCode!=cmSTRING || a_iIdx<0) - assert(0 && "muParser internal error"); - m_iIdx = a_iIdx; - } + } - //------------------------------------------------------------------------------ - /** \brief Return Index associated with the token related data. - - In cmSTRFUNC - This is the index to a string table in the main parser. + //------------------------------------------------------------------------------ + /** \brief Return Index associated with the token related data. - \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING - \return The index the result will take in the Bytecode calculatin array (#m_iIdx). - */ - int GetIdx() const - { - if (m_iIdx<0 || m_iCode!=cmSTRING ) - assert(0 && "muParser internal error"); + In cmSTRFUNC - This is the index to a string table in the main parser. + + \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING + \return The index the result will take in the Bytecode calculatin array (#m_iIdx). + */ + int GetIdx() const { + if (m_iIdx < 0 || m_iCode != cmSTRING) assert(0 && "muParser internal error"); return m_iIdx; - } + } - //------------------------------------------------------------------------------ - /** \brief Return the token type. - - \return #m_iType - \throw nothrow - */ - ECmdCode GetCode() const - { - if (m_pCallback.get()) - { - return m_pCallback->GetCode(); - } - else - { - return m_iCode; - } - } + //------------------------------------------------------------------------------ + /** \brief Return the token type. - //------------------------------------------------------------------------------ - ETypeCode GetType() const - { - if (m_pCallback.get()) - { - return m_pCallback->GetType(); + \return #m_iType + \throw nothrow + */ + ECmdCode GetCode() const { + if (m_pCallback.get()) { + return m_pCallback->GetCode(); + } else { + return m_iCode; } - else - { - return m_iType; + } + + //------------------------------------------------------------------------------ + ETypeCode GetType() const { + if (m_pCallback.get()) { + return m_pCallback->GetType(); + } else { + return m_iType; } - } - - //------------------------------------------------------------------------------ - int GetPri() const - { - if ( !m_pCallback.get()) - assert(0 && "muParser internal error"); - - if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX) - assert(0 && "muParser internal error"); + } + + //------------------------------------------------------------------------------ + int GetPri() const { + if (!m_pCallback.get()) assert(0 && "muParser internal error"); + + if (m_pCallback->GetCode() != cmOPRT_BIN && m_pCallback->GetCode() != cmOPRT_INFIX) + assert(0 && "muParser internal error"); return m_pCallback->GetPri(); - } + } - //------------------------------------------------------------------------------ - EOprtAssociativity GetAssociativity() const - { - if (m_pCallback.get()==NULL || m_pCallback->GetCode()!=cmOPRT_BIN) - assert(0 && "muParser internal error"); + //------------------------------------------------------------------------------ + EOprtAssociativity GetAssociativity() const { + if (m_pCallback.get() == NULL || m_pCallback->GetCode() != cmOPRT_BIN) + assert(0 && "muParser internal error"); return m_pCallback->GetAssociativity(); - } + } - //------------------------------------------------------------------------------ - /** \brief Return the address of the callback function assoziated with - function and operator tokens. + //------------------------------------------------------------------------------ + /** \brief Return the address of the callback function assoziated with + function and operator tokens. - \return The pointer stored in #m_pTok. - \throw exception_type if token type is non of: -
    -
  • cmFUNC
  • -
  • cmSTRFUNC
  • -
  • cmPOSTOP
  • -
  • cmINFIXOP
  • -
  • cmOPRT_BIN
  • -
- \sa ECmdCode - */ - generic_fun_type GetFuncAddr() const - { + \return The pointer stored in #m_pTok. + \throw exception_type if token type is non of: +
    +
  • cmFUNC
  • +
  • cmSTRFUNC
  • +
  • cmPOSTOP
  • +
  • cmINFIXOP
  • +
  • cmOPRT_BIN
  • +
+ \sa ECmdCode + */ + generic_fun_type GetFuncAddr() const { return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0; - } + } - //------------------------------------------------------------------------------ - /** \biref Get value of the token. - - Only applicable to variable and value tokens. - \throw exception_type if token is no value/variable token. - */ - TBase GetVal() const - { - switch (m_iCode) - { - case cmVAL: return m_fVal; - case cmVAR: return *((TBase*)m_pTok); - default: throw ParserError(ecVAL_EXPECTED); + //------------------------------------------------------------------------------ + /** \biref Get value of the token. + + Only applicable to variable and value tokens. + \throw exception_type if token is no value/variable token. + */ + TBase GetVal() const { + switch (m_iCode) { + case cmVAL: + return m_fVal; + case cmVAR: + return *((TBase *)m_pTok); + default: + throw ParserError(ecVAL_EXPECTED); } - } + } - //------------------------------------------------------------------------------ - /** \brief Get address of a variable token. + //------------------------------------------------------------------------------ + /** \brief Get address of a variable token. - Valid only if m_iType==CmdVar. - \throw exception_type if token is no variable token. - */ - TBase* GetVar() const - { - if (m_iCode!=cmVAR) - assert(0 && "muParser internal error"); + Valid only if m_iType==CmdVar. + \throw exception_type if token is no variable token. + */ + TBase *GetVar() const { + if (m_iCode != cmVAR) assert(0 && "muParser internal error"); - return (TBase*)m_pTok; - } + return (TBase *)m_pTok; + } - //------------------------------------------------------------------------------ - /** \brief Return the number of function arguments. + //------------------------------------------------------------------------------ + /** \brief Return the number of function arguments. - Valid only if m_iType==CmdFUNC. - */ - int GetArgCount() const - { + Valid only if m_iType==CmdFUNC. + */ + int GetArgCount() const { assert(m_pCallback.get()); - if (!m_pCallback->GetAddr()) - assert(0 && "muParser internal error"); + if (!m_pCallback->GetAddr()) assert(0 && "muParser internal error"); return m_pCallback->GetArgc(); - } + } - //------------------------------------------------------------------------------ - /** \brief Return the token identifier. - - If #m_iType is cmSTRING the token identifier is the value of the string argument - for a string function. - \return #m_strTok - \throw nothrow - \sa m_strTok - */ - const TString& GetAsString() const - { - return m_strTok; - } - }; -} // namespace mu + //------------------------------------------------------------------------------ + /** \brief Return the token identifier. + + If #m_iType is cmSTRING the token identifier is the value of the string argument + for a string function. + \return #m_strTok + \throw nothrow + \sa m_strTok + */ + const TString &GetAsString() const { return m_strTok; } +}; +} // namespace mu #endif diff --git a/muparser-2.2.5/include/muParserTokenReader.h b/muparser-2.2.5/include/muParserTokenReader.h index 654b59769..143069b43 100644 --- a/muparser-2.2.5/include/muParserTokenReader.h +++ b/muparser-2.2.5/include/muParserTokenReader.h @@ -1,26 +1,26 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef MU_PARSER_TOKEN_READER_H @@ -42,120 +42,108 @@ \brief This file contains the parser token reader definition. */ +namespace mu { +// Forward declaration +class ParserBase; -namespace mu -{ - // Forward declaration - class ParserBase; +/** \brief Token reader for the ParserBase class. - /** \brief Token reader for the ParserBase class. +*/ +class ParserTokenReader { + private: + typedef ParserToken token_type; - */ - class ParserTokenReader - { - private: + public: + ParserTokenReader(ParserBase *a_pParent); + ParserTokenReader *Clone(ParserBase *a_pParent) const; - typedef ParserToken token_type; + void AddValIdent(identfun_type a_pCallback); + void SetVarCreator(facfun_type a_pFactory, void *pUserData); + void SetFormula(const string_type &a_strFormula); + void SetArgSep(char_type cArgSep); - public: + int GetPos() const; + const string_type &GetExpr() const; + varmap_type &GetUsedVar(); + char_type GetArgSep() const; - ParserTokenReader(ParserBase *a_pParent); - ParserTokenReader* Clone(ParserBase *a_pParent) const; + void IgnoreUndefVar(bool bIgnore); + void ReInit(); + token_type ReadNextToken(); - void AddValIdent(identfun_type a_pCallback); - void SetVarCreator(facfun_type a_pFactory, void *pUserData); - void SetFormula(const string_type &a_strFormula); - void SetArgSep(char_type cArgSep); + private: + /** \brief Syntax codes. - int GetPos() const; - const string_type& GetExpr() const; - varmap_type& GetUsedVar(); - char_type GetArgSep() const; - - void IgnoreUndefVar(bool bIgnore); - void ReInit(); - token_type ReadNextToken(); - - private: - - /** \brief Syntax codes. - - The syntax codes control the syntax check done during the first time parsing of - the expression string. They are flags that indicate which tokens are allowed next - if certain tokens are identified. - */ - enum ESynCodes - { - noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" - noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" - noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" - noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a" + The syntax codes control the syntax check done during the first time parsing of + the expression string. They are flags that indicate which tokens are allowed next + if certain tokens are identified. + */ + enum ESynCodes { + noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" + noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" + noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" + noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a" noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ... - noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" - noOPT = 1 << 6, ///< to avoid i.e. "(+)" - noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!" - noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4" - noEND = 1 << 9, ///< to avoid unexpected end of formula - noSTR = 1 << 10, ///< to block numeric arguments on string functions - noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7" - noIF = 1 << 12, - noELSE = 1 << 13, + noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin" + noOPT = 1 << 6, ///< to avoid i.e. "(+)" + noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!" + noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4" + noEND = 1 << 9, ///< to avoid unexpected end of formula + noSTR = 1 << 10, ///< to block numeric arguments on string functions + noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7" + noIF = 1 << 12, + noELSE = 1 << 13, sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP, - noANY = ~0 ///< All of he above flags set - }; + noANY = ~0 ///< All of he above flags set + }; - ParserTokenReader(const ParserTokenReader &a_Reader); - ParserTokenReader& operator=(const ParserTokenReader &a_Reader); - void Assign(const ParserTokenReader &a_Reader); + ParserTokenReader(const ParserTokenReader &a_Reader); + ParserTokenReader &operator=(const ParserTokenReader &a_Reader); + void Assign(const ParserTokenReader &a_Reader); - void SetParent(ParserBase *a_pParent); - int ExtractToken(const char_type *a_szCharSet, - string_type &a_strTok, - int a_iPos) const; - int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const; + void SetParent(ParserBase *a_pParent); + int ExtractToken(const char_type *a_szCharSet, string_type &a_strTok, int a_iPos) const; + int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const; - bool IsBuiltIn(token_type &a_Tok); - bool IsArgSep(token_type &a_Tok); - bool IsEOF(token_type &a_Tok); - bool IsInfixOpTok(token_type &a_Tok); - bool IsFunTok(token_type &a_Tok); - bool IsPostOpTok(token_type &a_Tok); - bool IsOprt(token_type &a_Tok); - bool IsValTok(token_type &a_Tok); - bool IsVarTok(token_type &a_Tok); - bool IsStrVarTok(token_type &a_Tok); - bool IsUndefVarTok(token_type &a_Tok); - bool IsString(token_type &a_Tok); - void Error(EErrorCodes a_iErrc, - int a_iPos = -1, - const string_type &a_sTok = string_type() ) const; + bool IsBuiltIn(token_type &a_Tok); + bool IsArgSep(token_type &a_Tok); + bool IsEOF(token_type &a_Tok); + bool IsInfixOpTok(token_type &a_Tok); + bool IsFunTok(token_type &a_Tok); + bool IsPostOpTok(token_type &a_Tok); + bool IsOprt(token_type &a_Tok); + bool IsValTok(token_type &a_Tok); + bool IsVarTok(token_type &a_Tok); + bool IsStrVarTok(token_type &a_Tok); + bool IsUndefVarTok(token_type &a_Tok); + bool IsString(token_type &a_Tok); + void Error(EErrorCodes a_iErrc, int a_iPos = -1, + const string_type &a_sTok = string_type()) const; - token_type& SaveBeforeReturn(const token_type &tok); + token_type &SaveBeforeReturn(const token_type &tok); - ParserBase *m_pParser; - string_type m_strFormula; - int m_iPos; - int m_iSynFlags; - bool m_bIgnoreUndefVar; + ParserBase *m_pParser; + string_type m_strFormula; + int m_iPos; + int m_iSynFlags; + bool m_bIgnoreUndefVar; - const funmap_type *m_pFunDef; - const funmap_type *m_pPostOprtDef; - const funmap_type *m_pInfixOprtDef; - const funmap_type *m_pOprtDef; - const valmap_type *m_pConstDef; - const strmap_type *m_pStrVarDef; - varmap_type *m_pVarDef; ///< The only non const pointer to parser internals - facfun_type m_pFactory; - void *m_pFactoryData; - std::list m_vIdentFun; ///< Value token identification function - varmap_type m_UsedVar; - value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables - int m_iBrackets; - token_type m_lastTok; - char_type m_cArgSep; ///< The character used for separating function arguments - }; -} // namespace mu + const funmap_type *m_pFunDef; + const funmap_type *m_pPostOprtDef; + const funmap_type *m_pInfixOprtDef; + const funmap_type *m_pOprtDef; + const valmap_type *m_pConstDef; + const strmap_type *m_pStrVarDef; + varmap_type *m_pVarDef; ///< The only non const pointer to parser internals + facfun_type m_pFactory; + void *m_pFactoryData; + std::list m_vIdentFun; ///< Value token identification function + varmap_type m_UsedVar; + value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables + int m_iBrackets; + token_type m_lastTok; + char_type m_cArgSep; ///< The character used for separating function arguments +}; +} // namespace mu #endif - - diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index b536556b6..74b355567 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -1,41 +1,41 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ +/* + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParser.h" #include "muParserTemplateMagic.h" //--- Standard includes ------------------------------------------------------------------------ -#include #include +#include #include /** \brief Pi (what else?). */ -#define PARSER_CONST_PI 3.141592653589793238462643 +#define PARSER_CONST_PI 3.141592653589793238462643 /** \brief The Eulerian number. */ -#define PARSER_CONST_E 2.718281828459045235360287 +#define PARSER_CONST_E 2.718281828459045235360287 using namespace std; @@ -43,299 +43,258 @@ using namespace std; \brief Implementation of the standard floating point parser. */ - - /** \brief Namespace for mathematical applications. */ -namespace mu -{ +namespace mu { +//--------------------------------------------------------------------------- +// Trigonometric function +value_type Parser::Sin(value_type v) { return MathImpl::Sin(v); } +value_type Parser::Cos(value_type v) { return MathImpl::Cos(v); } +value_type Parser::Tan(value_type v) { return MathImpl::Tan(v); } +value_type Parser::ASin(value_type v) { return MathImpl::ASin(v); } +value_type Parser::ACos(value_type v) { return MathImpl::ACos(v); } +value_type Parser::ATan(value_type v) { return MathImpl::ATan(v); } +value_type Parser::ATan2(value_type v1, value_type v2) { + return MathImpl::ATan2(v1, v2); +} +value_type Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } +value_type Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } +value_type Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } +value_type Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } +value_type Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } +value_type Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } - //--------------------------------------------------------------------------- - // Trigonometric function - value_type Parser::Sin(value_type v) { return MathImpl::Sin(v); } - value_type Parser::Cos(value_type v) { return MathImpl::Cos(v); } - value_type Parser::Tan(value_type v) { return MathImpl::Tan(v); } - value_type Parser::ASin(value_type v) { return MathImpl::ASin(v); } - value_type Parser::ACos(value_type v) { return MathImpl::ACos(v); } - value_type Parser::ATan(value_type v) { return MathImpl::ATan(v); } - value_type Parser::ATan2(value_type v1, value_type v2) { return MathImpl::ATan2(v1, v2); } - value_type Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } - value_type Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } - value_type Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } - value_type Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } - value_type Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } - value_type Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } +//--------------------------------------------------------------------------- +// Logarithm functions - //--------------------------------------------------------------------------- - // Logarithm functions +// Logarithm base 2 +value_type Parser::Log2(value_type v) { +#ifdef MUP_MATH_EXCEPTIONS + if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Log2")); +#endif - // Logarithm base 2 - value_type Parser::Log2(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Log2")); - #endif + return MathImpl::Log2(v); +} - return MathImpl::Log2(v); - } +// Logarithm base 10 +value_type Parser::Log10(value_type v) { +#ifdef MUP_MATH_EXCEPTIONS + if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Log10")); +#endif - // Logarithm base 10 - value_type Parser::Log10(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Log10")); - #endif - - return MathImpl::Log10(v); - } + return MathImpl::Log10(v); +} // Logarithm base e (natural logarithm) - value_type Parser::Ln(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<=0) - throw ParserError(ecDOMAIN_ERROR, _T("Ln")); - #endif +value_type Parser::Ln(value_type v) { +#ifdef MUP_MATH_EXCEPTIONS + if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Ln")); +#endif - return MathImpl::Log(v); - } + return MathImpl::Log(v); +} - //--------------------------------------------------------------------------- - // misc - value_type Parser::Exp(value_type v) { return MathImpl::Exp(v); } - value_type Parser::Abs(value_type v) { return MathImpl::Abs(v); } - value_type Parser::Sqrt(value_type v) - { - #ifdef MUP_MATH_EXCEPTIONS - if (v<0) - throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); - #endif +//--------------------------------------------------------------------------- +// misc +value_type Parser::Exp(value_type v) { return MathImpl::Exp(v); } +value_type Parser::Abs(value_type v) { return MathImpl::Abs(v); } +value_type Parser::Sqrt(value_type v) { +#ifdef MUP_MATH_EXCEPTIONS + if (v < 0) throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); +#endif - return MathImpl::Sqrt(v); - } - value_type Parser::Rint(value_type v) { return MathImpl::Rint(v); } - value_type Parser::Sign(value_type v) { return MathImpl::Sign(v); } + return MathImpl::Sqrt(v); +} +value_type Parser::Rint(value_type v) { return MathImpl::Rint(v); } +value_type Parser::Sign(value_type v) { return MathImpl::Sign(v); } - //--------------------------------------------------------------------------- - /** \brief Callback for the unary minus operator. - \param v The value to negate - \return -v - */ - value_type Parser::UnaryMinus(value_type v) - { - return -v; - } +//--------------------------------------------------------------------------- +/** \brief Callback for the unary minus operator. + \param v The value to negate + \return -v +*/ +value_type Parser::UnaryMinus(value_type v) { return -v; } - //--------------------------------------------------------------------------- - /** \brief Callback for the unary minus operator. - \param v The value to negate - \return -v - */ - value_type Parser::UnaryPlus(value_type v) - { - return v; - } +//--------------------------------------------------------------------------- +/** \brief Callback for the unary minus operator. + \param v The value to negate + \return -v +*/ +value_type Parser::UnaryPlus(value_type v) { return v; } - //--------------------------------------------------------------------------- - /** \brief Callback for adding multiple values. - \param [in] a_afArg Vector with the function arguments - \param [in] a_iArgc The size of a_afArg - */ - value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) - { - if (!a_iArgc) - throw exception_type(_T("too few arguments for function sum.")); +//--------------------------------------------------------------------------- +/** \brief Callback for adding multiple values. + \param [in] a_afArg Vector with the function arguments + \param [in] a_iArgc The size of a_afArg +*/ +value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) { + if (!a_iArgc) throw exception_type(_T("too few arguments for function sum.")); - value_type fRes=0; - for (int i=0; i> fVal; - stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading + stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading - if (iEnd==(stringstream_type::pos_type)-1) - return 0; + if (iEnd == (stringstream_type::pos_type)-1) return 0; *a_iPos += (int)iEnd; *a_fVal = fVal; return 1; - } +} +//--------------------------------------------------------------------------- +/** \brief Constructor. - //--------------------------------------------------------------------------- - /** \brief Constructor. - - Call ParserBase class constructor and trigger Function, Operator and Constant initialization. - */ - Parser::Parser() - :ParserBase() - { + Call ParserBase class constructor and trigger Function, Operator and Constant initialization. +*/ +Parser::Parser() : ParserBase() { AddValIdent(IsVal); InitCharSets(); InitFun(); InitConst(); InitOprt(); - } +} - //--------------------------------------------------------------------------- - /** \brief Define the character sets. - \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars - - This function is used for initializing the default character sets that define - the characters to be useable in function and variable names and operators. - */ - void Parser::InitCharSets() - { - DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); - DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}") ); - DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") ); - } +//--------------------------------------------------------------------------- +/** \brief Define the character sets. + \sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars - //--------------------------------------------------------------------------- - /** \brief Initialize the default functions. */ - void Parser::InitFun() - { - if (mu::TypeInfo::IsInteger()) - { - // When setting MUP_BASETYPE to an integer type - // Place functions for dealing with integer values here - // ... - // ... - // ... + This function is used for initializing the default character sets that define + the characters to be useable in function and variable names and operators. +*/ +void Parser::InitCharSets() { + DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")); + DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}")); + DefineInfixOprtChars(_T("/+-*^?<>=#!$%&|~'_")); +} + +//--------------------------------------------------------------------------- +/** \brief Initialize the default functions. */ +void Parser::InitFun() { + if (mu::TypeInfo::IsInteger()) { + // When setting MUP_BASETYPE to an integer type + // Place functions for dealing with integer values here + // ... + // ... + // ... + } else { + // trigonometric functions + DefineFun(_T("sin"), Sin); + DefineFun(_T("cos"), Cos); + DefineFun(_T("tan"), Tan); + // arcus functions + DefineFun(_T("asin"), ASin); + DefineFun(_T("acos"), ACos); + DefineFun(_T("atan"), ATan); + DefineFun(_T("atan2"), ATan2); + // hyperbolic functions + DefineFun(_T("sinh"), Sinh); + DefineFun(_T("cosh"), Cosh); + DefineFun(_T("tanh"), Tanh); + // arcus hyperbolic functions + DefineFun(_T("asinh"), ASinh); + DefineFun(_T("acosh"), ACosh); + DefineFun(_T("atanh"), ATanh); + // Logarithm functions + DefineFun(_T("log2"), Log2); + DefineFun(_T("log10"), Log10); + DefineFun(_T("log"), Ln); + DefineFun(_T("ln"), Ln); + // misc + DefineFun(_T("exp"), Exp); + DefineFun(_T("sqrt"), Sqrt); + DefineFun(_T("sign"), Sign); + DefineFun(_T("rint"), Rint); + DefineFun(_T("abs"), Abs); + // Functions with variable number of arguments + DefineFun(_T("sum"), Sum); + DefineFun(_T("avg"), Avg); + DefineFun(_T("min"), Min); + DefineFun(_T("max"), Max); } - else - { - // trigonometric functions - DefineFun(_T("sin"), Sin); - DefineFun(_T("cos"), Cos); - DefineFun(_T("tan"), Tan); - // arcus functions - DefineFun(_T("asin"), ASin); - DefineFun(_T("acos"), ACos); - DefineFun(_T("atan"), ATan); - DefineFun(_T("atan2"), ATan2); - // hyperbolic functions - DefineFun(_T("sinh"), Sinh); - DefineFun(_T("cosh"), Cosh); - DefineFun(_T("tanh"), Tanh); - // arcus hyperbolic functions - DefineFun(_T("asinh"), ASinh); - DefineFun(_T("acosh"), ACosh); - DefineFun(_T("atanh"), ATanh); - // Logarithm functions - DefineFun(_T("log2"), Log2); - DefineFun(_T("log10"), Log10); - DefineFun(_T("log"), Ln); - DefineFun(_T("ln"), Ln); - // misc - DefineFun(_T("exp"), Exp); - DefineFun(_T("sqrt"), Sqrt); - DefineFun(_T("sign"), Sign); - DefineFun(_T("rint"), Rint); - DefineFun(_T("abs"), Abs); - // Functions with variable number of arguments - DefineFun(_T("sum"), Sum); - DefineFun(_T("avg"), Avg); - DefineFun(_T("min"), Min); - DefineFun(_T("max"), Max); - } - } +} - //--------------------------------------------------------------------------- - /** \brief Initialize constants. - - By default the parser recognizes two constants. Pi ("pi") and the Eulerian - number ("_e"). - */ - void Parser::InitConst() - { +//--------------------------------------------------------------------------- +/** \brief Initialize constants. + + By default the parser recognizes two constants. Pi ("pi") and the Eulerian + number ("_e"). +*/ +void Parser::InitConst() { DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); DefineConst(_T("_e"), (value_type)PARSER_CONST_E); - } +} - //--------------------------------------------------------------------------- - /** \brief Initialize operators. - - By default only the unary minus operator is added. - */ - void Parser::InitOprt() - { +//--------------------------------------------------------------------------- +/** \brief Initialize operators. + + By default only the unary minus operator is added. +*/ +void Parser::InitOprt() { DefineInfixOprt(_T("-"), UnaryMinus); DefineInfixOprt(_T("+"), UnaryPlus); - } +} - //--------------------------------------------------------------------------- - void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) - { +//--------------------------------------------------------------------------- +void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) { // this is just sample code to illustrate modifying variable names on the fly. // I'm not sure anyone really needs such a feature... /* @@ -343,7 +302,7 @@ namespace mu string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd); string sRepl = std::string("_") + sVar + "_"; - + int nOrigVarEnd = nEnd; cout << "variable detected!\n"; cout << " Expr: " << *pExpr << "\n"; @@ -356,42 +315,39 @@ namespace mu pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl); cout << " New expr: " << *pExpr << "\n"; */ - } +} - //--------------------------------------------------------------------------- - /** \brief Numerically differentiate with regard to a variable. - \param [in] a_Var Pointer to the differentiation variable. - \param [in] a_fPos Position at which the differentiation should take place. - \param [in] a_fEpsilon Epsilon used for the numerical differentiation. +//--------------------------------------------------------------------------- +/** \brief Numerically differentiate with regard to a variable. + \param [in] a_Var Pointer to the differentiation variable. + \param [in] a_fPos Position at which the differentiation should take place. + \param [in] a_fEpsilon Epsilon used for the numerical differentiation. - Numerical differentiation uses a 5 point operator yielding a 4th order - formula. The default value for epsilon is 0.00074 which is - numeric_limits::epsilon() ^ (1/5) as suggested in the muparser - forum: + Numerical differentiation uses a 5 point operator yielding a 4th order + formula. The default value for epsilon is 0.00074 which is + numeric_limits::epsilon() ^ (1/5) as suggested in the muparser + forum: - http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 - */ - value_type Parser::Diff(value_type *a_Var, - value_type a_fPos, - value_type a_fEpsilon) const - { - value_type fRes(0), - fBuf(*a_Var), - f[4] = {0,0,0,0}, - fEpsilon(a_fEpsilon); + http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 +*/ +value_type Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const { + value_type fRes(0), fBuf(*a_Var), f[4] = {0, 0, 0, 0}, fEpsilon(a_fEpsilon); // Backwards compatible calculation of epsilon inc case the user doesn't provide // his own epsilon - if (fEpsilon==0) - fEpsilon = (a_fPos==0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; + if (fEpsilon == 0) fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; - *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval(); - *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval(); - *a_Var = a_fPos-1 * fEpsilon; f[2] = Eval(); - *a_Var = a_fPos-2 * fEpsilon; f[3] = Eval(); - *a_Var = fBuf; // restore variable + *a_Var = a_fPos + 2 * fEpsilon; + f[0] = Eval(); + *a_Var = a_fPos + 1 * fEpsilon; + f[1] = Eval(); + *a_Var = a_fPos - 1 * fEpsilon; + f[2] = Eval(); + *a_Var = a_fPos - 2 * fEpsilon; + f[3] = Eval(); + *a_Var = fBuf; // restore variable - fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon); + fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon); return fRes; - } -} // namespace mu +} +} // namespace mu diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 0a58b1580..d3d0f1d80 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1,40 +1,40 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParserBase.h" #include "muParserTemplateMagic.h" //--- Standard includes ------------------------------------------------------------------------ -#include #include +#include #include -#include -#include #include -#include #include +#include +#include +#include using namespace std; @@ -42,1242 +42,555 @@ using namespace std; \brief This file contains the basic implementation of the muparser engine. */ -namespace mu -{ - std::locale ParserBase::s_locale = std::locale(std::locale::classic(), new change_dec_sep('.')); +namespace mu { +std::locale ParserBase::s_locale = + std::locale(std::locale::classic(), new change_dec_sep('.')); - bool ParserBase::g_DbgDumpCmdCode = false; - bool ParserBase::g_DbgDumpStack = false; +bool ParserBase::g_DbgDumpCmdCode = false; +bool ParserBase::g_DbgDumpStack = false; - //------------------------------------------------------------------------------ - /** \brief Identifiers for built in binary operators. +//------------------------------------------------------------------------------ +/** \brief Identifiers for built in binary operators. - When defining custom binary operators with #AddOprt(...) make sure not to choose - names conflicting with these definitions. - */ - const char_type* ParserBase::c_DefaultOprt[] = - { - _T("<="), _T(">="), _T("!="), - _T("=="), _T("<"), _T(">"), - _T("+"), _T("-"), _T("*"), - _T("/"), _T("^"), _T("&&"), - _T("||"), _T("="), _T("("), - _T(")"), _T("?"), _T(":"), 0 - }; + When defining custom binary operators with #AddOprt(...) make sure not to choose + names conflicting with these definitions. +*/ +const char_type *ParserBase::c_DefaultOprt[] = { + _T("<="), _T(">="), _T("!="), _T("=="), _T("<"), _T(">"), _T("+"), _T("-"), _T("*"), _T("/"), + _T("^"), _T("&&"), _T("||"), _T("="), _T("("), _T(")"), _T("?"), _T(":"), 0}; - //------------------------------------------------------------------------------ - /** \brief Constructor. - \param a_szFormula the formula to interpret. - \throw ParserException if a_szFormula is null. - */ - ParserBase::ParserBase() - :m_pParseFormula(&ParserBase::ParseString) - ,m_vRPN() - ,m_vStringBuf() - ,m_pTokenReader() - ,m_FunDef() - ,m_PostOprtDef() - ,m_InfixOprtDef() - ,m_OprtDef() - ,m_ConstDef() - ,m_StrVarDef() - ,m_VarDef() - ,m_bBuiltInOp(true) - ,m_sNameChars() - ,m_sOprtChars() - ,m_sInfixOprtChars() - ,m_nIfElseCounter(0) - ,m_vStackBuffer() - ,m_nFinalResultIdx(0) - { +//------------------------------------------------------------------------------ +/** \brief Constructor. + \param a_szFormula the formula to interpret. + \throw ParserException if a_szFormula is null. +*/ +ParserBase::ParserBase() + : m_pParseFormula(&ParserBase::ParseString), + m_vRPN(), + m_vStringBuf(), + m_pTokenReader(), + m_FunDef(), + m_PostOprtDef(), + m_InfixOprtDef(), + m_OprtDef(), + m_ConstDef(), + m_StrVarDef(), + m_VarDef(), + m_bBuiltInOp(true), + m_sNameChars(), + m_sOprtChars(), + m_sInfixOprtChars(), + m_nIfElseCounter(0), + m_vStackBuffer(), + m_nFinalResultIdx(0) { InitTokenReader(); - } +} - //--------------------------------------------------------------------------- - /** \brief Copy constructor. +//--------------------------------------------------------------------------- +/** \brief Copy constructor. - The parser can be safely copy constructed but the bytecode is reset during - copy construction. - */ - ParserBase::ParserBase(const ParserBase &a_Parser) - :m_pParseFormula(&ParserBase::ParseString) - ,m_vRPN() - ,m_vStringBuf() - ,m_pTokenReader() - ,m_FunDef() - ,m_PostOprtDef() - ,m_InfixOprtDef() - ,m_OprtDef() - ,m_ConstDef() - ,m_StrVarDef() - ,m_VarDef() - ,m_bBuiltInOp(true) - ,m_sNameChars() - ,m_sOprtChars() - ,m_sInfixOprtChars() - ,m_nIfElseCounter(0) - { + The parser can be safely copy constructed but the bytecode is reset during + copy construction. +*/ +ParserBase::ParserBase(const ParserBase &a_Parser) + : m_pParseFormula(&ParserBase::ParseString), + m_vRPN(), + m_vStringBuf(), + m_pTokenReader(), + m_FunDef(), + m_PostOprtDef(), + m_InfixOprtDef(), + m_OprtDef(), + m_ConstDef(), + m_StrVarDef(), + m_VarDef(), + m_bBuiltInOp(true), + m_sNameChars(), + m_sOprtChars(), + m_sInfixOprtChars(), + m_nIfElseCounter(0) { m_pTokenReader.reset(new token_reader_type(this)); Assign(a_Parser); - } +} - //--------------------------------------------------------------------------- - ParserBase::~ParserBase() - {} +//--------------------------------------------------------------------------- +ParserBase::~ParserBase() {} - //--------------------------------------------------------------------------- - /** \brief Assignment operator. +//--------------------------------------------------------------------------- +/** \brief Assignment operator. - Implemented by calling Assign(a_Parser). Self assignment is suppressed. - \param a_Parser Object to copy to this. - \return *this - \throw nothrow - */ - ParserBase& ParserBase::operator=(const ParserBase &a_Parser) - { + Implemented by calling Assign(a_Parser). Self assignment is suppressed. + \param a_Parser Object to copy to this. + \return *this + \throw nothrow +*/ +ParserBase &ParserBase::operator=(const ParserBase &a_Parser) { Assign(a_Parser); return *this; - } +} - //--------------------------------------------------------------------------- - /** \brief Copy state of a parser object to this. +//--------------------------------------------------------------------------- +/** \brief Copy state of a parser object to this. - Clears Variables and Functions of this parser. - Copies the states of all internal variables. - Resets parse function to string parse mode. + Clears Variables and Functions of this parser. + Copies the states of all internal variables. + Resets parse function to string parse mode. - \param a_Parser the source object. - */ - void ParserBase::Assign(const ParserBase &a_Parser) - { - if (&a_Parser==this) - return; + \param a_Parser the source object. +*/ +void ParserBase::Assign(const ParserBase &a_Parser) { + if (&a_Parser == this) return; // Don't copy bytecode instead cause the parser to create new bytecode // by resetting the parse function. ReInit(); - m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants - m_VarDef = a_Parser.m_VarDef; // Copy user defined variables - m_bBuiltInOp = a_Parser.m_bBuiltInOp; - m_vStringBuf = a_Parser.m_vStringBuf; - m_vStackBuffer = a_Parser.m_vStackBuffer; + m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants + m_VarDef = a_Parser.m_VarDef; // Copy user defined variables + m_bBuiltInOp = a_Parser.m_bBuiltInOp; + m_vStringBuf = a_Parser.m_vStringBuf; + m_vStackBuffer = a_Parser.m_vStackBuffer; m_nFinalResultIdx = a_Parser.m_nFinalResultIdx; - m_StrVarDef = a_Parser.m_StrVarDef; - m_vStringVarBuf = a_Parser.m_vStringVarBuf; - m_nIfElseCounter = a_Parser.m_nIfElseCounter; + m_StrVarDef = a_Parser.m_StrVarDef; + m_vStringVarBuf = a_Parser.m_vStringVarBuf; + m_nIfElseCounter = a_Parser.m_nIfElseCounter; m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this)); // Copy function and operator callbacks - m_FunDef = a_Parser.m_FunDef; // Copy function definitions - m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators - m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation - m_OprtDef = a_Parser.m_OprtDef; // binary operators + m_FunDef = a_Parser.m_FunDef; // Copy function definitions + m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators + m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation + m_OprtDef = a_Parser.m_OprtDef; // binary operators m_sNameChars = a_Parser.m_sNameChars; m_sOprtChars = a_Parser.m_sOprtChars; m_sInfixOprtChars = a_Parser.m_sInfixOprtChars; - } +} - //--------------------------------------------------------------------------- - /** \brief Set the decimal separator. - \param cDecSep Decimal separator as a character value. - \sa SetThousandsSep +//--------------------------------------------------------------------------- +/** \brief Set the decimal separator. + \param cDecSep Decimal separator as a character value. + \sa SetThousandsSep - By default muparser uses the "C" locale. The decimal separator of this - locale is overwritten by the one provided here. - */ - void ParserBase::SetDecSep(char_type cDecSep) - { - char_type cThousandsSep = std::use_facet< change_dec_sep >(s_locale).thousands_sep(); + By default muparser uses the "C" locale. The decimal separator of this + locale is overwritten by the one provided here. +*/ +void ParserBase::SetDecSep(char_type cDecSep) { + char_type cThousandsSep = std::use_facet >(s_locale).thousands_sep(); s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); - } - - //--------------------------------------------------------------------------- - /** \brief Sets the thousands operator. - \param cThousandsSep The thousands separator as a character - \sa SetDecSep +} - By default muparser uses the "C" locale. The thousands separator of this - locale is overwritten by the one provided here. - */ - void ParserBase::SetThousandsSep(char_type cThousandsSep) - { - char_type cDecSep = std::use_facet< change_dec_sep >(s_locale).decimal_point(); +//--------------------------------------------------------------------------- +/** \brief Sets the thousands operator. + \param cThousandsSep The thousands separator as a character + \sa SetDecSep + + By default muparser uses the "C" locale. The thousands separator of this + locale is overwritten by the one provided here. +*/ +void ParserBase::SetThousandsSep(char_type cThousandsSep) { + char_type cDecSep = std::use_facet >(s_locale).decimal_point(); s_locale = std::locale(std::locale("C"), new change_dec_sep(cDecSep, cThousandsSep)); - } +} - //--------------------------------------------------------------------------- - /** \brief Resets the locale. +//--------------------------------------------------------------------------- +/** \brief Resets the locale. - The default locale used "." as decimal separator, no thousands separator and - "," as function argument separator. - */ - void ParserBase::ResetLocale() - { + The default locale used "." as decimal separator, no thousands separator and + "," as function argument separator. +*/ +void ParserBase::ResetLocale() { s_locale = std::locale(std::locale("C"), new change_dec_sep('.')); SetArgSep(','); - } +} - //--------------------------------------------------------------------------- - /** \brief Initialize the token reader. +//--------------------------------------------------------------------------- +/** \brief Initialize the token reader. - Create new token reader object and submit pointers to function, operator, - constant and variable definitions. + Create new token reader object and submit pointers to function, operator, + constant and variable definitions. - \post m_pTokenReader.get()!=0 + \post m_pTokenReader.get()!=0 + \throw nothrow +*/ +void ParserBase::InitTokenReader() { m_pTokenReader.reset(new token_reader_type(this)); } + +//--------------------------------------------------------------------------- +/** \brief Reset parser to string parsing mode and clear internal buffers. + + Clear bytecode, reset the token reader. \throw nothrow - */ - void ParserBase::InitTokenReader() - { - m_pTokenReader.reset(new token_reader_type(this)); - } - - //--------------------------------------------------------------------------- - /** \brief Reset parser to string parsing mode and clear internal buffers. - - Clear bytecode, reset the token reader. - \throw nothrow - */ - void ParserBase::ReInit() const - { +*/ +void ParserBase::ReInit() const { m_pParseFormula = &ParserBase::ParseString; m_vStringBuf.clear(); m_vRPN.clear(); m_pTokenReader->ReInit(); m_nIfElseCounter = 0; - } +} - //--------------------------------------------------------------------------- - void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) - {} +//--------------------------------------------------------------------------- +void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) {} - //--------------------------------------------------------------------------- - /** \brief Returns the version of muparser. - \param eInfo A flag indicating whether the full version info should be - returned or not. +//--------------------------------------------------------------------------- +/** \brief Returns the version of muparser. + \param eInfo A flag indicating whether the full version info should be + returned or not. - Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS - are returned only if eInfo==pviFULL. - */ - string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const - { + Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS + are returned only if eInfo==pviFULL. +*/ +string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const { stringstream_type ss; ss << MUP_VERSION; - if (eInfo==pviFULL) - { - ss << _T(" (") << MUP_VERSION_DATE; - ss << std::dec << _T("; ") << sizeof(void*)*8 << _T("BIT"); + if (eInfo == pviFULL) { + ss << _T(" (") << MUP_VERSION_DATE; + ss << std::dec << _T("; ") << sizeof(void *) * 8 << _T("BIT"); #ifdef _DEBUG - ss << _T("; DEBUG"); -#else - ss << _T("; RELEASE"); + ss << _T("; DEBUG"); +#else + ss << _T("; RELEASE"); #endif #ifdef _UNICODE - ss << _T("; UNICODE"); + ss << _T("; UNICODE"); #else - #ifdef _MBCS - ss << _T("; MBCS"); - #else - ss << _T("; ASCII"); - #endif +#ifdef _MBCS + ss << _T("; MBCS"); +#else + ss << _T("; ASCII"); +#endif #endif #if defined(MUP_MATH_EXCEPTIONS) - ss << _T("; MATHEXC"); + ss << _T("; MATHEXC"); //#else // ss << _T("; NO_MATHEXC"); #endif - ss << _T(")"); + ss << _T(")"); } return ss.str(); - } +} - //--------------------------------------------------------------------------- - /** \brief Add a value parsing function. - - When parsing an expression muParser tries to detect values in the expression - string using different valident callbacks. Thus it's possible to parse - for hex values, binary values and floating point values. - */ - void ParserBase::AddValIdent(identfun_type a_pCallback) - { +//--------------------------------------------------------------------------- +/** \brief Add a value parsing function. + + When parsing an expression muParser tries to detect values in the expression + string using different valident callbacks. Thus it's possible to parse + for hex values, binary values and floating point values. +*/ +void ParserBase::AddValIdent(identfun_type a_pCallback) { m_pTokenReader->AddValIdent(a_pCallback); - } +} - //--------------------------------------------------------------------------- - /** \brief Set a function that can create variable pointer for unknown expression variables. - \param a_pFactory A pointer to the variable factory. - \param pUserData A user defined context pointer. - */ - void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData) - { - m_pTokenReader->SetVarCreator(a_pFactory, pUserData); - } +//--------------------------------------------------------------------------- +/** \brief Set a function that can create variable pointer for unknown expression variables. + \param a_pFactory A pointer to the variable factory. + \param pUserData A user defined context pointer. +*/ +void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData) { + m_pTokenReader->SetVarCreator(a_pFactory, pUserData); +} - //--------------------------------------------------------------------------- - /** \brief Add a function or operator callback to the parser. */ - void ParserBase::AddCallback( const string_type &a_strName, - const ParserCallback &a_Callback, - funmap_type &a_Storage, - const char_type *a_szCharSet ) - { - if (a_Callback.GetAddr()==0) - Error(ecINVALID_FUN_PTR); +//--------------------------------------------------------------------------- +/** \brief Add a function or operator callback to the parser. */ +void ParserBase::AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, + funmap_type &a_Storage, const char_type *a_szCharSet) { + if (a_Callback.GetAddr() == 0) Error(ecINVALID_FUN_PTR); const funmap_type *pFunMap = &a_Storage; // Check for conflicting operator or function names - if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); + if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); - if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); + if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); - if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); + if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && + m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); - if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() ) - Error(ecNAME_CONFLICT, -1, a_strName); + if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && + m_OprtDef.find(a_strName) != m_OprtDef.end()) + Error(ecNAME_CONFLICT, -1, a_strName); CheckOprt(a_strName, a_Callback, a_szCharSet); a_Storage[a_strName] = a_Callback; ReInit(); - } +} - //--------------------------------------------------------------------------- - /** \brief Check if a name contains invalid characters. +//--------------------------------------------------------------------------- +/** \brief Check if a name contains invalid characters. - \throw ParserException if the name contains invalid characters. - */ - void ParserBase::CheckOprt(const string_type &a_sName, - const ParserCallback &a_Callback, - const string_type &a_szCharSet) const - { - if ( !a_sName.length() || - (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || - (a_sName[0]>='0' && a_sName[0]<='9')) - { - switch(a_Callback.GetCode()) - { - case cmOPRT_POSTFIX: Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); - case cmOPRT_INFIX: Error(ecINVALID_INFIX_IDENT, -1, a_sName); - default: Error(ecINVALID_NAME, -1, a_sName); - } + \throw ParserException if the name contains invalid characters. +*/ +void ParserBase::CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, + const string_type &a_szCharSet) const { + if (!a_sName.length() || (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) || + (a_sName[0] >= '0' && a_sName[0] <= '9')) { + switch (a_Callback.GetCode()) { + case cmOPRT_POSTFIX: + Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); + case cmOPRT_INFIX: + Error(ecINVALID_INFIX_IDENT, -1, a_sName); + default: + Error(ecINVALID_NAME, -1, a_sName); + } } - } +} - //--------------------------------------------------------------------------- - /** \brief Check if a name contains invalid characters. +//--------------------------------------------------------------------------- +/** \brief Check if a name contains invalid characters. - \throw ParserException if the name contains invalid characters. - */ - void ParserBase::CheckName(const string_type &a_sName, - const string_type &a_szCharSet) const - { - if ( !a_sName.length() || - (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) || - (a_sName[0]>='0' && a_sName[0]<='9')) - { - Error(ecINVALID_NAME); + \throw ParserException if the name contains invalid characters. +*/ +void ParserBase::CheckName(const string_type &a_sName, const string_type &a_szCharSet) const { + if (!a_sName.length() || (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) || + (a_sName[0] >= '0' && a_sName[0] <= '9')) { + Error(ecINVALID_NAME); } - } +} - //--------------------------------------------------------------------------- - /** \brief Set the formula. - \param a_strFormula Formula as string_type - \throw ParserException in case of syntax errors. +//--------------------------------------------------------------------------- +/** \brief Set the formula. + \param a_strFormula Formula as string_type + \throw ParserException in case of syntax errors. - Triggers first time calculation thus the creation of the bytecode and - scanning of used variables. - */ - void ParserBase::SetExpr(const string_type &a_sExpr) - { + Triggers first time calculation thus the creation of the bytecode and + scanning of used variables. +*/ +void ParserBase::SetExpr(const string_type &a_sExpr) { // Check locale compatibility std::locale loc; - if (m_pTokenReader->GetArgSep()==std::use_facet >(loc).decimal_point()) - Error(ecLOCALE); + if (m_pTokenReader->GetArgSep() == std::use_facet >(loc).decimal_point()) + Error(ecLOCALE); // 20060222: Bugfix for Borland-Kylix: // adding a space to the expression will keep Borlands KYLIX from going wild - // when calling tellg on a stringstream created from the expression after + // when calling tellg on a stringstream created from the expression after // reading a value at the end of an expression. (mu::Parser::IsVal function) // (tellg returns -1 otherwise causing the parser to ignore the value) - string_type sBuf(a_sExpr + _T(" ") ); + string_type sBuf(a_sExpr + _T(" ")); m_pTokenReader->SetFormula(sBuf); ReInit(); - } +} - //--------------------------------------------------------------------------- - /** \brief Get the default symbols used for the built in operators. - \sa c_DefaultOprt - */ - const char_type** ParserBase::GetOprtDef() const - { - return (const char_type **)(&c_DefaultOprt[0]); - } +//--------------------------------------------------------------------------- +/** \brief Get the default symbols used for the built in operators. + \sa c_DefaultOprt +*/ +const char_type **ParserBase::GetOprtDef() const { return (const char_type **)(&c_DefaultOprt[0]); } - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - functions, variables, constants. - */ - void ParserBase::DefineNameChars(const char_type *a_szCharset) - { - m_sNameChars = a_szCharset; - } +//--------------------------------------------------------------------------- +/** \brief Define the set of valid characters to be used in names of + functions, variables, constants. +*/ +void ParserBase::DefineNameChars(const char_type *a_szCharset) { m_sNameChars = a_szCharset; } - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - binary operators and postfix operators. - */ - void ParserBase::DefineOprtChars(const char_type *a_szCharset) - { - m_sOprtChars = a_szCharset; - } +//--------------------------------------------------------------------------- +/** \brief Define the set of valid characters to be used in names of + binary operators and postfix operators. +*/ +void ParserBase::DefineOprtChars(const char_type *a_szCharset) { m_sOprtChars = a_szCharset; } - //--------------------------------------------------------------------------- - /** \brief Define the set of valid characters to be used in names of - infix operators. - */ - void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset) - { +//--------------------------------------------------------------------------- +/** \brief Define the set of valid characters to be used in names of + infix operators. +*/ +void ParserBase::DefineInfixOprtChars(const char_type *a_szCharset) { m_sInfixOprtChars = a_szCharset; - } +} - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in name identifiers. - \sa #ValidOprtChars, #ValidPrefixOprtChars - */ - const char_type* ParserBase::ValidNameChars() const - { +//--------------------------------------------------------------------------- +/** \brief Virtual function that defines the characters allowed in name identifiers. + \sa #ValidOprtChars, #ValidPrefixOprtChars +*/ +const char_type *ParserBase::ValidNameChars() const { assert(m_sNameChars.size()); return m_sNameChars.c_str(); - } +} - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in operator definitions. - \sa #ValidNameChars, #ValidPrefixOprtChars - */ - const char_type* ParserBase::ValidOprtChars() const - { +//--------------------------------------------------------------------------- +/** \brief Virtual function that defines the characters allowed in operator definitions. + \sa #ValidNameChars, #ValidPrefixOprtChars +*/ +const char_type *ParserBase::ValidOprtChars() const { assert(m_sOprtChars.size()); return m_sOprtChars.c_str(); - } +} - //--------------------------------------------------------------------------- - /** \brief Virtual function that defines the characters allowed in infix operator definitions. - \sa #ValidNameChars, #ValidOprtChars - */ - const char_type* ParserBase::ValidInfixOprtChars() const - { +//--------------------------------------------------------------------------- +/** \brief Virtual function that defines the characters allowed in infix operator definitions. + \sa #ValidNameChars, #ValidOprtChars +*/ +const char_type *ParserBase::ValidInfixOprtChars() const { assert(m_sInfixOprtChars.size()); return m_sInfixOprtChars.c_str(); - } +} - //--------------------------------------------------------------------------- - /** \brief Add a user defined operator. - \post Will reset the Parser to string parsing mode. - */ - void ParserBase::DefinePostfixOprt(const string_type &a_sName, - fun_type1 a_pFun, - bool a_bAllowOpt) - { - AddCallback(a_sName, - ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), - m_PostOprtDef, - ValidOprtChars() ); - } +//--------------------------------------------------------------------------- +/** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. +*/ +void ParserBase::DefinePostfixOprt(const string_type &a_sName, fun_type1 a_pFun, bool a_bAllowOpt) { + AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), + m_PostOprtDef, ValidOprtChars()); +} - //--------------------------------------------------------------------------- - /** \brief Initialize user defined functions. - - Calls the virtual functions InitFun(), InitConst() and InitOprt(). - */ - void ParserBase::Init() - { +//--------------------------------------------------------------------------- +/** \brief Initialize user defined functions. + + Calls the virtual functions InitFun(), InitConst() and InitOprt(). +*/ +void ParserBase::Init() { InitCharSets(); InitFun(); InitConst(); InitOprt(); - } +} - //--------------------------------------------------------------------------- - /** \brief Add a user defined operator. - \post Will reset the Parser to string parsing mode. - \param [in] a_sName operator Identifier - \param [in] a_pFun Operator callback function - \param [in] a_iPrec Operator Precedence (default=prSIGN) - \param [in] a_bAllowOpt True if operator is volatile (default=false) - \sa EPrec - */ - void ParserBase::DefineInfixOprt(const string_type &a_sName, - fun_type1 a_pFun, - int a_iPrec, - bool a_bAllowOpt) - { - AddCallback(a_sName, - ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), - m_InfixOprtDef, - ValidInfixOprtChars() ); - } +//--------------------------------------------------------------------------- +/** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. + \param [in] a_sName operator Identifier + \param [in] a_pFun Operator callback function + \param [in] a_iPrec Operator Precedence (default=prSIGN) + \param [in] a_bAllowOpt True if operator is volatile (default=false) + \sa EPrec +*/ +void ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, int a_iPrec, + bool a_bAllowOpt) { + AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, + ValidInfixOprtChars()); +} +//--------------------------------------------------------------------------- +/** \brief Define a binary operator. + \param [in] a_sName The identifier of the operator. + \param [in] a_pFun Pointer to the callback function. + \param [in] a_iPrec Precedence of the operator. + \param [in] a_eAssociativity The associativity of the operator. + \param [in] a_bAllowOpt If this is true the operator may be optimized away. - //--------------------------------------------------------------------------- - /** \brief Define a binary operator. - \param [in] a_sName The identifier of the operator. - \param [in] a_pFun Pointer to the callback function. - \param [in] a_iPrec Precedence of the operator. - \param [in] a_eAssociativity The associativity of the operator. - \param [in] a_bAllowOpt If this is true the operator may be optimized away. - - Adds a new Binary operator the the parser instance. - */ - void ParserBase::DefineOprt( const string_type &a_sName, - fun_type2 a_pFun, - unsigned a_iPrec, - EOprtAssociativity a_eAssociativity, - bool a_bAllowOpt ) - { + Adds a new Binary operator the the parser instance. +*/ +void ParserBase::DefineOprt(const string_type &a_sName, fun_type2 a_pFun, unsigned a_iPrec, + EOprtAssociativity a_eAssociativity, bool a_bAllowOpt) { // Check for conflicts with built in operator names - for (int i=0; m_bBuiltInOp && iIgnoreUndefVar(true); - CreateRPN(); // try to create bytecode, but don't use it for any further calculations since it - // may contain references to nonexisting variables. - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - } - catch(exception_type & /*e*/) - { - // Make sure to stay in string parse mode, dont call ReInit() - // because it deletes the array with the used variables - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - throw; - } - - return m_pTokenReader->GetUsedVar(); - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing the used variables only. */ - const varmap_type& ParserBase::GetVar() const - { - return m_VarDef; - } - - //--------------------------------------------------------------------------- - /** \brief Return a map containing all parser constants. */ - const valmap_type& ParserBase::GetConst() const - { - return m_ConstDef; - } - - //--------------------------------------------------------------------------- - /** \brief Return prototypes of all parser functions. - \return #m_FunDef - \sa FunProt - \throw nothrow - - The return type is a map of the public type #funmap_type containing the prototype - definitions for all numerical parser functions. String functions are not part of - this map. The Prototype definition is encapsulated in objects of the class FunProt - one per parser function each associated with function names via a map construct. - */ - const funmap_type& ParserBase::GetFunDef() const - { - return m_FunDef; - } - - //--------------------------------------------------------------------------- - /** \brief Retrieve the formula. */ - const string_type& ParserBase::GetExpr() const - { - return m_pTokenReader->GetExpr(); - } - - //--------------------------------------------------------------------------- - /** \brief Execute a function that takes a single string argument. - \param a_FunTok Function token. - \throw exception_type If the function token is not a string function - */ - ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const - { - if (a_vArg.back().GetCode()!=cmSTRING) - Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); - - token_type valTok; - generic_fun_type pFunc = a_FunTok.GetFuncAddr(); - assert(pFunc); - - try - { - // Check function arguments; write dummy value into valtok to represent the result - switch(a_FunTok.GetArgCount()) - { - case 0: valTok.SetVal(1); a_vArg[0].GetAsString(); break; - case 1: valTok.SetVal(1); a_vArg[1].GetAsString(); a_vArg[0].GetVal(); break; - case 2: valTok.SetVal(1); a_vArg[2].GetAsString(); a_vArg[1].GetVal(); a_vArg[0].GetVal(); break; - default: assert(0 && "Unexpected arg count"); - } - } - catch(ParserError& ) - { - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); - } - - // string functions won't be optimized - m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); - - // Push dummy value representing the function result to the stack - return valTok; - } - - //--------------------------------------------------------------------------- - /** \brief Apply a function token. - \param iArgCount Number of Arguments actually gathered used only for multiarg functions. - \post The result is pushed to the value stack - \post The function token is removed from the stack - \throw exception_type if Argument count does not match function requirements. - */ - void ParserBase::ApplyFunc( ParserStack &a_stOpt, - ParserStack &a_stVal, - int a_iArgCount) const - { - assert(m_pTokenReader.get()); - - // Operator stack empty or does not contain tokens with callback functions - if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 ) - return; - - token_type funTok = a_stOpt.pop(); - assert(funTok.GetFuncAddr()); - - // Binary operators must rely on their internal operator number - // since counting of operators relies on commas for function arguments - // binary operators do not have commas in their expression - int iArgCount = (funTok.GetCode()==cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount; - - // determine how many parameters the function needs. To remember iArgCount includes the - // string parameter whilst GetArgCount() counts only numeric parameters. - int iArgRequired = funTok.GetArgCount() + ((funTok.GetType()==tpSTR) ? 1 : 0); - - // Thats the number of numerical parameters - int iArgNumerical = iArgCount - ((funTok.GetType()==tpSTR) ? 1 : 0); - - if (funTok.GetCode()==cmFUNC_STR && iArgCount-iArgNumerical>1) - assert(0 && "muParser internal error"); - - if (funTok.GetArgCount()>=0 && iArgCount>iArgRequired) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); - - if (funTok.GetCode()!=cmOPRT_BIN && iArgCountGetPos()-1, funTok.GetAsString()); - - if (funTok.GetCode()==cmFUNC_STR && iArgCount>iArgRequired ) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString()); - - // Collect the numeric function arguments from the value stack and store them - // in a vector - std::vector stArg; - for (int i=0; iGetPos(), funTok.GetAsString()); - } - - switch(funTok.GetCode()) - { - case cmFUNC_STR: - stArg.push_back(a_stVal.pop()); - - if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR ) - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); - - ApplyStrFunc(funTok, stArg); - break; - - case cmFUNC_BULK: - m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); - break; - - case cmOPRT_BIN: - case cmOPRT_POSTFIX: - case cmOPRT_INFIX: - case cmFUNC: - if (funTok.GetArgCount()==-1 && iArgCount==0) - Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); - - m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount()==-1) ? -iArgNumerical : iArgNumerical); - break; - } - - // Push dummy value representing the function result to the stack - token_type token; - token.SetVal(1); - a_stVal.push(token); - } - - //--------------------------------------------------------------------------- - void ParserBase::ApplyIfElse(ParserStack &a_stOpt, - ParserStack &a_stVal) const - { - // Check if there is an if Else clause to be calculated - while (a_stOpt.size() && a_stOpt.top().GetCode()==cmELSE) - { - token_type opElse = a_stOpt.pop(); - MUP_ASSERT(a_stOpt.size()>0); - - // Take the value associated with the else branch from the value stack - token_type vVal2 = a_stVal.pop(); - - MUP_ASSERT(a_stOpt.size()>0); - MUP_ASSERT(a_stVal.size()>=2); - - // it then else is a ternary operator Pop all three values from the value s - // tack and just return the right value - token_type vVal1 = a_stVal.pop(); - token_type vExpr = a_stVal.pop(); - - a_stVal.push( (vExpr.GetVal()!=0) ? vVal1 : vVal2); - - token_type opIf = a_stOpt.pop(); - MUP_ASSERT(opElse.GetCode()==cmELSE); - MUP_ASSERT(opIf.GetCode()==cmIF); - - m_vRPN.AddIfElse(cmENDIF); - } // while pending if-else-clause found - } - - //--------------------------------------------------------------------------- - /** \brief Performs the necessary steps to write code for - the execution of binary operators into the bytecode. - */ - void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const - { - // is it a user defined binary operator? - if (a_stOpt.top().GetCode()==cmOPRT_BIN) - { - ApplyFunc(a_stOpt, a_stVal, 2); - } - else - { - MUP_ASSERT(a_stVal.size()>=2); - token_type valTok1 = a_stVal.pop(), - valTok2 = a_stVal.pop(), - optTok = a_stOpt.pop(), - resTok; - - if ( valTok1.GetType()!=valTok2.GetType() || - (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) ) - Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); - - if (optTok.GetCode()==cmASSIGN) - { - if (valTok2.GetCode()!=cmVAR) - Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); - - m_vRPN.AddAssignOp(valTok2.GetVar()); - } - else - m_vRPN.AddOp(optTok.GetCode()); - - resTok.SetVal(1); - a_stVal.push(resTok); - } - } - - //--------------------------------------------------------------------------- - /** \brief Apply a binary operator. - \param a_stOpt The operator stack - \param a_stVal The value stack - */ - void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, - ParserStack &stVal) const - { - while (stOpt.size() && - stOpt.top().GetCode() != cmBO && - stOpt.top().GetCode() != cmIF) - { - token_type tok = stOpt.top(); - switch (tok.GetCode()) - { - case cmOPRT_INFIX: - case cmOPRT_BIN: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmLT: - case cmGT: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmLAND: - case cmLOR: - case cmASSIGN: - if (stOpt.top().GetCode()==cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); - else - ApplyBinOprt(stOpt, stVal); - break; - - case cmELSE: - ApplyIfElse(stOpt, stVal); - break; - - default: - assert(0 && "muParser internal error"); - } - } - } - - //--------------------------------------------------------------------------- - /** \brief Parse the command code. - \sa ParseString(...) - - Command code contains precalculated stack positions of the values and the - associated operators. The Stack is filled beginning from index one the - value at index zero is not used at all. - */ - value_type ParserBase::ParseCmdCode() const - { - return ParseCmdCodeBulk(0, 0); - } - - //--------------------------------------------------------------------------- - /** \brief Evaluate the RPN. - \param nOffset The offset added to variable addresses (for bulk mode) - \param nThreadID OpenMP Thread id of the calling thread - */ - value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const - { - assert(nThreadID<=s_MaxNumOpenMPThreads); - - // Note: The check for nOffset==0 and nThreadID here is not necessary but - // brings a minor performance gain when not in bulk mode. - value_type *Stack = ((nOffset==0) && (nThreadID==0)) ? &m_vStackBuffer[0] : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; - value_type buf; - int sidx(0); - for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd!=cmEND ; ++pTok) - { - switch (pTok->Cmd) - { - // built in binary operators - case cmLE: --sidx; Stack[sidx] = Stack[sidx] <= Stack[sidx+1]; continue; - case cmGE: --sidx; Stack[sidx] = Stack[sidx] >= Stack[sidx+1]; continue; - case cmNEQ: --sidx; Stack[sidx] = Stack[sidx] != Stack[sidx+1]; continue; - case cmEQ: --sidx; Stack[sidx] = Stack[sidx] == Stack[sidx+1]; continue; - case cmLT: --sidx; Stack[sidx] = Stack[sidx] < Stack[sidx+1]; continue; - case cmGT: --sidx; Stack[sidx] = Stack[sidx] > Stack[sidx+1]; continue; - case cmADD: --sidx; Stack[sidx] += Stack[1+sidx]; continue; - case cmSUB: --sidx; Stack[sidx] -= Stack[1+sidx]; continue; - case cmMUL: --sidx; Stack[sidx] *= Stack[1+sidx]; continue; - case cmDIV: --sidx; - - #if defined(MUP_MATH_EXCEPTIONS) - if (Stack[1+sidx]==0) - Error(ecDIV_BY_ZERO); - #endif - Stack[sidx] /= Stack[1+sidx]; - continue; - - case cmPOW: - --sidx; Stack[sidx] = MathImpl::Pow(Stack[sidx], Stack[1+sidx]); - continue; - - case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue; - case cmLOR: --sidx; Stack[sidx] = Stack[sidx] || Stack[sidx+1]; continue; - - case cmASSIGN: - // Bugfix for Bulkmode: - // for details see: - // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws - --sidx; Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; continue; - // original code: - //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; - - //case cmBO: // unused, listed for compiler optimization purposes - //case cmBC: - // MUP_FAIL(INVALID_CODE_IN_BYTECODE); - // continue; - - case cmIF: - if (Stack[sidx--]==0) - pTok += pTok->Oprt.offset; - continue; - - case cmELSE: - pTok += pTok->Oprt.offset; - continue; - - case cmENDIF: - continue; - - //case cmARG_SEP: - // MUP_FAIL(INVALID_CODE_IN_BYTECODE); - // continue; - - // value and variable tokens - case cmVAR: Stack[++sidx] = *(pTok->Val.ptr + nOffset); continue; - case cmVAL: Stack[++sidx] = pTok->Val.data2; continue; - - case cmVARPOW2: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf; - continue; - - case cmVARPOW3: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf*buf; - continue; - - case cmVARPOW4: buf = *(pTok->Val.ptr + nOffset); - Stack[++sidx] = buf*buf*buf*buf; - continue; - - case cmVARMUL: Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; - continue; - - // Next is treatment of numeric functions - case cmFUNC: - { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch(iArgCount) - { - case 0: sidx += 1; Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); continue; - case 1: Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); continue; - case 2: sidx -= 1; Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1]); continue; - case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; - case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; - case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; - case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; - case 7: sidx -= 6; Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; - case 8: sidx -= 7; Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; - case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; - case 10:sidx -= 9; Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; - default: - if (iArgCount>0) // function with variable arguments store the number as a negative value - assert(0 && "muParser internal error"); - - sidx -= -iArgCount - 1; - Stack[sidx] =(*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); - continue; - } - } - - // Next is treatment of string functions - case cmFUNC_STR: - { - sidx -= pTok->Fun.argc -1; - - // The index of the string argument in the string table - int iIdxStack = pTok->Fun.idx; - MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() ); - - switch(pTok->Fun.argc) // switch according to argument count - { - case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue; - case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue; - case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue; - } - - continue; - } - - case cmFUNC_BULK: - { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch(iArgCount) - { - case 0: sidx += 1; Stack[sidx] = (*(bulkfun_type0 )pTok->Fun.ptr)(nOffset, nThreadID); continue; - case 1: Stack[sidx] = (*(bulkfun_type1 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); continue; - case 2: sidx -= 1; Stack[sidx] = (*(bulkfun_type2 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1]); continue; - case 3: sidx -= 2; Stack[sidx] = (*(bulkfun_type3 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2]); continue; - case 4: sidx -= 3; Stack[sidx] = (*(bulkfun_type4 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3]); continue; - case 5: sidx -= 4; Stack[sidx] = (*(bulkfun_type5 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4]); continue; - case 6: sidx -= 5; Stack[sidx] = (*(bulkfun_type6 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5]); continue; - case 7: sidx -= 6; Stack[sidx] = (*(bulkfun_type7 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6]); continue; - case 8: sidx -= 7; Stack[sidx] = (*(bulkfun_type8 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7]); continue; - case 9: sidx -= 8; Stack[sidx] = (*(bulkfun_type9 )pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8]); continue; - case 10:sidx -= 9; Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx], Stack[sidx+1], Stack[sidx+2], Stack[sidx+3], Stack[sidx+4], Stack[sidx+5], Stack[sidx+6], Stack[sidx+7], Stack[sidx+8], Stack[sidx+9]); continue; - default: - assert(0 && "muParser internal error"); - continue; - } - } - - default: - assert(0 && "muParser internal error"); - return 0; - } // switch CmdCode - } // for all bytecode tokens - - return Stack[m_nFinalResultIdx]; - } - - //--------------------------------------------------------------------------- - void ParserBase::CreateRPN() const - { - if (!m_pTokenReader->GetExpr().length()) - Error(ecUNEXPECTED_EOF, 0); - - ParserStack stOpt, stVal; - ParserStack stArgCount; - token_type opta, opt; // for storing operators - token_type val, tval; // for storing value - - ReInit(); - - // The outermost counter counts the number of separated items - // such as in "a=10,b=20,c=c+a" - stArgCount.push(1); - - for(;;) - { - opt = m_pTokenReader->ReadNextToken(); - - switch (opt.GetCode()) - { - // - // Next three are different kind of value entries - // - case cmSTRING: - opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token - stVal.push(opt); - m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer - break; - - case cmVAR: - stVal.push(opt); - m_vRPN.AddVar( static_cast(opt.GetVar()) ); - break; - - case cmVAL: - stVal.push(opt); - m_vRPN.AddVal( opt.GetVal() ); - break; - - case cmELSE: - m_nIfElseCounter--; - if (m_nIfElseCounter<0) - Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); - - ApplyRemainingOprt(stOpt, stVal); - m_vRPN.AddIfElse(cmELSE); - stOpt.push(opt); - break; - - - case cmARG_SEP: - if (stArgCount.empty()) - Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); - - ++stArgCount.top(); - // fallthrough intentional (no break!) - +} + +//--------------------------------------------------------------------------- +/** \brief Get operator priority. + \throw ParserException if a_Oprt is no operator code +*/ +int ParserBase::GetOprtPrecedence(const token_type &a_Tok) const { + switch (a_Tok.GetCode()) { + // built in operators case cmEND: - ApplyRemainingOprt(stOpt, stVal); - break; - - case cmBC: - { - // The argument count for parameterless functions is zero - // by default an opening bracket sets parameter count to 1 - // in preparation of arguments to come. If the last token - // was an opening bracket we know better... - if (opta.GetCode()==cmBO) - --stArgCount.top(); - - ApplyRemainingOprt(stOpt, stVal); - - // Check if the bracket content has been evaluated completely - if (stOpt.size() && stOpt.top().GetCode()==cmBO) - { - // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check - // if there is either a function or a sign pending - // neither the opening nor the closing bracket will be pushed back to - // the operator stack - // Check if a function is standing in front of the opening bracket, - // if yes evaluate it afterwards check for infix operators - assert(stArgCount.size()); - int iArgCount = stArgCount.pop(); - - stOpt.pop(); // Take opening bracket from stack - - if (iArgCount>1 && ( stOpt.size()==0 || - (stOpt.top().GetCode()!=cmFUNC && - stOpt.top().GetCode()!=cmFUNC_BULK && - stOpt.top().GetCode()!=cmFUNC_STR) ) ) - Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); - - // The opening bracket was popped from the stack now check if there - // was a function before this bracket - if (stOpt.size() && - stOpt.top().GetCode()!=cmOPRT_INFIX && - stOpt.top().GetCode()!=cmOPRT_BIN && - stOpt.top().GetFuncAddr()!=0) - { - ApplyFunc(stOpt, stVal, iArgCount); - } - } - } // if bracket content is evaluated - break; - - // - // Next are the binary operator entries - // - //case cmAND: // built in binary operators - //case cmOR: - //case cmXOR: + return -5; + case cmARG_SEP: + return -4; + case cmASSIGN: + return -1; + case cmELSE: case cmIF: - m_nIfElseCounter++; - // fallthrough intentional (no break!) + return 0; + case cmLAND: + return prLAND; + case cmLOR: + return prLOR; + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + return prCMP; + case cmADD: + case cmSUB: + return prADD_SUB; + case cmMUL: + case cmDIV: + return prMUL_DIV; + case cmPOW: + return prPOW; + // user defined binary operators + case cmOPRT_INFIX: + case cmOPRT_BIN: + return a_Tok.GetPri(); + default: + assert(0 && "Unexpected operator in muParser"); + return 999; + } +} + +//--------------------------------------------------------------------------- +/** \brief Get operator priority. + \throw ParserException if a_Oprt is no operator code +*/ +EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) const { + switch (a_Tok.GetCode()) { + case cmASSIGN: case cmLAND: case cmLOR: case cmLT: @@ -1290,435 +603,1132 @@ namespace mu case cmSUB: case cmMUL: case cmDIV: + return oaLEFT; case cmPOW: - case cmASSIGN: + return oaRIGHT; case cmOPRT_BIN: + return a_Tok.GetAssociativity(); + default: + return oaNONE; + } +} - // A binary operator (user defined or built in) has been found. - while ( stOpt.size() && - stOpt.top().GetCode() != cmBO && - stOpt.top().GetCode() != cmELSE && - stOpt.top().GetCode() != cmIF) - { - int nPrec1 = GetOprtPrecedence(stOpt.top()), - nPrec2 = GetOprtPrecedence(opt); +//--------------------------------------------------------------------------- +/** \brief Return a map containing the used variables only. */ +const varmap_type &ParserBase::GetUsedVar() const { + try { + m_pTokenReader->IgnoreUndefVar(true); + CreateRPN(); // try to create bytecode, but don't use it for any further calculations since + // it + // may contain references to nonexisting variables. + m_pParseFormula = &ParserBase::ParseString; + m_pTokenReader->IgnoreUndefVar(false); + } catch (exception_type & /*e*/) { + // Make sure to stay in string parse mode, dont call ReInit() + // because it deletes the array with the used variables + m_pParseFormula = &ParserBase::ParseString; + m_pTokenReader->IgnoreUndefVar(false); + throw; + } - if (stOpt.top().GetCode()==opt.GetCode()) - { + return m_pTokenReader->GetUsedVar(); +} - // Deal with operator associativity - EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt); - if ( (eOprtAsct==oaRIGHT && (nPrec1 <= nPrec2)) || - (eOprtAsct==oaLEFT && (nPrec1 < nPrec2)) ) - { - break; - } - } - else if (nPrec1 < nPrec2) - { - // In case the operators are not equal the precedence decides alone... - break; - } - - if (stOpt.top().GetCode()==cmOPRT_INFIX) +//--------------------------------------------------------------------------- +/** \brief Return a map containing the used variables only. */ +const varmap_type &ParserBase::GetVar() const { return m_VarDef; } + +//--------------------------------------------------------------------------- +/** \brief Return a map containing all parser constants. */ +const valmap_type &ParserBase::GetConst() const { return m_ConstDef; } + +//--------------------------------------------------------------------------- +/** \brief Return prototypes of all parser functions. + \return #m_FunDef + \sa FunProt + \throw nothrow + + The return type is a map of the public type #funmap_type containing the prototype + definitions for all numerical parser functions. String functions are not part of + this map. The Prototype definition is encapsulated in objects of the class FunProt + one per parser function each associated with function names via a map construct. +*/ +const funmap_type &ParserBase::GetFunDef() const { return m_FunDef; } + +//--------------------------------------------------------------------------- +/** \brief Retrieve the formula. */ +const string_type &ParserBase::GetExpr() const { return m_pTokenReader->GetExpr(); } + +//--------------------------------------------------------------------------- +/** \brief Execute a function that takes a single string argument. + \param a_FunTok Function token. + \throw exception_type If the function token is not a string function +*/ +ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, + const std::vector &a_vArg) const { + if (a_vArg.back().GetCode() != cmSTRING) + Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + + token_type valTok; + generic_fun_type pFunc = a_FunTok.GetFuncAddr(); + assert(pFunc); + + try { + // Check function arguments; write dummy value into valtok to represent the result + switch (a_FunTok.GetArgCount()) { + case 0: + valTok.SetVal(1); + a_vArg[0].GetAsString(); + break; + case 1: + valTok.SetVal(1); + a_vArg[1].GetAsString(); + a_vArg[0].GetVal(); + break; + case 2: + valTok.SetVal(1); + a_vArg[2].GetAsString(); + a_vArg[1].GetVal(); + a_vArg[0].GetVal(); + break; + default: + assert(0 && "Unexpected arg count"); + } + } catch (ParserError &) { + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + } + + // string functions won't be optimized + m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); + + // Push dummy value representing the function result to the stack + return valTok; +} + +//--------------------------------------------------------------------------- +/** \brief Apply a function token. + \param iArgCount Number of Arguments actually gathered used only for multiarg functions. + \post The result is pushed to the value stack + \post The function token is removed from the stack + \throw exception_type if Argument count does not match function requirements. +*/ +void ParserBase::ApplyFunc(ParserStack &a_stOpt, ParserStack &a_stVal, + int a_iArgCount) const { + assert(m_pTokenReader.get()); + + // Operator stack empty or does not contain tokens with callback functions + if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0) return; + + token_type funTok = a_stOpt.pop(); + assert(funTok.GetFuncAddr()); + + // Binary operators must rely on their internal operator number + // since counting of operators relies on commas for function arguments + // binary operators do not have commas in their expression + int iArgCount = (funTok.GetCode() == cmOPRT_BIN) ? funTok.GetArgCount() : a_iArgCount; + + // determine how many parameters the function needs. To remember iArgCount includes the + // string parameter whilst GetArgCount() counts only numeric parameters. + int iArgRequired = funTok.GetArgCount() + ((funTok.GetType() == tpSTR) ? 1 : 0); + + // Thats the number of numerical parameters + int iArgNumerical = iArgCount - ((funTok.GetType() == tpSTR) ? 1 : 0); + + if (funTok.GetCode() == cmFUNC_STR && iArgCount - iArgNumerical > 1) + assert(0 && "muParser internal error"); + + if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired) + Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + + if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired) + Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + + if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired) + Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + + // Collect the numeric function arguments from the value stack and store them + // in a vector + std::vector stArg; + for (int i = 0; i < iArgNumerical; ++i) { + stArg.push_back(a_stVal.pop()); + if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR) + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + } + + switch (funTok.GetCode()) { + case cmFUNC_STR: + stArg.push_back(a_stVal.pop()); + + if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR) + Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + + ApplyStrFunc(funTok, stArg); + break; + + case cmFUNC_BULK: + m_vRPN.AddBulkFun(funTok.GetFuncAddr(), (int)stArg.size()); + break; + + case cmOPRT_BIN: + case cmOPRT_POSTFIX: + case cmOPRT_INFIX: + case cmFUNC: + if (funTok.GetArgCount() == -1 && iArgCount == 0) + Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); + + m_vRPN.AddFun(funTok.GetFuncAddr(), + (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical); + break; + } + + // Push dummy value representing the function result to the stack + token_type token; + token.SetVal(1); + a_stVal.push(token); +} + +//--------------------------------------------------------------------------- +void ParserBase::ApplyIfElse(ParserStack &a_stOpt, + ParserStack &a_stVal) const { + // Check if there is an if Else clause to be calculated + while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE) { + token_type opElse = a_stOpt.pop(); + MUP_ASSERT(a_stOpt.size() > 0); + + // Take the value associated with the else branch from the value stack + token_type vVal2 = a_stVal.pop(); + + MUP_ASSERT(a_stOpt.size() > 0); + MUP_ASSERT(a_stVal.size() >= 2); + + // it then else is a ternary operator Pop all three values from the value s + // tack and just return the right value + token_type vVal1 = a_stVal.pop(); + token_type vExpr = a_stVal.pop(); + + a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2); + + token_type opIf = a_stOpt.pop(); + MUP_ASSERT(opElse.GetCode() == cmELSE); + MUP_ASSERT(opIf.GetCode() == cmIF); + + m_vRPN.AddIfElse(cmENDIF); + } // while pending if-else-clause found +} + +//--------------------------------------------------------------------------- +/** \brief Performs the necessary steps to write code for + the execution of binary operators into the bytecode. +*/ +void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, + ParserStack &a_stVal) const { + // is it a user defined binary operator? + if (a_stOpt.top().GetCode() == cmOPRT_BIN) { + ApplyFunc(a_stOpt, a_stVal, 2); + } else { + MUP_ASSERT(a_stVal.size() >= 2); + token_type valTok1 = a_stVal.pop(), valTok2 = a_stVal.pop(), optTok = a_stOpt.pop(), resTok; + + if (valTok1.GetType() != valTok2.GetType() || + (valTok1.GetType() == tpSTR && valTok2.GetType() == tpSTR)) + Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); + + if (optTok.GetCode() == cmASSIGN) { + if (valTok2.GetCode() != cmVAR) Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); + + m_vRPN.AddAssignOp(valTok2.GetVar()); + } else + m_vRPN.AddOp(optTok.GetCode()); + + resTok.SetVal(1); + a_stVal.push(resTok); + } +} + +//--------------------------------------------------------------------------- +/** \brief Apply a binary operator. + \param a_stOpt The operator stack + \param a_stVal The value stack +*/ +void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, + ParserStack &stVal) const { + while (stOpt.size() && stOpt.top().GetCode() != cmBO && stOpt.top().GetCode() != cmIF) { + token_type tok = stOpt.top(); + switch (tok.GetCode()) { + case cmOPRT_INFIX: + case cmOPRT_BIN: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmLT: + case cmGT: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmLAND: + case cmLOR: + case cmASSIGN: + if (stOpt.top().GetCode() == cmOPRT_INFIX) ApplyFunc(stOpt, stVal, 1); - else + else ApplyBinOprt(stOpt, stVal); - } // while ( ... ) + break; - if (opt.GetCode()==cmIF) - m_vRPN.AddIfElse(opt.GetCode()); + case cmELSE: + ApplyIfElse(stOpt, stVal); + break; - // The operator can't be evaluated right now, push back to the operator stack + default: + assert(0 && "muParser internal error"); + } + } +} + +//--------------------------------------------------------------------------- +/** \brief Parse the command code. + \sa ParseString(...) + + Command code contains precalculated stack positions of the values and the + associated operators. The Stack is filled beginning from index one the + value at index zero is not used at all. +*/ +value_type ParserBase::ParseCmdCode() const { return ParseCmdCodeBulk(0, 0); } + +//--------------------------------------------------------------------------- +/** \brief Evaluate the RPN. + \param nOffset The offset added to variable addresses (for bulk mode) + \param nThreadID OpenMP Thread id of the calling thread +*/ +value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const { + assert(nThreadID <= s_MaxNumOpenMPThreads); + + // Note: The check for nOffset==0 and nThreadID here is not necessary but + // brings a minor performance gain when not in bulk mode. + value_type *Stack = + ((nOffset == 0) && (nThreadID == 0)) + ? &m_vStackBuffer[0] + : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; + value_type buf; + int sidx(0); + for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok) { + switch (pTok->Cmd) { + // built in binary operators + case cmLE: + --sidx; + Stack[sidx] = Stack[sidx] <= Stack[sidx + 1]; + continue; + case cmGE: + --sidx; + Stack[sidx] = Stack[sidx] >= Stack[sidx + 1]; + continue; + case cmNEQ: + --sidx; + Stack[sidx] = Stack[sidx] != Stack[sidx + 1]; + continue; + case cmEQ: + --sidx; + Stack[sidx] = Stack[sidx] == Stack[sidx + 1]; + continue; + case cmLT: + --sidx; + Stack[sidx] = Stack[sidx] < Stack[sidx + 1]; + continue; + case cmGT: + --sidx; + Stack[sidx] = Stack[sidx] > Stack[sidx + 1]; + continue; + case cmADD: + --sidx; + Stack[sidx] += Stack[1 + sidx]; + continue; + case cmSUB: + --sidx; + Stack[sidx] -= Stack[1 + sidx]; + continue; + case cmMUL: + --sidx; + Stack[sidx] *= Stack[1 + sidx]; + continue; + case cmDIV: + --sidx; + +#if defined(MUP_MATH_EXCEPTIONS) + if (Stack[1 + sidx] == 0) Error(ecDIV_BY_ZERO); +#endif + Stack[sidx] /= Stack[1 + sidx]; + continue; + + case cmPOW: + --sidx; + Stack[sidx] = MathImpl::Pow(Stack[sidx], Stack[1 + sidx]); + continue; + + case cmLAND: + --sidx; + Stack[sidx] = Stack[sidx] && Stack[sidx + 1]; + continue; + case cmLOR: + --sidx; + Stack[sidx] = Stack[sidx] || Stack[sidx + 1]; + continue; + + case cmASSIGN: + // Bugfix for Bulkmode: + // for details see: + // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws + --sidx; + Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; + continue; + // original code: + //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; + + // case cmBO: // unused, listed for compiler optimization purposes + // case cmBC: + // MUP_FAIL(INVALID_CODE_IN_BYTECODE); + // continue; + + case cmIF: + if (Stack[sidx--] == 0) pTok += pTok->Oprt.offset; + continue; + + case cmELSE: + pTok += pTok->Oprt.offset; + continue; + + case cmENDIF: + continue; + + // case cmARG_SEP: + // MUP_FAIL(INVALID_CODE_IN_BYTECODE); + // continue; + + // value and variable tokens + case cmVAR: + Stack[++sidx] = *(pTok->Val.ptr + nOffset); + continue; + case cmVAL: + Stack[++sidx] = pTok->Val.data2; + continue; + + case cmVARPOW2: + buf = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = buf * buf; + continue; + + case cmVARPOW3: + buf = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = buf * buf * buf; + continue; + + case cmVARPOW4: + buf = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = buf * buf * buf * buf; + continue; + + case cmVARMUL: + Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; + continue; + + // Next is treatment of numeric functions + case cmFUNC: { + int iArgCount = pTok->Fun.argc; + + // switch according to argument count + switch (iArgCount) { + case 0: + sidx += 1; + Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); + continue; + case 1: + Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); + continue; + case 2: + sidx -= 1; + Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1]); + continue; + case 3: + sidx -= 2; + Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2]); + continue; + case 4: + sidx -= 3; + Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2], Stack[sidx + 3]); + continue; + case 5: + sidx -= 4; + Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4]); + continue; + case 6: + sidx -= 5; + Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5]); + continue; + case 7: + sidx -= 6; + Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)( + Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]); + continue; + case 8: + sidx -= 7; + Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)( + Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7]); + continue; + case 9: + sidx -= 8; + Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)( + Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], + Stack[sidx + 8]); + continue; + case 10: + sidx -= 9; + Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)( + Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], + Stack[sidx + 8], Stack[sidx + 9]); + continue; + default: + if (iArgCount > 0) // function with variable arguments store the number as + // a negative value + assert(0 && "muParser internal error"); + + sidx -= -iArgCount - 1; + Stack[sidx] = (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); + continue; + } + } + + // Next is treatment of string functions + case cmFUNC_STR: { + sidx -= pTok->Fun.argc - 1; + + // The index of the string argument in the string table + int iIdxStack = pTok->Fun.idx; + MUP_ASSERT(iIdxStack >= 0 && iIdxStack < (int)m_vStringBuf.size()); + + switch (pTok->Fun.argc) // switch according to argument count + { + case 0: + Stack[sidx] = + (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); + continue; + case 1: + Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)( + m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); + continue; + case 2: + Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)( + m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1]); + continue; + } + + continue; + } + + case cmFUNC_BULK: { + int iArgCount = pTok->Fun.argc; + + // switch according to argument count + switch (iArgCount) { + case 0: + sidx += 1; + Stack[sidx] = (*(bulkfun_type0)pTok->Fun.ptr)(nOffset, nThreadID); + continue; + case 1: + Stack[sidx] = + (*(bulkfun_type1)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); + continue; + case 2: + sidx -= 1; + Stack[sidx] = (*(bulkfun_type2)pTok->Fun.ptr)(nOffset, nThreadID, + Stack[sidx], Stack[sidx + 1]); + continue; + case 3: + sidx -= 2; + Stack[sidx] = (*(bulkfun_type3)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]); + continue; + case 4: + sidx -= 3; + Stack[sidx] = (*(bulkfun_type4)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3]); + continue; + case 5: + sidx -= 4; + Stack[sidx] = (*(bulkfun_type5)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4]); + continue; + case 6: + sidx -= 5; + Stack[sidx] = (*(bulkfun_type6)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5]); + continue; + case 7: + sidx -= 6; + Stack[sidx] = (*(bulkfun_type7)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]); + continue; + case 8: + sidx -= 7; + Stack[sidx] = (*(bulkfun_type8)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], + Stack[sidx + 7]); + continue; + case 9: + sidx -= 8; + Stack[sidx] = (*(bulkfun_type9)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], + Stack[sidx + 7], Stack[sidx + 8]); + continue; + case 10: + sidx -= 9; + Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)( + nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], + Stack[sidx + 7], Stack[sidx + 8], Stack[sidx + 9]); + continue; + default: + assert(0 && "muParser internal error"); + continue; + } + } + + default: + assert(0 && "muParser internal error"); + return 0; + } // switch CmdCode + } // for all bytecode tokens + + return Stack[m_nFinalResultIdx]; +} + +//--------------------------------------------------------------------------- +void ParserBase::CreateRPN() const { + if (!m_pTokenReader->GetExpr().length()) Error(ecUNEXPECTED_EOF, 0); + + ParserStack stOpt, stVal; + ParserStack stArgCount; + token_type opta, opt; // for storing operators + token_type val, tval; // for storing value + + ReInit(); + + // The outermost counter counts the number of separated items + // such as in "a=10,b=20,c=c+a" + stArgCount.push(1); + + for (;;) { + opt = m_pTokenReader->ReadNextToken(); + + switch (opt.GetCode()) { + // + // Next three are different kind of value entries + // + case cmSTRING: + opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token + stVal.push(opt); + m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer + break; + + case cmVAR: + stVal.push(opt); + m_vRPN.AddVar(static_cast(opt.GetVar())); + break; + + case cmVAL: + stVal.push(opt); + m_vRPN.AddVal(opt.GetVal()); + break; + + case cmELSE: + m_nIfElseCounter--; + if (m_nIfElseCounter < 0) Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + + ApplyRemainingOprt(stOpt, stVal); + m_vRPN.AddIfElse(cmELSE); stOpt.push(opt); break; - // - // Last section contains functions and operators implicitly mapped to functions - // - case cmBO: + case cmARG_SEP: + if (stArgCount.empty()) Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); + + ++stArgCount.top(); + // fallthrough intentional (no break!) + + case cmEND: + ApplyRemainingOprt(stOpt, stVal); + break; + + case cmBC: { + // The argument count for parameterless functions is zero + // by default an opening bracket sets parameter count to 1 + // in preparation of arguments to come. If the last token + // was an opening bracket we know better... + if (opta.GetCode() == cmBO) --stArgCount.top(); + + ApplyRemainingOprt(stOpt, stVal); + + // Check if the bracket content has been evaluated completely + if (stOpt.size() && stOpt.top().GetCode() == cmBO) { + // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to + // check + // if there is either a function or a sign pending + // neither the opening nor the closing bracket will be pushed back to + // the operator stack + // Check if a function is standing in front of the opening bracket, + // if yes evaluate it afterwards check for infix operators + assert(stArgCount.size()); + int iArgCount = stArgCount.pop(); + + stOpt.pop(); // Take opening bracket from stack + + if (iArgCount > 1 && + (stOpt.size() == 0 || + (stOpt.top().GetCode() != cmFUNC && stOpt.top().GetCode() != cmFUNC_BULK && + stOpt.top().GetCode() != cmFUNC_STR))) + Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); + + // The opening bracket was popped from the stack now check if there + // was a function before this bracket + if (stOpt.size() && stOpt.top().GetCode() != cmOPRT_INFIX && + stOpt.top().GetCode() != cmOPRT_BIN && stOpt.top().GetFuncAddr() != 0) { + ApplyFunc(stOpt, stVal, iArgCount); + } + } + } // if bracket content is evaluated + break; + + // + // Next are the binary operator entries + // + // case cmAND: // built in binary operators + // case cmOR: + // case cmXOR: + case cmIF: + m_nIfElseCounter++; + // fallthrough intentional (no break!) + + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmASSIGN: + case cmOPRT_BIN: + + // A binary operator (user defined or built in) has been found. + while (stOpt.size() && stOpt.top().GetCode() != cmBO && + stOpt.top().GetCode() != cmELSE && stOpt.top().GetCode() != cmIF) { + int nPrec1 = GetOprtPrecedence(stOpt.top()), nPrec2 = GetOprtPrecedence(opt); + + if (stOpt.top().GetCode() == opt.GetCode()) { + // Deal with operator associativity + EOprtAssociativity eOprtAsct = GetOprtAssociativity(opt); + if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) || + (eOprtAsct == oaLEFT && (nPrec1 < nPrec2))) { + break; + } + } else if (nPrec1 < nPrec2) { + // In case the operators are not equal the precedence decides alone... + break; + } + + if (stOpt.top().GetCode() == cmOPRT_INFIX) + ApplyFunc(stOpt, stVal, 1); + else + ApplyBinOprt(stOpt, stVal); + } // while ( ... ) + + if (opt.GetCode() == cmIF) m_vRPN.AddIfElse(opt.GetCode()); + + // The operator can't be evaluated right now, push back to the operator stack + stOpt.push(opt); + break; + + // + // Last section contains functions and operators implicitly mapped to functions + // + case cmBO: stArgCount.push(1); stOpt.push(opt); break; - case cmOPRT_INFIX: - case cmFUNC: - case cmFUNC_BULK: - case cmFUNC_STR: + case cmOPRT_INFIX: + case cmFUNC: + case cmFUNC_BULK: + case cmFUNC_STR: stOpt.push(opt); break; - case cmOPRT_POSTFIX: + case cmOPRT_POSTFIX: stOpt.push(opt); ApplyFunc(stOpt, stVal, 1); // this is the postfix operator break; - default: assert(0 && "muParser internal error"); - } // end of switch operator-token + default: + assert(0 && "muParser internal error"); + } // end of switch operator-token - opta = opt; + opta = opt; - if ( opt.GetCode() == cmEND ) - { - m_vRPN.Finalize(); - break; - } + if (opt.GetCode() == cmEND) { + m_vRPN.Finalize(); + break; + } - if (ParserBase::g_DbgDumpStack) - { - StackDump(stVal, stOpt); - m_vRPN.AsciiDump(); - } - } // while (true) + if (ParserBase::g_DbgDumpStack) { + StackDump(stVal, stOpt); + m_vRPN.AsciiDump(); + } + } // while (true) - if (ParserBase::g_DbgDumpCmdCode) - m_vRPN.AsciiDump(); + if (ParserBase::g_DbgDumpCmdCode) m_vRPN.AsciiDump(); - if (m_nIfElseCounter>0) - Error(ecMISSING_ELSE_CLAUSE); + if (m_nIfElseCounter > 0) Error(ecMISSING_ELSE_CLAUSE); // get the last value (= final result) from the stack - MUP_ASSERT(stArgCount.size()==1); + MUP_ASSERT(stArgCount.size() == 1); m_nFinalResultIdx = stArgCount.top(); - if (m_nFinalResultIdx==0) - assert(0 && "muParser internal error"); + if (m_nFinalResultIdx == 0) assert(0 && "muParser internal error"); - if (stVal.size()==0) - Error(ecEMPTY_EXPRESSION); + if (stVal.size() == 0) Error(ecEMPTY_EXPRESSION); - if (stVal.top().GetType()!=tpDBL) - Error(ecSTR_RESULT); + if (stVal.top().GetType() != tpDBL) Error(ecSTR_RESULT); m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); - } +} - //--------------------------------------------------------------------------- - /** \brief One of the two main parse functions. - \sa ParseCmdCode(...) +//--------------------------------------------------------------------------- +/** \brief One of the two main parse functions. + \sa ParseCmdCode(...) - Parse expression from input string. Perform syntax checking and create - bytecode. After parsing the string and creating the bytecode the function - pointer #m_pParseFormula will be changed to the second parse routine the - uses bytecode instead of string parsing. - */ - value_type ParserBase::ParseString() const - { - try - { - CreateRPN(); - m_pParseFormula = &ParserBase::ParseCmdCode; - return (this->*m_pParseFormula)(); + Parse expression from input string. Perform syntax checking and create + bytecode. After parsing the string and creating the bytecode the function + pointer #m_pParseFormula will be changed to the second parse routine the + uses bytecode instead of string parsing. +*/ +value_type ParserBase::ParseString() const { + try { + CreateRPN(); + m_pParseFormula = &ParserBase::ParseCmdCode; + return (this->*m_pParseFormula)(); + } catch (ParserError &exc) { + exc.SetFormula(m_pTokenReader->GetExpr()); + throw; } - catch(ParserError &exc) - { - exc.SetFormula(m_pTokenReader->GetExpr()); - throw; - } - } +} - //--------------------------------------------------------------------------- - /** \brief Create an error containing the parse error position. +//--------------------------------------------------------------------------- +/** \brief Create an error containing the parse error position. - This function will create an Parser Exception object containing the error text and - its position. + This function will create an Parser Exception object containing the error text and + its position. - \param a_iErrc [in] The error code of type #EErrorCodes. - \param a_iPos [in] The position where the error was detected. - \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. - */ - void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const - { + \param a_iErrc [in] The error code of type #EErrorCodes. + \param a_iPos [in] The position where the error was detected. + \param a_strTok [in] The token string representation associated with the error. + \throw ParserException always throws thats the only purpose of this function. +*/ +void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const { throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); - } +} - //------------------------------------------------------------------------------ - /** \brief Clear all user defined variables. - \throw nothrow +//------------------------------------------------------------------------------ +/** \brief Clear all user defined variables. + \throw nothrow - Resets the parser to string parsing mode by calling #ReInit. - */ - void ParserBase::ClearVar() - { + Resets the parser to string parsing mode by calling #ReInit. +*/ +void ParserBase::ClearVar() { m_VarDef.clear(); ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Remove a variable from internal storage. - \throw nothrow +//------------------------------------------------------------------------------ +/** \brief Remove a variable from internal storage. + \throw nothrow - Removes a variable if it exists. If the Variable does not exist nothing will be done. - */ - void ParserBase::RemoveVar(const string_type &a_strVarName) - { + Removes a variable if it exists. If the Variable does not exist nothing will be done. +*/ +void ParserBase::RemoveVar(const string_type &a_strVarName) { varmap_type::iterator item = m_VarDef.find(a_strVarName); - if (item!=m_VarDef.end()) - { - m_VarDef.erase(item); - ReInit(); + if (item != m_VarDef.end()) { + m_VarDef.erase(item); + ReInit(); } - } +} - //------------------------------------------------------------------------------ - /** \brief Clear all functions. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearFun() - { +//------------------------------------------------------------------------------ +/** \brief Clear all functions. + \post Resets the parser to string parsing mode. + \throw nothrow +*/ +void ParserBase::ClearFun() { m_FunDef.clear(); ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Clear all user defined constants. +//------------------------------------------------------------------------------ +/** \brief Clear all user defined constants. - Both numeric and string constants will be removed from the internal storage. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearConst() - { + Both numeric and string constants will be removed from the internal storage. + \post Resets the parser to string parsing mode. + \throw nothrow +*/ +void ParserBase::ClearConst() { m_ConstDef.clear(); m_StrVarDef.clear(); ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Clear all user defined postfix operators. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearPostfixOprt() - { +//------------------------------------------------------------------------------ +/** \brief Clear all user defined postfix operators. + \post Resets the parser to string parsing mode. + \throw nothrow +*/ +void ParserBase::ClearPostfixOprt() { m_PostOprtDef.clear(); ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Clear all user defined binary operators. - \post Resets the parser to string parsing mode. - \throw nothrow - */ - void ParserBase::ClearOprt() - { +//------------------------------------------------------------------------------ +/** \brief Clear all user defined binary operators. + \post Resets the parser to string parsing mode. + \throw nothrow +*/ +void ParserBase::ClearOprt() { m_OprtDef.clear(); ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Clear the user defined Prefix operators. - \post Resets the parser to string parser mode. - \throw nothrow - */ - void ParserBase::ClearInfixOprt() - { +//------------------------------------------------------------------------------ +/** \brief Clear the user defined Prefix operators. + \post Resets the parser to string parser mode. + \throw nothrow +*/ +void ParserBase::ClearInfixOprt() { m_InfixOprtDef.clear(); ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Enable or disable the formula optimization feature. - \post Resets the parser to string parser mode. - \throw nothrow - */ - void ParserBase::EnableOptimizer(bool a_bIsOn) - { +//------------------------------------------------------------------------------ +/** \brief Enable or disable the formula optimization feature. + \post Resets the parser to string parser mode. + \throw nothrow +*/ +void ParserBase::EnableOptimizer(bool a_bIsOn) { m_vRPN.EnableOptimizer(a_bIsOn); ReInit(); - } +} - //--------------------------------------------------------------------------- - /** \brief Enable the dumping of bytecode and stack content on the console. - \param bDumpCmd Flag to enable dumping of the current bytecode to the console. - \param bDumpStack Flag to enable dumping of the stack content is written to the console. +//--------------------------------------------------------------------------- +/** \brief Enable the dumping of bytecode and stack content on the console. + \param bDumpCmd Flag to enable dumping of the current bytecode to the console. + \param bDumpStack Flag to enable dumping of the stack content is written to the console. - This function is for debug purposes only! - */ - void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) - { + This function is for debug purposes only! +*/ +void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) { ParserBase::g_DbgDumpCmdCode = bDumpCmd; - ParserBase::g_DbgDumpStack = bDumpStack; - } + ParserBase::g_DbgDumpStack = bDumpStack; +} - //------------------------------------------------------------------------------ - /** \brief Enable or disable the built in binary operators. - \throw nothrow - \sa m_bBuiltInOp, ReInit() +//------------------------------------------------------------------------------ +/** \brief Enable or disable the built in binary operators. + \throw nothrow + \sa m_bBuiltInOp, ReInit() - If you disable the built in binary operators there will be no binary operators - defined. Thus you must add them manually one by one. It is not possible to - disable built in operators selectively. This function will Reinitialize the - parser by calling ReInit(). - */ - void ParserBase::EnableBuiltInOprt(bool a_bIsOn) - { + If you disable the built in binary operators there will be no binary operators + defined. Thus you must add them manually one by one. It is not possible to + disable built in operators selectively. This function will Reinitialize the + parser by calling ReInit(). +*/ +void ParserBase::EnableBuiltInOprt(bool a_bIsOn) { m_bBuiltInOp = a_bIsOn; ReInit(); - } +} - //------------------------------------------------------------------------------ - /** \brief Query status of built in variables. - \return #m_bBuiltInOp; true if built in operators are enabled. - \throw nothrow - */ - bool ParserBase::HasBuiltInOprt() const - { - return m_bBuiltInOp; - } +//------------------------------------------------------------------------------ +/** \brief Query status of built in variables. + \return #m_bBuiltInOp; true if built in operators are enabled. + \throw nothrow +*/ +bool ParserBase::HasBuiltInOprt() const { return m_bBuiltInOp; } - //------------------------------------------------------------------------------ - /** \brief Get the argument separator character. - */ - char_type ParserBase::GetArgSep() const - { - return m_pTokenReader->GetArgSep(); - } +//------------------------------------------------------------------------------ +/** \brief Get the argument separator character. +*/ +char_type ParserBase::GetArgSep() const { return m_pTokenReader->GetArgSep(); } - //------------------------------------------------------------------------------ - /** \brief Set argument separator. - \param cArgSep the argument separator character. - */ - void ParserBase::SetArgSep(char_type cArgSep) - { - m_pTokenReader->SetArgSep(cArgSep); - } +//------------------------------------------------------------------------------ +/** \brief Set argument separator. + \param cArgSep the argument separator character. +*/ +void ParserBase::SetArgSep(char_type cArgSep) { m_pTokenReader->SetArgSep(cArgSep); } - //------------------------------------------------------------------------------ - /** \brief Dump stack content. +//------------------------------------------------------------------------------ +/** \brief Dump stack content. - This function is used for debugging only. - */ - void ParserBase::StackDump(const ParserStack &a_stVal, - const ParserStack &a_stOprt) const - { - ParserStack stOprt(a_stOprt), - stVal(a_stVal); + This function is used for debugging only. +*/ +void ParserBase::StackDump(const ParserStack &a_stVal, + const ParserStack &a_stOprt) const { + ParserStack stOprt(a_stOprt), stVal(a_stVal); mu::console() << _T("\nValue stack:\n"); - while ( !stVal.empty() ) - { - token_type val = stVal.pop(); - if (val.GetType()==tpSTR) - mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); - else - mu::console() << _T(" ") << val.GetVal() << _T(" "); + while (!stVal.empty()) { + token_type val = stVal.pop(); + if (val.GetType() == tpSTR) + mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); + else + mu::console() << _T(" ") << val.GetVal() << _T(" "); } mu::console() << "\nOperator stack:\n"; - while ( !stOprt.empty() ) - { - if (stOprt.top().GetCode()<=cmASSIGN) - { - mu::console() << _T("OPRT_INTRNL \"") - << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] - << _T("\" \n"); - } - else - { - switch(stOprt.top().GetCode()) - { - case cmVAR: mu::console() << _T("VAR\n"); break; - case cmVAL: mu::console() << _T("VAL\n"); break; - case cmFUNC: mu::console() << _T("FUNC \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmFUNC_BULK: mu::console() << _T("FUNC_BULK \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"") - << stOprt.top().GetAsString() - << _T("\"\n"); break; - case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break; - case cmEND: mu::console() << _T("END\n"); break; - case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break; - case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break; - case cmBC: mu::console() << _T("BRACKET \")\"\n"); break; - case cmIF: mu::console() << _T("IF\n"); break; - case cmELSE: mu::console() << _T("ELSE\n"); break; - case cmENDIF: mu::console() << _T("ENDIF\n"); break; - default: mu::console() << stOprt.top().GetCode() << _T(" "); break; + while (!stOprt.empty()) { + if (stOprt.top().GetCode() <= cmASSIGN) { + mu::console() << _T("OPRT_INTRNL \"") + << ParserBase::c_DefaultOprt[stOprt.top().GetCode()] << _T("\" \n"); + } else { + switch (stOprt.top().GetCode()) { + case cmVAR: + mu::console() << _T("VAR\n"); + break; + case cmVAL: + mu::console() << _T("VAL\n"); + break; + case cmFUNC: + mu::console() << _T("FUNC \"") << stOprt.top().GetAsString() << _T("\"\n"); + break; + case cmFUNC_BULK: + mu::console() << _T("FUNC_BULK \"") << stOprt.top().GetAsString() << _T("\"\n"); + break; + case cmOPRT_INFIX: + mu::console() << _T("OPRT_INFIX \"") << stOprt.top().GetAsString() + << _T("\"\n"); + break; + case cmOPRT_BIN: + mu::console() << _T("OPRT_BIN \"") << stOprt.top().GetAsString() << _T("\"\n"); + break; + case cmFUNC_STR: + mu::console() << _T("FUNC_STR\n"); + break; + case cmEND: + mu::console() << _T("END\n"); + break; + case cmUNKNOWN: + mu::console() << _T("UNKNOWN\n"); + break; + case cmBO: + mu::console() << _T("BRACKET \"(\"\n"); + break; + case cmBC: + mu::console() << _T("BRACKET \")\"\n"); + break; + case cmIF: + mu::console() << _T("IF\n"); + break; + case cmELSE: + mu::console() << _T("ELSE\n"); + break; + case cmENDIF: + mu::console() << _T("ENDIF\n"); + break; + default: + mu::console() << stOprt.top().GetCode() << _T(" "); + break; + } } - } - stOprt.pop(); + stOprt.pop(); } mu::console() << dec << endl; - } +} - //------------------------------------------------------------------------------ - /** \brief Evaluate an expression containing comma separated subexpressions - \param [out] nStackSize The total number of results available - \return Pointer to the array containing all expression results +//------------------------------------------------------------------------------ +/** \brief Evaluate an expression containing comma separated subexpressions + \param [out] nStackSize The total number of results available + \return Pointer to the array containing all expression results - This member function can be used to retrieve all results of an expression - made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") - */ - value_type* ParserBase::Eval(int &nStackSize) const - { - (this->*m_pParseFormula)(); + This member function can be used to retrieve all results of an expression + made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") +*/ +value_type *ParserBase::Eval(int &nStackSize) const { + (this->*m_pParseFormula)(); nStackSize = m_nFinalResultIdx; // (for historic reasons the stack starts at position 1) return &m_vStackBuffer[1]; - } +} - //--------------------------------------------------------------------------- - /** \brief Return the number of results on the calculation stack. - - If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). - There may be more than one return value. This function returns the number of - available results. - */ - int ParserBase::GetNumResults() const - { - return m_nFinalResultIdx; - } +//--------------------------------------------------------------------------- +/** \brief Return the number of results on the calculation stack. - //--------------------------------------------------------------------------- - /** \brief Calculate the result. - - A note on const correctness: - I consider it important that Calc is a const function. - Due to caching operations Calc changes only the state of internal variables with one exception - m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making - Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. - - \pre A formula must be set. - \pre Variables must have been set (if needed) - - \sa #m_pParseFormula - \return The evaluation result - \throw ParseException if no Formula is set or in case of any other error related to the formula. - */ - value_type ParserBase::Eval() const - { - return (this->*m_pParseFormula)(); - } - - //--------------------------------------------------------------------------- - void ParserBase::Eval(value_type *results, int nBulkSize) - { -/* Commented because it is making a unit test impossible - - // Parallelization does not make sense for fewer than 10000 computations - // due to thread creation overhead. If the bulk size is below 2000 - // computation is refused. - if (nBulkSize<2000) - { - throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS); - } + If the expression contains comma separated subexpressions (i.e. "sin(y), x+y"). + There may be more than one return value. This function returns the number of + available results. */ +int ParserBase::GetNumResults() const { return m_nFinalResultIdx; } + +//--------------------------------------------------------------------------- +/** \brief Calculate the result. + + A note on const correctness: + I consider it important that Calc is a const function. + Due to caching operations Calc changes only the state of internal variables with one exception + m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making + Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. + + \pre A formula must be set. + \pre Variables must have been set (if needed) + + \sa #m_pParseFormula + \return The evaluation result + \throw ParseException if no Formula is set or in case of any other error related to the formula. +*/ +value_type ParserBase::Eval() const { return (this->*m_pParseFormula)(); } + +//--------------------------------------------------------------------------- +void ParserBase::Eval(value_type *results, int nBulkSize) { + /* Commented because it is making a unit test impossible + + // Parallelization does not make sense for fewer than 10000 computations + // due to thread creation overhead. If the bulk size is below 2000 + // computation is refused. + if (nBulkSize<2000) + { + throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS); + } + */ CreateRPN(); int i = 0; - for (i=0; i \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParserBytecode.h" #include #include -#include -#include -#include #include +#include +#include +#include #include "muParserDef.h" #include "muParserError.h" -#include "muParserToken.h" #include "muParserStack.h" #include "muParserTemplateMagic.h" +#include "muParserToken.h" - -namespace mu -{ - //--------------------------------------------------------------------------- - /** \brief Bytecode default constructor. */ - ParserByteCode::ParserByteCode() - :m_iStackPos(0) - ,m_iMaxStackSize(0) - ,m_vRPN() - ,m_bEnableOptimizer(true) - { +namespace mu { +//--------------------------------------------------------------------------- +/** \brief Bytecode default constructor. */ +ParserByteCode::ParserByteCode() + : m_iStackPos(0), m_iMaxStackSize(0), m_vRPN(), m_bEnableOptimizer(true) { m_vRPN.reserve(50); - } +} - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) - */ - ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode) - { - Assign(a_ByteCode); - } +//--------------------------------------------------------------------------- +/** \brief Copy constructor. - //--------------------------------------------------------------------------- - /** \brief Assignment operator. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) - */ - ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode) - { + Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) +*/ +ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode) { Assign(a_ByteCode); } + +//--------------------------------------------------------------------------- +/** \brief Assignment operator. + + Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) +*/ +ParserByteCode &ParserByteCode::operator=(const ParserByteCode &a_ByteCode) { Assign(a_ByteCode); return *this; - } +} - //--------------------------------------------------------------------------- - void ParserByteCode::EnableOptimizer(bool bStat) - { - m_bEnableOptimizer = bStat; - } +//--------------------------------------------------------------------------- +void ParserByteCode::EnableOptimizer(bool bStat) { m_bEnableOptimizer = bStat; } - //--------------------------------------------------------------------------- - /** \brief Copy state of another object to this. - - \throw nowthrow - */ - void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) - { - if (this==&a_ByteCode) - return; +//--------------------------------------------------------------------------- +/** \brief Copy state of another object to this. + + \throw nowthrow +*/ +void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) { + if (this == &a_ByteCode) return; m_iStackPos = a_ByteCode.m_iStackPos; m_vRPN = a_ByteCode.m_vRPN; m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; - m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; - } + m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; +} - //--------------------------------------------------------------------------- - /** \brief Add a Variable pointer to bytecode. - \param a_pVar Pointer to be added. - \throw nothrow - */ - void ParserByteCode::AddVar(value_type *a_pVar) - { +//--------------------------------------------------------------------------- +/** \brief Add a Variable pointer to bytecode. + \param a_pVar Pointer to be added. + \throw nothrow +*/ +void ParserByteCode::AddVar(value_type *a_pVar) { ++m_iStackPos; m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); // optimization does not apply SToken tok; - tok.Cmd = cmVAR; - tok.Val.ptr = a_pVar; - tok.Val.data = 1; + tok.Cmd = cmVAR; + tok.Val.ptr = a_pVar; + tok.Val.data = 1; tok.Val.data2 = 0; m_vRPN.push_back(tok); - } +} - //--------------------------------------------------------------------------- - /** \brief Add a Variable pointer to bytecode. +//--------------------------------------------------------------------------- +/** \brief Add a Variable pointer to bytecode. - Value entries in byte code consist of: -
    -
  • value array position of the value
  • -
  • the operator code according to ParserToken::cmVAL
  • -
  • the value stored in #mc_iSizeVal number of bytecode entries.
  • -
+ Value entries in byte code consist of: +
    +
  • value array position of the value
  • +
  • the operator code according to ParserToken::cmVAL
  • +
  • the value stored in #mc_iSizeVal number of bytecode entries.
  • +
- \param a_pVal Value to be added. - \throw nothrow - */ - void ParserByteCode::AddVal(value_type a_fVal) - { + \param a_pVal Value to be added. + \throw nothrow +*/ +void ParserByteCode::AddVal(value_type a_fVal) { ++m_iStackPos; m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); // If optimization does not apply SToken tok; tok.Cmd = cmVAL; - tok.Val.ptr = NULL; - tok.Val.data = 0; + tok.Val.ptr = NULL; + tok.Val.data = 0; tok.Val.data2 = a_fVal; m_vRPN.push_back(tok); - } +} - //--------------------------------------------------------------------------- - void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) - { +//--------------------------------------------------------------------------- +void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) { std::size_t sz = m_vRPN.size(); - value_type &x = m_vRPN[sz-2].Val.data2, - &y = m_vRPN[sz-1].Val.data2; - switch (a_Oprt) - { - case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break; - case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break; - case cmLT: x = x < y; m_vRPN.pop_back(); break; - case cmGT: x = x > y; m_vRPN.pop_back(); break; - case cmLE: x = x <= y; m_vRPN.pop_back(); break; - case cmGE: x = x >= y; m_vRPN.pop_back(); break; - case cmNEQ: x = x != y; m_vRPN.pop_back(); break; - case cmEQ: x = x == y; m_vRPN.pop_back(); break; - case cmADD: x = x + y; m_vRPN.pop_back(); break; - case cmSUB: x = x - y; m_vRPN.pop_back(); break; - case cmMUL: x = x * y; m_vRPN.pop_back(); break; - case cmDIV: + value_type &x = m_vRPN[sz - 2].Val.data2, &y = m_vRPN[sz - 1].Val.data2; + switch (a_Oprt) { + case cmLAND: + x = (int)x && (int)y; + m_vRPN.pop_back(); + break; + case cmLOR: + x = (int)x || (int)y; + m_vRPN.pop_back(); + break; + case cmLT: + x = x < y; + m_vRPN.pop_back(); + break; + case cmGT: + x = x > y; + m_vRPN.pop_back(); + break; + case cmLE: + x = x <= y; + m_vRPN.pop_back(); + break; + case cmGE: + x = x >= y; + m_vRPN.pop_back(); + break; + case cmNEQ: + x = x != y; + m_vRPN.pop_back(); + break; + case cmEQ: + x = x == y; + m_vRPN.pop_back(); + break; + case cmADD: + x = x + y; + m_vRPN.pop_back(); + break; + case cmSUB: + x = x - y; + m_vRPN.pop_back(); + break; + case cmMUL: + x = x * y; + m_vRPN.pop_back(); + break; + case cmDIV: #if defined(MUP_MATH_EXCEPTIONS) - if (y==0) - throw ParserError(ecDIV_BY_ZERO, _T("0")); + if (y == 0) throw ParserError(ecDIV_BY_ZERO, _T("0")); #endif - x = x / y; - m_vRPN.pop_back(); - break; + x = x / y; + m_vRPN.pop_back(); + break; - case cmPOW: x = MathImpl::Pow(x, y); - m_vRPN.pop_back(); - break; + case cmPOW: + x = MathImpl::Pow(x, y); + m_vRPN.pop_back(); + break; - default: - break; - } // switch opcode - } + default: + break; + } // switch opcode +} - //--------------------------------------------------------------------------- - /** \brief Add an operator identifier to bytecode. - - Operator entries in byte code consist of: -
    -
  • value array position of the result
  • -
  • the operator code according to ParserToken::ECmdCode
  • -
+//--------------------------------------------------------------------------- +/** \brief Add an operator identifier to bytecode. - \sa ParserToken::ECmdCode - */ - void ParserByteCode::AddOp(ECmdCode a_Oprt) - { + Operator entries in byte code consist of: +
    +
  • value array position of the result
  • +
  • the operator code according to ParserToken::ECmdCode
  • +
+ + \sa ParserToken::ECmdCode +*/ +void ParserByteCode::AddOp(ECmdCode a_Oprt) { bool bOptimized = false; - if (m_bEnableOptimizer) - { - std::size_t sz = m_vRPN.size(); + if (m_bEnableOptimizer) { + std::size_t sz = m_vRPN.size(); - // Check for foldable constants like: - // cmVAL cmVAL cmADD - // where cmADD can stand fopr any binary operator applied to - // two constant values. - if (sz>=2 && m_vRPN[sz-2].Cmd == cmVAL && m_vRPN[sz-1].Cmd == cmVAL) - { - ConstantFolding(a_Oprt); - bOptimized = true; - } - else - { - switch(a_Oprt) - { - case cmPOW: - // Optimization for polynomials of low order - if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL) - { - if (m_vRPN[sz-1].Val.data2==2) - m_vRPN[sz-2].Cmd = cmVARPOW2; - else if (m_vRPN[sz-1].Val.data2==3) - m_vRPN[sz-2].Cmd = cmVARPOW3; - else if (m_vRPN[sz-1].Val.data2==4) - m_vRPN[sz-2].Cmd = cmVARPOW4; - else - break; + // Check for foldable constants like: + // cmVAL cmVAL cmADD + // where cmADD can stand fopr any binary operator applied to + // two constant values. + if (sz >= 2 && m_vRPN[sz - 2].Cmd == cmVAL && m_vRPN[sz - 1].Cmd == cmVAL) { + ConstantFolding(a_Oprt); + bOptimized = true; + } else { + switch (a_Oprt) { + case cmPOW: + // Optimization for polynomials of low order + if (m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 1].Cmd == cmVAL) { + if (m_vRPN[sz - 1].Val.data2 == 2) + m_vRPN[sz - 2].Cmd = cmVARPOW2; + else if (m_vRPN[sz - 1].Val.data2 == 3) + m_vRPN[sz - 2].Cmd = cmVARPOW3; + else if (m_vRPN[sz - 1].Val.data2 == 4) + m_vRPN[sz - 2].Cmd = cmVARPOW4; + else + break; - m_vRPN.pop_back(); - bOptimized = true; - } - break; + m_vRPN.pop_back(); + bOptimized = true; + } + break; - case cmSUB: - case cmADD: - // Simple optimization based on pattern recognition for a shitload of different - // bytecode combinations of addition/subtraction - if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ) - { - assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) || - (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) || - (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ); + case cmSUB: + case cmADD: + // Simple optimization based on pattern recognition for a shitload of different + // bytecode combinations of addition/subtraction + if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) || + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR) || + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL) || + (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && + m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || + (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && + m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAR && + m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && + m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)) { + assert((m_vRPN[sz - 2].Val.ptr == NULL && m_vRPN[sz - 1].Val.ptr != NULL) || + (m_vRPN[sz - 2].Val.ptr != NULL && m_vRPN[sz - 1].Val.ptr == NULL) || + (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)); - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable - m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset - m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplicand - m_vRPN.pop_back(); - bOptimized = true; - } - break; + m_vRPN[sz - 2].Cmd = cmVARMUL; + m_vRPN[sz - 2].Val.ptr = + (value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) | + (long long)(m_vRPN[sz - 1].Val.ptr)); // variable + m_vRPN[sz - 2].Val.data2 += + ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2; // offset + m_vRPN[sz - 2].Val.data += + ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data; // multiplicand + m_vRPN.pop_back(); + bOptimized = true; + } + break; - case cmMUL: - if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || - (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) - { - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); - m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 = 0; - m_vRPN.pop_back(); - bOptimized = true; - } - else if ( (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || - (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ) - { - // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 - m_vRPN[sz-2].Cmd = cmVARMUL; - m_vRPN[sz-2].Val.ptr = (value_type*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); - if (m_vRPN[sz-1].Cmd == cmVAL) - { - m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 *= m_vRPN[sz-1].Val.data2; - } - else - { - m_vRPN[sz-2].Val.data = m_vRPN[sz-1].Val.data * m_vRPN[sz-2].Val.data2; - m_vRPN[sz-2].Val.data2 = m_vRPN[sz-1].Val.data2 * m_vRPN[sz-2].Val.data2; - } - m_vRPN.pop_back(); - bOptimized = true; - } - else if (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && - m_vRPN[sz-1].Val.ptr == m_vRPN[sz-2].Val.ptr) - { - // Optimization: a*a -> a^2 - m_vRPN[sz-2].Cmd = cmVARPOW2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; + case cmMUL: + if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) || + (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR)) { + m_vRPN[sz - 2].Cmd = cmVARMUL; + m_vRPN[sz - 2].Val.ptr = + (value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) | + (long long)(m_vRPN[sz - 1].Val.ptr)); + m_vRPN[sz - 2].Val.data = + m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2; + m_vRPN[sz - 2].Val.data2 = 0; + m_vRPN.pop_back(); + bOptimized = true; + } else if ((m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) || + (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL)) { + // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 + m_vRPN[sz - 2].Cmd = cmVARMUL; + m_vRPN[sz - 2].Val.ptr = + (value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) | + (long long)(m_vRPN[sz - 1].Val.ptr)); + if (m_vRPN[sz - 1].Cmd == cmVAL) { + m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2; + m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2; + } else { + m_vRPN[sz - 2].Val.data = + m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2; + m_vRPN[sz - 2].Val.data2 = + m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2; + } + m_vRPN.pop_back(); + bOptimized = true; + } else if (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && + m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr) { + // Optimization: a*a -> a^2 + m_vRPN[sz - 2].Cmd = cmVARPOW2; + m_vRPN.pop_back(); + bOptimized = true; + } + break; - case cmDIV: - if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0) - { - // Optimization: 4*a/2 -> 2*a - m_vRPN[sz-2].Val.data /= m_vRPN[sz-1].Val.data2; - m_vRPN[sz-2].Val.data2 /= m_vRPN[sz-1].Val.data2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - } // switch a_Oprt - } + case cmDIV: + if (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && + m_vRPN[sz - 1].Val.data2 != 0) { + // Optimization: 4*a/2 -> 2*a + m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2; + m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2; + m_vRPN.pop_back(); + bOptimized = true; + } + break; + + } // switch a_Oprt + } } // If optimization can't be applied just write the value - if (!bOptimized) - { - --m_iStackPos; - SToken tok; - tok.Cmd = a_Oprt; - m_vRPN.push_back(tok); + if (!bOptimized) { + --m_iStackPos; + SToken tok; + tok.Cmd = a_Oprt; + m_vRPN.push_back(tok); } - } +} - //--------------------------------------------------------------------------- - void ParserByteCode::AddIfElse(ECmdCode a_Oprt) - { +//--------------------------------------------------------------------------- +void ParserByteCode::AddIfElse(ECmdCode a_Oprt) { SToken tok; tok.Cmd = a_Oprt; m_vRPN.push_back(tok); - } +} - //--------------------------------------------------------------------------- - /** \brief Add an assignment operator - - Operator entries in byte code consist of: -
    -
  • cmASSIGN code
  • -
  • the pointer of the destination variable
  • -
+//--------------------------------------------------------------------------- +/** \brief Add an assignment operator - \sa ParserToken::ECmdCode - */ - void ParserByteCode::AddAssignOp(value_type *a_pVar) - { + Operator entries in byte code consist of: +
    +
  • cmASSIGN code
  • +
  • the pointer of the destination variable
  • +
+ + \sa ParserToken::ECmdCode +*/ +void ParserByteCode::AddAssignOp(value_type *a_pVar) { --m_iStackPos; SToken tok; tok.Cmd = cmASSIGN; tok.Oprt.ptr = a_pVar; m_vRPN.push_back(tok); - } +} - //--------------------------------------------------------------------------- - /** \brief Add function to bytecode. +//--------------------------------------------------------------------------- +/** \brief Add function to bytecode. - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. - */ - void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) - { - if (a_iArgc>=0) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; - } - else - { - // function with unlimited number of arguments - m_iStackPos = m_iStackPos + a_iArgc + 1; + \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. + \param a_pFun Pointer to function callback. +*/ +void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) { + if (a_iArgc >= 0) { + m_iStackPos = m_iStackPos - a_iArgc + 1; + } else { + // function with unlimited number of arguments + m_iStackPos = m_iStackPos + a_iArgc + 1; } m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); @@ -374,17 +379,16 @@ namespace mu tok.Fun.argc = a_iArgc; tok.Fun.ptr = a_pFun; m_vRPN.push_back(tok); - } +} - //--------------------------------------------------------------------------- - /** \brief Add a bulk function to bytecode. +//--------------------------------------------------------------------------- +/** \brief Add a bulk function to bytecode. - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. - */ - void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) - { - m_iStackPos = m_iStackPos - a_iArgc + 1; + \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. + \param a_pFun Pointer to function callback. +*/ +void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) { + m_iStackPos = m_iStackPos - a_iArgc + 1; m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); SToken tok; @@ -392,18 +396,17 @@ namespace mu tok.Fun.argc = a_iArgc; tok.Fun.ptr = a_pFun; m_vRPN.push_back(tok); - } +} - //--------------------------------------------------------------------------- - /** \brief Add Strung function entry to the parser bytecode. - \throw nothrow +//--------------------------------------------------------------------------- +/** \brief Add Strung function entry to the parser bytecode. + \throw nothrow - A string function entry consists of the stack position of the return value, - followed by a cmSTRFUNC code, the function pointer and an index into the - string buffer maintained by the parser. - */ - void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) - { + A string function entry consists of the stack position of the return value, + followed by a cmSTRFUNC code, the function pointer and an index into the + string buffer maintained by the parser. +*/ +void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) { m_iStackPos = m_iStackPos - a_iArgc + 1; SToken tok; @@ -414,174 +417,196 @@ namespace mu m_vRPN.push_back(tok); m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - } +} - //--------------------------------------------------------------------------- - /** \brief Add end marker to bytecode. - - \throw nothrow - */ - void ParserByteCode::Finalize() - { +//--------------------------------------------------------------------------- +/** \brief Add end marker to bytecode. + + \throw nothrow +*/ +void ParserByteCode::Finalize() { SToken tok; tok.Cmd = cmEND; m_vRPN.push_back(tok); - rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit + rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit // Determine the if-then-else jump offsets ParserStack stIf, stElse; int idx; - for (int i=0; i<(int)m_vRPN.size(); ++i) - { - switch(m_vRPN[i].Cmd) - { - case cmIF: - stIf.push(i); - break; + for (int i = 0; i < (int)m_vRPN.size(); ++i) { + switch (m_vRPN[i].Cmd) { + case cmIF: + stIf.push(i); + break; - case cmELSE: - stElse.push(i); - idx = stIf.pop(); - m_vRPN[idx].Oprt.offset = i - idx; - break; - - case cmENDIF: - idx = stElse.pop(); - m_vRPN[idx].Oprt.offset = i - idx; - break; + case cmELSE: + stElse.push(i); + idx = stIf.pop(); + m_vRPN[idx].Oprt.offset = i - idx; + break; - default: - break; - } + case cmENDIF: + idx = stElse.pop(); + m_vRPN[idx].Oprt.offset = i - idx; + break; + + default: + break; + } } - } +} - //--------------------------------------------------------------------------- - const SToken* ParserByteCode::GetBase() const - { - if (m_vRPN.size()==0) - assert(0 && "muParser internal error"); +//--------------------------------------------------------------------------- +const SToken *ParserByteCode::GetBase() const { + if (m_vRPN.size() == 0) assert(0 && "muParser internal error"); return &m_vRPN[0]; - } +} - //--------------------------------------------------------------------------- - std::size_t ParserByteCode::GetMaxStackSize() const - { - return m_iMaxStackSize+1; - } +//--------------------------------------------------------------------------- +std::size_t ParserByteCode::GetMaxStackSize() const { return m_iMaxStackSize + 1; } - //--------------------------------------------------------------------------- - /** \brief Returns the number of entries in the bytecode. */ - std::size_t ParserByteCode::GetSize() const - { - return m_vRPN.size(); - } +//--------------------------------------------------------------------------- +/** \brief Returns the number of entries in the bytecode. */ +std::size_t ParserByteCode::GetSize() const { return m_vRPN.size(); } - //--------------------------------------------------------------------------- - /** \brief Delete the bytecode. - - \throw nothrow +//--------------------------------------------------------------------------- +/** \brief Delete the bytecode. - The name of this function is a violation of my own coding guidelines - but this way it's more in line with the STL functions thus more - intuitive. - */ - void ParserByteCode::clear() - { + \throw nothrow + + The name of this function is a violation of my own coding guidelines + but this way it's more in line with the STL functions thus more + intuitive. +*/ +void ParserByteCode::clear() { m_vRPN.clear(); m_iStackPos = 0; m_iMaxStackSize = 0; - } +} - //--------------------------------------------------------------------------- - /** \brief Dump bytecode (for debugging only!). */ - void ParserByteCode::AsciiDump() - { - if (!m_vRPN.size()) - { - mu::console() << _T("No bytecode available\n"); - return; +//--------------------------------------------------------------------------- +/** \brief Dump bytecode (for debugging only!). */ +void ParserByteCode::AsciiDump() { + if (!m_vRPN.size()) { + mu::console() << _T("No bytecode available\n"); + return; } mu::console() << _T("Number of RPN tokens:") << (int)m_vRPN.size() << _T("\n"); - for (std::size_t i=0; i \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2004-2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParserCallback.h" @@ -29,435 +29,365 @@ \brief Implementation of the parser callback class. */ +namespace mu { +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(0), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} -namespace mu -{ - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) + : m_pFun((void*)a_pFun), + m_iArgc(1), + m_iPri(a_iPrec), + m_eOprtAsct(oaNONE), + m_iCode(a_iCode), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(a_iPrec) - ,m_eOprtAsct(oaNONE) - ,m_iCode(a_iCode) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +/** \brief Constructor for constructing function callbacks taking two arguments. + \throw nothrow +*/ +ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(2), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} +//--------------------------------------------------------------------------- +/** \brief Constructor for constructing binary operator callbacks. + \param a_pFun Pointer to a static function taking two arguments + \param a_bAllowOpti A flag indicating this function can be optimized + \param a_iPrec The operator precedence + \param a_eOprtAsct The operators associativity + \throw nothrow +*/ +ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, + EOprtAssociativity a_eOprtAsct) + : m_pFun((void*)a_pFun), + m_iArgc(2), + m_iPri(a_iPrec), + m_eOprtAsct(a_eOprtAsct), + m_iCode(cmOPRT_BIN), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow - */ - ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(3), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing binary operator callbacks. - \param a_pFun Pointer to a static function taking two arguments - \param a_bAllowOpti A flag indicating this function can be optimized - \param a_iPrec The operator precedence - \param a_eOprtAsct The operators associativity - \throw nothrow - */ - ParserCallback::ParserCallback(fun_type2 a_pFun, - bool a_bAllowOpti, - int a_iPrec, - EOprtAssociativity a_eOprtAsct) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(a_iPrec) - ,m_eOprtAsct(a_eOprtAsct) - ,m_iCode(cmOPRT_BIN) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(4), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(3) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(5), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(6), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(4) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(7), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(8), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(5) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(9), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(6) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(10), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(7) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(0), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(8) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(1), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(9) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +/** \brief Constructor for constructing function callbacks taking two arguments. + \throw nothrow +*/ +ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(2), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(10) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(3), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(4), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(5), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(6), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow - */ - ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(7), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(3) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(8), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(9), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(4) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(10), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_BULK), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(-1), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC), + m_iType(tpDBL), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(5) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(0), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_STR), + m_iType(tpSTR), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(6) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(1), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_STR), + m_iType(tpSTR), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(7) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) + : m_pFun((void*)a_pFun), + m_iArgc(2), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmFUNC_STR), + m_iType(tpSTR), + m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(8) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} +//--------------------------------------------------------------------------- +/** \brief Default constructor. + \throw nothrow +*/ +ParserCallback::ParserCallback() + : m_pFun(0), + m_iArgc(0), + m_iPri(-1), + m_eOprtAsct(oaNONE), + m_iCode(cmUNKNOWN), + m_iType(tpVOID), + m_bAllowOpti(0) {} - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(9) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(10) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_BULK) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(-1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC) - ,m_iType(tpDBL) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(1) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) - :m_pFun((void*)a_pFun) - ,m_iArgc(2) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmFUNC_STR) - ,m_iType(tpSTR) - ,m_bAllowOpti(a_bAllowOpti) - {} - - - //--------------------------------------------------------------------------- - /** \brief Default constructor. - \throw nothrow - */ - ParserCallback::ParserCallback() - :m_pFun(0) - ,m_iArgc(0) - ,m_iPri(-1) - ,m_eOprtAsct(oaNONE) - ,m_iCode(cmUNKNOWN) - ,m_iType(tpVOID) - ,m_bAllowOpti(0) - {} - - - //--------------------------------------------------------------------------- - /** \brief Copy constructor. - \throw nothrow - */ - ParserCallback::ParserCallback(const ParserCallback &ref) - { - m_pFun = ref.m_pFun; - m_iArgc = ref.m_iArgc; +//--------------------------------------------------------------------------- +/** \brief Copy constructor. + \throw nothrow +*/ +ParserCallback::ParserCallback(const ParserCallback& ref) { + m_pFun = ref.m_pFun; + m_iArgc = ref.m_iArgc; m_bAllowOpti = ref.m_bAllowOpti; - m_iCode = ref.m_iCode; - m_iType = ref.m_iType; - m_iPri = ref.m_iPri; - m_eOprtAsct = ref.m_eOprtAsct; - } + m_iCode = ref.m_iCode; + m_iType = ref.m_iType; + m_iPri = ref.m_iPri; + m_eOprtAsct = ref.m_eOprtAsct; +} - //--------------------------------------------------------------------------- - /** \brief Clone this instance and return a pointer to the new instance. */ - ParserCallback* ParserCallback::Clone() const - { - return new ParserCallback(*this); - } +//--------------------------------------------------------------------------- +/** \brief Clone this instance and return a pointer to the new instance. */ +ParserCallback* ParserCallback::Clone() const { return new ParserCallback(*this); } - //--------------------------------------------------------------------------- - /** \brief Return tru if the function is conservative. +//--------------------------------------------------------------------------- +/** \brief Return tru if the function is conservative. - Conservative functions return always the same result for the same argument. - \throw nothrow - */ - bool ParserCallback::IsOptimizable() const - { - return m_bAllowOpti; - } + Conservative functions return always the same result for the same argument. + \throw nothrow +*/ +bool ParserCallback::IsOptimizable() const { return m_bAllowOpti; } - //--------------------------------------------------------------------------- - /** \brief Get the callback address for the parser function. - - The type of the address is void. It needs to be recasted according to the - argument number to the right type. +//--------------------------------------------------------------------------- +/** \brief Get the callback address for the parser function. - \throw nothrow - \return #pFun - */ - void* ParserCallback::GetAddr() const - { - return m_pFun; - } + The type of the address is void. It needs to be recasted according to the + argument number to the right type. - //--------------------------------------------------------------------------- - /** \brief Return the callback code. */ - ECmdCode ParserCallback::GetCode() const - { - return m_iCode; - } - - //--------------------------------------------------------------------------- - ETypeCode ParserCallback::GetType() const - { - return m_iType; - } + \throw nothrow + \return #pFun +*/ +void* ParserCallback::GetAddr() const { return m_pFun; } +//--------------------------------------------------------------------------- +/** \brief Return the callback code. */ +ECmdCode ParserCallback::GetCode() const { return m_iCode; } - //--------------------------------------------------------------------------- - /** \brief Return the operator precedence. - \throw nothrown +//--------------------------------------------------------------------------- +ETypeCode ParserCallback::GetType() const { return m_iType; } - Only valid if the callback token is an operator token (binary or infix). - */ - int ParserCallback::GetPri() const - { - return m_iPri; - } +//--------------------------------------------------------------------------- +/** \brief Return the operator precedence. + \throw nothrown - //--------------------------------------------------------------------------- - /** \brief Return the operators associativity. - \throw nothrown + Only valid if the callback token is an operator token (binary or infix). +*/ +int ParserCallback::GetPri() const { return m_iPri; } - Only valid if the callback token is a binary operator token. - */ - EOprtAssociativity ParserCallback::GetAssociativity() const - { - return m_eOprtAsct; - } +//--------------------------------------------------------------------------- +/** \brief Return the operators associativity. + \throw nothrown - //--------------------------------------------------------------------------- - /** \brief Returns the number of function Arguments. */ - int ParserCallback::GetArgc() const - { - return m_iArgc; - } -} // namespace mu + Only valid if the callback token is a binary operator token. +*/ +EOprtAssociativity ParserCallback::GetAssociativity() const { return m_eOprtAsct; } + +//--------------------------------------------------------------------------- +/** \brief Returns the number of function Arguments. */ +int ParserCallback::GetArgc() const { return m_iArgc; } +} // namespace mu diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 142020a04..df3196877 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -7,55 +7,56 @@ \/ \/ \/ \/ Copyright (C) 2004-2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software + Permission is hereby granted, free of charge, to any person obtaining a copy of + this + software and associated documentation files (the "Software"), to deal in the + Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: + permit persons to whom the Software is furnished to do so, subject to the following + conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. */ -#if defined(MUPARSER_DLL) +#if defined(MUPARSER_DLL) #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include #endif -#include "muParserDLL.h" #include "muParser.h" -#include "muParserInt.h" +#include "muParserDLL.h" #include "muParserError.h" +#include "muParserInt.h" - -#define MU_TRY \ - try \ - { - -#define MU_CATCH \ - } \ - catch (muError_t &e) \ - { \ - ParserTag *pTag = static_cast(a_hParser); \ - pTag->exc = e; \ - pTag->bError = true; \ -if (pTag->errHandler) \ - (pTag->errHandler)(a_hParser); \ - } \ - catch (...) \ - { \ - ParserTag *pTag = static_cast(a_hParser); \ - pTag->bError = true; \ -if (pTag->errHandler) \ - (pTag->errHandler)(a_hParser); \ - } +#define MU_TRY try { +#define MU_CATCH \ + } \ + catch (muError_t & e) { \ + ParserTag* pTag = static_cast(a_hParser); \ + pTag->exc = e; \ + pTag->bError = true; \ + if (pTag->errHandler) (pTag->errHandler)(a_hParser); \ + } \ + catch (...) { \ + ParserTag* pTag = static_cast(a_hParser); \ + pTag->bError = true; \ + if (pTag->errHandler) (pTag->errHandler)(a_hParser); \ + } /** \file \brief This file contains the implementation of the DLL interface of muparser. @@ -69,31 +70,27 @@ typedef mu::ParserBase muParser_t; int g_nBulkSize; //--------------------------------------------------------------------------- -class ParserTag -{ -public: +class ParserTag { + public: ParserTag(int nType) - :pParser((nType == muBASETYPE_FLOAT) ? (mu::ParserBase*)new mu::Parser() : - (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL) - , exc() - , errHandler(NULL) - , bError(false) - , m_nParserType(nType) - {} + : pParser((nType == muBASETYPE_FLOAT) + ? (mu::ParserBase*)new mu::Parser() + : (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL), + exc(), + errHandler(NULL), + bError(false), + m_nParserType(nType) {} - ~ParserTag() - { - delete pParser; - } + ~ParserTag() { delete pParser; } - mu::ParserBase *pParser; + mu::ParserBase* pParser; mu::ParserBase::exception_type exc; muErrorHandler_t errHandler; bool bError; -private: - ParserTag(const ParserTag &ref); - ParserTag& operator=(const ParserTag &ref); + private: + ParserTag(const ParserTag& ref); + ParserTag& operator=(const ParserTag& ref); int m_nParserType; }; @@ -109,34 +106,26 @@ static muChar_t s_tmpOutBuf[2048]; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -muParser_t* AsParser(muParserHandle_t a_hParser) -{ +muParser_t* AsParser(muParserHandle_t a_hParser) { return static_cast(a_hParser)->pParser; } //--------------------------------------------------------------------------- -ParserTag* AsParserTag(muParserHandle_t a_hParser) -{ - return static_cast(a_hParser); -} +ParserTag* AsParserTag(muParserHandle_t a_hParser) { return static_cast(a_hParser); } //--------------------------------------------------------------------------- #if defined(_WIN32) #define _CRT_SECURE_NO_DEPRECATE -BOOL APIENTRY DllMain(HANDLE /*hModule*/, - DWORD ul_reason_for_call, - LPVOID /*lpReserved*/) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - break; +BOOL APIENTRY DllMain(HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; } return TRUE; @@ -152,10 +141,10 @@ BOOL APIENTRY DllMain(HANDLE /*hModule*/, // //--------------------------------------------------------------------------- -API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData) -{ +API_EXPORT(void) +mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData) { MU_TRY - muParser_t* p(AsParser(a_hParser)); + muParser_t* p(AsParser(a_hParser)); p->SetVarFactory(a_pFactory, pUserData); MU_CATCH } @@ -163,32 +152,31 @@ API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFact //--------------------------------------------------------------------------- /** \brief Create a new Parser instance and return its handle. */ -API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) -{ - switch (nBaseType) - { - case muBASETYPE_FLOAT: return (void*)(new ParserTag(muBASETYPE_FLOAT)); - case muBASETYPE_INT: return (void*)(new ParserTag(muBASETYPE_INT)); - default: return NULL; +API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) { + switch (nBaseType) { + case muBASETYPE_FLOAT: + return (void*)(new ParserTag(muBASETYPE_FLOAT)); + case muBASETYPE_INT: + return (void*)(new ParserTag(muBASETYPE_INT)); + default: + return NULL; } } //--------------------------------------------------------------------------- /** \brief Release the parser instance related with a parser handle. */ -API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) { MU_TRY - ParserTag* p = static_cast(a_hParser); + ParserTag* p = static_cast(a_hParser); delete p; MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) -{ +API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); #ifndef _UNICODE sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str()); @@ -199,58 +187,53 @@ API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) return s_tmpOutBuf; MU_CATCH - return _T(""); + return _T(""); } //--------------------------------------------------------------------------- /** \brief Evaluate the expression. */ -API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) -{ +API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); return p->Eval(); MU_CATCH - return 0; + return 0; } //--------------------------------------------------------------------------- -API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int *nNum) -{ +API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) { MU_TRY - assert(nNum != NULL); + assert(nNum != NULL); muParser_t* const p(AsParser(a_hParser)); return p->Eval(*nNum); MU_CATCH - return 0; + return 0; } //--------------------------------------------------------------------------- -API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_res, int nSize) -{ +API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_res, int nSize) { MU_TRY - muParser_t* p(AsParser(a_hParser)); + muParser_t* p(AsParser(a_hParser)); p->Eval(a_res, nSize); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) -{ +API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->SetExpr(a_szExpr); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) -{ +API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->RemoveVar(a_szName); MU_CATCH } @@ -259,10 +242,9 @@ API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szNa /** \brief Release all parser variables. \param a_hParser Handle to the parser instance. */ -API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->ClearVar(); MU_CATCH } @@ -271,10 +253,9 @@ API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) /** \brief Release all parser variables. \param a_hParser Handle to the parser instance. */ -API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->ClearConst(); MU_CATCH } @@ -283,391 +264,320 @@ API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) /** \brief Clear all user defined operators. \param a_hParser Handle to the parser instance. */ -API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->ClearOprt(); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->ClearFun(); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun0(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun0_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun0_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun1(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun2(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun2_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun3(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun3_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun4(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun4_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun5(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun5_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun6(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun6_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun7(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun7_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun8(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun8_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun9(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun9_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFun10_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun0(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muBulkFun0_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun1(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muBulkFun1_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun2(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muBulkFun2_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun3(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun3_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun4(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun4_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun5(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun5_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun6(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun6_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun7(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun7_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun8(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun8_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun9(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun9_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkFun10(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muBulkFun10_t a_pFun) -{ +API_EXPORT(void) +mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muStrFun1_t a_pFun) -{ +API_EXPORT(void) +mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muStrFun2_t a_pFun) -{ +API_EXPORT(void) +mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muStrFun3_t a_pFun) -{ +API_EXPORT(void) +mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, false); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineMultFun(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muMultFun_t a_pFun, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun2_t a_pFun, - muInt_t a_nPrec, - muInt_t a_nOprtAsct, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, + muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineOprt(a_szName, - a_pFun, - a_nPrec, - (mu::EOprtAssociativity)a_nOprtAsct, - a_bAllowOpt != 0); + muParser_t* const p(AsParser(a_hParser)); + p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFloat_t *a_pVar) -{ +API_EXPORT(void) +mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineVar(a_szName, a_pVar); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFloat_t *a_pVar) -{ +API_EXPORT(void) +mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineVar(a_szName, a_pVar); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, - const muChar_t *a_szName, - muFloat_t a_fVal) -{ +API_EXPORT(void) +mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineConst(a_szName, a_fVal); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, - const muChar_t *a_szName, - const muChar_t *a_szVal) -{ +API_EXPORT(void) +mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineStrConst(a_szName, a_szVal); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) -{ +API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. +// C# explodes when pMsg is returned directly. For some reason it can't access +// the memory where the message lies directly. #ifndef _UNICODE sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str()); #else @@ -678,54 +588,44 @@ API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) MU_CATCH - return _T(""); + return _T(""); } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); MU_CATCH } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineInfixOprt(muParserHandle_t a_hParser, - const muChar_t* a_szName, - muFun1_t a_pOprt, - muBool_t a_bAllowOpt) -{ +API_EXPORT(void) +mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, + muBool_t a_bAllowOpt) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); MU_CATCH } // Define character sets for identifiers //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, - const muChar_t* a_szCharset) -{ +API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) { muParser_t* const p(AsParser(a_hParser)); p->DefineNameChars(a_szCharset); } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, - const muChar_t* a_szCharset) -{ +API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) { muParser_t* const p(AsParser(a_hParser)); p->DefineOprtChars(a_szCharset); } //--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, - const muChar_t *a_szCharset) -{ +API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) { muParser_t* const p(AsParser(a_hParser)); p->DefineInfixOprtChars(a_szCharset); } @@ -736,15 +636,14 @@ API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, \return The number of used variables. \sa mupGetExprVar */ -API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) -{ +API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); const mu::varmap_type VarMap = p->GetVar(); return (int)VarMap.size(); MU_CATCH - return 0; // never reached + return 0; // never reached } //--------------------------------------------------------------------------- @@ -763,21 +662,18 @@ API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) During the calculation user defined callback functions present in the expression will be called, this is unavoidable. */ -API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, - unsigned a_iVar, - const muChar_t **a_szName, - muFloat_t **a_pVar) -{ +API_EXPORT(void) +mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, + muFloat_t** a_pVar) { // A static buffer is needed for the name since i cant return the // pointer from the map. - static muChar_t szName[1024]; + static muChar_t szName[1024]; MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); const mu::varmap_type VarMap = p->GetVar(); - if (a_iVar >= VarMap.size()) - { + if (a_iVar >= VarMap.size()) { *a_szName = 0; *a_pVar = 0; return; @@ -785,8 +681,7 @@ API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, mu::varmap_type::const_iterator item; item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; + for (unsigned i = 0; i < a_iVar; ++i) ++item; #ifndef _UNICODE strncpy(szName, item->first.c_str(), sizeof(szName)); @@ -794,7 +689,7 @@ API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, wcsncpy(szName, item->first.c_str(), sizeof(szName)); #endif - szName[sizeof(szName)-1] = 0; + szName[sizeof(szName) - 1] = 0; *a_szName = &szName[0]; *a_pVar = item->second; @@ -802,7 +697,7 @@ API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, MU_CATCH - *a_szName = 0; + *a_szName = 0; *a_pVar = 0; } @@ -812,15 +707,14 @@ API_EXPORT(void) mupGetVar(muParserHandle_t a_hParser, \return The number of used variables. \sa mupGetExprVar */ -API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) -{ +API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); const mu::varmap_type VarMap = p->GetUsedVar(); return (int)VarMap.size(); MU_CATCH - return 0; // never reached + return 0; // never reached } //--------------------------------------------------------------------------- @@ -840,21 +734,18 @@ API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) \param a_pVar [out] Pointer to the variable. \throw nothrow */ -API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, - unsigned a_iVar, - const muChar_t **a_szName, - muFloat_t **a_pVar) -{ +API_EXPORT(void) +mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, + muFloat_t** a_pVar) { // A static buffer is needed for the name since i cant return the // pointer from the map. - static muChar_t szName[1024]; + static muChar_t szName[1024]; MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); const mu::varmap_type VarMap = p->GetUsedVar(); - if (a_iVar >= VarMap.size()) - { + if (a_iVar >= VarMap.size()) { *a_szName = 0; *a_pVar = 0; return; @@ -862,8 +753,7 @@ API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, mu::varmap_type::const_iterator item; item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; + for (unsigned i = 0; i < a_iVar; ++i) ++item; #ifndef _UNICODE strncpy(szName, item->first.c_str(), sizeof(szName)); @@ -871,7 +761,7 @@ API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, wcsncpy(szName, item->first.c_str(), sizeof(szName)); #endif - szName[sizeof(szName)-1] = 0; + szName[sizeof(szName) - 1] = 0; *a_szName = &szName[0]; *a_pVar = item->second; @@ -879,55 +769,50 @@ API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, MU_CATCH - *a_szName = 0; + *a_szName = 0; *a_pVar = 0; } //--------------------------------------------------------------------------- /** \brief Return the number of constants defined in a parser. */ -API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) -{ +API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); const mu::valmap_type ValMap = p->GetConst(); return (int)ValMap.size(); MU_CATCH - return 0; // never reached + return 0; // never reached } //----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) -{ +API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->SetArgSep(cArgSep); MU_CATCH } //----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->ResetLocale(); MU_CATCH } //----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) -{ +API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->SetDecSep(cDecSep); MU_CATCH } //----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) -{ +API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) { MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); p->SetThousandsSep(cThousandsSep); MU_CATCH } @@ -939,21 +824,18 @@ API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t c \param a_pszName [out] pointer to a null terminated string with the constant name \param [out] The constant value */ -API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, - unsigned a_iVar, - const muChar_t **a_pszName, - muFloat_t *a_fVal) -{ +API_EXPORT(void) +mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, + muFloat_t* a_fVal) { // A static buffer is needed for the name since i cant return the // pointer from the map. static muChar_t szName[1024]; MU_TRY - muParser_t* const p(AsParser(a_hParser)); + muParser_t* const p(AsParser(a_hParser)); const mu::valmap_type ValMap = p->GetConst(); - if (a_iVar >= ValMap.size()) - { + if (a_iVar >= ValMap.size()) { *a_pszName = 0; *a_fVal = 0; return; @@ -961,8 +843,7 @@ API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, mu::valmap_type::const_iterator item; item = ValMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) - ++item; + for (unsigned i = 0; i < a_iVar; ++i) ++item; #ifndef _UNICODE strncpy(szName, item->first.c_str(), sizeof(szName)); @@ -970,7 +851,7 @@ API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, wcsncpy(szName, item->first.c_str(), sizeof(szName)); #endif - szName[sizeof(szName)-1] = 0; + szName[sizeof(szName) - 1] = 0; *a_pszName = &szName[0]; *a_fVal = item->second; @@ -978,18 +859,16 @@ API_EXPORT(void) mupGetConst(muParserHandle_t a_hParser, MU_CATCH - *a_pszName = 0; + *a_pszName = 0; *a_fVal = 0; } //--------------------------------------------------------------------------- /** \brief Add a custom value recognition function. */ -API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, - muIdentFun_t a_pFun) -{ +API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t a_pFun) { MU_TRY - muParser_t* p(AsParser(a_hParser)); + muParser_t* p(AsParser(a_hParser)); p->AddValIdent(a_pFun); MU_CATCH } @@ -1000,8 +879,7 @@ API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, After querying the internal error bit will be reset. So a consecutive call will return false. */ -API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) -{ +API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) { bool bError(AsParserTag(a_hParser)->bError); AsParserTag(a_hParser)->bError = false; return bError; @@ -1010,27 +888,24 @@ API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) //--------------------------------------------------------------------------- /** \brief Reset the internal error flag. */ -API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) -{ +API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) { AsParserTag(a_hParser)->bError = false; } //--------------------------------------------------------------------------- -API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) -{ +API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) { AsParserTag(a_hParser)->errHandler = a_pHandler; } //--------------------------------------------------------------------------- /** \brief Return the message associated with the last error. */ -API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) -{ +API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) { ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t *pMsg = p->exc.GetMsg().c_str(); + const muChar_t* pMsg = p->exc.GetMsg().c_str(); - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. +// C# explodes when pMsg is returned directly. For some reason it can't access +// the memory where the message lies directly. #ifndef _UNICODE sprintf(s_tmpOutBuf, "%s", pMsg); #else @@ -1043,13 +918,12 @@ API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) //--------------------------------------------------------------------------- /** \brief Return the message associated with the last error. */ -API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) -{ +API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) { ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t *pToken = p->exc.GetToken().c_str(); + const muChar_t* pToken = p->exc.GetToken().c_str(); - // C# explodes when pMsg is returned directly. For some reason it can't access - // the memory where the message lies directly. +// C# explodes when pMsg is returned directly. For some reason it can't access +// the memory where the message lies directly. #ifndef _UNICODE sprintf(s_tmpOutBuf, "%s", pToken); #else @@ -1062,34 +936,26 @@ API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) //--------------------------------------------------------------------------- /** \brief Return the code associated with the last error. */ -API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) -{ +API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) { return AsParserTag(a_hParser)->exc.GetCode(); } //--------------------------------------------------------------------------- /** \brief Return the position associated with the last error. */ -API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) -{ +API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) { return (int)AsParserTag(a_hParser)->exc.GetPos(); } ////----------------------------------------------------------------------------------------------------- -//API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser) +// API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser) //{ // return AsParserTag(a_hParser)->exc.GetExpr().c_str(); //} //----------------------------------------------------------------------------------------------------- -API_EXPORT(muFloat_t*) mupCreateVar() -{ - return new muFloat_t(0); -} +API_EXPORT(muFloat_t*) mupCreateVar() { return new muFloat_t(0); } //----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupReleaseVar(muFloat_t *ptr) -{ - delete ptr; -} +API_EXPORT(void) mupReleaseVar(muFloat_t* ptr) { delete ptr; } -#endif // MUPARSER_DLL +#endif // MUPARSER_DLL diff --git a/muparser-2.2.5/src/muParserError.cpp b/muparser-2.2.5/src/muParserError.cpp index 566c41d60..bdcc4da6a 100644 --- a/muparser-2.2.5/src/muParserError.cpp +++ b/muparser-2.2.5/src/muParserError.cpp @@ -1,243 +1,225 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParserError.h" +namespace mu { +const ParserErrorMsg ParserErrorMsg::m_Instance; -namespace mu -{ - const ParserErrorMsg ParserErrorMsg::m_Instance; +//------------------------------------------------------------------------------ +const ParserErrorMsg &ParserErrorMsg::Instance() { return m_Instance; } - //------------------------------------------------------------------------------ - const ParserErrorMsg& ParserErrorMsg::Instance() - { - return m_Instance; - } +//------------------------------------------------------------------------------ +string_type ParserErrorMsg::operator[](unsigned a_iIdx) const { + return (a_iIdx < m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type(); +} - //------------------------------------------------------------------------------ - string_type ParserErrorMsg::operator[](unsigned a_iIdx) const - { - return (a_iIdx \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2011 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParserInt.h" -#include #include +#include #include using namespace std; @@ -36,245 +36,210 @@ using namespace std; */ /** \brief Namespace for mathematical applications. */ -namespace mu -{ -value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } -value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; } -value_type ParserInt::Ite(value_type v1, - value_type v2, - value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); } -value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } -value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } -value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } -value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } -value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } +namespace mu { +value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } +value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; } +value_type ParserInt::Ite(value_type v1, value_type v2, value_type v3) { + return (Round(v1) == 1) ? Round(v2) : Round(v3); +} +value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } +value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } +value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } +value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } +value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } -value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } +value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } -value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } -value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } -value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } -value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } +value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } +value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } +value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } +value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } -value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } -value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } +value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } +value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } value_type ParserInt::Not(value_type v) { return !Round(v); } -value_type ParserInt::Pow(value_type v1, value_type v2) -{ - return std::pow((double)Round(v1), (double)Round(v2)); +value_type ParserInt::Pow(value_type v1, value_type v2) { + return std::pow((double)Round(v1), (double)Round(v2)); } //--------------------------------------------------------------------------- // Unary operator Callbacks: Infix operators -value_type ParserInt::UnaryMinus(value_type v) -{ - return -Round(v); +value_type ParserInt::UnaryMinus(value_type v) { return -Round(v); } + +//--------------------------------------------------------------------------- +value_type ParserInt::Sum(const value_type *a_afArg, int a_iArgc) { + if (!a_iArgc) throw ParserError(_T("too few arguments for function sum.")); + + value_type fRes = 0; + for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; + + return fRes; } //--------------------------------------------------------------------------- -value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc) -{ - if (!a_iArgc) - throw ParserError(_T("too few arguments for function sum.")); +value_type ParserInt::Min(const value_type *a_afArg, int a_iArgc) { + if (!a_iArgc) throw ParserError(_T("too few arguments for function min.")); - value_type fRes=0; - for (int i=0; i> iVal; - if (stream.fail()) - return 0; - - stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading - if (stream.fail()) - iEnd = stream.str().length(); + stream >> iVal; + if (stream.fail()) return 0; - if (iEnd==(stringstream_type::pos_type)-1) - return 0; + stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading + if (stream.fail()) iEnd = stream.str().length(); - *a_iPos += (int)iEnd; - *a_fVal = (value_type)iVal; - return 1; + if (iEnd == (stringstream_type::pos_type)-1) return 0; + + *a_iPos += (int)iEnd; + *a_fVal = (value_type)iVal; + return 1; } //--------------------------------------------------------------------------- -/** \brief Check a given position in the expression for the presence of - a hex value. +/** \brief Check a given position in the expression for the presence of + a hex value. \param a_szExpr Pointer to the expression string - \param [in/out] a_iPos Pointer to an integer value holding the current parsing + \param [in/out] a_iPos Pointer to an integer value holding the current parsing position in the expression. \param [out] a_fVal Pointer to the position where the detected value shall be stored. Hey values must be prefixed with "0x" in order to be detected properly. */ -int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) - return 0; +int ParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) { + if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x')) return 0; - unsigned iVal(0); + unsigned iVal(0); - // New code based on streams for UNICODE compliance: - stringstream_type::pos_type nPos(0); - stringstream_type ss(a_szExpr + 2); - ss >> std::hex >> iVal; - nPos = ss.tellg(); + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); - if (nPos==(stringstream_type::pos_type)0) + if (nPos == (stringstream_type::pos_type)0) return 1; + + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; return 1; - - *a_iPos += (int)(2 + nPos); - *a_fVal = (value_type)iVal; - return 1; } //--------------------------------------------------------------------------- -int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[0]!='#') - return 0; +int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) { + if (a_szExpr[0] != '#') return 0; - unsigned iVal(0), - iBits(sizeof(iVal)*8), - i(0); + unsigned iVal(0), iBits(sizeof(iVal) * 8), i(0); - for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i> (iBits-i) ); - *a_iPos += i+1; + *a_fVal = (unsigned)(iVal >> (iBits - i)); + *a_iPos += i + 1; - return 1; + return 1; } //--------------------------------------------------------------------------- -/** \brief Constructor. +/** \brief Constructor. Call ParserBase class constructor and trigger Function, Operator and Constant initialization. */ -ParserInt::ParserInt() - :ParserBase() -{ - AddValIdent(IsVal); // lowest priority - AddValIdent(IsBinVal); - AddValIdent(IsHexVal); // highest priority +ParserInt::ParserInt() : ParserBase() { + AddValIdent(IsVal); // lowest priority + AddValIdent(IsBinVal); + AddValIdent(IsHexVal); // highest priority - InitCharSets(); - InitFun(); - InitOprt(); + InitCharSets(); + InitFun(); + InitOprt(); } //--------------------------------------------------------------------------- -void ParserInt::InitConst() -{ -} +void ParserInt::InitConst() {} //--------------------------------------------------------------------------- -void ParserInt::InitCharSets() -{ - DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") ); - DefineOprtChars( _T("+-*^/?<>=!%&|~'_") ); - DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") ); +void ParserInt::InitCharSets() { + DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")); + DefineOprtChars(_T("+-*^/?<>=!%&|~'_")); + DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_")); } //--------------------------------------------------------------------------- /** \brief Initialize the default functions. */ -void ParserInt::InitFun() -{ - DefineFun( _T("sign"), Sign); - DefineFun( _T("abs"), Abs); - DefineFun( _T("if"), Ite); - DefineFun( _T("sum"), Sum); - DefineFun( _T("min"), Min); - DefineFun( _T("max"), Max); +void ParserInt::InitFun() { + DefineFun(_T("sign"), Sign); + DefineFun(_T("abs"), Abs); + DefineFun(_T("if"), Ite); + DefineFun(_T("sum"), Sum); + DefineFun(_T("min"), Min); + DefineFun(_T("max"), Max); } //--------------------------------------------------------------------------- /** \brief Initialize operators. */ -void ParserInt::InitOprt() -{ - // disable all built in operators, not all of them useful for integer numbers - // (they don't do rounding of values) - EnableBuiltInOprt(false); +void ParserInt::InitOprt() { + // disable all built in operators, not all of them useful for integer numbers + // (they don't do rounding of values) + EnableBuiltInOprt(false); - // Disable all built in operators, they wont work with integer numbers - // since they are designed for floating point numbers - DefineInfixOprt( _T("-"), UnaryMinus); - DefineInfixOprt( _T("!"), Not); + // Disable all built in operators, they wont work with integer numbers + // since they are designed for floating point numbers + DefineInfixOprt(_T("-"), UnaryMinus); + DefineInfixOprt(_T("!"), Not); - DefineOprt( _T("&"), LogAnd, prLOGIC); - DefineOprt( _T("|"), LogOr, prLOGIC); - DefineOprt( _T("&&"), And, prLOGIC); - DefineOprt( _T("||"), Or, prLOGIC); + DefineOprt(_T("&"), LogAnd, prLOGIC); + DefineOprt(_T("|"), LogOr, prLOGIC); + DefineOprt(_T("&&"), And, prLOGIC); + DefineOprt(_T("||"), Or, prLOGIC); - DefineOprt( _T("<"), Less, prCMP); - DefineOprt( _T(">"), Greater, prCMP); - DefineOprt( _T("<="), LessEq, prCMP); - DefineOprt( _T(">="), GreaterEq, prCMP); - DefineOprt( _T("=="), Equal, prCMP); - DefineOprt( _T("!="), NotEqual, prCMP); + DefineOprt(_T("<"), Less, prCMP); + DefineOprt(_T(">"), Greater, prCMP); + DefineOprt(_T("<="), LessEq, prCMP); + DefineOprt(_T(">="), GreaterEq, prCMP); + DefineOprt(_T("=="), Equal, prCMP); + DefineOprt(_T("!="), NotEqual, prCMP); - DefineOprt( _T("+"), Add, prADD_SUB); - DefineOprt( _T("-"), Sub, prADD_SUB); + DefineOprt(_T("+"), Add, prADD_SUB); + DefineOprt(_T("-"), Sub, prADD_SUB); - DefineOprt( _T("*"), Mul, prMUL_DIV); - DefineOprt( _T("/"), Div, prMUL_DIV); - DefineOprt( _T("%"), Mod, prMUL_DIV); + DefineOprt(_T("*"), Mul, prMUL_DIV); + DefineOprt(_T("/"), Div, prMUL_DIV); + DefineOprt(_T("%"), Mod, prMUL_DIV); - DefineOprt( _T("^"), Pow, prPOW, oaRIGHT); - DefineOprt( _T(">>"), Shr, prMUL_DIV+1); - DefineOprt( _T("<<"), Shl, prMUL_DIV+1); + DefineOprt(_T("^"), Pow, prPOW, oaRIGHT); + DefineOprt(_T(">>"), Shr, prMUL_DIV + 1); + DefineOprt(_T("<<"), Shl, prMUL_DIV + 1); } -} // namespace mu +} // namespace mu diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index e84e38852..c63b7d41a 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -1,37 +1,37 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParserTest.h" -#include #include +#include #include #include -#define PARSER_CONST_PI 3.141592653589793238462643 -#define PARSER_CONST_E 2.718281828459045235360287 +#define PARSER_CONST_PI 3.141592653589793238462643 +#define PARSER_CONST_E 2.718281828459045235360287 using namespace std; @@ -39,1179 +39,1117 @@ using namespace std; \brief This file contains the implementation of parser test cases. */ -namespace mu -{ - namespace Test - { - int ParserTester::c_iCount = 0; +namespace mu { +namespace Test { +int ParserTester::c_iCount = 0; - //--------------------------------------------------------------------------------------------- - ParserTester::ParserTester() - :m_vTestFun() - { - AddTest(&ParserTester::TestNames); - AddTest(&ParserTester::TestSyntax); - AddTest(&ParserTester::TestPostFix); - AddTest(&ParserTester::TestInfixOprt); - AddTest(&ParserTester::TestVarConst); - AddTest(&ParserTester::TestMultiArg); - AddTest(&ParserTester::TestExpression); - AddTest(&ParserTester::TestIfThenElse); - AddTest(&ParserTester::TestInterface); - AddTest(&ParserTester::TestBinOprt); - AddTest(&ParserTester::TestException); - AddTest(&ParserTester::TestStrArg); - AddTest(&ParserTester::TestBulkMode); +//--------------------------------------------------------------------------------------------- +ParserTester::ParserTester() : m_vTestFun() { + AddTest(&ParserTester::TestNames); + AddTest(&ParserTester::TestSyntax); + AddTest(&ParserTester::TestPostFix); + AddTest(&ParserTester::TestInfixOprt); + AddTest(&ParserTester::TestVarConst); + AddTest(&ParserTester::TestMultiArg); + AddTest(&ParserTester::TestExpression); + AddTest(&ParserTester::TestIfThenElse); + AddTest(&ParserTester::TestInterface); + AddTest(&ParserTester::TestBinOprt); + AddTest(&ParserTester::TestException); + AddTest(&ParserTester::TestStrArg); + AddTest(&ParserTester::TestBulkMode); - ParserTester::c_iCount = 0; - } + ParserTester::c_iCount = 0; +} - //--------------------------------------------------------------------------------------------- - int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) - { - if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) - return 0; +//--------------------------------------------------------------------------------------------- +int ParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) { + if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x')) return 0; - unsigned iVal(0); + unsigned iVal(0); - // New code based on streams for UNICODE compliance: - stringstream_type::pos_type nPos(0); - stringstream_type ss(a_szExpr + 2); - ss >> std::hex >> iVal; - nPos = ss.tellg(); + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); - if (nPos==(stringstream_type::pos_type)0) - return 1; + if (nPos == (stringstream_type::pos_type)0) return 1; - *a_iPos += (int)(2 + nPos); - *a_fVal = (value_type)iVal; - return 1; - } + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; + return 1; +} - //--------------------------------------------------------------------------------------------- - int ParserTester::TestInterface() - { - int iStat = 0; - mu::console() << _T("testing member functions..."); - - // Test RemoveVar - value_type afVal[3] = {1,2,3}; - Parser p; - - try - { - p.DefineVar( _T("a"), &afVal[0]); - p.DefineVar( _T("b"), &afVal[1]); - p.DefineVar( _T("c"), &afVal[2]); - p.SetExpr( _T("a+b+c") ); +//--------------------------------------------------------------------------------------------- +int ParserTester::TestInterface() { + int iStat = 0; + mu::console() << _T("testing member functions..."); + + // Test RemoveVar + value_type afVal[3] = {1, 2, 3}; + Parser p; + + try { + p.DefineVar(_T("a"), &afVal[0]); + p.DefineVar(_T("b"), &afVal[1]); + p.DefineVar(_T("c"), &afVal[2]); + p.SetExpr(_T("a+b+c")); p.Eval(); - } - catch(...) - { - iStat += 1; // this is not supposed to happen - } + } catch (...) { + iStat += 1; // this is not supposed to happen + } - try - { - p.RemoveVar( _T("c") ); + try { + p.RemoveVar(_T("c")); p.Eval(); iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... - } - catch(...) - { + } catch (...) { // failure is expected... - } - - if (iStat==0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; } - //--------------------------------------------------------------------------------------------- - int ParserTester::TestStrArg() - { - int iStat = 0; - mu::console() << _T("testing string arguments..."); - - iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash - iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true); - iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true); - // use in expressions with variables - iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true); - iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true); - // string + numeric arguments - iStat += EqnTest(_T("strfun1(\"100\")"), 100, true); - iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true); - iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true); - // string constants - iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true); - - if (iStat==0) + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; + return iStat; +} + +//--------------------------------------------------------------------------------------------- +int ParserTester::TestStrArg() { + int iStat = 0; + mu::console() << _T("testing string arguments..."); + + iStat += EqnTest(_T("valueof(\"\")"), 123, true); // empty string arguments caused a crash + iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true); + iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true); + // use in expressions with variables + iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true); + iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true); + // string + numeric arguments + iStat += EqnTest(_T("strfun1(\"100\")"), 100, true); + iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true); + iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true); + // string constants + iStat += EqnTest(_T("atof(str1)+atof(str2)"), 3.33, true); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + + return iStat; +} + +//--------------------------------------------------------------------------------------------- +int ParserTester::TestBulkMode() { + int iStat = 0; + mu::console() << _T("testing bulkmode..."); + +#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \ + { \ + double res[] = {R1, R2, R3, R4}; \ + iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \ } - //--------------------------------------------------------------------------------------------- - int ParserTester::TestBulkMode() - { - int iStat = 0; - mu::console() << _T("testing bulkmode..."); - -#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \ - { \ - double res[] = { R1, R2, R3, R4 }; \ - iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \ - } - - // Bulk Variables for the test: - // a: 1,2,3,4 - // b: 2,2,2,2 - // c: 3,3,3,3 - // d: 5,4,3,2 - EQN_TEST_BULK("a", 1, 1, 1, 1, false) - EQN_TEST_BULK("a", 1, 2, 3, 4, true) - EQN_TEST_BULK("b=a", 1, 2, 3, 4, true) - EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true) - EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true) - EQN_TEST_BULK("a+b", 3, 4, 5, 6, true) - EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true) + // Bulk Variables for the test: + // a: 1,2,3,4 + // b: 2,2,2,2 + // c: 3,3,3,3 + // d: 5,4,3,2 + EQN_TEST_BULK("a", 1, 1, 1, 1, false) + EQN_TEST_BULK("a", 1, 2, 3, 4, true) + EQN_TEST_BULK("b=a", 1, 2, 3, 4, true) + EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true) + EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true) + EQN_TEST_BULK("a+b", 3, 4, 5, 6, true) + EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true) #undef EQN_TEST_BULK - if (iStat == 0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } - - //--------------------------------------------------------------------------------------------- - int ParserTester::TestBinOprt() - { - int iStat = 0; - mu::console() << _T("testing binary operators..."); - - // built in operators - // xor operator - - iStat += EqnTest(_T("a++b"), 3, true); - iStat += EqnTest(_T("a ++ b"), 3, true); - iStat += EqnTest(_T("1++2"), 3, true); - iStat += EqnTest(_T("1 ++ 2"), 3, true); - iStat += EqnTest(_T("a add b"), 3, true); - iStat += EqnTest(_T("1 add 2"), 3, true); - iStat += EqnTest(_T("aa"), 1, true); - iStat += EqnTest(_T("a>a"), 0, true); - iStat += EqnTest(_T("aa"), 0, true); - iStat += EqnTest(_T("a<=a"), 1, true); - iStat += EqnTest(_T("a<=b"), 1, true); - iStat += EqnTest(_T("b<=a"), 0, true); - iStat += EqnTest(_T("a>=a"), 1, true); - iStat += EqnTest(_T("b>=a"), 1, true); - iStat += EqnTest(_T("a>=b"), 0, true); - - // Test logical operators, especially if user defined "&" and the internal "&&" collide - iStat += EqnTest(_T("1 && 1"), 1, true); - iStat += EqnTest(_T("1 && 0"), 0, true); - iStat += EqnTest(_T("(aa)"), 1, true); - iStat += EqnTest(_T("(ab)"), 0, true); - //iStat += EqnTest(_T("12 and 255"), 12, true); - //iStat += EqnTest(_T("12 and 0"), 0, true); - iStat += EqnTest(_T("12 & 255"), 12, true); - iStat += EqnTest(_T("12 & 0"), 0, true); - iStat += EqnTest(_T("12&255"), 12, true); - iStat += EqnTest(_T("12&0"), 0, true); - - // Assignment operator - iStat += EqnTest(_T("a = b"), 2, true); - iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); - iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true); - iStat += EqnTest(_T("(a=b)*2"), 4, true); - iStat += EqnTest(_T("2*(a=b)"), 4, true); - iStat += EqnTest(_T("2*(a=b+1)"), 6, true); - iStat += EqnTest(_T("(a=b+1)*2"), 6, true); - iStat += EqnTest(_T("a=c, a*10"), 30, true); - - iStat += EqnTest(_T("2^2^3"), 256, true); - iStat += EqnTest(_T("1/2/3"), 1.0/6.0, true); - - // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3 - iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); - - // Test user defined binary operators - iStat += EqnTestInt(_T("1 | 2"), 3, true); - iStat += EqnTestInt(_T("1 || 2"), 1, true); - iStat += EqnTestInt(_T("123 & 456"), 72, true); - iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true); - iStat += EqnTestInt(_T("1 && 0"), 0, true); - iStat += EqnTestInt(_T("123 && 456"), 1, true); - iStat += EqnTestInt(_T("1 << 3"), 8, true); - iStat += EqnTestInt(_T("8 >> 3"), 1, true); - iStat += EqnTestInt(_T("9 / 4"), 2, true); - iStat += EqnTestInt(_T("9 % 4"), 1, true); - iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true); - iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true); - iStat += EqnTestInt(_T("-10+1"), -9, true); - iStat += EqnTestInt(_T("1+2*3"), 7, true); - iStat += EqnTestInt(_T("const1 != const2"), 1, true); - iStat += EqnTestInt(_T("const1 != const2"), 0, false); - iStat += EqnTestInt(_T("const1 == const2"), 0, true); - iStat += EqnTestInt(_T("const1 == 1"), 1, true); - iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true); - iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true); - iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false); - iStat += EqnTestInt(_T("const1 < const2"), 1, true); - iStat += EqnTestInt(_T("const2 > const1"), 1, true); - iStat += EqnTestInt(_T("const1 <= 1"), 1, true); - iStat += EqnTestInt(_T("const2 >= 2"), 1, true); - iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true); - iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true); - iStat += EqnTestInt(_T("a != b"), 1, true); - iStat += EqnTestInt(_T("a != b"), 0, false); - iStat += EqnTestInt(_T("a == b"), 0, true); - iStat += EqnTestInt(_T("a == 1"), 1, true); - iStat += EqnTestInt(_T("10*(a == 1)"), 10, true); - iStat += EqnTestInt(_T("2*(a | b)"), 6, true); - iStat += EqnTestInt(_T("2*(a | b)"), 7, false); - iStat += EqnTestInt(_T("a < b"), 1, true); - iStat += EqnTestInt(_T("b > a"), 1, true); - iStat += EqnTestInt(_T("a <= 1"), 1, true); - iStat += EqnTestInt(_T("b >= 2"), 1, true); - iStat += EqnTestInt(_T("2*(a + b)"), 6, true); - iStat += EqnTestInt(_T("2*(a - b)"), -2, true); - iStat += EqnTestInt(_T("a + (a << b)"), 5, true); - iStat += EqnTestInt(_T("-2^2"), -4, true); - iStat += EqnTestInt(_T("3--a"), 4, true); - iStat += EqnTestInt(_T("3+-3^2"), -6, true); - - // Test reading of hex values: - iStat += EqnTestInt(_T("0xff"), 255, true); - iStat += EqnTestInt(_T("10+0xff"), 265, true); - iStat += EqnTestInt(_T("0xff+10"), 265, true); - iStat += EqnTestInt(_T("10*0xff"), 2550, true); - iStat += EqnTestInt(_T("0xff*10"), 2550, true); - iStat += EqnTestInt(_T("10+0xff+1"), 266, true); - iStat += EqnTestInt(_T("1+0xff+10"), 266, true); - -// incorrect: '^' is yor here, not power -// iStat += EqnTestInt("-(1+2)^2", -9, true); -// iStat += EqnTestInt("-1^3", -1, true); - - // Test precedence - // a=1, b=2, c=3 - iStat += EqnTestInt(_T("a + b * c"), 7, true); - iStat += EqnTestInt(_T("a * b + c"), 5, true); - iStat += EqnTestInt(_T("a10"), 0, true); - iStat += EqnTestInt(_T("a"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1) - PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1) - // Binary operator - // The following must fail with builtin operators activated - // p.EnableBuiltInOp(true); -> this is the default - p.ClearPostfixOprt(); - PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2) - PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2) - // without activated built in operators it should work - p.EnableBuiltInOprt(false); - PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2) - PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2) - #undef PARSER_THROWCHECK + iStat += EqnTest(_T("a++b"), 3, true); + iStat += EqnTest(_T("a ++ b"), 3, true); + iStat += EqnTest(_T("1++2"), 3, true); + iStat += EqnTest(_T("1 ++ 2"), 3, true); + iStat += EqnTest(_T("a add b"), 3, true); + iStat += EqnTest(_T("1 add 2"), 3, true); + iStat += EqnTest(_T("aa"), 1, true); + iStat += EqnTest(_T("a>a"), 0, true); + iStat += EqnTest(_T("aa"), 0, true); + iStat += EqnTest(_T("a<=a"), 1, true); + iStat += EqnTest(_T("a<=b"), 1, true); + iStat += EqnTest(_T("b<=a"), 0, true); + iStat += EqnTest(_T("a>=a"), 1, true); + iStat += EqnTest(_T("b>=a"), 1, true); + iStat += EqnTest(_T("a>=b"), 0, true); - if (iStat==0) + // Test logical operators, especially if user defined "&" and the internal "&&" collide + iStat += EqnTest(_T("1 && 1"), 1, true); + iStat += EqnTest(_T("1 && 0"), 0, true); + iStat += EqnTest(_T("(aa)"), 1, true); + iStat += EqnTest(_T("(ab)"), 0, true); + // iStat += EqnTest(_T("12 and 255"), 12, true); + // iStat += EqnTest(_T("12 and 0"), 0, true); + iStat += EqnTest(_T("12 & 255"), 12, true); + iStat += EqnTest(_T("12 & 0"), 0, true); + iStat += EqnTest(_T("12&255"), 12, true); + iStat += EqnTest(_T("12&0"), 0, true); + + // Assignment operator + iStat += EqnTest(_T("a = b"), 2, true); + iStat += EqnTest(_T("a = sin(b)"), 0.909297, true); + iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true); + iStat += EqnTest(_T("(a=b)*2"), 4, true); + iStat += EqnTest(_T("2*(a=b)"), 4, true); + iStat += EqnTest(_T("2*(a=b+1)"), 6, true); + iStat += EqnTest(_T("(a=b+1)*2"), 6, true); + iStat += EqnTest(_T("a=c, a*10"), 30, true); + + iStat += EqnTest(_T("2^2^3"), 256, true); + iStat += EqnTest(_T("1/2/3"), 1.0 / 6.0, true); + + // reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3 + iStat += EqnTest(_T("3+4*2/(1-5)^2^3"), 3.0001220703125, true); + + // Test user defined binary operators + iStat += EqnTestInt(_T("1 | 2"), 3, true); + iStat += EqnTestInt(_T("1 || 2"), 1, true); + iStat += EqnTestInt(_T("123 & 456"), 72, true); + iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true); + iStat += EqnTestInt(_T("1 && 0"), 0, true); + iStat += EqnTestInt(_T("123 && 456"), 1, true); + iStat += EqnTestInt(_T("1 << 3"), 8, true); + iStat += EqnTestInt(_T("8 >> 3"), 1, true); + iStat += EqnTestInt(_T("9 / 4"), 2, true); + iStat += EqnTestInt(_T("9 % 4"), 1, true); + iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true); + iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true); + iStat += EqnTestInt(_T("-10+1"), -9, true); + iStat += EqnTestInt(_T("1+2*3"), 7, true); + iStat += EqnTestInt(_T("const1 != const2"), 1, true); + iStat += EqnTestInt(_T("const1 != const2"), 0, false); + iStat += EqnTestInt(_T("const1 == const2"), 0, true); + iStat += EqnTestInt(_T("const1 == 1"), 1, true); + iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true); + iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true); + iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false); + iStat += EqnTestInt(_T("const1 < const2"), 1, true); + iStat += EqnTestInt(_T("const2 > const1"), 1, true); + iStat += EqnTestInt(_T("const1 <= 1"), 1, true); + iStat += EqnTestInt(_T("const2 >= 2"), 1, true); + iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true); + iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true); + iStat += EqnTestInt(_T("a != b"), 1, true); + iStat += EqnTestInt(_T("a != b"), 0, false); + iStat += EqnTestInt(_T("a == b"), 0, true); + iStat += EqnTestInt(_T("a == 1"), 1, true); + iStat += EqnTestInt(_T("10*(a == 1)"), 10, true); + iStat += EqnTestInt(_T("2*(a | b)"), 6, true); + iStat += EqnTestInt(_T("2*(a | b)"), 7, false); + iStat += EqnTestInt(_T("a < b"), 1, true); + iStat += EqnTestInt(_T("b > a"), 1, true); + iStat += EqnTestInt(_T("a <= 1"), 1, true); + iStat += EqnTestInt(_T("b >= 2"), 1, true); + iStat += EqnTestInt(_T("2*(a + b)"), 6, true); + iStat += EqnTestInt(_T("2*(a - b)"), -2, true); + iStat += EqnTestInt(_T("a + (a << b)"), 5, true); + iStat += EqnTestInt(_T("-2^2"), -4, true); + iStat += EqnTestInt(_T("3--a"), 4, true); + iStat += EqnTestInt(_T("3+-3^2"), -6, true); + + // Test reading of hex values: + iStat += EqnTestInt(_T("0xff"), 255, true); + iStat += EqnTestInt(_T("10+0xff"), 265, true); + iStat += EqnTestInt(_T("0xff+10"), 265, true); + iStat += EqnTestInt(_T("10*0xff"), 2550, true); + iStat += EqnTestInt(_T("0xff*10"), 2550, true); + iStat += EqnTestInt(_T("10+0xff+1"), 266, true); + iStat += EqnTestInt(_T("1+0xff+10"), 266, true); + + // incorrect: '^' is yor here, not power + // iStat += EqnTestInt("-(1+2)^2", -9, true); + // iStat += EqnTestInt("-1^3", -1, true); + + // Test precedence + // a=1, b=2, c=3 + iStat += EqnTestInt(_T("a + b * c"), 7, true); + iStat += EqnTestInt(_T("a * b + c"), 5, true); + iStat += EqnTestInt(_T("a10"), 0, true); + iStat += EqnTestInt(_T("a"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1) + PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1) + // Binary operator + // The following must fail with builtin operators activated + // p.EnableBuiltInOp(true); -> this is the default + p.ClearPostfixOprt(); + PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("^"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("&&"), f1of2) + PARSER_THROWCHECK(Oprt, false, _T("||"), f1of2) + // without activated built in operators it should work + p.EnableBuiltInOprt(false); + PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("^"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("&&"), f1of2) + PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2) +#undef PARSER_THROWCHECK + + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; - } + return iStat; +} - //--------------------------------------------------------------------------- - int ParserTester::TestVarConst() - { - int iStat = 0; - mu::console() << _T("testing variable/constant detection..."); +//--------------------------------------------------------------------------- +int ParserTester::TestSyntax() { + int iStat = 0; + mu::console() << _T("testing syntax engine..."); - // Test if the result changes when a variable changes - iStat += EqnTestWithVarChange( _T("a"), 1, 1, 2, 2 ); - iStat += EqnTestWithVarChange( _T("2*a"), 2, 4, 3, 6 ); + iStat += ThrowTest(_T("1,"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("a,"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("sin(8),"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("(sin(8)),"), ecUNEXPECTED_EOF); // incomplete hex definition + iStat += ThrowTest(_T("a{m},"), ecUNEXPECTED_EOF); // incomplete hex definition - // distinguish constants with same basename - iStat += EqnTest( _T("const"), 1, true); - iStat += EqnTest( _T("const1"), 2, true); - iStat += EqnTest( _T("const2"), 3, true); - iStat += EqnTest( _T("2*const"), 2, true); - iStat += EqnTest( _T("2*const1"), 4, true); - iStat += EqnTest( _T("2*const2"), 6, true); - iStat += EqnTest( _T("2*const+1"), 3, true); - iStat += EqnTest( _T("2*const1+1"), 5, true); - iStat += EqnTest( _T("2*const2+1"), 7, true); - iStat += EqnTest( _T("const"), 0, false); - iStat += EqnTest( _T("const1"), 0, false); - iStat += EqnTest( _T("const2"), 0, false); + iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula + iStat += EqnTest(_T("sqrt((4))"), 2, true); // Multiple brackets + iStat += EqnTest(_T("sqrt((2)+2)"), 2, true); // Multiple brackets + iStat += EqnTest(_T("sqrt(2+(2))"), 2, true); // Multiple brackets + iStat += EqnTest(_T("sqrt(a+(3))"), 2, true); // Multiple brackets + iStat += EqnTest(_T("sqrt((3)+a)"), 2, true); // Multiple brackets + iStat += EqnTest(_T("order(1,2)"), 1, true); // May not cause name collision with operator "or" + iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket + iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator + iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator + iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("--2"), 0, false); // double sign + iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token + iStat += EqnTest(_T("()"), 0, false); // empty bracket without a function + iStat += EqnTest(_T("5+()"), 0, false); // empty bracket without a function + iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function + iStat += EqnTest(_T("5t6"), 0, false); // unknown token + iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token + iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula + iStat += EqnTest(_T(",3"), 0, false); // unexpected comma + iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma + iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args + iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args + iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket + iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket - // distinguish variables with same basename - iStat += EqnTest( _T("a"), 1, true); - iStat += EqnTest( _T("aa"), 2, true); - iStat += EqnTest( _T("2*a"), 2, true); - iStat += EqnTest( _T("2*aa"), 4, true); - iStat += EqnTest( _T("2*a-1"), 1, true); - iStat += EqnTest( _T("2*aa-1"), 3, true); + if (iStat == 0) + mu::console() << _T("passed") << endl; + else + mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - // custom value recognition - iStat += EqnTest( _T("0xff"), 255, true); - iStat += EqnTest( _T("0x97 + 0xff"), 406, true); + return iStat; +} - // Finally test querying of used variables - try - { +//--------------------------------------------------------------------------- +int ParserTester::TestVarConst() { + int iStat = 0; + mu::console() << _T("testing variable/constant detection..."); + + // Test if the result changes when a variable changes + iStat += EqnTestWithVarChange(_T("a"), 1, 1, 2, 2); + iStat += EqnTestWithVarChange(_T("2*a"), 2, 4, 3, 6); + + // distinguish constants with same basename + iStat += EqnTest(_T("const"), 1, true); + iStat += EqnTest(_T("const1"), 2, true); + iStat += EqnTest(_T("const2"), 3, true); + iStat += EqnTest(_T("2*const"), 2, true); + iStat += EqnTest(_T("2*const1"), 4, true); + iStat += EqnTest(_T("2*const2"), 6, true); + iStat += EqnTest(_T("2*const+1"), 3, true); + iStat += EqnTest(_T("2*const1+1"), 5, true); + iStat += EqnTest(_T("2*const2+1"), 7, true); + iStat += EqnTest(_T("const"), 0, false); + iStat += EqnTest(_T("const1"), 0, false); + iStat += EqnTest(_T("const2"), 0, false); + + // distinguish variables with same basename + iStat += EqnTest(_T("a"), 1, true); + iStat += EqnTest(_T("aa"), 2, true); + iStat += EqnTest(_T("2*a"), 2, true); + iStat += EqnTest(_T("2*aa"), 4, true); + iStat += EqnTest(_T("2*a-1"), 1, true); + iStat += EqnTest(_T("2*aa-1"), 3, true); + + // custom value recognition + iStat += EqnTest(_T("0xff"), 255, true); + iStat += EqnTest(_T("0x97 + 0xff"), 406, true); + + // Finally test querying of used variables + try { int idx; mu::Parser p; - mu::value_type vVarVal[] = { 1, 2, 3, 4, 5}; - p.DefineVar( _T("a"), &vVarVal[0]); - p.DefineVar( _T("b"), &vVarVal[1]); - p.DefineVar( _T("c"), &vVarVal[2]); - p.DefineVar( _T("d"), &vVarVal[3]); - p.DefineVar( _T("e"), &vVarVal[4]); + mu::value_type vVarVal[] = {1, 2, 3, 4, 5}; + p.DefineVar(_T("a"), &vVarVal[0]); + p.DefineVar(_T("b"), &vVarVal[1]); + p.DefineVar(_T("c"), &vVarVal[2]); + p.DefineVar(_T("d"), &vVarVal[3]); + p.DefineVar(_T("e"), &vVarVal[4]); // Test lookup of defined variables // 4 used variables - p.SetExpr( _T("a+b+c+d") ); + p.SetExpr(_T("a+b+c+d")); mu::varmap_type UsedVar = p.GetUsedVar(); int iCount = (int)UsedVar.size(); - if (iCount!=4) - throw false; - - // the next check will fail if the parser + if (iCount != 4) throw false; + + // the next check will fail if the parser // erroneously creates new variables internally - if (p.GetVar().size()!=5) - throw false; + if (p.GetVar().size() != 5) throw false; mu::varmap_type::const_iterator item = UsedVar.begin(); - for (idx=0; item!=UsedVar.end(); ++item) - { - if (&vVarVal[idx++]!=item->second) - throw false; + for (idx = 0; item != UsedVar.end(); ++item) { + if (&vVarVal[idx++] != item->second) throw false; } // Test lookup of undefined variables - p.SetExpr( _T("undef1+undef2+undef3") ); + p.SetExpr(_T("undef1+undef2+undef3")); UsedVar = p.GetUsedVar(); iCount = (int)UsedVar.size(); - if (iCount!=3) - throw false; + if (iCount != 3) throw false; - // the next check will fail if the parser + // the next check will fail if the parser // erroneously creates new variables internally - if (p.GetVar().size()!=5) - throw false; + if (p.GetVar().size() != 5) throw false; - for (item = UsedVar.begin(); item!=UsedVar.end(); ++item) - { - if (item->second!=0) - throw false; // all pointers to undefined variables must be null + for (item = UsedVar.begin(); item != UsedVar.end(); ++item) { + if (item->second != 0) throw false; // all pointers to undefined variables must be null } // 1 used variables - p.SetExpr( _T("a+b") ); + p.SetExpr(_T("a+b")); UsedVar = p.GetUsedVar(); iCount = (int)UsedVar.size(); - if (iCount!=2) throw false; + if (iCount != 2) throw false; item = UsedVar.begin(); - for (idx=0; item!=UsedVar.end(); ++item) - if (&vVarVal[idx++]!=item->second) throw false; + for (idx = 0; item != UsedVar.end(); ++item) + if (&vVarVal[idx++] != item->second) throw false; - } - catch(...) - { + } catch (...) { iStat += 1; - } + } - if (iStat==0) + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; - } + return iStat; +} - //--------------------------------------------------------------------------- - int ParserTester::TestMultiArg() - { - int iStat = 0; - mu::console() << _T("testing multiarg functions..."); - - // Compound expressions - iStat += EqnTest( _T("1,2,3"), 3, true); - iStat += EqnTest( _T("a,b,c"), 3, true); - iStat += EqnTest( _T("a=10,b=20,c=a*b"), 200, true); - iStat += EqnTest( _T("1,\n2,\n3"), 3, true); - iStat += EqnTest( _T("a,\nb,\nc"), 3, true); - iStat += EqnTest( _T("a=10,\nb=20,\nc=a*b"), 200, true); - iStat += EqnTest( _T("1,\r\n2,\r\n3"), 3, true); - iStat += EqnTest( _T("a,\r\nb,\r\nc"), 3, true); - iStat += EqnTest( _T("a=10,\r\nb=20,\r\nc=a*b"), 200, true); +//--------------------------------------------------------------------------- +int ParserTester::TestMultiArg() { + int iStat = 0; + mu::console() << _T("testing multiarg functions..."); - // picking the right argument - iStat += EqnTest( _T("f1of1(1)"), 1, true); - iStat += EqnTest( _T("f1of2(1, 2)"), 1, true); - iStat += EqnTest( _T("f2of2(1, 2)"), 2, true); - iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true); - iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true); - iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true); - iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true); - iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true); - iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true); - iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true); - iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true); - iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true); - iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true); - iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true); - iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true); - // Too few arguments / Too many arguments - iStat += EqnTest( _T("1+ping()"), 11, true); - iStat += EqnTest( _T("ping()+1"), 11, true); - iStat += EqnTest( _T("2*ping()"), 20, true); - iStat += EqnTest( _T("ping()*2"), 20, true); - iStat += EqnTest( _T("ping(1,2)"), 0, false); - iStat += EqnTest( _T("1+ping(1,2)"), 0, false); - iStat += EqnTest( _T("f1of1(1,2)"), 0, false); - iStat += EqnTest( _T("f1of1()"), 0, false); - iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false); - iStat += EqnTest( _T("f1of2(1)"), 0, false); - iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false); - iStat += EqnTest( _T("f1of3(1)"), 0, false); - iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false); - iStat += EqnTest( _T("f1of4(1)"), 0, false); - iStat += EqnTest( _T("(1,2,3)"), 0, false); - iStat += EqnTest( _T("1,2,3"), 0, false); - iStat += EqnTest( _T("(1*a,2,3)"), 0, false); - iStat += EqnTest( _T("1,2*a,3"), 0, false); - - // correct calculation of arguments - iStat += EqnTest( _T("min(a, 1)"), 1, true); - iStat += EqnTest( _T("min(3*2, 1)"), 1, true); - iStat += EqnTest( _T("min(3*2, 1)"), 6, false); - iStat += EqnTest( _T("firstArg(2,3,4)"), 2, true); - iStat += EqnTest( _T("lastArg(2,3,4)"), 4, true); - iStat += EqnTest( _T("min(3*a+1, 1)"), 1, true); - iStat += EqnTest( _T("max(3*a+1, 1)"), 4, true); - iStat += EqnTest( _T("max(3*a+1, 1)*2"), 8, true); - iStat += EqnTest( _T("2*max(3*a+1, 1)+2"), 10, true); + // Compound expressions + iStat += EqnTest(_T("1,2,3"), 3, true); + iStat += EqnTest(_T("a,b,c"), 3, true); + iStat += EqnTest(_T("a=10,b=20,c=a*b"), 200, true); + iStat += EqnTest(_T("1,\n2,\n3"), 3, true); + iStat += EqnTest(_T("a,\nb,\nc"), 3, true); + iStat += EqnTest(_T("a=10,\nb=20,\nc=a*b"), 200, true); + iStat += EqnTest(_T("1,\r\n2,\r\n3"), 3, true); + iStat += EqnTest(_T("a,\r\nb,\r\nc"), 3, true); + iStat += EqnTest(_T("a=10,\r\nb=20,\r\nc=a*b"), 200, true); - // functions with Variable argument count - iStat += EqnTest( _T("sum(a)"), 1, true); - iStat += EqnTest( _T("sum(1,2,3)"), 6, true); - iStat += EqnTest( _T("sum(a,b,c)"), 6, true); - iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true); - iStat += EqnTest( _T("2*sum(1,2,3)"), 12, true); - iStat += EqnTest( _T("2*sum(1,2,3)+2"), 14, true); - iStat += EqnTest( _T("2*sum(-1,2,3)+2"), 10, true); - iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"), 6, true); - iStat += EqnTest( _T("2*sum(-1,10,-a)+2"), 18, true); - iStat += EqnTest( _T("2*sum(1,2,3)*2"), 24, true); - iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true); - iStat += EqnTest( _T("sum(1*3, 4, a+2)"), 10, true); - iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true); - iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true); + // picking the right argument + iStat += EqnTest(_T("f1of1(1)"), 1, true); + iStat += EqnTest(_T("f1of2(1, 2)"), 1, true); + iStat += EqnTest(_T("f2of2(1, 2)"), 2, true); + iStat += EqnTest(_T("f1of3(1, 2, 3)"), 1, true); + iStat += EqnTest(_T("f2of3(1, 2, 3)"), 2, true); + iStat += EqnTest(_T("f3of3(1, 2, 3)"), 3, true); + iStat += EqnTest(_T("f1of4(1, 2, 3, 4)"), 1, true); + iStat += EqnTest(_T("f2of4(1, 2, 3, 4)"), 2, true); + iStat += EqnTest(_T("f3of4(1, 2, 3, 4)"), 3, true); + iStat += EqnTest(_T("f4of4(1, 2, 3, 4)"), 4, true); + iStat += EqnTest(_T("f1of5(1, 2, 3, 4, 5)"), 1, true); + iStat += EqnTest(_T("f2of5(1, 2, 3, 4, 5)"), 2, true); + iStat += EqnTest(_T("f3of5(1, 2, 3, 4, 5)"), 3, true); + iStat += EqnTest(_T("f4of5(1, 2, 3, 4, 5)"), 4, true); + iStat += EqnTest(_T("f5of5(1, 2, 3, 4, 5)"), 5, true); + // Too few arguments / Too many arguments + iStat += EqnTest(_T("1+ping()"), 11, true); + iStat += EqnTest(_T("ping()+1"), 11, true); + iStat += EqnTest(_T("2*ping()"), 20, true); + iStat += EqnTest(_T("ping()*2"), 20, true); + iStat += EqnTest(_T("ping(1,2)"), 0, false); + iStat += EqnTest(_T("1+ping(1,2)"), 0, false); + iStat += EqnTest(_T("f1of1(1,2)"), 0, false); + iStat += EqnTest(_T("f1of1()"), 0, false); + iStat += EqnTest(_T("f1of2(1, 2, 3)"), 0, false); + iStat += EqnTest(_T("f1of2(1)"), 0, false); + iStat += EqnTest(_T("f1of3(1, 2, 3, 4)"), 0, false); + iStat += EqnTest(_T("f1of3(1)"), 0, false); + iStat += EqnTest(_T("f1of4(1, 2, 3, 4, 5)"), 0, false); + iStat += EqnTest(_T("f1of4(1)"), 0, false); + iStat += EqnTest(_T("(1,2,3)"), 0, false); + iStat += EqnTest(_T("1,2,3"), 0, false); + iStat += EqnTest(_T("(1*a,2,3)"), 0, false); + iStat += EqnTest(_T("1,2*a,3"), 0, false); - // some failures - iStat += EqnTest( _T("sum()"), 0, false); - iStat += EqnTest( _T("sum(,)"), 0, false); - iStat += EqnTest( _T("sum(1,2,)"), 0, false); - iStat += EqnTest( _T("sum(,1,2)"), 0, false); + // correct calculation of arguments + iStat += EqnTest(_T("min(a, 1)"), 1, true); + iStat += EqnTest(_T("min(3*2, 1)"), 1, true); + iStat += EqnTest(_T("min(3*2, 1)"), 6, false); + iStat += EqnTest(_T("firstArg(2,3,4)"), 2, true); + iStat += EqnTest(_T("lastArg(2,3,4)"), 4, true); + iStat += EqnTest(_T("min(3*a+1, 1)"), 1, true); + iStat += EqnTest(_T("max(3*a+1, 1)"), 4, true); + iStat += EqnTest(_T("max(3*a+1, 1)*2"), 8, true); + iStat += EqnTest(_T("2*max(3*a+1, 1)+2"), 10, true); - if (iStat==0) + // functions with Variable argument count + iStat += EqnTest(_T("sum(a)"), 1, true); + iStat += EqnTest(_T("sum(1,2,3)"), 6, true); + iStat += EqnTest(_T("sum(a,b,c)"), 6, true); + iStat += EqnTest(_T("sum(1,-max(1,2),3)*2"), 4, true); + iStat += EqnTest(_T("2*sum(1,2,3)"), 12, true); + iStat += EqnTest(_T("2*sum(1,2,3)+2"), 14, true); + iStat += EqnTest(_T("2*sum(-1,2,3)+2"), 10, true); + iStat += EqnTest(_T("2*sum(-1,2,-(-a))+2"), 6, true); + iStat += EqnTest(_T("2*sum(-1,10,-a)+2"), 18, true); + iStat += EqnTest(_T("2*sum(1,2,3)*2"), 24, true); + iStat += EqnTest(_T("sum(1,-max(1,2),3)*2"), 4, true); + iStat += EqnTest(_T("sum(1*3, 4, a+2)"), 10, true); + iStat += EqnTest(_T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true); + iStat += EqnTest(_T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true); + + // some failures + iStat += EqnTest(_T("sum()"), 0, false); + iStat += EqnTest(_T("sum(,)"), 0, false); + iStat += EqnTest(_T("sum(1,2,)"), 0, false); + iStat += EqnTest(_T("sum(,1,2)"), 0, false); + + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; - } + return iStat; +} - //--------------------------------------------------------------------------- - int ParserTester::TestInfixOprt() - { - int iStat(0); - mu::console() << "testing infix operators..."; +//--------------------------------------------------------------------------- +int ParserTester::TestInfixOprt() { + int iStat(0); + mu::console() << "testing infix operators..."; - iStat += EqnTest( _T("+1"), +1, true); - iStat += EqnTest( _T("-(+1)"), -1, true); - iStat += EqnTest( _T("-(+1)*2"), -2, true); - iStat += EqnTest( _T("-(+2)*sqrt(4)"), -4, true); - iStat += EqnTest( _T("3-+a"), 2, true); - iStat += EqnTest( _T("+1*3"), 3, true); + iStat += EqnTest(_T("+1"), +1, true); + iStat += EqnTest(_T("-(+1)"), -1, true); + iStat += EqnTest(_T("-(+1)*2"), -2, true); + iStat += EqnTest(_T("-(+2)*sqrt(4)"), -4, true); + iStat += EqnTest(_T("3-+a"), 2, true); + iStat += EqnTest(_T("+1*3"), 3, true); - iStat += EqnTest( _T("-1"), -1, true); - iStat += EqnTest( _T("-(-1)"), 1, true); - iStat += EqnTest( _T("-(-1)*2"), 2, true); - iStat += EqnTest( _T("-(-2)*sqrt(4)"), 4, true); - iStat += EqnTest( _T("-_pi"), -PARSER_CONST_PI, true); - iStat += EqnTest( _T("-a"), -1, true); - iStat += EqnTest( _T("-(a)"), -1, true); - iStat += EqnTest( _T("-(-a)"), 1, true); - iStat += EqnTest( _T("-(-a)*2"), 2, true); - iStat += EqnTest( _T("-(8)"), -8, true); - iStat += EqnTest( _T("-8"), -8, true); - iStat += EqnTest( _T("-(2+1)"), -3, true); - iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true); - iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true); - iStat += EqnTest( _T("-sin(8)"), -0.989358, true); - iStat += EqnTest( _T("3-(-a)"), 4, true); - iStat += EqnTest( _T("3--a"), 4, true); - iStat += EqnTest( _T("-1*3"), -3, true); + iStat += EqnTest(_T("-1"), -1, true); + iStat += EqnTest(_T("-(-1)"), 1, true); + iStat += EqnTest(_T("-(-1)*2"), 2, true); + iStat += EqnTest(_T("-(-2)*sqrt(4)"), 4, true); + iStat += EqnTest(_T("-_pi"), -PARSER_CONST_PI, true); + iStat += EqnTest(_T("-a"), -1, true); + iStat += EqnTest(_T("-(a)"), -1, true); + iStat += EqnTest(_T("-(-a)"), 1, true); + iStat += EqnTest(_T("-(-a)*2"), 2, true); + iStat += EqnTest(_T("-(8)"), -8, true); + iStat += EqnTest(_T("-8"), -8, true); + iStat += EqnTest(_T("-(2+1)"), -3, true); + iStat += EqnTest(_T("-(f1of1(1+2*3)+1*2)"), -9, true); + iStat += EqnTest(_T("-(-f1of1(1+2*3)+1*2)"), 5, true); + iStat += EqnTest(_T("-sin(8)"), -0.989358, true); + iStat += EqnTest(_T("3-(-a)"), 4, true); + iStat += EqnTest(_T("3--a"), 4, true); + iStat += EqnTest(_T("-1*3"), -3, true); - // Postfix / infix priorities - iStat += EqnTest( _T("~2#"), 8, true); - iStat += EqnTest( _T("~f1of1(2)#"), 8, true); - iStat += EqnTest( _T("~(b)#"), 8, true); - iStat += EqnTest( _T("(~b)#"), 12, true); - iStat += EqnTest( _T("~(2#)"), 8, true); - iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true); - // - iStat += EqnTest( _T("-2^2"),-4, true); - iStat += EqnTest( _T("-(a+b)^2"),-9, true); - iStat += EqnTest( _T("(-3)^2"),9, true); - iStat += EqnTest( _T("-(-2^2)"),4, true); - iStat += EqnTest( _T("3+-3^2"),-6, true); - // The following assumes use of sqr as postfix operator ("§") together - // with a sign operator of low priority: - iStat += EqnTest( _T("-2'"), -4, true); - iStat += EqnTest( _T("-(1+1)'"),-4, true); - iStat += EqnTest( _T("2+-(1+1)'"),-2, true); - iStat += EqnTest( _T("2+-2'"), -2, true); - // This is the classic behaviour of the infix sign operator (here: "$") which is - // now deprecated: - iStat += EqnTest( _T("$2^2"),4, true); - iStat += EqnTest( _T("$(a+b)^2"),9, true); - iStat += EqnTest( _T("($3)^2"),9, true); - iStat += EqnTest( _T("$($2^2)"),-4, true); - iStat += EqnTest( _T("3+$3^2"),12, true); + // Postfix / infix priorities + iStat += EqnTest(_T("~2#"), 8, true); + iStat += EqnTest(_T("~f1of1(2)#"), 8, true); + iStat += EqnTest(_T("~(b)#"), 8, true); + iStat += EqnTest(_T("(~b)#"), 12, true); + iStat += EqnTest(_T("~(2#)"), 8, true); + iStat += EqnTest(_T("~(f1of1(2)#)"), 8, true); + // + iStat += EqnTest(_T("-2^2"), -4, true); + iStat += EqnTest(_T("-(a+b)^2"), -9, true); + iStat += EqnTest(_T("(-3)^2"), 9, true); + iStat += EqnTest(_T("-(-2^2)"), 4, true); + iStat += EqnTest(_T("3+-3^2"), -6, true); + // The following assumes use of sqr as postfix operator ("§") together + // with a sign operator of low priority: + iStat += EqnTest(_T("-2'"), -4, true); + iStat += EqnTest(_T("-(1+1)'"), -4, true); + iStat += EqnTest(_T("2+-(1+1)'"), -2, true); + iStat += EqnTest(_T("2+-2'"), -2, true); + // This is the classic behaviour of the infix sign operator (here: "$") which is + // now deprecated: + iStat += EqnTest(_T("$2^2"), 4, true); + iStat += EqnTest(_T("$(a+b)^2"), 9, true); + iStat += EqnTest(_T("($3)^2"), 9, true); + iStat += EqnTest(_T("$($2^2)"), -4, true); + iStat += EqnTest(_T("3+$3^2"), 12, true); - // infix operators sharing the first few characters - iStat += EqnTest( _T("~ 123"), 123+2, true); - iStat += EqnTest( _T("~~ 123"), 123+2, true); + // infix operators sharing the first few characters + iStat += EqnTest(_T("~ 123"), 123 + 2, true); + iStat += EqnTest(_T("~~ 123"), 123 + 2, true); - if (iStat==0) + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; - } + return iStat; +} +//--------------------------------------------------------------------------- +int ParserTester::TestPostFix() { + int iStat = 0; + mu::console() << _T("testing postfix operators..."); - //--------------------------------------------------------------------------- - int ParserTester::TestPostFix() - { - int iStat = 0; - mu::console() << _T("testing postfix operators..."); + // application + iStat += EqnTest(_T("3{m}+5"), 5.003, true); + iStat += EqnTest(_T("1000{m}"), 1, true); + iStat += EqnTest(_T("1000 {m}"), 1, true); + iStat += EqnTest(_T("(a){m}"), 1e-3, true); + iStat += EqnTest(_T("a{m}"), 1e-3, true); + iStat += EqnTest(_T("a {m}"), 1e-3, true); + iStat += EqnTest(_T("-(a){m}"), -1e-3, true); + iStat += EqnTest(_T("-2{m}"), -2e-3, true); + iStat += EqnTest(_T("-2 {m}"), -2e-3, true); + iStat += EqnTest(_T("f1of1(1000){m}"), 1, true); + iStat += EqnTest(_T("-f1of1(1000){m}"), -1, true); + iStat += EqnTest(_T("-f1of1(-1000){m}"), 1, true); + iStat += EqnTest(_T("f4of4(0,0,0,1000){m}"), 1, true); + iStat += EqnTest(_T("2+(a*1000){m}"), 3, true); - // application - iStat += EqnTest( _T("3{m}+5"), 5.003, true); - iStat += EqnTest( _T("1000{m}"), 1, true); - iStat += EqnTest( _T("1000 {m}"), 1, true); - iStat += EqnTest( _T("(a){m}"), 1e-3, true); - iStat += EqnTest( _T("a{m}"), 1e-3, true); - iStat += EqnTest( _T("a {m}"), 1e-3, true); - iStat += EqnTest( _T("-(a){m}"), -1e-3, true); - iStat += EqnTest( _T("-2{m}"), -2e-3, true); - iStat += EqnTest( _T("-2 {m}"), -2e-3, true); - iStat += EqnTest( _T("f1of1(1000){m}"), 1, true); - iStat += EqnTest( _T("-f1of1(1000){m}"), -1, true); - iStat += EqnTest( _T("-f1of1(-1000){m}"), 1, true); - iStat += EqnTest( _T("f4of4(0,0,0,1000){m}"), 1, true); - iStat += EqnTest( _T("2+(a*1000){m}"), 3, true); + // can postfix operators "m" und "meg" be told apart properly? + iStat += EqnTest(_T("2*3000meg+2"), 2 * 3e9 + 2, true); - // can postfix operators "m" und "meg" be told apart properly? - iStat += EqnTest( _T("2*3000meg+2"), 2*3e9+2, true); + // some incorrect results + iStat += EqnTest(_T("1000{m}"), 0.1, false); + iStat += EqnTest(_T("(a){m}"), 2, false); + // failure due to syntax checking + iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition + iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); + iStat += ThrowTest(_T("4 + {m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("{m}4"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("sin({m})"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("{m} {m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("{m}(8)"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("4,{m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("-{m}"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("2(-{m})"), ecUNEXPECTED_PARENS); + iStat += ThrowTest(_T("2({m})"), ecUNEXPECTED_PARENS); - // some incorrect results - iStat += EqnTest( _T("1000{m}"), 0.1, false); - iStat += EqnTest( _T("(a){m}"), 2, false); - // failure due to syntax checking - iStat += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex definition - iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); - iStat += ThrowTest( _T("4 + {m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("{m}4"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("sin({m})"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("{m} {m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("{m}(8)"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("4,{m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("-{m}"), ecUNASSIGNABLE_TOKEN); - iStat += ThrowTest( _T("2(-{m})"), ecUNEXPECTED_PARENS); - iStat += ThrowTest( _T("2({m})"), ecUNEXPECTED_PARENS); - - iStat += ThrowTest( _T("multi*1.0"), ecUNASSIGNABLE_TOKEN); + iStat += ThrowTest(_T("multi*1.0"), ecUNASSIGNABLE_TOKEN); - if (iStat==0) + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; - } + return iStat; +} - //--------------------------------------------------------------------------- - int ParserTester::TestExpression() - { - int iStat = 0; - mu::console() << _T("testing expression samples..."); +//--------------------------------------------------------------------------- +int ParserTester::TestExpression() { + int iStat = 0; + mu::console() << _T("testing expression samples..."); - value_type b = 2; + value_type b = 2; - // Optimization - iStat += EqnTest( _T("2*b*5"), 20, true); - iStat += EqnTest( _T("2*b*5 + 4*b"), 28, true); - iStat += EqnTest( _T("2*a/3"), 2.0/3.0, true); + // Optimization + iStat += EqnTest(_T("2*b*5"), 20, true); + iStat += EqnTest(_T("2*b*5 + 4*b"), 28, true); + iStat += EqnTest(_T("2*a/3"), 2.0 / 3.0, true); - // Addition auf cmVARMUL - iStat += EqnTest( _T("3+b"), b+3, true); - iStat += EqnTest( _T("b+3"), b+3, true); - iStat += EqnTest( _T("b*3+2"), b*3+2, true); - iStat += EqnTest( _T("3*b+2"), b*3+2, true); - iStat += EqnTest( _T("2+b*3"), b*3+2, true); - iStat += EqnTest( _T("2+3*b"), b*3+2, true); - iStat += EqnTest( _T("b+3*b"), b+3*b, true); - iStat += EqnTest( _T("3*b+b"), b+3*b, true); + // Addition auf cmVARMUL + iStat += EqnTest(_T("3+b"), b + 3, true); + iStat += EqnTest(_T("b+3"), b + 3, true); + iStat += EqnTest(_T("b*3+2"), b * 3 + 2, true); + iStat += EqnTest(_T("3*b+2"), b * 3 + 2, true); + iStat += EqnTest(_T("2+b*3"), b * 3 + 2, true); + iStat += EqnTest(_T("2+3*b"), b * 3 + 2, true); + iStat += EqnTest(_T("b+3*b"), b + 3 * b, true); + iStat += EqnTest(_T("3*b+b"), b + 3 * b, true); - iStat += EqnTest( _T("2+b*3+b"), 2+b*3+b, true); - iStat += EqnTest( _T("b+2+b*3"), b+2+b*3, true); + iStat += EqnTest(_T("2+b*3+b"), 2 + b * 3 + b, true); + iStat += EqnTest(_T("b+2+b*3"), b + 2 + b * 3, true); - iStat += EqnTest( _T("(2*b+1)*4"), (2*b+1)*4, true); - iStat += EqnTest( _T("4*(2*b+1)"), (2*b+1)*4, true); + iStat += EqnTest(_T("(2*b+1)*4"), (2 * b + 1) * 4, true); + iStat += EqnTest(_T("4*(2*b+1)"), (2 * b + 1) * 4, true); - // operator precedences - iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true); - iStat += EqnTest( _T("1^2/3*4-5+6"), 2.33333333, true); - iStat += EqnTest( _T("1+2*3"), 7, true); - iStat += EqnTest( _T("1+2*3"), 7, true); - iStat += EqnTest( _T("(1+2)*3"), 9, true); - iStat += EqnTest( _T("(1+2)*(-3)"), -9, true); - iStat += EqnTest( _T("2/4"), 0.5, true); + // operator precedences + iStat += EqnTest(_T("1+2-3*4/5^6"), 2.99923, true); + iStat += EqnTest(_T("1^2/3*4-5+6"), 2.33333333, true); + iStat += EqnTest(_T("1+2*3"), 7, true); + iStat += EqnTest(_T("1+2*3"), 7, true); + iStat += EqnTest(_T("(1+2)*3"), 9, true); + iStat += EqnTest(_T("(1+2)*(-3)"), -9, true); + iStat += EqnTest(_T("2/4"), 0.5, true); - iStat += EqnTest( _T("exp(ln(7))"), 7, true); - iStat += EqnTest( _T("e^ln(7)"), 7, true); - iStat += EqnTest( _T("e^(ln(7))"), 7, true); - iStat += EqnTest( _T("(e^(ln(7)))"), 7, true); - iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true); - iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true); - iStat += EqnTest( _T("10^log(5)"), pow(10.0, log(5.0)), true); - iStat += EqnTest( _T("10^log10(5)"), 5, true); - iStat += EqnTest( _T("2^log2(4)"), 4, true); - iStat += EqnTest( _T("-(sin(0)+1)"), -1, true); - iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true); + iStat += EqnTest(_T("exp(ln(7))"), 7, true); + iStat += EqnTest(_T("e^ln(7)"), 7, true); + iStat += EqnTest(_T("e^(ln(7))"), 7, true); + iStat += EqnTest(_T("(e^(ln(7)))"), 7, true); + iStat += EqnTest(_T("1-(e^(ln(7)))"), -6, true); + iStat += EqnTest(_T("2*(e^(ln(7)))"), 14, true); + iStat += EqnTest(_T("10^log(5)"), pow(10.0, log(5.0)), true); + iStat += EqnTest(_T("10^log10(5)"), 5, true); + iStat += EqnTest(_T("2^log2(4)"), 4, true); + iStat += EqnTest(_T("-(sin(0)+1)"), -1, true); + iStat += EqnTest(_T("-(2^1.1)"), -2.14354692, true); - iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true); - iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true); - iStat += EqnTest( _T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true); - iStat += EqnTest( _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))"), 0.00377999, true); + iStat += EqnTest(_T("(cos(2.41)/b)"), -0.372056, true); + iStat += EqnTest(_T("(1*(2*(3*(4*(5*(6*(a+b)))))))"), 2160, true); + iStat += EqnTest(_T("(1*(2*(3*(4*(5*(6*(7*(a+b))))))))"), 15120, true); + iStat += EqnTest( + _T("(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/") + _T("a))+a)+b))+b)*a)-pi))"), + 0.00377999, true); - // long formula (Reference: Matlab) - iStat += EqnTest( - _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))") - _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/") - _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-") - _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6") - _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e") - _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), -12.23016549, true); + // long formula (Reference: Matlab) + iStat += EqnTest( + _T("(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/") + _T("(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))") + _T("/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/") + _T("(-6)*1*(-1))*(-6)+(-e)))))/") + _T("((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/") + _T("(sqrt((((((1+(-7))))+((((-") + _T("e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/") + _T("(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6") + _T("+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/") + _T("sqrt((((9))+((((pi))-8+2))+pi))/e") + _T("*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)"), + -12.23016549, true); - // long formula (Reference: Matlab) - iStat += EqnTest( - _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e") - _T(")+a)))*2.77)"), -2.16995656, true); + // long formula (Reference: Matlab) + iStat += EqnTest( + _T("(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/") + _T("0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e") + _T(")+a)))*2.77)"), + -2.16995656, true); - // long formula (Reference: Matlab) - iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true); - - if (iStat==0) - mu::console() << _T("passed") << endl; - else + // long formula (Reference: Matlab) + iStat += EqnTest(_T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true); + + if (iStat == 0) + mu::console() << _T("passed") << endl; + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; - } + return iStat; +} +//--------------------------------------------------------------------------- +int ParserTester::TestIfThenElse() { + int iStat = 0; + mu::console() << _T("testing if-then-else operator..."); + // Test error detection + iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); + iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); + iStat += ThrowTest(_T("(ab) ? 10 : 11"), 11, true); + iStat += EqnTest(_T("(ab) ? c : d"), -2, true); - // Test error detection - iStat += ThrowTest(_T(":3"), ecUNEXPECTED_CONDITIONAL); - iStat += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); - iStat += ThrowTest(_T("(ab) ? 1 : 0"), 0, true); + iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true); + iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true); + iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true); - iStat += EqnTest(_T("1 ? 128 : 255"), 128, true); - iStat += EqnTest(_T("1<2 ? 128 : 255"), 128, true); - iStat += EqnTest(_T("ab) ? 10 : 11"), 11, true); - iStat += EqnTest(_T("(ab) ? c : d"), -2, true); + iStat += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2, true); + iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true); + iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true); + iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true); + iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true); + iStat += EqnTest(_T("sum(3, (ab) ? 3 : 10)"), 130, true); + iStat += EqnTest(_T("10*sum(3, (ab) ? 3 : 10)*10"), 130, true); + iStat += EqnTest(_T("sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? 1 : 0"), 0, true); - iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : 2"), 2, true); - iStat += EqnTest(_T("((a>b) ? 1 : 0) ? 1 : sum((a>b) ? 1 : 2)"), 2, true); - iStat += EqnTest(_T("((a>b) ? 0 : 1) ? 1 : sum((a>b) ? 1 : 2)"), 1, true); + // todo: auch für muParserX hinzufügen! + iStat += EqnTest(_T("(ab)&&(a2)&&(1<2) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true); + iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true); + iStat += EqnTest(_T("((ab)&&(ab) ? 1 : 2)"), 2, true); - iStat += EqnTest(_T("sum((1) ? 1 : 2)"), 1, true); - iStat += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102, true); - iStat += EqnTest(_T("sum((1) ? 1 : 2, 100)"), 101, true); - iStat += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13, true); - iStat += EqnTest(_T("sum(3, (ab) ? 3 : 10)"), 130, true); - iStat += EqnTest(_T("10*sum(3, (ab) ? 3 : 10)*10"), 130, true); - iStat += EqnTest(_T("sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? sum(3, (a0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true); + iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true); + iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true); + iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true); + iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true); + iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true); + iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true); + iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true); - // todo: auch für muParserX hinzufügen! - iStat += EqnTest(_T("(ab)&&(a2)&&(1<2) ? 128 : 255"), 255, true); - iStat += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128, true); - iStat += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255, true); - iStat += EqnTest(_T("((ab)&&(ab)&&(a0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255, true); - iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255, true); - iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128, true); - iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128, true); - iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32, true); - iStat += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64, true); - iStat += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50, true); - iStat += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50, true); - iStat += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128, true); - iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32, true); - iStat += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32, true); - iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255, true); - iStat += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255, true); - iStat += EqnTest(_T("1 ? 0 ? 128 : 255 : 1 ? 32 : 64"), 255, true); + iStat += EqnTest(_T("a=1?b=1?3:4:5, a"), 3, true); + iStat += EqnTest(_T("a=1?b=1?3:4:5, b"), 3, true); + iStat += EqnTest(_T("a=0?b=1?3:4:5, a"), 5, true); + iStat += EqnTest(_T("a=0?b=1?3:4:5, b"), 2, true); - // assignment operators - iStat += EqnTest(_T("a= 0 ? 128 : 255, a"), 255, true); - iStat += EqnTest(_T("a=((a>b)&&(a - // this is now legal, for reference see: - // https://sourceforge.net/forum/message.php?msg_id=7411373 - // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); - //
+ // + // this is now legal, for reference see: + // https://sourceforge.net/forum/message.php?msg_id=7411373 + // iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR); + // - iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR); - iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR); - iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT); + iStat += ThrowTest(_T("(8)=5"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest(_T("(a)=5"), ecUNEXPECTED_OPERATOR); + iStat += ThrowTest(_T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT); - if (iStat==0) + if (iStat == 0) mu::console() << _T("passed") << endl; - else + else mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - return iStat; - } + return iStat; +} +//--------------------------------------------------------------------------- +void ParserTester::AddTest(testfun_type a_pFun) { m_vTestFun.push_back(a_pFun); } - //--------------------------------------------------------------------------- - void ParserTester::AddTest(testfun_type a_pFun) - { - m_vTestFun.push_back(a_pFun); - } - - //--------------------------------------------------------------------------- - void ParserTester::Run() - { - int iStat = 0; - try - { - for (int i=0; i<(int)m_vTestFun.size(); ++i) - iStat += (this->*m_vTestFun[i])(); - } - catch(Parser::exception_type &e) - { +//--------------------------------------------------------------------------- +void ParserTester::Run() { + int iStat = 0; + try { + for (int i = 0; i < (int)m_vTestFun.size(); ++i) iStat += (this->*m_vTestFun[i])(); + } catch (Parser::exception_type &e) { mu::console() << "\n" << e.GetMsg() << endl; mu::console() << e.GetToken() << endl; Abort(); - } - catch(std::exception &e) - { + } catch (std::exception &e) { mu::console() << e.what() << endl; Abort(); - } - catch(...) - { + } catch (...) { mu::console() << "Internal error"; Abort(); - } - - if (iStat==0) - { - mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl; - } - else - { - mu::console() << "Test failed with " << iStat - << " errors (" << ParserTester::c_iCount - << " expressions)" << endl; - } - ParserTester::c_iCount = 0; } + if (iStat == 0) { + mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl; + } else { + mu::console() << "Test failed with " << iStat << " errors (" << ParserTester::c_iCount + << " expressions)" << endl; + } + ParserTester::c_iCount = 0; +} - //--------------------------------------------------------------------------- - int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) - { - ParserTester::c_iCount++; +//--------------------------------------------------------------------------- +int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) { + ParserTester::c_iCount++; - try - { - value_type fVal[] = {1,1,1}; + try { + value_type fVal[] = {1, 1, 1}; Parser p; - p.DefineVar( _T("a"), &fVal[0]); - p.DefineVar( _T("b"), &fVal[1]); - p.DefineVar( _T("c"), &fVal[2]); - p.DefinePostfixOprt( _T("{m}"), Milli); - p.DefinePostfixOprt( _T("m"), Milli); - p.DefineFun( _T("ping"), Ping); - p.DefineFun( _T("valueof"), ValueOf); - p.DefineFun( _T("strfun1"), StrFun1); - p.DefineFun( _T("strfun2"), StrFun2); - p.DefineFun( _T("strfun3"), StrFun3); + p.DefineVar(_T("a"), &fVal[0]); + p.DefineVar(_T("b"), &fVal[1]); + p.DefineVar(_T("c"), &fVal[2]); + p.DefinePostfixOprt(_T("{m}"), Milli); + p.DefinePostfixOprt(_T("m"), Milli); + p.DefineFun(_T("ping"), Ping); + p.DefineFun(_T("valueof"), ValueOf); + p.DefineFun(_T("strfun1"), StrFun1); + p.DefineFun(_T("strfun2"), StrFun2); + p.DefineFun(_T("strfun3"), StrFun3); p.SetExpr(a_str); p.Eval(); - } - catch(ParserError &e) - { + } catch (ParserError &e) { // output the formula in case of an failed test - if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) ) - { - mu::console() << _T("\n ") - << _T("Expression: ") << a_str - << _T(" Code:") << e.GetCode() << _T("(") << e.GetMsg() << _T(")") - << _T(" Expected:") << a_iErrc; + if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) { + mu::console() << _T("\n ") + << _T("Expression: ") << a_str << _T(" Code:") << e.GetCode() << _T("(") + << e.GetMsg() << _T(")") + << _T(" Expected:") << a_iErrc; } - return (a_iErrc==e.GetCode()) ? 0 : 1; - } - - // if a_bFail==false no exception is expected - bool bRet((a_bFail==false) ? 0 : 1); - if (bRet==1) - { - mu::console() << _T("\n ") - << _T("Expression: ") << a_str - << _T(" did evaluate; Expected error:") << a_iErrc; - } - - return bRet; + return (a_iErrc == e.GetCode()) ? 0 : 1; } - //--------------------------------------------------------------------------- - /** \brief Evaluate a tet expression. + // if a_bFail==false no exception is expected + bool bRet((a_bFail == false) ? 0 : 1); + if (bRet == 1) { + mu::console() << _T("\n ") + << _T("Expression: ") << a_str << _T(" did evaluate; Expected error:") + << a_iErrc; + } - \return 1 in case of a failure, 0 otherwise. - */ - int ParserTester::EqnTestWithVarChange(const string_type &a_str, - double a_fVar1, - double a_fRes1, - double a_fVar2, - double a_fRes2) - { - ParserTester::c_iCount++; + return bRet; +} - try - { - value_type fVal[2] = {-999, -999 }; // should be equal - - Parser p; +//--------------------------------------------------------------------------- +/** \brief Evaluate a tet expression. + + \return 1 in case of a failure, 0 otherwise. +*/ +int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1, double a_fRes1, + double a_fVar2, double a_fRes2) { + ParserTester::c_iCount++; + + try { + value_type fVal[2] = {-999, -999}; // should be equal + + Parser p; value_type var = 0; // variable - p.DefineVar( _T("a"), &var); + p.DefineVar(_T("a"), &var); p.SetExpr(a_str); var = a_fVar1; @@ -1219,334 +1157,294 @@ namespace mu var = a_fVar2; fVal[1] = p.Eval(); - - if ( fabs(a_fRes1-fVal[0]) > 0.0000000001) - throw std::runtime_error("incorrect result (first pass)"); - if ( fabs(a_fRes2-fVal[1]) > 0.0000000001) - throw std::runtime_error("incorrect result (second pass)"); - } - catch(Parser::exception_type &e) - { + if (fabs(a_fRes1 - fVal[0]) > 0.0000000001) + throw std::runtime_error("incorrect result (first pass)"); + + if (fabs(a_fRes2 - fVal[1]) > 0.0000000001) + throw std::runtime_error("incorrect result (second pass)"); + } catch (Parser::exception_type &e) { mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); return 1; - } - catch(std::exception &e) - { + } catch (std::exception &e) { mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); return 1; // always return a failure since this exception is not expected - } - catch(...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + } catch (...) { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); return 1; // exceptions other than ParserException are not allowed - } - - return 0; } - //--------------------------------------------------------------------------- - /** \brief Evaluate a tet expression. + return 0; +} - \return 1 in case of a failure, 0 otherwise. - */ - int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) - { - ParserTester::c_iCount++; - int iRet(0); - value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different +//--------------------------------------------------------------------------- +/** \brief Evaluate a tet expression. - try - { + \return 1 in case of a failure, 0 otherwise. +*/ +int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) { + ParserTester::c_iCount++; + int iRet(0); + value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different + + try { std::auto_ptr p1; - Parser p2, p3; // three parser objects - // they will be used for testing copy and assignment operators + Parser p2, p3; // three parser objects + // they will be used for testing copy and assignment operators // p1 is a pointer since i'm going to delete it in order to test if // parsers after copy construction still refer to members of it. // !! If this is the case this function will crash !! - - p1.reset(new mu::Parser()); + + p1.reset(new mu::Parser()); // Add constants - p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI); - p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E); - p1->DefineConst( _T("const"), 1); - p1->DefineConst( _T("const1"), 2); - p1->DefineConst( _T("const2"), 3); + p1->DefineConst(_T("pi"), (value_type)PARSER_CONST_PI); + p1->DefineConst(_T("e"), (value_type)PARSER_CONST_E); + p1->DefineConst(_T("const"), 1); + p1->DefineConst(_T("const1"), 2); + p1->DefineConst(_T("const2"), 3); // string constants - p1->DefineStrConst( _T("str1"), _T("1.11")); - p1->DefineStrConst( _T("str2"), _T("2.22")); + p1->DefineStrConst(_T("str1"), _T("1.11")); + p1->DefineStrConst(_T("str2"), _T("2.22")); // variables - value_type vVarVal[] = { 1, 2, 3, -2}; - p1->DefineVar( _T("a"), &vVarVal[0]); - p1->DefineVar( _T("aa"), &vVarVal[1]); - p1->DefineVar( _T("b"), &vVarVal[1]); - p1->DefineVar( _T("c"), &vVarVal[2]); - p1->DefineVar( _T("d"), &vVarVal[3]); - + value_type vVarVal[] = {1, 2, 3, -2}; + p1->DefineVar(_T("a"), &vVarVal[0]); + p1->DefineVar(_T("aa"), &vVarVal[1]); + p1->DefineVar(_T("b"), &vVarVal[1]); + p1->DefineVar(_T("c"), &vVarVal[2]); + p1->DefineVar(_T("d"), &vVarVal[3]); + // custom value ident functions - p1->AddValIdent(&ParserTester::IsHexVal); + p1->AddValIdent(&ParserTester::IsHexVal); // functions - p1->DefineFun( _T("ping"), Ping); - p1->DefineFun( _T("f1of1"), f1of1); // one parameter - p1->DefineFun( _T("f1of2"), f1of2); // two parameter - p1->DefineFun( _T("f2of2"), f2of2); - p1->DefineFun( _T("f1of3"), f1of3); // three parameter - p1->DefineFun( _T("f2of3"), f2of3); - p1->DefineFun( _T("f3of3"), f3of3); - p1->DefineFun( _T("f1of4"), f1of4); // four parameter - p1->DefineFun( _T("f2of4"), f2of4); - p1->DefineFun( _T("f3of4"), f3of4); - p1->DefineFun( _T("f4of4"), f4of4); - p1->DefineFun( _T("f1of5"), f1of5); // five parameter - p1->DefineFun( _T("f2of5"), f2of5); - p1->DefineFun( _T("f3of5"), f3of5); - p1->DefineFun( _T("f4of5"), f4of5); - p1->DefineFun( _T("f5of5"), f5of5); + p1->DefineFun(_T("ping"), Ping); + p1->DefineFun(_T("f1of1"), f1of1); // one parameter + p1->DefineFun(_T("f1of2"), f1of2); // two parameter + p1->DefineFun(_T("f2of2"), f2of2); + p1->DefineFun(_T("f1of3"), f1of3); // three parameter + p1->DefineFun(_T("f2of3"), f2of3); + p1->DefineFun(_T("f3of3"), f3of3); + p1->DefineFun(_T("f1of4"), f1of4); // four parameter + p1->DefineFun(_T("f2of4"), f2of4); + p1->DefineFun(_T("f3of4"), f3of4); + p1->DefineFun(_T("f4of4"), f4of4); + p1->DefineFun(_T("f1of5"), f1of5); // five parameter + p1->DefineFun(_T("f2of5"), f2of5); + p1->DefineFun(_T("f3of5"), f3of5); + p1->DefineFun(_T("f4of5"), f4of5); + p1->DefineFun(_T("f5of5"), f5of5); // binary operators - p1->DefineOprt( _T("add"), add, 0); - p1->DefineOprt( _T("++"), add, 0); - p1->DefineOprt( _T("&"), land, prLAND); + p1->DefineOprt(_T("add"), add, 0); + p1->DefineOprt(_T("++"), add, 0); + p1->DefineOprt(_T("&"), land, prLAND); // sample functions - p1->DefineFun( _T("min"), Min); - p1->DefineFun( _T("max"), Max); - p1->DefineFun( _T("sum"), Sum); - p1->DefineFun( _T("valueof"), ValueOf); - p1->DefineFun( _T("atof"), StrToFloat); - p1->DefineFun( _T("strfun1"), StrFun1); - p1->DefineFun( _T("strfun2"), StrFun2); - p1->DefineFun( _T("strfun3"), StrFun3); - p1->DefineFun( _T("lastArg"), LastArg); - p1->DefineFun( _T("firstArg"), FirstArg); - p1->DefineFun( _T("order"), FirstArg); + p1->DefineFun(_T("min"), Min); + p1->DefineFun(_T("max"), Max); + p1->DefineFun(_T("sum"), Sum); + p1->DefineFun(_T("valueof"), ValueOf); + p1->DefineFun(_T("atof"), StrToFloat); + p1->DefineFun(_T("strfun1"), StrFun1); + p1->DefineFun(_T("strfun2"), StrFun2); + p1->DefineFun(_T("strfun3"), StrFun3); + p1->DefineFun(_T("lastArg"), LastArg); + p1->DefineFun(_T("firstArg"), FirstArg); + p1->DefineFun(_T("order"), FirstArg); // infix / postfix operator - // Note: Identifiers used here do not have any meaning + // Note: Identifiers used here do not have any meaning // they are mere placeholders to test certain features. - p1->DefineInfixOprt( _T("$"), sign, prPOW+1); // sign with high priority - p1->DefineInfixOprt( _T("~"), plus2); // high priority - p1->DefineInfixOprt( _T("~~"), plus2); - p1->DefinePostfixOprt( _T("{m}"), Milli); - p1->DefinePostfixOprt( _T("{M}"), Mega); - p1->DefinePostfixOprt( _T("m"), Milli); - p1->DefinePostfixOprt( _T("meg"), Mega); - p1->DefinePostfixOprt( _T("#"), times3); - p1->DefinePostfixOprt( _T("'"), sqr); + p1->DefineInfixOprt(_T("$"), sign, prPOW + 1); // sign with high priority + p1->DefineInfixOprt(_T("~"), plus2); // high priority + p1->DefineInfixOprt(_T("~~"), plus2); + p1->DefinePostfixOprt(_T("{m}"), Milli); + p1->DefinePostfixOprt(_T("{M}"), Mega); + p1->DefinePostfixOprt(_T("m"), Milli); + p1->DefinePostfixOprt(_T("meg"), Mega); + p1->DefinePostfixOprt(_T("#"), times3); + p1->DefinePostfixOprt(_T("'"), sqr); p1->SetExpr(a_str); // Test bytecode integrity // String parsing and bytecode parsing must yield the same result - fVal[0] = p1->Eval(); // result from stringparsing - fVal[1] = p1->Eval(); // result from bytecode - if (fVal[0]!=fVal[1]) - throw Parser::exception_type( _T("Bytecode / string parsing mismatch.") ); + fVal[0] = p1->Eval(); // result from stringparsing + fVal[1] = p1->Eval(); // result from bytecode + if (fVal[0] != fVal[1]) + throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); // Test copy and assignment operators - try - { - // Test copy constructor - std::vector vParser; - vParser.push_back(*(p1.get())); - mu::Parser p2 = vParser[0]; // take parser from vector - - // destroy the originals from p2 - vParser.clear(); // delete the vector - p1.reset(0); + try { + // Test copy constructor + std::vector vParser; + vParser.push_back(*(p1.get())); + mu::Parser p2 = vParser[0]; // take parser from vector - fVal[2] = p2.Eval(); + // destroy the originals from p2 + vParser.clear(); // delete the vector + p1.reset(0); - // Test assignment operator - // additionally disable Optimizer this time - mu::Parser p3; - p3 = p2; - p3.EnableOptimizer(false); - fVal[3] = p3.Eval(); + fVal[2] = p2.Eval(); - // Test Eval function for multiple return values - // use p2 since it has the optimizer enabled! - int nNum; - value_type *v = p2.Eval(nNum); - fVal[4] = v[nNum-1]; - } - catch(std::exception &e) - { - mu::console() << _T("\n ") << e.what() << _T("\n"); + // Test assignment operator + // additionally disable Optimizer this time + mu::Parser p3; + p3 = p2; + p3.EnableOptimizer(false); + fVal[3] = p3.Eval(); + + // Test Eval function for multiple return values + // use p2 since it has the optimizer enabled! + int nNum; + value_type *v = p2.Eval(nNum); + fVal[4] = v[nNum - 1]; + } catch (std::exception &e) { + mu::console() << _T("\n ") << e.what() << _T("\n"); } // limited floating point accuracy requires the following test bool bCloseEnough(true); - for (unsigned i=0; i::has_infinity) - #pragma warning(pop) - { - bCloseEnough &= (fabs(fVal[i]) != numeric_limits::infinity()); - } - } +// The tests equations never result in infinity, if they do thats a bug. +// reference: +// http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825 +#pragma warning(push) +#pragma warning(disable : 4127) + if (std::numeric_limits::has_infinity) +#pragma warning(pop) + { + bCloseEnough &= (fabs(fVal[i]) != numeric_limits::infinity()); + } + } iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; - - - if (iRet==1) - { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: ") << a_fRes - << _T(" ;calculated: ") << fVal[0] << _T(",") - << fVal[1] << _T(",") - << fVal[2] << _T(",") - << fVal[3] << _T(",") - << fVal[4] << _T(")."); + + if (iRet == 1) { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: ") << a_fRes << _T(" ;calculated: ") + << fVal[0] << _T(",") << fVal[1] << _T(",") << fVal[2] << _T(",") + << fVal[3] << _T(",") << fVal[4] << _T(")."); } - } - catch(Parser::exception_type &e) - { - if (a_fPass) - { - if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998) - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)"); - else - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); - return 1; + } catch (Parser::exception_type &e) { + if (a_fPass) { + if (fVal[0] != fVal[2] && fVal[0] != -999 && fVal[1] != -998) + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)"); + else + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() + << _T(")"); + return 1; } - } - catch(std::exception &e) - { + } catch (std::exception &e) { mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")"); return 1; // always return a failure since this exception is not expected - } - catch(...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + } catch (...) { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); return 1; // exceptions other than ParserException are not allowed - } - - return iRet; } - //--------------------------------------------------------------------------- - int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass) - { - ParserTester::c_iCount++; + return iRet; +} - value_type vVarVal[] = {1, 2, 3}; // variable values - int iRet(0); +//--------------------------------------------------------------------------- +int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass) { + ParserTester::c_iCount++; - try - { - value_type fVal[2] = {-99, -999}; // results: initially should be different + value_type vVarVal[] = {1, 2, 3}; // variable values + int iRet(0); + + try { + value_type fVal[2] = {-99, -999}; // results: initially should be different ParserInt p; - p.DefineConst( _T("const1"), 1); - p.DefineConst( _T("const2"), 2); - p.DefineVar( _T("a"), &vVarVal[0]); - p.DefineVar( _T("b"), &vVarVal[1]); - p.DefineVar( _T("c"), &vVarVal[2]); + p.DefineConst(_T("const1"), 1); + p.DefineConst(_T("const2"), 2); + p.DefineVar(_T("a"), &vVarVal[0]); + p.DefineVar(_T("b"), &vVarVal[1]); + p.DefineVar(_T("c"), &vVarVal[2]); p.SetExpr(a_str); - fVal[0] = p.Eval(); // result from stringparsing - fVal[1] = p.Eval(); // result from bytecode + fVal[0] = p.Eval(); // result from stringparsing + fVal[1] = p.Eval(); // result from bytecode - if (fVal[0]!=fVal[1]) - throw Parser::exception_type( _T("Bytecode corrupt.") ); + if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt.")); - iRet = ( (a_fRes==fVal[0] && a_fPass) || - (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1; - if (iRet==1) - { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: ") << a_fRes - << _T(" ;calculated: ") << fVal[0]<< _T(")."); + iRet = ((a_fRes == fVal[0] && a_fPass) || (a_fRes != fVal[0] && !a_fPass)) ? 0 : 1; + if (iRet == 1) { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: ") << a_fRes << _T(" ;calculated: ") + << fVal[0] << _T(")."); } - } - catch(Parser::exception_type &e) - { - if (a_fPass) - { - mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); - iRet = 1; + } catch (Parser::exception_type &e) { + if (a_fPass) { + mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + iRet = 1; } - } - catch(...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + } catch (...) { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); iRet = 1; // exceptions other than ParserException are not allowed - } - - return iRet; } - //--------------------------------------------------------------------------- - /** \brief Test an expression in Bulk Mode. */ - int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass) - { - ParserTester::c_iCount++; + return iRet; +} - // Define Bulk Variables - int nBulkSize = 4; - value_type vVariableA[] = { 1, 2, 3, 4 }; // variable values - value_type vVariableB[] = { 2, 2, 2, 2 }; // variable values - value_type vVariableC[] = { 3, 3, 3, 3 }; // variable values - value_type vResults[] = { 0, 0, 0, 0 }; // variable values - int iRet(0); +//--------------------------------------------------------------------------- +/** \brief Test an expression in Bulk Mode. */ +int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass) { + ParserTester::c_iCount++; - try - { - Parser p; - p.DefineConst(_T("const1"), 1); - p.DefineConst(_T("const2"), 2); - p.DefineVar(_T("a"), vVariableA); - p.DefineVar(_T("b"), vVariableB); - p.DefineVar(_T("c"), vVariableC); + // Define Bulk Variables + int nBulkSize = 4; + value_type vVariableA[] = {1, 2, 3, 4}; // variable values + value_type vVariableB[] = {2, 2, 2, 2}; // variable values + value_type vVariableC[] = {3, 3, 3, 3}; // variable values + value_type vResults[] = {0, 0, 0, 0}; // variable values + int iRet(0); - p.SetExpr(a_str); - p.Eval(vResults, nBulkSize); + try { + Parser p; + p.DefineConst(_T("const1"), 1); + p.DefineConst(_T("const2"), 2); + p.DefineVar(_T("a"), vVariableA); + p.DefineVar(_T("b"), vVariableB); + p.DefineVar(_T("c"), vVariableC); - bool bCloseEnough(true); - for (int i = 0; i < nBulkSize; ++i) - { - bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001)); - } + p.SetExpr(a_str); + p.Eval(vResults, nBulkSize); - iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; - if (iRet == 1) - { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}") - << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}"); - } - } - catch (Parser::exception_type &e) - { - if (a_fPass) - { - mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); - iRet = 1; - } - } - catch (...) - { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); - iRet = 1; // exceptions other than ParserException are not allowed + bool bCloseEnough(true); + for (int i = 0; i < nBulkSize; ++i) { + bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001)); } - return iRet; + iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; + if (iRet == 1) { + mu::console() << _T("\n fail: ") << a_str.c_str() + << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") + << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}") + << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] + << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}"); + } + } catch (Parser::exception_type &e) { + if (a_fPass) { + mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + iRet = 1; + } + } catch (...) { + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); + iRet = 1; // exceptions other than ParserException are not allowed } - //--------------------------------------------------------------------------- - /** \brief Internal error in test class Test is going to be aborted. */ - void ParserTester::Abort() const - { - mu::console() << _T("Test failed (internal error in test class)") << endl; - while (!getchar()); - exit(-1); - } - } // namespace test -} // namespace mu + return iRet; +} + +//--------------------------------------------------------------------------- +/** \brief Internal error in test class Test is going to be aborted. */ +void ParserTester::Abort() const { + mu::console() << _T("Test failed (internal error in test class)") << endl; + while (!getchar()) + ; + exit(-1); +} +} // namespace test +} // namespace mu diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 4d49f5e52..234d54a83 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -1,26 +1,26 @@ /* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ + __________ + _____ __ __\______ \_____ _______ ______ ____ _______ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ + |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| + \/ \/ \/ \/ Copyright (C) 2013 Ingo Berg - Permission is hereby granted, free of charge, to any person obtaining a copy of this + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all copies or + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include @@ -29,768 +29,681 @@ #include #include -#include "muParserTokenReader.h" #include "muParserBase.h" +#include "muParserTokenReader.h" /** \file \brief This file contains the parser token reader implementation. */ +namespace mu { -namespace mu -{ +// Forward declaration +class ParserBase; - // Forward declaration - class ParserBase; +//--------------------------------------------------------------------------- +/** \brief Copy constructor. - //--------------------------------------------------------------------------- - /** \brief Copy constructor. + \sa Assign + \throw nothrow +*/ +ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) { Assign(a_Reader); } - \sa Assign - \throw nothrow - */ - ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) - { - Assign(a_Reader); - } - - //--------------------------------------------------------------------------- - /** \brief Assignment operator. +//--------------------------------------------------------------------------- +/** \brief Assignment operator. - Self assignment will be suppressed otherwise #Assign is called. + Self assignment will be suppressed otherwise #Assign is called. - \param a_Reader Object to copy to this token reader. - \throw nothrow - */ - ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader) - { - if (&a_Reader!=this) - Assign(a_Reader); + \param a_Reader Object to copy to this token reader. + \throw nothrow +*/ +ParserTokenReader &ParserTokenReader::operator=(const ParserTokenReader &a_Reader) { + if (&a_Reader != this) Assign(a_Reader); return *this; - } +} - //--------------------------------------------------------------------------- - /** \brief Assign state of a token reader to this token reader. - - \param a_Reader Object from which the state should be copied. - \throw nothrow - */ - void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) - { +//--------------------------------------------------------------------------- +/** \brief Assign state of a token reader to this token reader. + + \param a_Reader Object from which the state should be copied. + \throw nothrow +*/ +void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) { m_pParser = a_Reader.m_pParser; m_strFormula = a_Reader.m_strFormula; m_iPos = a_Reader.m_iPos; m_iSynFlags = a_Reader.m_iSynFlags; - - m_UsedVar = a_Reader.m_UsedVar; - m_pFunDef = a_Reader.m_pFunDef; - m_pConstDef = a_Reader.m_pConstDef; - m_pVarDef = a_Reader.m_pVarDef; - m_pStrVarDef = a_Reader.m_pStrVarDef; - m_pPostOprtDef = a_Reader.m_pPostOprtDef; - m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; - m_pOprtDef = a_Reader.m_pOprtDef; + + m_UsedVar = a_Reader.m_UsedVar; + m_pFunDef = a_Reader.m_pFunDef; + m_pConstDef = a_Reader.m_pConstDef; + m_pVarDef = a_Reader.m_pVarDef; + m_pStrVarDef = a_Reader.m_pStrVarDef; + m_pPostOprtDef = a_Reader.m_pPostOprtDef; + m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; + m_pOprtDef = a_Reader.m_pOprtDef; m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar; - m_vIdentFun = a_Reader.m_vIdentFun; - m_pFactory = a_Reader.m_pFactory; - m_pFactoryData = a_Reader.m_pFactoryData; - m_iBrackets = a_Reader.m_iBrackets; - m_cArgSep = a_Reader.m_cArgSep; - m_fZero = a_Reader.m_fZero; - m_lastTok = a_Reader.m_lastTok; - } + m_vIdentFun = a_Reader.m_vIdentFun; + m_pFactory = a_Reader.m_pFactory; + m_pFactoryData = a_Reader.m_pFactoryData; + m_iBrackets = a_Reader.m_iBrackets; + m_cArgSep = a_Reader.m_cArgSep; + m_fZero = a_Reader.m_fZero; + m_lastTok = a_Reader.m_lastTok; +} - //--------------------------------------------------------------------------- - /** \brief Constructor. - - Create a Token reader and bind it to a parser object. +//--------------------------------------------------------------------------- +/** \brief Constructor. - \pre [assert] a_pParser may not be NULL - \post #m_pParser==a_pParser - \param a_pParent Parent parser object of the token reader. - */ - ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) - :m_pParser(a_pParent) - ,m_strFormula() - ,m_iPos(0) - ,m_iSynFlags(0) - ,m_bIgnoreUndefVar(false) - ,m_pFunDef(NULL) - ,m_pPostOprtDef(NULL) - ,m_pInfixOprtDef(NULL) - ,m_pOprtDef(NULL) - ,m_pConstDef(NULL) - ,m_pStrVarDef(NULL) - ,m_pVarDef(NULL) - ,m_pFactory(NULL) - ,m_pFactoryData(NULL) - ,m_vIdentFun() - ,m_UsedVar() - ,m_fZero(0) - ,m_iBrackets(0) - ,m_lastTok() - ,m_cArgSep(',') - { + Create a Token reader and bind it to a parser object. + + \pre [assert] a_pParser may not be NULL + \post #m_pParser==a_pParser + \param a_pParent Parent parser object of the token reader. +*/ +ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) + : m_pParser(a_pParent), + m_strFormula(), + m_iPos(0), + m_iSynFlags(0), + m_bIgnoreUndefVar(false), + m_pFunDef(NULL), + m_pPostOprtDef(NULL), + m_pInfixOprtDef(NULL), + m_pOprtDef(NULL), + m_pConstDef(NULL), + m_pStrVarDef(NULL), + m_pVarDef(NULL), + m_pFactory(NULL), + m_pFactoryData(NULL), + m_vIdentFun(), + m_UsedVar(), + m_fZero(0), + m_iBrackets(0), + m_lastTok(), + m_cArgSep(',') { assert(m_pParser); SetParent(m_pParser); - } - - //--------------------------------------------------------------------------- - /** \brief Create instance of a ParserTokenReader identical with this - and return its pointer. +} - This is a factory method the calling function must take care of the object destruction. +//--------------------------------------------------------------------------- +/** \brief Create instance of a ParserTokenReader identical with this + and return its pointer. - \return A new ParserTokenReader object. - \throw nothrow - */ - ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const - { + This is a factory method the calling function must take care of the object destruction. + + \return A new ParserTokenReader object. + \throw nothrow +*/ +ParserTokenReader *ParserTokenReader::Clone(ParserBase *a_pParent) const { std::auto_ptr ptr(new ParserTokenReader(*this)); ptr->SetParent(a_pParent); return ptr.release(); - } +} - //--------------------------------------------------------------------------- - ParserTokenReader::token_type& ParserTokenReader::SaveBeforeReturn(const token_type &tok) - { +//--------------------------------------------------------------------------- +ParserTokenReader::token_type &ParserTokenReader::SaveBeforeReturn(const token_type &tok) { m_lastTok = tok; return m_lastTok; - } +} - //--------------------------------------------------------------------------- - void ParserTokenReader::AddValIdent(identfun_type a_pCallback) - { +//--------------------------------------------------------------------------- +void ParserTokenReader::AddValIdent(identfun_type a_pCallback) { // Use push_front is used to give user defined callbacks a higher priority than // the built in ones. Otherwise reading hex numbers would not work - // since the "0" in "0xff" would always be read first making parsing of + // since the "0" in "0xff" would always be read first making parsing of // the rest impossible. // reference: // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/4824956 m_vIdentFun.push_front(a_pCallback); - } +} - //--------------------------------------------------------------------------- - void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData) - { +//--------------------------------------------------------------------------- +void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData) { m_pFactory = a_pFactory; m_pFactoryData = pUserData; - } +} - //--------------------------------------------------------------------------- - /** \brief Return the current position of the token reader in the formula string. +//--------------------------------------------------------------------------- +/** \brief Return the current position of the token reader in the formula string. - \return #m_iPos - \throw nothrow - */ - int ParserTokenReader::GetPos() const - { - return m_iPos; - } + \return #m_iPos + \throw nothrow +*/ +int ParserTokenReader::GetPos() const { return m_iPos; } - //--------------------------------------------------------------------------- - /** \brief Return a reference to the formula. +//--------------------------------------------------------------------------- +/** \brief Return a reference to the formula. - \return #m_strFormula - \throw nothrow - */ - const string_type& ParserTokenReader::GetExpr() const - { - return m_strFormula; - } + \return #m_strFormula + \throw nothrow +*/ +const string_type &ParserTokenReader::GetExpr() const { return m_strFormula; } - //--------------------------------------------------------------------------- - /** \brief Return a map containing the used variables only. */ - varmap_type& ParserTokenReader::GetUsedVar() - { - return m_UsedVar; - } +//--------------------------------------------------------------------------- +/** \brief Return a map containing the used variables only. */ +varmap_type &ParserTokenReader::GetUsedVar() { return m_UsedVar; } - //--------------------------------------------------------------------------- - /** \brief Initialize the token Reader. - - Sets the formula position index to zero and set Syntax flags to default for initial formula parsing. - \pre [assert] triggered if a_szFormula==0 - */ - void ParserTokenReader::SetFormula(const string_type &a_strFormula) - { +//--------------------------------------------------------------------------- +/** \brief Initialize the token Reader. + + Sets the formula position index to zero and set Syntax flags to default for initial formula + parsing. + \pre [assert] triggered if a_szFormula==0 +*/ +void ParserTokenReader::SetFormula(const string_type &a_strFormula) { m_strFormula = a_strFormula; ReInit(); - } +} - //--------------------------------------------------------------------------- - /** \brief Set Flag that controls behaviour in case of undefined variables being found. - - If true, the parser does not throw an exception if an undefined variable is found. - otherwise it does. This variable is used internally only! - It suppresses a "undefined variable" exception in GetUsedVar(). - Those function should return a complete list of variables including - those the are not defined by the time of it's call. - */ - void ParserTokenReader::IgnoreUndefVar(bool bIgnore) - { - m_bIgnoreUndefVar = bIgnore; - } +//--------------------------------------------------------------------------- +/** \brief Set Flag that controls behaviour in case of undefined variables being found. - //--------------------------------------------------------------------------- - /** \brief Reset the token reader to the start of the formula. + If true, the parser does not throw an exception if an undefined variable is found. + otherwise it does. This variable is used internally only! + It suppresses a "undefined variable" exception in GetUsedVar(). + Those function should return a complete list of variables including + those the are not defined by the time of it's call. +*/ +void ParserTokenReader::IgnoreUndefVar(bool bIgnore) { m_bIgnoreUndefVar = bIgnore; } - The syntax flags will be reset to a value appropriate for the - start of a formula. - \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR - \throw nothrow - \sa ESynCodes - */ - void ParserTokenReader::ReInit() - { +//--------------------------------------------------------------------------- +/** \brief Reset the token reader to the start of the formula. + + The syntax flags will be reset to a value appropriate for the + start of a formula. + \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR + \throw nothrow + \sa ESynCodes +*/ +void ParserTokenReader::ReInit() { m_iPos = 0; m_iSynFlags = sfSTART_OF_LINE; m_iBrackets = 0; m_UsedVar.clear(); m_lastTok = token_type(); - } +} - //--------------------------------------------------------------------------- - /** \brief Read the next token from the string. */ - ParserTokenReader::token_type ParserTokenReader::ReadNextToken() - { +//--------------------------------------------------------------------------- +/** \brief Read the next token from the string. */ +ParserTokenReader::token_type ParserTokenReader::ReadNextToken() { assert(m_pParser); const char_type *szFormula = m_strFormula.c_str(); token_type tok; // Ignore all non printable characters when reading the expression - while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20) - ++m_iPos; + while (szFormula[m_iPos] > 0 && szFormula[m_iPos] <= 0x20) ++m_iPos; - if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula - if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator - if ( IsFunTok(tok) ) return SaveBeforeReturn(tok); // Check for function token - if ( IsBuiltIn(tok) ) return SaveBeforeReturn(tok); // Check built in operators / tokens - if ( IsArgSep(tok) ) return SaveBeforeReturn(tok); // Check for function argument separators - if ( IsValTok(tok) ) return SaveBeforeReturn(tok); // Check for values / constant tokens - if ( IsVarTok(tok) ) return SaveBeforeReturn(tok); // Check for variable tokens - if ( IsStrVarTok(tok) ) return SaveBeforeReturn(tok); // Check for string variables - if ( IsString(tok) ) return SaveBeforeReturn(tok); // Check for String tokens - if ( IsInfixOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators - if ( IsPostOpTok(tok) ) return SaveBeforeReturn(tok); // Check for unary operators + if (IsEOF(tok)) return SaveBeforeReturn(tok); // Check for end of formula + if (IsOprt(tok)) return SaveBeforeReturn(tok); // Check for user defined binary operator + if (IsFunTok(tok)) return SaveBeforeReturn(tok); // Check for function token + if (IsBuiltIn(tok)) return SaveBeforeReturn(tok); // Check built in operators / tokens + if (IsArgSep(tok)) return SaveBeforeReturn(tok); // Check for function argument separators + if (IsValTok(tok)) return SaveBeforeReturn(tok); // Check for values / constant tokens + if (IsVarTok(tok)) return SaveBeforeReturn(tok); // Check for variable tokens + if (IsStrVarTok(tok)) return SaveBeforeReturn(tok); // Check for string variables + if (IsString(tok)) return SaveBeforeReturn(tok); // Check for String tokens + if (IsInfixOpTok(tok)) return SaveBeforeReturn(tok); // Check for unary operators + if (IsPostOpTok(tok)) return SaveBeforeReturn(tok); // Check for unary operators - // Check String for undefined variable token. Done only if a + // Check String for undefined variable token. Done only if a // flag is set indicating to ignore undefined variables. - // This is a way to conditionally avoid an error if - // undefined variables occur. + // This is a way to conditionally avoid an error if + // undefined variables occur. // (The GetUsedVar function must suppress the error for - // undefined variables in order to collect all variable + // undefined variables in order to collect all variable // names including the undefined ones.) - if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) - return SaveBeforeReturn(tok); + if ((m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok)) return SaveBeforeReturn(tok); // Check for unknown token - // + // // !!! From this point on there is no exit without an exception possible... - // + // string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd!=m_iPos) - Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + if (iEnd != m_iPos) Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); - return token_type(); // never reached - } + return token_type(); // never reached +} - //--------------------------------------------------------------------------- - void ParserTokenReader::SetParent(ParserBase *a_pParent) - { - m_pParser = a_pParent; - m_pFunDef = &a_pParent->m_FunDef; - m_pOprtDef = &a_pParent->m_OprtDef; +//--------------------------------------------------------------------------- +void ParserTokenReader::SetParent(ParserBase *a_pParent) { + m_pParser = a_pParent; + m_pFunDef = &a_pParent->m_FunDef; + m_pOprtDef = &a_pParent->m_OprtDef; m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; - m_pPostOprtDef = &a_pParent->m_PostOprtDef; - m_pVarDef = &a_pParent->m_VarDef; - m_pStrVarDef = &a_pParent->m_StrVarDef; - m_pConstDef = &a_pParent->m_ConstDef; - } + m_pPostOprtDef = &a_pParent->m_PostOprtDef; + m_pVarDef = &a_pParent->m_VarDef; + m_pStrVarDef = &a_pParent->m_StrVarDef; + m_pConstDef = &a_pParent->m_ConstDef; +} - //--------------------------------------------------------------------------- - /** \brief Extract all characters that belong to a certain charset. +//--------------------------------------------------------------------------- +/** \brief Extract all characters that belong to a certain charset. - \param a_szCharSet [in] Const char array of the characters allowed in the token. - \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. - \param a_iPos [in] Position in the string from where to start reading. - \return The Position of the first character not listed in a_szCharSet. - \throw nothrow - */ - int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, - string_type &a_sTok, - int a_iPos) const - { + \param a_szCharSet [in] Const char array of the characters allowed in the token. + \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. + \param a_iPos [in] Position in the string from where to start reading. + \return The Position of the first character not listed in a_szCharSet. + \throw nothrow +*/ +int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, string_type &a_sTok, + int a_iPos) const { int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos); - if (iEnd==(int)string_type::npos) - iEnd = (int)m_strFormula.length(); - + if (iEnd == (int)string_type::npos) iEnd = (int)m_strFormula.length(); + // Assign token string if there was something found - if (a_iPos!=iEnd) - a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd); + if (a_iPos != iEnd) + a_sTok = string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); return iEnd; - } +} - //--------------------------------------------------------------------------- - /** \brief Check Expression for the presence of a binary operator token. - - Userdefined binary operator "++" gives inconsistent parsing result for - the equations "a++b" and "a ++ b" if alphabetic characters are allowed - in operator tokens. To avoid this this function checks specifically - for operator tokens. - */ - int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, - int a_iPos) const - { +//--------------------------------------------------------------------------- +/** \brief Check Expression for the presence of a binary operator token. + + Userdefined binary operator "++" gives inconsistent parsing result for + the equations "a++b" and "a ++ b" if alphabetic characters are allowed + in operator tokens. To avoid this this function checks specifically + for operator tokens. +*/ +int ParserTokenReader::ExtractOperatorToken(string_type &a_sTok, int a_iPos) const { // Changed as per Issue 6: https://code.google.com/p/muparser/issues/detail?id=6 int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidOprtChars(), a_iPos); - if (iEnd==(int)string_type::npos) - iEnd = (int)m_strFormula.length(); + if (iEnd == (int)string_type::npos) iEnd = (int)m_strFormula.length(); // Assign token string if there was something found - if (a_iPos!=iEnd) - { - a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); - return iEnd; + if (a_iPos != iEnd) { + a_sTok = string_type(m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd); + return iEnd; + } else { + // There is still the chance of having to deal with an operator consisting exclusively + // of alphabetic characters. + return ExtractToken(MUP_CHARS, a_sTok, a_iPos); } - else - { - // There is still the chance of having to deal with an operator consisting exclusively - // of alphabetic characters. - return ExtractToken(MUP_CHARS, a_sTok, a_iPos); - } - } +} - //--------------------------------------------------------------------------- - /** \brief Check if a built in operator or other token can be found - \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. - \return true if an operator token has been found. - */ - bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) - { +//--------------------------------------------------------------------------- +/** \brief Check if a built in operator or other token can be found + \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an + infix operator token. + \return true if an operator token has been found. +*/ +bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { const char_type **const pOprtDef = m_pParser->GetOprtDef(), - *const szFormula = m_strFormula.c_str(); + *const szFormula = m_strFormula.c_str(); // Compare token with function and operator strings // check string for operator/function - for (int i=0; pOprtDef[i]; i++) - { - std::size_t len( std::char_traits::length(pOprtDef[i]) ); - if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) ) - { - switch(i) - { - //case cmAND: - //case cmOR: - //case cmXOR: - case cmLAND: - case cmLOR: - case cmLT: - case cmGT: - case cmLE: - case cmGE: - case cmNEQ: - case cmEQ: - case cmADD: - case cmSUB: - case cmMUL: - case cmDIV: - case cmPOW: - case cmASSIGN: - //if (len!=sTok.length()) - // continue; + for (int i = 0; pOprtDef[i]; i++) { + std::size_t len(std::char_traits::length(pOprtDef[i])); + if (string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len)) { + switch (i) { + // case cmAND: + // case cmOR: + // case cmXOR: + case cmLAND: + case cmLOR: + case cmLT: + case cmGT: + case cmLE: + case cmGE: + case cmNEQ: + case cmEQ: + case cmADD: + case cmSUB: + case cmMUL: + case cmDIV: + case cmPOW: + case cmASSIGN: + // if (len!=sTok.length()) + // continue; - // The assignment operator need special treatment - if (i==cmASSIGN && m_iSynFlags & noASSIGN) - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + // The assignment operator need special treatment + if (i == cmASSIGN && m_iSynFlags & noASSIGN) + Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); - if (!m_pParser->HasBuiltInOprt()) continue; - if (m_iSynFlags & noOPT) - { - // Maybe its an infix operator not an operator - // Both operator types can share characters in - // their identifiers - if ( IsInfixOpTok(a_Tok) ) - return true; + if (!m_pParser->HasBuiltInOprt()) continue; + if (m_iSynFlags & noOPT) { + // Maybe its an infix operator not an operator + // Both operator types can share characters in + // their identifiers + if (IsInfixOpTok(a_Tok)) return true; - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); - } + Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + } - m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND; - break; + m_iSynFlags = + noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE | noEND; + break; - case cmBO: - if (m_iSynFlags & noBO) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - - if (m_lastTok.GetCode()==cmFUNC) - m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; - else - m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN| noIF | noELSE; + case cmBO: + if (m_iSynFlags & noBO) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - ++m_iBrackets; - break; + if (m_lastTok.GetCode() == cmFUNC) + m_iSynFlags = + noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; + else + m_iSynFlags = + noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE; - case cmBC: - if (m_iSynFlags & noBC) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + ++m_iBrackets; + break; - m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; + case cmBC: + if (m_iSynFlags & noBC) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - if (--m_iBrackets<0) - Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); - break; + m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; - case cmELSE: - if (m_iSynFlags & noELSE) - Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + if (--m_iBrackets < 0) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + break; - m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; - break; + case cmELSE: + if (m_iSynFlags & noELSE) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); - case cmIF: - if (m_iSynFlags & noIF) - Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; + break; - m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; - break; + case cmIF: + if (m_iSynFlags & noIF) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); - default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... - assert(0 && "missing operator in muParser"); - } // switch operator id + m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; + break; + + default: // The operator is listed in c_DefaultOprt, but not here. This is a bad + // thing... + assert(0 && "missing operator in muParser"); + } // switch operator id + + m_iPos += (int)len; + a_Tok.Set((ECmdCode)i, pOprtDef[i]); + return true; + } // if operator string found + } // end of for all operator strings - m_iPos += (int)len; - a_Tok.Set( (ECmdCode)i, pOprtDef[i] ); - return true; - } // if operator string found - } // end of for all operator strings - return false; - } +} - //--------------------------------------------------------------------------- - bool ParserTokenReader::IsArgSep(token_type &a_Tok) - { - const char_type* szFormula = m_strFormula.c_str(); +//--------------------------------------------------------------------------- +bool ParserTokenReader::IsArgSep(token_type &a_Tok) { + const char_type *szFormula = m_strFormula.c_str(); - if (szFormula[m_iPos]==m_cArgSep) - { - // copy the separator into null terminated string - char_type szSep[2]; - szSep[0] = m_cArgSep; - szSep[1] = 0; + if (szFormula[m_iPos] == m_cArgSep) { + // copy the separator into null terminated string + char_type szSep[2]; + szSep[0] = m_cArgSep; + szSep[1] = 0; - if (m_iSynFlags & noARG_SEP) - Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); + if (m_iSynFlags & noARG_SEP) Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); - m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; - m_iPos++; - a_Tok.Set(cmARG_SEP, szSep); - return true; + m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; + m_iPos++; + a_Tok.Set(cmARG_SEP, szSep); + return true; } return false; - } +} - //--------------------------------------------------------------------------- - /** \brief Check for End of Formula. +//--------------------------------------------------------------------------- +/** \brief Check for End of Formula. - \return true if an end of formula is found false otherwise. - \param a_Tok [out] If an eof is found the corresponding token will be stored there. - \throw nothrow - \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok - */ - bool ParserTokenReader::IsEOF(token_type &a_Tok) - { - const char_type* szFormula = m_strFormula.c_str(); + \return true if an end of formula is found false otherwise. + \param a_Tok [out] If an eof is found the corresponding token will be stored there. + \throw nothrow + \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok +*/ +bool ParserTokenReader::IsEOF(token_type &a_Tok) { + const char_type *szFormula = m_strFormula.c_str(); // check for EOF - if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) - { - if ( m_iSynFlags & noEND ) - Error(ecUNEXPECTED_EOF, m_iPos); + if (!szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) { + if (m_iSynFlags & noEND) Error(ecUNEXPECTED_EOF, m_iPos); - if (m_iBrackets>0) - Error(ecMISSING_PARENS, m_iPos, _T(")")); + if (m_iBrackets > 0) Error(ecMISSING_PARENS, m_iPos, _T(")")); - m_iSynFlags = 0; - a_Tok.Set(cmEND); - return true; + m_iSynFlags = 0; + a_Tok.Set(cmEND); + return true; } return false; - } +} - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a unary infix operator. - \return true if a function token has been found false otherwise. - */ - bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) - { +//--------------------------------------------------------------------------- +/** \brief Check if a string position contains a unary infix operator. + \return true if a function token has been found false otherwise. +*/ +bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) { string_type sTok; int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos); - if (iEnd==m_iPos) - return false; + if (iEnd == m_iPos) return false; // iterate over all postfix operator strings funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin(); - for ( ; it!=m_pInfixOprtDef->rend(); ++it) - { - if (sTok.find(it->first)!=0) - continue; + for (; it != m_pInfixOprtDef->rend(); ++it) { + if (sTok.find(it->first) != 0) continue; - a_Tok.Set(it->second, it->first); - m_iPos += (int)it->first.length(); + a_Tok.Set(it->second, it->first); + m_iPos += (int)it->first.length(); - if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + if (m_iSynFlags & noINFIXOP) Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; - return true; + m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; + return true; } return false; -/* - a_Tok.Set(item->second, sTok); - m_iPos = (int)iEnd; + /* + a_Tok.Set(item->second, sTok); + m_iPos = (int)iEnd; - if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + if (m_iSynFlags & noINFIXOP) + Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; - return true; + m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; + return true; + */ +} + +//--------------------------------------------------------------------------- +/** \brief Check whether the token at a given position is a function token. + \param a_Tok [out] If a value token is found it will be placed here. + \throw ParserException if Syntaxflags do not allow a function at a_iPos + \return true if a function token has been found false otherwise. + \pre [assert] m_pParser!=0 */ - } - - //--------------------------------------------------------------------------- - /** \brief Check whether the token at a given position is a function token. - \param a_Tok [out] If a value token is found it will be placed here. - \throw ParserException if Syntaxflags do not allow a function at a_iPos - \return true if a function token has been found false otherwise. - \pre [assert] m_pParser!=0 - */ - bool ParserTokenReader::IsFunTok(token_type &a_Tok) - { +bool ParserTokenReader::IsFunTok(token_type &a_Tok) { string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; + if (iEnd == m_iPos) return false; funmap_type::const_iterator item = m_pFunDef->find(strTok); - if (item==m_pFunDef->end()) - return false; + if (item == m_pFunDef->end()) return false; // Check if the next sign is an opening bracket const char_type *szFormula = m_strFormula.c_str(); - if (szFormula[iEnd]!='(') - return false; + if (szFormula[iEnd] != '(') return false; a_Tok.Set(item->second, strTok); m_iPos = (int)iEnd; if (m_iSynFlags & noFUN) - Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); + Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); m_iSynFlags = noANY ^ noBO; return true; - } +} - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a binary operator. - \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. - \return true if an operator token has been found. - */ - bool ParserTokenReader::IsOprt(token_type &a_Tok) - { +//--------------------------------------------------------------------------- +/** \brief Check if a string position contains a binary operator. + \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an + infix operator token. + \return true if an operator token has been found. +*/ +bool ParserTokenReader::IsOprt(token_type &a_Tok) { const char_type *const szExpr = m_strFormula.c_str(); string_type strTok; int iEnd = ExtractOperatorToken(strTok, m_iPos); - if (iEnd==m_iPos) - return false; + if (iEnd == m_iPos) return false; // Check if the operator is a built in operator, if so ignore it here const char_type **const pOprtDef = m_pParser->GetOprtDef(); - for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i) - { - if (string_type(pOprtDef[i])==strTok) - return false; + for (int i = 0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i) { + if (string_type(pOprtDef[i]) == strTok) return false; } // Note: // All tokens in oprt_bin_maptype are have been sorted by their length // Long operators must come first! Otherwise short names (like: "add") that - // are part of long token names (like: "add123") will be found instead + // are part of long token names (like: "add123") will be found instead // of the long ones. // Length sorting is done with ascending length so we use a reverse iterator here. funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin(); - for ( ; it!=m_pOprtDef->rend(); ++it) - { - const string_type &sID = it->first; - if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) ) - { - a_Tok.Set(it->second, strTok); + for (; it != m_pOprtDef->rend(); ++it) { + const string_type &sID = it->first; + if (sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length())) { + a_Tok.Set(it->second, strTok); - // operator was found - if (m_iSynFlags & noOPT) - { - // An operator was found but is not expected to occur at - // this position of the formula, maybe it is an infix - // operator, not a binary operator. Both operator types - // can share characters in their identifiers. - if ( IsInfixOpTok(a_Tok) ) + // operator was found + if (m_iSynFlags & noOPT) { + // An operator was found but is not expected to occur at + // this position of the formula, maybe it is an infix + // operator, not a binary operator. Both operator types + // can share characters in their identifiers. + if (IsInfixOpTok(a_Tok)) + return true; + else { + // nope, no infix operator + return false; + // Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + } + } + + m_iPos += (int)sID.length(); + m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN; return true; - else - { - // nope, no infix operator - return false; - //Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); - } - } - - m_iPos += (int)sID.length(); - m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noEND | noASSIGN; - return true; - } } return false; - } +} - //--------------------------------------------------------------------------- - /** \brief Check if a string position contains a unary post value operator. */ - bool ParserTokenReader::IsPostOpTok(token_type &a_Tok) - { +//--------------------------------------------------------------------------- +/** \brief Check if a string position contains a unary post value operator. */ +bool ParserTokenReader::IsPostOpTok(token_type &a_Tok) { // Do not check for postfix operators if they are not allowed at // the current expression index. // - // This will fix the bug reported here: + // This will fix the bug reported here: // // http://sourceforge.net/tracker/index.php?func=detail&aid=3343891&group_id=137191&atid=737979 // - if (m_iSynFlags & noPOSTOP) - return false; + if (m_iSynFlags & noPOSTOP) return false; // // Tricky problem with equations like "3m+5": - // m is a postfix operator, + is a valid sign for postfix operators and - // for binary operators parser detects "m+" as operator string and + // m is a postfix operator, + is a valid sign for postfix operators and + // for binary operators parser detects "m+" as operator string and // finds no matching postfix operator. - // + // // This is a special case so this routine slightly differs from the other // token readers. - + // Test if there could be a postfix operator string_type sTok; int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos); - if (iEnd==m_iPos) - return false; + if (iEnd == m_iPos) return false; // iterate over all postfix operator strings funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin(); - for ( ; it!=m_pPostOprtDef->rend(); ++it) - { - if (sTok.find(it->first)!=0) - continue; + for (; it != m_pPostOprtDef->rend(); ++it) { + if (sTok.find(it->first) != 0) continue; - a_Tok.Set(it->second, sTok); - m_iPos += (int)it->first.length(); + a_Tok.Set(it->second, sTok); + m_iPos += (int)it->first.length(); - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN; - return true; + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN; + return true; } return false; - } +} - //--------------------------------------------------------------------------- - /** \brief Check whether the token at a given position is a value token. +//--------------------------------------------------------------------------- +/** \brief Check whether the token at a given position is a value token. - Value tokens are either values or constants. + Value tokens are either values or constants. - \param a_Tok [out] If a value token is found it will be placed here. - \return true if a value token has been found. - */ - bool ParserTokenReader::IsValTok(token_type &a_Tok) - { + \param a_Tok [out] If a value token is found it will be placed here. + \return true if a value token has been found. +*/ +bool ParserTokenReader::IsValTok(token_type &a_Tok) { assert(m_pConstDef); assert(m_pParser); string_type strTok; value_type fVal(0); int iEnd(0); - + // 2.) Check for user defined constant // Read everything that could be a constant name iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd!=m_iPos) - { - valmap_type::const_iterator item = m_pConstDef->find(strTok); - if (item!=m_pConstDef->end()) - { - m_iPos = iEnd; - a_Tok.SetVal(item->second, strTok); + if (iEnd != m_iPos) { + valmap_type::const_iterator item = m_pConstDef->find(strTok); + if (item != m_pConstDef->end()) { + m_iPos = iEnd; + a_Tok.SetVal(item->second, strTok); - if (m_iSynFlags & noVAL) - Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } } // 3.call the value recognition functions provided by the user // Call user defined value recognition functions std::list::const_iterator item = m_vIdentFun.begin(); - for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item) - { - int iStart = m_iPos; - if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 ) - { - // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 - strTok.assign(m_strFormula.c_str(), iStart, m_iPos-iStart); + for (item = m_vIdentFun.begin(); item != m_vIdentFun.end(); ++item) { + int iStart = m_iPos; + if ((*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal) == 1) { + // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 + strTok.assign(m_strFormula.c_str(), iStart, m_iPos - iStart); - if (m_iSynFlags & noVAL) - Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); - a_Tok.SetVal(fVal, strTok); - m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; - return true; - } + a_Tok.SetVal(fVal, strTok); + m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + return true; + } } return false; - } +} - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is a variable token. - \param a_Tok [out] If a variable token has been found it will be placed here. - \return true if a variable token has been found. - */ - bool ParserTokenReader::IsVarTok(token_type &a_Tok) - { - if (m_pVarDef->empty()) - return false; +//--------------------------------------------------------------------------- +/** \brief Check wheter a token at a given position is a variable token. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a variable token has been found. +*/ +bool ParserTokenReader::IsVarTok(token_type &a_Tok) { + if (m_pVarDef->empty()) return false; string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; + if (iEnd == m_iPos) return false; - varmap_type::const_iterator item = m_pVarDef->find(strTok); - if (item==m_pVarDef->end()) - return false; + varmap_type::const_iterator item = m_pVarDef->find(strTok); + if (item == m_pVarDef->end()) return false; - if (m_iSynFlags & noVAR) - Error(ecUNEXPECTED_VAR, m_iPos, strTok); + if (m_iSynFlags & noVAR) Error(ecUNEXPECTED_VAR, m_iPos, strTok); m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); @@ -800,82 +713,70 @@ namespace mu m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR; -// Zur Info hier die SynFlags von IsVal(): -// m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; + // Zur Info hier die SynFlags von IsVal(): + // m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; return true; - } +} - //--------------------------------------------------------------------------- - bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) - { - if (!m_pStrVarDef || m_pStrVarDef->empty()) - return false; +//--------------------------------------------------------------------------- +bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) { + if (!m_pStrVarDef || m_pStrVarDef->empty()) return false; string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd==m_iPos) - return false; + if (iEnd == m_iPos) return false; - strmap_type::const_iterator item = m_pStrVarDef->find(strTok); - if (item==m_pStrVarDef->end()) - return false; + strmap_type::const_iterator item = m_pStrVarDef->find(strTok); + if (item == m_pStrVarDef->end()) return false; - if (m_iSynFlags & noSTR) - Error(ecUNEXPECTED_VAR, m_iPos, strTok); + if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_VAR, m_iPos, strTok); m_iPos = iEnd; - if (!m_pParser->m_vStringVarBuf.size()) - assert(0 && "muParser internal error"); + if (!m_pParser->m_vStringVarBuf.size()) assert(0 && "muParser internal error"); - a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() ); + a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size()); - m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noARG_SEP); + m_iSynFlags = noANY ^ (noBC | noOPT | noEND | noARG_SEP); return true; - } +} +//--------------------------------------------------------------------------- +/** \brief Check wheter a token at a given position is an undefined variable. - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is an undefined variable. - - \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. - \return true if a variable token has been found. - \throw nothrow - */ - bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) - { + \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed + here. + \return true if a variable token has been found. + \throw nothrow +*/ +bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) { string_type strTok; - int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) ); - if ( iEnd==m_iPos ) - return false; + int iEnd(ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos)); + if (iEnd == m_iPos) return false; - if (m_iSynFlags & noVAR) - { - // 20061021 added token string strTok instead of a_Tok.GetAsString() as the - // token identifier. - // related bug report: - // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 - Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); + if (m_iSynFlags & noVAR) { + // 20061021 added token string strTok instead of a_Tok.GetAsString() as the + // token identifier. + // related bug report: + // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 + Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); } // If a factory is available implicitely create new variables - if (m_pFactory) - { - value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData); - a_Tok.SetVar(fVar, strTok ); + if (m_pFactory) { + value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData); + a_Tok.SetVar(fVar, strTok); - // Do not use m_pParser->DefineVar( strTok, fVar ); - // in order to define the new variable, it will clear the - // m_UsedVar array which will kill previously defined variables - // from the list - // This is safe because the new variable can never override an existing one - // because they are checked first! - (*m_pVarDef)[strTok] = fVar; - m_UsedVar[strTok] = fVar; // Add variable to used-var-list - } - else - { - a_Tok.SetVar((value_type*)&m_fZero, strTok); - m_UsedVar[strTok] = 0; // Add variable to used-var-list + // Do not use m_pParser->DefineVar( strTok, fVar ); + // in order to define the new variable, it will clear the + // m_UsedVar array which will kill previously defined variables + // from the list + // This is safe because the new variable can never override an existing one + // because they are checked first! + (*m_pVarDef)[strTok] = fVar; + m_UsedVar[strTok] = fVar; // Add variable to used-var-list + } else { + a_Tok.SetVar((value_type *)&m_fZero, strTok); + m_UsedVar[strTok] = 0; // Add variable to used-var-list } m_iPos = iEnd; @@ -883,76 +784,62 @@ namespace mu // Call the variable factory in order to let it define a new parser variable m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR; return true; - } +} +//--------------------------------------------------------------------------- +/** \brief Check wheter a token at a given position is a string. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a string token has been found. + \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok + \throw nothrow +*/ +bool ParserTokenReader::IsString(token_type &a_Tok) { + if (m_strFormula[m_iPos] != '"') return false; - //--------------------------------------------------------------------------- - /** \brief Check wheter a token at a given position is a string. - \param a_Tok [out] If a variable token has been found it will be placed here. - \return true if a string token has been found. - \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok - \throw nothrow - */ - bool ParserTokenReader::IsString(token_type &a_Tok) - { - if (m_strFormula[m_iPos]!='"') - return false; - - string_type strBuf(&m_strFormula[m_iPos+1]); + string_type strBuf(&m_strFormula[m_iPos + 1]); std::size_t iEnd(0), iSkip(0); // parser over escaped '\"' end replace them with '"' - for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd)) - { - if (strBuf[iEnd-1]!='\\') break; - strBuf.replace(iEnd-1, 2, _T("\"") ); - iSkip++; + for (iEnd = (int)strBuf.find(_T("\"")); iEnd != 0 && iEnd != string_type::npos; + iEnd = (int)strBuf.find(_T("\""), iEnd)) { + if (strBuf[iEnd - 1] != '\\') break; + strBuf.replace(iEnd - 1, 2, _T("\"")); + iSkip++; } - if (iEnd==string_type::npos) - Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") ); + if (iEnd == string_type::npos) Error(ecUNTERMINATED_STRING, m_iPos, _T("\"")); - string_type strTok(strBuf.begin(), strBuf.begin()+iEnd); + string_type strTok(strBuf.begin(), strBuf.begin() + iEnd); - if (m_iSynFlags & noSTR) - Error(ecUNEXPECTED_STR, m_iPos, strTok); + if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_STR, m_iPos, strTok); - m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer + m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); - m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen - m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND ); + m_iPos += (int)strTok.length() + 2 + + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen + m_iSynFlags = noANY ^ (noARG_SEP | noBC | noOPT | noEND); return true; - } +} - //--------------------------------------------------------------------------- - /** \brief Create an error containing the parse error position. +//--------------------------------------------------------------------------- +/** \brief Create an error containing the parse error position. - This function will create an Parser Exception object containing the error text and its position. + This function will create an Parser Exception object containing the error text and its position. - \param a_iErrc [in] The error code of type #EErrorCodes. - \param a_iPos [in] The position where the error was detected. - \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. - */ - void ParserTokenReader::Error( EErrorCodes a_iErrc, - int a_iPos, - const string_type &a_sTok) const - { + \param a_iErrc [in] The error code of type #EErrorCodes. + \param a_iPos [in] The position where the error was detected. + \param a_strTok [in] The token string representation associated with the error. + \throw ParserException always throws thats the only purpose of this function. +*/ +void ParserTokenReader::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const { m_pParser->Error(a_iErrc, a_iPos, a_sTok); - } +} - //--------------------------------------------------------------------------- - void ParserTokenReader::SetArgSep(char_type cArgSep) - { - m_cArgSep = cArgSep; - } - - //--------------------------------------------------------------------------- - char_type ParserTokenReader::GetArgSep() const - { - return m_cArgSep; - } -} // namespace mu +//--------------------------------------------------------------------------- +void ParserTokenReader::SetArgSep(char_type cArgSep) { m_cArgSep = cArgSep; } +//--------------------------------------------------------------------------- +char_type ParserTokenReader::GetArgSep() const { return m_cArgSep; } +} // namespace mu From cad9bbd2a244c2efbcd6aca27612899b43427101 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 14:16:14 -0800 Subject: [PATCH 05/62] [muparser] Remove muParserStack.h This was a silly data structure that didn't carry its weight. Replace it with a wrapper around std::vector that doesn't explicitly throw exceptions. It's unclear if muparser relied on the exception throwing behavior of ParserStack, and it seems there's no way to find out except removing it and seeing what breaks. The tests pass for what that's worth! --- muparser-2.2.5/Makefile.in | 2 - muparser-2.2.5/include/muParserBase.h | 3 +- muparser-2.2.5/include/muParserDef.h | 19 ++++- muparser-2.2.5/include/muParserStack.h | 104 ------------------------ muparser-2.2.5/src/muParserBytecode.cpp | 5 +- 5 files changed, 21 insertions(+), 112 deletions(-) delete mode 100644 muparser-2.2.5/include/muParserStack.h diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index 157be77de..1b33e6629 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -64,7 +64,6 @@ MUPARSER_LIB_HEADERS = \ include/muParserError.h \ include/muParserFixes.h \ include/muParserInt.h \ - include/muParserStack.h \ include/muParserTemplateMagic.h \ include/muParserTest.h \ include/muParserToken.h \ @@ -91,7 +90,6 @@ MUPARSER_DLL_HEADERS = \ include/muParserError.h \ include/muParserFixes.h \ include/muParserInt.h \ - include/muParserStack.h \ include/muParserTemplateMagic.h \ include/muParserTest.h \ include/muParserToken.h \ diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index c02aa0547..fccb478e2 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -38,7 +38,6 @@ #include "muParserBytecode.h" #include "muParserDef.h" #include "muParserError.h" -#include "muParserStack.h" #include "muParserTokenReader.h" namespace mu { @@ -286,6 +285,6 @@ class ParserBase { m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine mutable int m_nFinalResultIdx; }; -} // namespace mu +} // namespace mu #endif diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 7c2131438..615ded58c 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "muParserFixes.h" @@ -120,6 +121,22 @@ inline std::istream& console_in() { return std::cin; } #endif +/// Our stack type. +template +class ParserStack : public std::vector { + public: + // Convenience to get the top value and pop it. + T pop() { + T val = std::move(this->back()); + this->pop_back(); + return val; + } + + T& top() { return this->back(); } + + void push(T val) { this->push_back(std::move(val)); } +}; + //------------------------------------------------------------------------------ /** \brief Bytecode values. @@ -163,7 +180,7 @@ enum ECmdCode { cmFUNC, ///< Code for a generic function item cmFUNC_STR, ///< Code for a function with a string parameter cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk - ///index + /// index cmSTRING, ///< Code for a string token cmOPRT_BIN, ///< user defined binary operator cmOPRT_POSTFIX, ///< code for postfix operators diff --git a/muparser-2.2.5/include/muParserStack.h b/muparser-2.2.5/include/muParserStack.h deleted file mode 100644 index af6a8a0fc..000000000 --- a/muparser-2.2.5/include/muParserStack.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_STACK_H -#define MU_PARSER_STACK_H - -#include -#include -#include -#include - -#include "muParserError.h" -#include "muParserToken.h" - -/** \file - \brief This file defines the stack used by muparser. -*/ - -namespace mu { - -/** \brief Parser stack implementation. - - Stack implementation based on a std::stack. The behaviour of pop() had been - slightly changed in order to get an error code if the stack is empty. - The stack is used within the Parser both as a value stack and as an operator stack. - - \author (C) 2004-2011 Ingo Berg -*/ -template -class ParserStack { - private: - /** \brief Type of the underlying stack implementation. */ - typedef std::stack > impl_type; - - impl_type m_Stack; ///< This is the actual stack. - - public: - //--------------------------------------------------------------------------- - ParserStack() : m_Stack() {} - - //--------------------------------------------------------------------------- - virtual ~ParserStack() {} - - //--------------------------------------------------------------------------- - /** \brief Pop a value from the stack. - - Unlike the standard implementation this function will return the value that - is going to be taken from the stack. - - \throw ParserException in case the stack is empty. - \sa pop(int &a_iErrc) - */ - TValueType pop() { - if (empty()) throw ParserError(_T("stack is empty.")); - - TValueType el = top(); - m_Stack.pop(); - return el; - } - - /** \brief Push an object into the stack. - - \param a_Val object to push into the stack. - \throw nothrow - */ - void push(const TValueType& a_Val) { m_Stack.push(a_Val); } - - /** \brief Return the number of stored elements. */ - unsigned size() const { return (unsigned)m_Stack.size(); } - - /** \brief Returns true if stack is empty false otherwise. */ - bool empty() const { return m_Stack.empty(); } - - /** \brief Return reference to the top object in the stack. - - The top object is the one pushed most recently. - */ - TValueType& top() { return m_Stack.top(); } -}; -} // namespace MathUtils - -#endif diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index 9786d988f..61efc9533 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -34,7 +34,6 @@ #include "muParserDef.h" #include "muParserError.h" -#include "muParserStack.h" #include "muParserTemplateMagic.h" #include "muParserToken.h" @@ -436,11 +435,11 @@ void ParserByteCode::Finalize() { for (int i = 0; i < (int)m_vRPN.size(); ++i) { switch (m_vRPN[i].Cmd) { case cmIF: - stIf.push(i); + stIf.push_back(i); break; case cmELSE: - stElse.push(i); + stElse.push_back(i); idx = stIf.pop(); m_vRPN[idx].Oprt.offset = i - idx; break; From 5f7f1102dbefcb00d3c1dc264e0f1f0de6ec9ea6 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 16:03:26 -0800 Subject: [PATCH 06/62] [muparser] Remove ParserErrorMsg This was a class to "manage" error messages. Remove it and replace it with a function. --- muparser-2.2.5/include/muParserError.h | 23 +-- muparser-2.2.5/src/muParserError.cpp | 201 +++++++++++-------------- 2 files changed, 91 insertions(+), 133 deletions(-) diff --git a/muparser-2.2.5/include/muParserError.h b/muparser-2.2.5/include/muParserError.h index 0bfb30437..e3a97589d 100644 --- a/muparser-2.2.5/include/muParserError.h +++ b/muparser-2.2.5/include/muParserError.h @@ -94,26 +94,8 @@ enum EErrorCodes { ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages }; -//--------------------------------------------------------------------------- -/** \brief A class that handles the error messages. -*/ -class ParserErrorMsg { - public: - typedef ParserErrorMsg self_type; - - ParserErrorMsg &operator=(const ParserErrorMsg &); - ParserErrorMsg(const ParserErrorMsg &); - ParserErrorMsg(); - - ~ParserErrorMsg(); - - static const ParserErrorMsg &Instance(); - string_type operator[](unsigned a_iIdx) const; - - private: - std::vector m_vErrMsg; ///< A vector with the predefined error messages - static const self_type m_Instance; ///< The instance pointer -}; +/// \return an error message for the given code. +string_type parser_error_for_code(EErrorCodes code); //--------------------------------------------------------------------------- /** \brief Error class of the parser. @@ -153,7 +135,6 @@ class ParserError { string_type m_strTok; ///< Token related with the error int m_iPos; ///< Formula position related to the error EErrorCodes m_iErrc; ///< Error code - const ParserErrorMsg &m_ErrMsg; }; } // namespace mu diff --git a/muparser-2.2.5/src/muParserError.cpp b/muparser-2.2.5/src/muParserError.cpp index bdcc4da6a..1ef75898e 100644 --- a/muparser-2.2.5/src/muParserError.cpp +++ b/muparser-2.2.5/src/muParserError.cpp @@ -25,83 +25,86 @@ #include "muParserError.h" namespace mu { -const ParserErrorMsg ParserErrorMsg::m_Instance; - -//------------------------------------------------------------------------------ -const ParserErrorMsg &ParserErrorMsg::Instance() { return m_Instance; } - -//------------------------------------------------------------------------------ -string_type ParserErrorMsg::operator[](unsigned a_iIdx) const { - return (a_iIdx < m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type(); -} - //--------------------------------------------------------------------------- -ParserErrorMsg::~ParserErrorMsg() {} - -//--------------------------------------------------------------------------- -/** \brief Assignement operator is deactivated. -*/ -ParserErrorMsg &ParserErrorMsg::operator=(const ParserErrorMsg &) { - assert(false); - return *this; -} - -//--------------------------------------------------------------------------- -ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg &) {} - -//--------------------------------------------------------------------------- -ParserErrorMsg::ParserErrorMsg() : m_vErrMsg(0) { - m_vErrMsg.resize(ecCOUNT); - - m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unexpected token \"$TOK$\" found at position $POS$."); - m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name: \"$TOK$\"."); - m_vErrMsg[ecINVALID_BINOP_IDENT] = _T("Invalid binary operator identifier: \"$TOK$\"."); - m_vErrMsg[ecINVALID_INFIX_IDENT] = _T("Invalid infix operator identifier: \"$TOK$\"."); - m_vErrMsg[ecINVALID_POSTFIX_IDENT] = _T("Invalid postfix operator identifier: \"$TOK$\"."); - m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function."); - m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty."); - m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable."); - m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$"); - m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression at position $POS$"); - m_vErrMsg[ecUNEXPECTED_ARG_SEP] = _T("Unexpected argument separator at position $POS$"); - m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$"); - m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$"); - m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$"); - m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$"); - m_vErrMsg[ecUNEXPECTED_ARG] = - _T("Function arguments used without a function (position: $POS$)"); - m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis"); - m_vErrMsg[ecTOO_MANY_PARAMS] = - _T("Too many parameters for function \"$TOK$\" at expression position $POS$"); - m_vErrMsg[ecTOO_FEW_PARAMS] = - _T("Too few parameters for function \"$TOK$\" at expression position $POS$"); - m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero"); - m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error"); - m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict"); - m_vErrMsg[ecOPT_PRI] = - _T("Invalid value for operator priority (must be greater or equal to zero)."); - m_vErrMsg[ecBUILTIN_OVERLOAD] = - _T("user defined binary operator \"$TOK$\" conflicts with a built in operator."); - m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$."); - m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$."); - m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument."); - m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected."); - m_vErrMsg[ecOPRT_TYPE_CONFLICT] = - _T("No suitable overload for operator \"$TOK$\" at position $POS$."); - m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string."); - m_vErrMsg[ecGENERIC] = _T("Parser error."); - m_vErrMsg[ecLOCALE] = _T("Decimal separator is identic to function argument separator."); - m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = - _T("The \"$TOK$\" operator must be preceeded by a closing bracket."); - m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause"); - m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$"); - m_vErrMsg[ecUNREASONABLE_NUMBER_OF_COMPUTATIONS] = - _T("Number of computations to small for bulk mode. (Vectorisation overhead too costly)"); - -#if defined(_DEBUG) - for (int i = 0; i < ecCOUNT; ++i) - if (!m_vErrMsg[i].length()) assert(false); -#endif +string_type parser_error_for_code(EErrorCodes code) { + switch (code) { + case ecUNASSIGNABLE_TOKEN: + return _T("Unexpected token \"$TOK$\" found at position $POS$."); + case ecINVALID_NAME: + return _T("Invalid function-, variable- or constant name: \"$TOK$\"."); + case ecINVALID_BINOP_IDENT: + return _T("Invalid binary operator identifier: \"$TOK$\"."); + case ecINVALID_INFIX_IDENT: + return _T("Invalid infix operator identifier: \"$TOK$\"."); + case ecINVALID_POSTFIX_IDENT: + return _T("Invalid postfix operator identifier: \"$TOK$\"."); + case ecINVALID_FUN_PTR: + return _T("Invalid pointer to callback function."); + case ecEMPTY_EXPRESSION: + return _T("Expression is empty."); + case ecINVALID_VAR_PTR: + return _T("Invalid pointer to variable."); + case ecUNEXPECTED_OPERATOR: + return _T("Unexpected operator \"$TOK$\" found at position $POS$"); + case ecUNEXPECTED_EOF: + return _T("Unexpected end of expression at position $POS$"); + case ecUNEXPECTED_ARG_SEP: + return _T("Unexpected argument separator at position $POS$"); + case ecUNEXPECTED_PARENS: + return _T("Unexpected parenthesis \"$TOK$\" at position $POS$"); + case ecUNEXPECTED_FUN: + return _T("Unexpected function \"$TOK$\" at position $POS$"); + case ecUNEXPECTED_VAL: + return _T("Unexpected value \"$TOK$\" found at position $POS$"); + case ecUNEXPECTED_VAR: + return _T("Unexpected variable \"$TOK$\" found at position $POS$"); + case ecUNEXPECTED_ARG: + return _T("Function arguments used without a function (position: $POS$)"); + case ecMISSING_PARENS: + return _T("Missing parenthesis"); + case ecTOO_MANY_PARAMS: + return _T("Too many parameters for function \"$TOK$\" at expression position $POS$"); + case ecTOO_FEW_PARAMS: + return _T("Too few parameters for function \"$TOK$\" at expression position $POS$"); + case ecDIV_BY_ZERO: + return _T("Divide by zero"); + case ecDOMAIN_ERROR: + return _T("Domain error"); + case ecNAME_CONFLICT: + return _T("Name conflict"); + case ecOPT_PRI: + return _T("Invalid value for operator priority (must be greater or equal to zero)."); + case ecBUILTIN_OVERLOAD: + return _T("user defined binary operator \"$TOK$\" conflicts with a built in operator."); + case ecUNEXPECTED_STR: + return _T("Unexpected string token found at position $POS$."); + case ecUNTERMINATED_STRING: + return _T("Unterminated string starting at position $POS$."); + case ecSTRING_EXPECTED: + return _T("String function called with a non string type of argument."); + case ecVAL_EXPECTED: + return _T("String value used where a numerical argument is expected."); + case ecOPRT_TYPE_CONFLICT: + return _T("No suitable overload for operator \"$TOK$\" at position $POS$."); + case ecSTR_RESULT: + return _T("Function result is a string."); + case ecGENERIC: + return _T("Parser error."); + case ecLOCALE: + return _T("Decimal separator is identic to function argument separator."); + case ecUNEXPECTED_CONDITIONAL: + return _T("The \"$TOK$\" operator must be preceeded by a closing bracket."); + case ecMISSING_ELSE_CLAUSE: + return _T("If-then-else operator is missing an else clause"); + case ecMISPLACED_COLON: + return _T("Misplaced colon at position $POS$"); + case ecUNREASONABLE_NUMBER_OF_COMPUTATIONS: + return _T("Number of computations to small for bulk mode. (Vectorisation overhead too ") + _T("costly)"); + default: + assert(0 && "Invalid error code"); + return string_type(); + } } //--------------------------------------------------------------------------- @@ -112,12 +115,7 @@ ParserErrorMsg::ParserErrorMsg() : m_vErrMsg(0) { /** \brief Default constructor. */ ParserError::ParserError() - : m_strMsg(), - m_strFormula(), - m_strTok(), - m_iPos(-1), - m_iErrc(ecUNDEFINED), - m_ErrMsg(ParserErrorMsg::Instance()) {} + : m_strMsg(), m_strFormula(), m_strTok(), m_iPos(-1), m_iErrc(ecUNDEFINED) {} //------------------------------------------------------------------------------ /** \brief This Constructor is used for internal exceptions only. @@ -125,13 +123,8 @@ ParserError::ParserError() It does not contain any information but the error code. */ ParserError::ParserError(EErrorCodes a_iErrc) - : m_strMsg(), - m_strFormula(), - m_strTok(), - m_iPos(-1), - m_iErrc(a_iErrc), - m_ErrMsg(ParserErrorMsg::Instance()) { - m_strMsg = m_ErrMsg[m_iErrc]; + : m_strMsg(), m_strFormula(), m_strTok(), m_iPos(-1), m_iErrc(a_iErrc) { + m_strMsg = parser_error_for_code(m_iErrc); stringstream_type stream; stream << (int)m_iPos; ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); @@ -140,7 +133,7 @@ ParserError::ParserError(EErrorCodes a_iErrc) //------------------------------------------------------------------------------ /** \brief Construct an error from a message text. */ -ParserError::ParserError(const string_type &sMsg) : m_ErrMsg(ParserErrorMsg::Instance()) { +ParserError::ParserError(const string_type &sMsg) { Reset(); m_strMsg = sMsg; } @@ -154,13 +147,8 @@ ParserError::ParserError(const string_type &sMsg) : m_ErrMsg(ParserErrorMsg::Ins */ ParserError::ParserError(EErrorCodes iErrc, const string_type &sTok, const string_type &sExpr, int iPos) - : m_strMsg(), - m_strFormula(sExpr), - m_strTok(sTok), - m_iPos(iPos), - m_iErrc(iErrc), - m_ErrMsg(ParserErrorMsg::Instance()) { - m_strMsg = m_ErrMsg[m_iErrc]; + : m_strMsg(), m_strFormula(sExpr), m_strTok(sTok), m_iPos(iPos), m_iErrc(iErrc) { + m_strMsg = parser_error_for_code(m_iErrc); stringstream_type stream; stream << (int)m_iPos; ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); @@ -174,13 +162,8 @@ ParserError::ParserError(EErrorCodes iErrc, const string_type &sTok, const strin \param [in] sTok The token string related to this error. */ ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) - : m_strMsg(), - m_strFormula(), - m_strTok(sTok), - m_iPos(iPos), - m_iErrc(iErrc), - m_ErrMsg(ParserErrorMsg::Instance()) { - m_strMsg = m_ErrMsg[m_iErrc]; + : m_strMsg(), m_strFormula(), m_strTok(sTok), m_iPos(iPos), m_iErrc(iErrc) { + m_strMsg = parser_error_for_code(m_iErrc); stringstream_type stream; stream << (int)m_iPos; ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); @@ -194,12 +177,7 @@ ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) \param [in] sTok The token string related to this error. */ ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) - : m_strMsg(szMsg), - m_strFormula(), - m_strTok(sTok), - m_iPos(iPos), - m_iErrc(ecGENERIC), - m_ErrMsg(ParserErrorMsg::Instance()) { + : m_strMsg(szMsg), m_strFormula(), m_strTok(sTok), m_iPos(iPos), m_iErrc(ecGENERIC) { stringstream_type stream; stream << (int)m_iPos; ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); @@ -213,8 +191,7 @@ ParserError::ParserError(const ParserError &a_Obj) m_strFormula(a_Obj.m_strFormula), m_strTok(a_Obj.m_strTok), m_iPos(a_Obj.m_iPos), - m_iErrc(a_Obj.m_iErrc), - m_ErrMsg(ParserErrorMsg::Instance()) {} + m_iErrc(a_Obj.m_iErrc) {} //------------------------------------------------------------------------------ /** \brief Assignment operator. */ From 38a2e0218d833e5ee420e4501cbcd7d95913a471 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 16:42:51 -0800 Subject: [PATCH 07/62] [muparser] Remove muParserError.h To help remove exception handling, we will need to have a type that has visibility into both ParserError and value_type. We're going to put this type in muParserDef.h. Remove the error header and fold its contents into muParserDef.h. --- muparser-2.2.5/Makefile.in | 2 - muparser-2.2.5/include/muParserBase.h | 1 - muparser-2.2.5/include/muParserBytecode.h | 1 - muparser-2.2.5/include/muParserDef.h | 120 +++++++++++++-- muparser-2.2.5/include/muParserError.h | 142 ------------------ .../include/muParserTemplateMagic.h | 1 - muparser-2.2.5/include/muParserToken.h | 1 - muparser-2.2.5/src/muParserBytecode.cpp | 1 - muparser-2.2.5/src/muParserDLL.cpp | 1 - muparser-2.2.5/src/muParserError.cpp | 4 +- 10 files changed, 111 insertions(+), 163 deletions(-) delete mode 100644 muparser-2.2.5/include/muParserError.h diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index 1b33e6629..39ce45817 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -61,7 +61,6 @@ MUPARSER_LIB_HEADERS = \ include/muParserCallback.h \ include/muParserDLL.h \ include/muParserDef.h \ - include/muParserError.h \ include/muParserFixes.h \ include/muParserInt.h \ include/muParserTemplateMagic.h \ @@ -87,7 +86,6 @@ MUPARSER_DLL_HEADERS = \ include/muParserCallback.h \ include/muParserDLL.h \ include/muParserDef.h \ - include/muParserError.h \ include/muParserFixes.h \ include/muParserInt.h \ include/muParserTemplateMagic.h \ diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index fccb478e2..ac61e139b 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -37,7 +37,6 @@ //--- Parser includes -------------------------------------------------------------------------- #include "muParserBytecode.h" #include "muParserDef.h" -#include "muParserError.h" #include "muParserTokenReader.h" namespace mu { diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index 8544b17a2..c3557d808 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -31,7 +31,6 @@ #include #include "muParserDef.h" -#include "muParserError.h" #include "muParserToken.h" /** \file diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 615ded58c..bbe693907 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -100,10 +100,10 @@ namespace mu { //------------------------------------------------------------------------------ /** \brief Encapsulate wcout. */ -inline std::wostream& console() { return std::wcout; } +inline std::wostream &console() { return std::wcout; } /** \brief Encapsulate cin. */ -inline std::wistream& console_in() { return std::wcin; } +inline std::wistream &console_in() { return std::wcin; } #else @@ -111,13 +111,13 @@ inline std::wistream& console_in() { return std::wcin; } Used for supporting UNICODE more easily. */ -inline std::ostream& console() { return std::cout; } +inline std::ostream &console() { return std::cout; } /** \brief Encapsulate cin. Used for supporting UNICODE more easily. */ -inline std::istream& console_in() { return std::cin; } +inline std::istream &console_in() { return std::cin; } #endif @@ -132,7 +132,7 @@ class ParserStack : public std::vector { return val; } - T& top() { return this->back(); } + T &top() { return this->back(); } void push(T val) { this->push_back(std::move(val)); } }; @@ -250,7 +250,7 @@ typedef std::basic_stringstream, std::all // Data container types /** \brief Type used for storing variables. */ -typedef std::map varmap_type; +typedef std::map varmap_type; /** \brief Type used for storing constants. */ typedef std::map valmap_type; @@ -258,6 +258,102 @@ typedef std::map valmap_type; /** \brief Type for assigning a string name to an index in the internal string table. */ typedef std::map strmap_type; +/** \brief Error codes. */ +enum EErrorCodes { + // Formula syntax errors + ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found + ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. + ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") + ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") + ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found + ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found + ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found + ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing + ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position + ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument + ecVAL_EXPECTED = + 10, ///< A numerical function has been called with a non value type of argument + ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") + ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") + ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") + ecTOO_MANY_PARAMS = 14, ///< Too many function parameters + ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") + ecOPRT_TYPE_CONFLICT = + 16, ///< binary operators may only be applied to value items of the same type + ecSTR_RESULT = 17, ///< result is a string + + // Invalid Parser input Parameters + ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. + ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier + ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. + ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. + + ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator + ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer + ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer + ecEMPTY_EXPRESSION = 25, ///< The Expression is empty + ecNAME_CONFLICT = 26, ///< Name conflict + ecOPT_PRI = 27, ///< Invalid operator priority + // + ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) + ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) + ecGENERIC = 30, ///< Generic error + ecLOCALE = 31, ///< Conflict with current locale + + ecUNEXPECTED_CONDITIONAL = 32, + ecMISSING_ELSE_CLAUSE = 33, + ecMISPLACED_COLON = 34, + + ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, + + // The last two are special entries + ecCOUNT, ///< This is no error code, It just stores just the total number of error codes + ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages +}; + +/// \return an error message for the given code. +string_type parser_error_for_code(EErrorCodes code); + +//--------------------------------------------------------------------------- +/** \brief Error class of the parser. + \author Ingo Berg + + Part of the math parser package. + */ +class ParserError { + private: + /** \brief Replace all ocuurences of a substring with another string. */ + void ReplaceSubString(string_type &strSource, const string_type &strFind, + const string_type &strReplaceWith); + void Reset(); + + public: + ParserError(); + explicit ParserError(EErrorCodes a_iErrc); + explicit ParserError(const string_type &sMsg); + ParserError(EErrorCodes a_iErrc, const string_type &sTok, + const string_type &sFormula = string_type(), int a_iPos = -1); + ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type &sTok); + ParserError(const char_type *a_szMsg, int a_iPos = -1, const string_type &sTok = string_type()); + ParserError(const ParserError &a_Obj); + ParserError &operator=(const ParserError &a_Obj); + ~ParserError(); + + void SetFormula(const string_type &a_strFormula); + const string_type &GetExpr() const; + const string_type &GetMsg() const; + int GetPos() const; + const string_type &GetToken() const; + EErrorCodes GetCode() const; + + private: + string_type m_strMsg; ///< The message string + string_type m_strFormula; ///< Formula string + string_type m_strTok; ///< Token related with the error + int m_iPos; ///< Formula position related to the error + EErrorCodes m_iErrc; ///< Error code +}; + // Parser callbacks /** \brief Callback type used for functions without arguments. */ @@ -342,22 +438,22 @@ typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_typ value_type); /** \brief Callback type used for functions with a variable argument list. */ -typedef value_type (*multfun_type)(const value_type*, int); +typedef value_type (*multfun_type)(const value_type *, int); /** \brief Callback type used for functions taking a string as an argument. */ -typedef value_type (*strfun_type1)(const char_type*); +typedef value_type (*strfun_type1)(const char_type *); /** \brief Callback type used for functions taking a string and a value as arguments. */ -typedef value_type (*strfun_type2)(const char_type*, value_type); +typedef value_type (*strfun_type2)(const char_type *, value_type); /** \brief Callback type used for functions taking a string and two values as arguments. */ -typedef value_type (*strfun_type3)(const char_type*, value_type, value_type); +typedef value_type (*strfun_type3)(const char_type *, value_type, value_type); /** \brief Callback used for functions that identify values in a string. */ -typedef int (*identfun_type)(const char_type* sExpr, int* nPos, value_type* fVal); +typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal); /** \brief Callback used for variable creation factory functions. */ -typedef value_type* (*facfun_type)(const char_type*, void*); +typedef value_type *(*facfun_type)(const char_type *, void *); } // end of namespace #endif diff --git a/muparser-2.2.5/include/muParserError.h b/muparser-2.2.5/include/muParserError.h deleted file mode 100644 index e3a97589d..000000000 --- a/muparser-2.2.5/include/muParserError.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_ERROR_H -#define MU_PARSER_ERROR_H - -#include -#include -#include -#include -#include -#include - -#include "muParserDef.h" - -/** \file - \brief This file defines the error class used by the parser. -*/ - -namespace mu { - -/** \brief Error codes. */ -enum EErrorCodes { - // Formula syntax errors - ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found - ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified. - ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(") - ecUNEXPECTED_ARG_SEP = 3, ///< An unexpected comma has been found. (Example: "1,23") - ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found - ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found - ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found - ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing - ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position - ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument - ecVAL_EXPECTED = - 10, ///< A numerical function has been called with a non value type of argument - ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3") - ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)") - ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)") - ecTOO_MANY_PARAMS = 14, ///< Too many function parameters - ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)") - ecOPRT_TYPE_CONFLICT = - 16, ///< binary operators may only be applied to value items of the same type - ecSTR_RESULT = 17, ///< result is a string - - // Invalid Parser input Parameters - ecINVALID_NAME = 18, ///< Invalid function, variable or constant name. - ecINVALID_BINOP_IDENT = 19, ///< Invalid binary operator identifier - ecINVALID_INFIX_IDENT = 20, ///< Invalid function, variable or constant name. - ecINVALID_POSTFIX_IDENT = 21, ///< Invalid function, variable or constant name. - - ecBUILTIN_OVERLOAD = 22, ///< Trying to overload builtin operator - ecINVALID_FUN_PTR = 23, ///< Invalid callback function pointer - ecINVALID_VAR_PTR = 24, ///< Invalid variable pointer - ecEMPTY_EXPRESSION = 25, ///< The Expression is empty - ecNAME_CONFLICT = 26, ///< Name conflict - ecOPT_PRI = 27, ///< Invalid operator priority - // - ecDOMAIN_ERROR = 28, ///< catch division by zero, sqrt(-1), log(0) (currently unused) - ecDIV_BY_ZERO = 29, ///< Division by zero (currently unused) - ecGENERIC = 30, ///< Generic error - ecLOCALE = 31, ///< Conflict with current locale - - ecUNEXPECTED_CONDITIONAL = 32, - ecMISSING_ELSE_CLAUSE = 33, - ecMISPLACED_COLON = 34, - - ecUNREASONABLE_NUMBER_OF_COMPUTATIONS = 35, - - // The last two are special entries - ecCOUNT, ///< This is no error code, It just stores just the total number of error codes - ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages -}; - -/// \return an error message for the given code. -string_type parser_error_for_code(EErrorCodes code); - -//--------------------------------------------------------------------------- -/** \brief Error class of the parser. - \author Ingo Berg - - Part of the math parser package. -*/ -class ParserError { - private: - /** \brief Replace all ocuurences of a substring with another string. */ - void ReplaceSubString(string_type &strSource, const string_type &strFind, - const string_type &strReplaceWith); - void Reset(); - - public: - ParserError(); - explicit ParserError(EErrorCodes a_iErrc); - explicit ParserError(const string_type &sMsg); - ParserError(EErrorCodes a_iErrc, const string_type &sTok, - const string_type &sFormula = string_type(), int a_iPos = -1); - ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type &sTok); - ParserError(const char_type *a_szMsg, int a_iPos = -1, const string_type &sTok = string_type()); - ParserError(const ParserError &a_Obj); - ParserError &operator=(const ParserError &a_Obj); - ~ParserError(); - - void SetFormula(const string_type &a_strFormula); - const string_type &GetExpr() const; - const string_type &GetMsg() const; - int GetPos() const; - const string_type &GetToken() const; - EErrorCodes GetCode() const; - - private: - string_type m_strMsg; ///< The message string - string_type m_strFormula; ///< Formula string - string_type m_strTok; ///< Token related with the error - int m_iPos; ///< Formula position related to the error - EErrorCodes m_iErrc; ///< Error code -}; - -} // namespace mu - -#endif diff --git a/muparser-2.2.5/include/muParserTemplateMagic.h b/muparser-2.2.5/include/muParserTemplateMagic.h index dc52ff763..69a54c8d2 100644 --- a/muparser-2.2.5/include/muParserTemplateMagic.h +++ b/muparser-2.2.5/include/muParserTemplateMagic.h @@ -2,7 +2,6 @@ #define MU_PARSER_TEMPLATE_MAGIC_H #include -#include "muParserError.h" namespace mu { //----------------------------------------------------------------------------------------------- diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index b8ea6c133..36222c622 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -33,7 +33,6 @@ #include #include "muParserCallback.h" -#include "muParserError.h" /** \file \brief This file contains the parser token definition. diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index 61efc9533..b181f0021 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -33,7 +33,6 @@ #include #include "muParserDef.h" -#include "muParserError.h" #include "muParserTemplateMagic.h" #include "muParserToken.h" diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index df3196877..7d361c3ba 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -40,7 +40,6 @@ #include "muParser.h" #include "muParserDLL.h" -#include "muParserError.h" #include "muParserInt.h" #define MU_TRY try { diff --git a/muparser-2.2.5/src/muParserError.cpp b/muparser-2.2.5/src/muParserError.cpp index 1ef75898e..2ccad2399 100644 --- a/muparser-2.2.5/src/muParserError.cpp +++ b/muparser-2.2.5/src/muParserError.cpp @@ -22,7 +22,9 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "muParserError.h" +#include "muParserDef.h" + +#include namespace mu { //--------------------------------------------------------------------------- From dac13d51faa2df78639addb47c30196091690bd6 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 17:00:03 -0800 Subject: [PATCH 08/62] [muparser] Switch autoconf build to C++11 This will enable testing via muparser's test suite while incorporating C++11 features. --- muparser-2.2.5/Makefile.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index 39ce45817..f7636d194 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -43,7 +43,7 @@ LDFLAGS = @LDFLAGS@ DESTDIR = MUPARSER_LIB_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \ - -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS) + -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS) -std=c++11 MUPARSER_LIB_OBJECTS = \ muParser_lib_muParser.o \ muParser_lib_muParserBase.o \ @@ -68,7 +68,7 @@ MUPARSER_LIB_HEADERS = \ include/muParserToken.h \ include/muParserTokenReader.h MUPARSER_DLL_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \ - -I$(srcdir)/include $(PIC_FLAG) $(CPPFLAGS) $(CXXFLAGS) + -I$(srcdir)/include $(PIC_FLAG) $(CPPFLAGS) $(CXXFLAGS) -std=c++11 MUPARSER_DLL_OBJECTS = \ muParser_dll_muParser.o \ muParser_dll_muParserBase.o \ @@ -92,7 +92,7 @@ MUPARSER_DLL_HEADERS = \ include/muParserTest.h \ include/muParserToken.h \ include/muParserTokenReader.h -EXAMPLE1_CXXFLAGS = $(____DEBUG) -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS) +EXAMPLE1_CXXFLAGS = $(____DEBUG) -I$(srcdir)/include $(CPPFLAGS) $(CXXFLAGS) -std=c++11 EXAMPLE1_OBJECTS = \ example1_example1.o From c5a0c58cfb51a7161162c0a9a3edb45faaac57fd Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Thu, 23 Nov 2017 10:03:01 -0800 Subject: [PATCH 09/62] [muparser] Remove NDEBUG from its autoconf build Ensure that assertions are tripped. --- muparser-2.2.5/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index f7636d194..0619f08a0 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -200,7 +200,7 @@ COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_uninst_cmd = rm -f \ @COND_SHARED_1@____SHARED = -DMUPARSER_DLL @COND_SHARED_0@____SHARED_0 = @COND_SHARED_1@____SHARED_0 = -DMUPARSERLIB_EXPORTS -@COND_DEBUG_0@____DEBUG = -DNDEBUG +@COND_DEBUG_0@____DEBUG = @COND_DEBUG_1@____DEBUG = ### Targets: ### From 85334432ed98f2ec9c9f6e0fb60d2ad0a4607664 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 10:28:14 -0800 Subject: [PATCH 10/62] [muparser] Remove cmFUNC_BULK fish does not need bulk functions, which are used to enable parallel computations. --- muparser-2.2.5/include/muParserBase.h | 1 - muparser-2.2.5/include/muParserBytecode.h | 1 - muparser-2.2.5/include/muParserCallback.h | 12 - muparser-2.2.5/include/muParserDLL.h | 46 -- muparser-2.2.5/include/muParserDef.h | 42 -- muparser-2.2.5/include/muParserTest.h | 4 - muparser-2.2.5/samples/example1/example1.cpp | 728 ++++++++----------- muparser-2.2.5/src/muParserBase.cpp | 134 +--- muparser-2.2.5/src/muParserBytecode.cpp | 19 +- muparser-2.2.5/src/muParserCallback.cpp | 113 --- muparser-2.2.5/src/muParserDLL.cpp | 107 --- muparser-2.2.5/src/muParserTest.cpp | 84 --- 12 files changed, 319 insertions(+), 972 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index ac61e139b..a613e59c5 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -99,7 +99,6 @@ class ParserBase { value_type Eval() const; value_type *Eval(int &nStackSize) const; - void Eval(value_type *results, int nBulkSize); int GetNumResults() const; diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index c3557d808..7ea808ff2 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -111,7 +111,6 @@ class ParserByteCode { void AddIfElse(ECmdCode a_Oprt); void AddAssignOp(value_type *a_pVar); void AddFun(generic_fun_type a_pFun, int a_iArgc); - void AddBulkFun(generic_fun_type a_pFun, int a_iArgc); void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx); void EnableOptimizer(bool bStat); diff --git a/muparser-2.2.5/include/muParserCallback.h b/muparser-2.2.5/include/muParserCallback.h index ee48e734a..e153165af 100644 --- a/muparser-2.2.5/include/muParserCallback.h +++ b/muparser-2.2.5/include/muParserCallback.h @@ -63,18 +63,6 @@ class ParserCallback { ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti); - ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti); - ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti); ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); diff --git a/muparser-2.2.5/include/muParserDLL.h b/muparser-2.2.5/include/muParserDLL.h index 1b8d60946..7dae903f4 100644 --- a/muparser-2.2.5/include/muParserDLL.h +++ b/muparser-2.2.5/include/muParserDLL.h @@ -73,24 +73,6 @@ typedef muFloat_t (*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloa typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -// Function prototypes for bulkmode functions -typedef muFloat_t (*muBulkFun0_t)(int, int); -typedef muFloat_t (*muBulkFun1_t)(int, int, muFloat_t); -typedef muFloat_t (*muBulkFun2_t)(int, int, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun3_t)(int, int, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun4_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun5_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun6_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t); -typedef muFloat_t (*muBulkFun7_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun8_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun9_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muBulkFun10_t)(int, int, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); - typedef muFloat_t (*muMultFun_t)(const muFloat_t *, muInt_t); typedef muFloat_t (*muStrFun1_t)(const muChar_t *); typedef muFloat_t (*muStrFun2_t)(const muChar_t *, muFloat_t); @@ -130,7 +112,6 @@ mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserD API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser); API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); API_EXPORT(muFloat_t *) mupEvalMulti(muParserHandle_t a_hParser, int *nNum); -API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t *a_fResult, int nSize); // Defining callbacks / variables / constants API_EXPORT(void) @@ -167,30 +148,6 @@ API_EXPORT(void) mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, muBool_t a_bOptimize); -// Defining bulkmode functions -API_EXPORT(void) -mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun0_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun1_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun2_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun3_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun4_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun5_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun6_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun7_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun8_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun9_t a_pFun); -API_EXPORT(void) -mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muBulkFun10_t a_pFun); - // string functions API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun); @@ -216,9 +173,6 @@ mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t *a_szName, const mu API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar); -API_EXPORT(void) -mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar); - API_EXPORT(void) mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pOprt, muBool_t a_bOptimize); diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index bbe693907..6666df808 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -179,8 +179,6 @@ enum ECmdCode { // operators and functions cmFUNC, ///< Code for a generic function item cmFUNC_STR, ///< Code for a function with a string parameter - cmFUNC_BULK, ///< Special callbacks for Bulk mode with an additional parameter for the bulk - /// index cmSTRING, ///< Code for a string token cmOPRT_BIN, ///< user defined binary operator cmOPRT_POSTFIX, ///< code for postfix operators @@ -397,46 +395,6 @@ typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type, value_type); -/** \brief Callback type used for functions without arguments. */ -typedef value_type (*bulkfun_type0)(int, int); - -/** \brief Callback type used for functions with a single arguments. */ -typedef value_type (*bulkfun_type1)(int, int, value_type); - -/** \brief Callback type used for functions with two arguments. */ -typedef value_type (*bulkfun_type2)(int, int, value_type, value_type); - -/** \brief Callback type used for functions with three arguments. */ -typedef value_type (*bulkfun_type3)(int, int, value_type, value_type, value_type); - -/** \brief Callback type used for functions with four arguments. */ -typedef value_type (*bulkfun_type4)(int, int, value_type, value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef value_type (*bulkfun_type5)(int, int, value_type, value_type, value_type, value_type, - value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef value_type (*bulkfun_type6)(int, int, value_type, value_type, value_type, value_type, - value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef value_type (*bulkfun_type7)(int, int, value_type, value_type, value_type, value_type, - value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef value_type (*bulkfun_type8)(int, int, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef value_type (*bulkfun_type9)(int, int, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef value_type (*bulkfun_type10)(int, int, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type, value_type, - value_type); - /** \brief Callback type used for functions with a variable argument list. */ typedef value_type (*multfun_type)(const value_type *, int); diff --git a/muparser-2.2.5/include/muParserTest.h b/muparser-2.2.5/include/muParserTest.h index 5793a98b1..2ad907b80 100644 --- a/muparser-2.2.5/include/muParserTest.h +++ b/muparser-2.2.5/include/muParserTest.h @@ -172,7 +172,6 @@ class ParserTester // final int TestException(); int TestStrArg(); int TestIfThenElse(); - int TestBulkMode(); void Abort() const; @@ -194,9 +193,6 @@ class ParserTester // final // Test Int Parser int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass); - - // Test Bulkmode - int EqnTestBulk(const string_type& a_str, double a_fRes[4], bool a_fPass); }; } // namespace Test } // namespace mu diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index af3279a1e..dc7005e34 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -1,11 +1,11 @@ //--------------------------------------------------------------------------- // -// __________ -// _____ __ __\______ \_____ _______ ______ ____ _______ +// __________ +// _____ __ __\______ \_____ _______ ______ ____ _______ // / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ // | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ -// |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| -// \/ \/ \/ \/ +// |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| +// \/ \/ \/ \/ // (C) 2015 Ingo Berg // // example1.cpp - using the parser as a static library @@ -15,209 +15,178 @@ #include "muParserTest.h" #if defined(_WIN32) && defined(_DEBUG) - #define _CRTDBG_MAP_ALLOC - #include - #include - #define CREATE_LEAKAGE_REPORT +#define _CRTDBG_MAP_ALLOC +#include +#include +#define CREATE_LEAKAGE_REPORT #endif -#if defined( USINGDLL ) && defined( _WIN32 ) +#if defined(USINGDLL) && defined(_WIN32) #error This sample can be used only with STATIC builds of muParser (on win32) #endif /** \brief This macro will enable mathematical constants like M_PI. */ -#define _USE_MATH_DEFINES +#define _USE_MATH_DEFINES +#include #include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include +#include #include "muParser.h" using namespace std; using namespace mu; - #if defined(CREATE_LEAKAGE_REPORT) // Dumping memory leaks in the destructor of the static guard -// guarantees i won't get false positives from the ParserErrorMsg +// guarantees i won't get false positives from the ParserErrorMsg // class wich is a singleton with a static instance. -struct DumpLeaks -{ - ~DumpLeaks() - { - _CrtDumpMemoryLeaks(); - } +struct DumpLeaks { + ~DumpLeaks() { _CrtDumpMemoryLeaks(); } } static LeakDumper; #endif -// Forward declarations -void CalcBulk(); - // Operator callback functions value_type Mega(value_type a_fVal) { return a_fVal * 1e6; } value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } -value_type Rnd(value_type v) { return v*std::rand()/(value_type)(RAND_MAX+1.0); } -value_type Not(value_type v) { return v==0; } -value_type Add(value_type v1, value_type v2) { return v1+v2; } -value_type Mul(value_type v1, value_type v2) { return v1*v2; } +value_type Rnd(value_type v) { return v * std::rand() / (value_type)(RAND_MAX + 1.0); } +value_type Not(value_type v) { return v == 0; } +value_type Add(value_type v1, value_type v2) { return v1 + v2; } +value_type Mul(value_type v1, value_type v2) { return v1 * v2; } //--------------------------------------------------------------------------- -value_type ThrowAnException(value_type) -{ - throw std::runtime_error("This function does throw an exception."); +value_type ThrowAnException(value_type) { + throw std::runtime_error("This function does throw an exception."); } //--------------------------------------------------------------------------- -value_type BulkFun1(int nBulkIdx, int nThreadIdx, value_type v1) -{ - // Note: I'm just doing something with all three parameters to shut - // compiler warnings up! - return nBulkIdx + nThreadIdx + v1; +value_type Ping() { + mu::console() << "ping\n"; + return 0; } //--------------------------------------------------------------------------- -value_type Ping() -{ - mu::console() << "ping\n"; - return 0; +value_type StrFun0(const char_type *szMsg) { + if (szMsg) mu::console() << szMsg << std::endl; + + return 999; } //--------------------------------------------------------------------------- -value_type StrFun0(const char_type *szMsg) -{ - if (szMsg) - mu::console() << szMsg << std::endl; - - return 999; +value_type StrFun2(const char_type *v1, value_type v2, value_type v3) { + mu::console() << v1 << std::endl; + return v2 + v3; } //--------------------------------------------------------------------------- -value_type StrFun2(const char_type *v1, value_type v2,value_type v3) -{ - mu::console() << v1 << std::endl; - return v2+v3; -} - -//--------------------------------------------------------------------------- -value_type Debug(mu::value_type v1, mu::value_type v2) -{ - ParserBase::EnableDebugDump(v1!=0, v2!=0); - mu::console() << _T("Bytecode dumping ") << ((v1!=0) ? _T("active") : _T("inactive")) << _T("\n"); - return 1; +value_type Debug(mu::value_type v1, mu::value_type v2) { + ParserBase::EnableDebugDump(v1 != 0, v2 != 0); + mu::console() << _T("Bytecode dumping ") << ((v1 != 0) ? _T("active") : _T("inactive")) + << _T("\n"); + return 1; } //--------------------------------------------------------------------------- // Factory function for creating new parser variables // This could as well be a function performing database queries. -value_type* AddVariable(const char_type *a_szName, void *a_pUserData) -{ - // I don't want dynamic allocation here, so i used this static buffer - // If you want dynamic allocation you must allocate all variables dynamically - // in order to delete them later on. Or you find other ways to keep track of - // variables that have been created implicitely. - static value_type afValBuf[100]; - static int iVal = -1; +value_type *AddVariable(const char_type *a_szName, void *a_pUserData) { + // I don't want dynamic allocation here, so i used this static buffer + // If you want dynamic allocation you must allocate all variables dynamically + // in order to delete them later on. Or you find other ways to keep track of + // variables that have been created implicitely. + static value_type afValBuf[100]; + static int iVal = -1; - ++iVal; + ++iVal; - mu::console() << _T("Generating new variable \"") - << a_szName << std::dec << _T("\" (slots left: ") - << 99-iVal << _T(")") - << _T(" User data pointer is:") - << std::hex << a_pUserData <=99) - throw mu::ParserError( _T("Variable buffer overflow.") ); - else - return &afValBuf[iVal]; + if (iVal >= 99) + throw mu::ParserError(_T("Variable buffer overflow.")); + else + return &afValBuf[iVal]; } -int IsHexValue(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) -{ - if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') ) - return 0; +int IsHexValue(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal) { + if (a_szExpr[1] == 0 || (a_szExpr[0] != '0' || a_szExpr[1] != 'x')) return 0; - unsigned iVal(0); + unsigned iVal(0); - // New code based on streams for UNICODE compliance: - stringstream_type::pos_type nPos(0); - stringstream_type ss(a_szExpr + 2); - ss >> std::hex >> iVal; - nPos = ss.tellg(); + // New code based on streams for UNICODE compliance: + stringstream_type::pos_type nPos(0); + stringstream_type ss(a_szExpr + 2); + ss >> std::hex >> iVal; + nPos = ss.tellg(); + + if (nPos == (stringstream_type::pos_type)0) return 1; + + *a_iPos += (int)(2 + nPos); + *a_fVal = (value_type)iVal; - if (nPos==(stringstream_type::pos_type)0) return 1; - - *a_iPos += (int)(2 + nPos); - *a_fVal = (value_type)iVal; - - return 1; } //--------------------------------------------------------------------------- -void Splash() -{ - mu::console() << _T(" __________ \n"); - mu::console() << _T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n"); - mu::console() << _T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n"); - mu::console() << _T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n"); - mu::console() << _T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n"); - mu::console() << _T(" \\/ \\/ \\/ \\/ \n"); - mu::console() << _T(" Version ") << Parser().GetVersion(pviFULL) << _T("\n"); - mu::console() << _T(" (C) 2015 Ingo Berg\n"); +void Splash() { + mu::console() << _T(" __________ \n"); + mu::console() << _T(" _____ __ __\\______ \\_____ _______ ______ ____ _______\n"); + mu::console() + << _T(" / \\ | | \\| ___/\\__ \\ \\_ __ \\/ ___/_/ __ \\\\_ __ \\ \n"); + mu::console() + << _T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n"); + mu::console() << _T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n"); + mu::console() << _T(" \\/ \\/ \\/ \\/ \n"); + mu::console() << _T(" Version ") << Parser().GetVersion(pviFULL) << _T("\n"); + mu::console() << _T(" (C) 2015 Ingo Berg\n"); } //--------------------------------------------------------------------------- -value_type SelfTest() -{ - mu::console() << _T( "-----------------------------------------------------------\n"); - mu::console() << _T( "Running test suite:\n\n"); +value_type SelfTest() { + mu::console() << _T( "-----------------------------------------------------------\n"); + mu::console() << _T( "Running test suite:\n\n"); - // Skip the self test if the value type is set to an integer type. - if (mu::TypeInfo::IsInteger()) - { - mu::console() << _T( " Test skipped: integer data type are not compatible with the unit test!\n\n"); - } - else - { - mu::Test::ParserTester pt; - pt.Run(); - } + // Skip the self test if the value type is set to an integer type. + if (mu::TypeInfo::IsInteger()) { + mu::console() + << _T( " Test skipped: integer data type are not compatible with the unit test!\n\n"); + } else { + mu::Test::ParserTester pt; + pt.Run(); + } - return 0; + return 0; } //--------------------------------------------------------------------------- -value_type Help() -{ - mu::console() << _T( "-----------------------------------------------------------\n"); - mu::console() << _T( "Commands:\n\n"); - mu::console() << _T( " list var - list parser variables\n"); - mu::console() << _T( " list exprvar - list expression variables\n"); - mu::console() << _T( " list const - list all numeric parser constants\n"); - mu::console() << _T( " opt on - enable optimizer (default)\n"); - mu::console() << _T( " opt off - disable optimizer\n"); - mu::console() << _T( " locale de - switch to german locale\n"); - mu::console() << _T( " locale en - switch to english locale\n"); - mu::console() << _T( " locale reset - reset locale\n"); - mu::console() << _T( " test bulk - test bulk mode\n"); - mu::console() << _T( " quit - exits the parser\n"); - mu::console() << _T( "\nConstants:\n\n"); - mu::console() << _T( " \"_e\" 2.718281828459045235360287\n"); - mu::console() << _T( " \"_pi\" 3.141592653589793238462643\n"); - mu::console() << _T( "-----------------------------------------------------------\n"); - return 0; +value_type Help() { + mu::console() << _T( "-----------------------------------------------------------\n"); + mu::console() << _T( "Commands:\n\n"); + mu::console() << _T( " list var - list parser variables\n"); + mu::console() << _T( " list exprvar - list expression variables\n"); + mu::console() << _T( " list const - list all numeric parser constants\n"); + mu::console() << _T( " opt on - enable optimizer (default)\n"); + mu::console() << _T( " opt off - disable optimizer\n"); + mu::console() << _T( " locale de - switch to german locale\n"); + mu::console() << _T( " locale en - switch to english locale\n"); + mu::console() << _T( " locale reset - reset locale\n"); + mu::console() << _T( " quit - exits the parser\n"); + mu::console() << _T( "\nConstants:\n\n"); + mu::console() << _T( " \"_e\" 2.718281828459045235360287\n"); + mu::console() << _T( " \"_pi\" 3.141592653589793238462643\n"); + mu::console() << _T( "-----------------------------------------------------------\n"); + return 0; } //--------------------------------------------------------------------------- @@ -233,11 +202,16 @@ void CheckLocale() { std::locale loc("German_germany"); console() << _T("Locale settings:\n"); - console() << _T(" Decimal point: '") << std::use_facet >(loc).decimal_point() << _T("'\n"); - console() << _T(" Thousands sep: '") << std::use_facet >(loc).thousands_sep() << _T("'\n"); - console() << _T(" Grouping: '") << std::use_facet >(loc).grouping() << _T("'\n"); - console() << _T(" True is named: '") << std::use_facet >(loc).truename() << _T("'\n"); - console() << _T(" False is named: '") << std::use_facet >(loc).falsename() << _T("'\n"); + console() << _T(" Decimal point: '") << std::use_facet +>(loc).decimal_point() << _T("'\n"); + console() << _T(" Thousands sep: '") << std::use_facet +>(loc).thousands_sep() << _T("'\n"); + console() << _T(" Grouping: '") << std::use_facet >(loc).grouping() +<< _T("'\n"); + console() << _T(" True is named: '") << std::use_facet >(loc).truename() +<< _T("'\n"); + console() << _T(" False is named: '") << std::use_facet >(loc).falsename() +<< _T("'\n"); console() << _T("-----------------------------------------------------------\n"); } catch(...) @@ -252,17 +226,18 @@ void CheckLocale() void CheckDiff() { mu::Parser parser; - value_type x = 1, + value_type x = 1, v1, v2, v3, eps(pow(std::numeric_limits::epsilon(), 0.2)); parser.DefineVar(_T("x"), &x); parser.SetExpr(_T("_e^-x*sin(x)")); - + v1 = parser.Diff(&x, 1), v2 = parser.Diff(&x, 1, eps); - v3 = cos((value_type)1.0)/exp((value_type)1) - sin((value_type)1.0)/exp((value_type)1); //-0.110793765307; + v3 = cos((value_type)1.0)/exp((value_type)1) - sin((value_type)1.0)/exp((value_type)1); +//-0.110793765307; mu::console() << parser.GetExpr() << _T("\n"); mu::console() << _T("v1 = ") << v1 << _T("; v1-v3 = ") << v1-v3 << _T("\n"); mu::console() << _T("v2 = ") << v2 << _T("; v2-v3 = ") << v2-v3 << _T("\n"); @@ -270,323 +245,238 @@ void CheckDiff() */ //--------------------------------------------------------------------------- -void ListVar(const mu::ParserBase &parser) -{ - // Query the used variables (must be done after calc) - mu::varmap_type variables = parser.GetVar(); - if (!variables.size()) - return; +void ListVar(const mu::ParserBase &parser) { + // Query the used variables (must be done after calc) + mu::varmap_type variables = parser.GetVar(); + if (!variables.size()) return; - cout << "\nParser variables:\n"; - cout << "-----------------\n"; - cout << "Number: " << (int)variables.size() << "\n"; - varmap_type::const_iterator item = variables.begin(); - for (; item!=variables.end(); ++item) - mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second << _T("]\n"); + cout << "\nParser variables:\n"; + cout << "-----------------\n"; + cout << "Number: " << (int)variables.size() << "\n"; + varmap_type::const_iterator item = variables.begin(); + for (; item != variables.end(); ++item) + mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second + << _T("]\n"); } //--------------------------------------------------------------------------- -void ListConst(const mu::ParserBase &parser) -{ - mu::console() << _T("\nParser constants:\n"); - mu::console() << _T("-----------------\n"); +void ListConst(const mu::ParserBase &parser) { + mu::console() << _T("\nParser constants:\n"); + mu::console() << _T("-----------------\n"); - mu::valmap_type cmap = parser.GetConst(); - if (!cmap.size()) - { - mu::console() << _T("Expression does not contain constants\n"); - } - else - { - valmap_type::const_iterator item = cmap.begin(); - for (; item!=cmap.end(); ++item) - mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n"); - } + mu::valmap_type cmap = parser.GetConst(); + if (!cmap.size()) { + mu::console() << _T("Expression does not contain constants\n"); + } else { + valmap_type::const_iterator item = cmap.begin(); + for (; item != cmap.end(); ++item) + mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n"); + } } //--------------------------------------------------------------------------- -void ListExprVar(const mu::ParserBase &parser) -{ - string_type sExpr = parser.GetExpr(); - if (sExpr.length()==0) - { - cout << _T("Expression string is empty\n"); - return; - } +void ListExprVar(const mu::ParserBase &parser) { + string_type sExpr = parser.GetExpr(); + if (sExpr.length() == 0) { + cout << _T("Expression string is empty\n"); + return; + } - // Query the used variables (must be done after calc) - mu::console() << _T("\nExpression variables:\n"); - mu::console() << _T("---------------------\n"); - mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n"); + // Query the used variables (must be done after calc) + mu::console() << _T("\nExpression variables:\n"); + mu::console() << _T("---------------------\n"); + mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n"); - varmap_type variables = parser.GetUsedVar(); - if (!variables.size()) - { - mu::console() << _T("Expression does not contain variables\n"); - } - else - { - mu::console() << _T("Number: ") << (int)variables.size() << _T("\n"); - mu::varmap_type::const_iterator item = variables.begin(); - for (; item!=variables.end(); ++item) - mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second << _T("]\n"); - } + varmap_type variables = parser.GetUsedVar(); + if (!variables.size()) { + mu::console() << _T("Expression does not contain variables\n"); + } else { + mu::console() << _T("Number: ") << (int)variables.size() << _T("\n"); + mu::varmap_type::const_iterator item = variables.begin(); + for (; item != variables.end(); ++item) + mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second + << _T("]\n"); + } } //--------------------------------------------------------------------------- /** \brief Check for external keywords. */ -int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) -{ - string_type sLine(a_szLine); +int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) { + string_type sLine(a_szLine); - if ( sLine == _T("quit") ) - { - return -1; - } - else if ( sLine == _T("list var") ) - { - ListVar(a_Parser); - return 1; - } - else if ( sLine == _T("opt on") ) - { - a_Parser.EnableOptimizer(true); - mu::console() << _T("Optimizer enabled\n"); - return 1; - } - else if ( sLine == _T("opt off") ) - { - a_Parser.EnableOptimizer(false); - mu::console() << _T("Optimizer disabled\n"); - return 1; - } - else if ( sLine == _T("list const") ) - { - ListConst(a_Parser); - return 1; - } - else if ( sLine == _T("list exprvar") ) - { - ListExprVar(a_Parser); - return 1; - } - else if ( sLine == _T("locale de") ) - { - mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"); - a_Parser.SetArgSep(';'); - a_Parser.SetDecSep(','); - a_Parser.SetThousandsSep('.'); - return 1; - } - else if ( sLine == _T("locale en") ) - { - mu::console() << _T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n"); - a_Parser.SetArgSep(','); - a_Parser.SetDecSep('.'); - a_Parser.SetThousandsSep(); - return 1; - } - else if ( sLine == _T("locale reset") ) - { - mu::console() << _T("Resetting locale\n"); - a_Parser.ResetLocale(); - return 1; - } - else if ( sLine == _T("test bulk") ) - { - mu::console() << _T("Testing bulk mode\n"); - CalcBulk(); - return 1; - } + if (sLine == _T("quit")) { + return -1; + } else if (sLine == _T("list var")) { + ListVar(a_Parser); + return 1; + } else if (sLine == _T("opt on")) { + a_Parser.EnableOptimizer(true); + mu::console() << _T("Optimizer enabled\n"); + return 1; + } else if (sLine == _T("opt off")) { + a_Parser.EnableOptimizer(false); + mu::console() << _T("Optimizer disabled\n"); + return 1; + } else if (sLine == _T("list const")) { + ListConst(a_Parser); + return 1; + } else if (sLine == _T("list exprvar")) { + ListExprVar(a_Parser); + return 1; + } else if (sLine == _T("locale de")) { + mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"); + a_Parser.SetArgSep(';'); + a_Parser.SetDecSep(','); + a_Parser.SetThousandsSep('.'); + return 1; + } else if (sLine == _T("locale en")) { + mu::console() << _T("Setting english locale: ArgSep=',' DecSep='.' ThousandsSep=''\n"); + a_Parser.SetArgSep(','); + a_Parser.SetDecSep('.'); + a_Parser.SetThousandsSep(); + return 1; + } else if (sLine == _T("locale reset")) { + mu::console() << _T("Resetting locale\n"); + a_Parser.ResetLocale(); + return 1; + } - return 0; + return 0; } //--------------------------------------------------------------------------- -void CalcBulk() -{ - const int nBulkSize = 200; - value_type *x = new value_type[nBulkSize]; - value_type *y = new value_type[nBulkSize]; - value_type *result = new value_type[nBulkSize]; +void Calc() { + mu::Parser parser; - try - { - for (int i=0; i1) - { - mu::console() << _T("Multiple return values detected! Complete list:\n"); + // 2.) As an alternative you can also retrieve multiple return values using this API: + int nNum = parser.GetNumResults(); + if (nNum > 1) { + mu::console() << _T("Multiple return values detected! Complete list:\n"); - // this is the hard way if you need to retrieve multiple subexpression - // results - value_type *v = parser.Eval(nNum); - mu::console() << std::setprecision(12); - for (int i=0; i> sBuf; - } - catch(std::exception & /*exc*/) - { - // there is no unicode compliant way to query exc.what() - // so i'll leave it for this example. - console() << _T("aborting...\n"); - } + try { + Calc(); + } catch (Parser::exception_type &e) { + // Only erros raised during the initialization will end up here + // formula related errors are treated in Calc() + console() << _T("Initialization error: ") << e.GetMsg() << endl; + console() << _T("aborting...") << endl; + string_type sBuf; + console_in() >> sBuf; + } catch (std::exception & /*exc*/) { + // there is no unicode compliant way to query exc.what() + // so i'll leave it for this example. + console() << _T("aborting...\n"); + } - return 0; + return 0; } diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index d3d0f1d80..c6762c56e 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -765,10 +765,6 @@ void ParserBase::ApplyFunc(ParserStack &a_stOpt, ParserStack &stOpt, associated operators. The Stack is filled beginning from index one the value at index zero is not used at all. */ -value_type ParserBase::ParseCmdCode() const { return ParseCmdCodeBulk(0, 0); } - -//--------------------------------------------------------------------------- -/** \brief Evaluate the RPN. - \param nOffset The offset added to variable addresses (for bulk mode) - \param nThreadID OpenMP Thread id of the calling thread -*/ -value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const { - assert(nThreadID <= s_MaxNumOpenMPThreads); - - // Note: The check for nOffset==0 and nThreadID here is not necessary but - // brings a minor performance gain when not in bulk mode. - value_type *Stack = - ((nOffset == 0) && (nThreadID == 0)) - ? &m_vStackBuffer[0] - : &m_vStackBuffer[nThreadID * (m_vStackBuffer.size() / s_MaxNumOpenMPThreads)]; +value_type ParserBase::ParseCmdCode() const { + value_type *Stack = &m_vStackBuffer[0]; value_type buf; int sidx(0); for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok) { @@ -980,7 +962,7 @@ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const { // for details see: // https://groups.google.com/forum/embed/?place=forum/muparser-dev&showsearch=true&showpopout=true&showtabs=false&parenturl=http://muparser.beltoforion.de/mup_forum.html&afterlogin&pli=1#!topic/muparser-dev/szgatgoHTws --sidx; - Stack[sidx] = *(pTok->Oprt.ptr + nOffset) = Stack[sidx + 1]; + Stack[sidx] = *(pTok->Oprt.ptr) = Stack[sidx + 1]; continue; // original code: //--sidx; Stack[sidx] = *pTok->Oprt.ptr = Stack[sidx+1]; continue; @@ -1007,29 +989,29 @@ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const { // value and variable tokens case cmVAR: - Stack[++sidx] = *(pTok->Val.ptr + nOffset); + Stack[++sidx] = *(pTok->Val.ptr); continue; case cmVAL: Stack[++sidx] = pTok->Val.data2; continue; case cmVARPOW2: - buf = *(pTok->Val.ptr + nOffset); + buf = *(pTok->Val.ptr); Stack[++sidx] = buf * buf; continue; case cmVARPOW3: - buf = *(pTok->Val.ptr + nOffset); + buf = *(pTok->Val.ptr); Stack[++sidx] = buf * buf * buf; continue; case cmVARPOW4: - buf = *(pTok->Val.ptr + nOffset); + buf = *(pTok->Val.ptr); Stack[++sidx] = buf * buf * buf * buf; continue; case cmVARMUL: - Stack[++sidx] = *(pTok->Val.ptr + nOffset) * pTok->Val.data + pTok->Val.data2; + Stack[++sidx] = *(pTok->Val.ptr) * pTok->Val.data + pTok->Val.data2; continue; // Next is treatment of numeric functions @@ -1135,80 +1117,6 @@ value_type ParserBase::ParseCmdCodeBulk(int nOffset, int nThreadID) const { continue; } - case cmFUNC_BULK: { - int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch (iArgCount) { - case 0: - sidx += 1; - Stack[sidx] = (*(bulkfun_type0)pTok->Fun.ptr)(nOffset, nThreadID); - continue; - case 1: - Stack[sidx] = - (*(bulkfun_type1)pTok->Fun.ptr)(nOffset, nThreadID, Stack[sidx]); - continue; - case 2: - sidx -= 1; - Stack[sidx] = (*(bulkfun_type2)pTok->Fun.ptr)(nOffset, nThreadID, - Stack[sidx], Stack[sidx + 1]); - continue; - case 3: - sidx -= 2; - Stack[sidx] = (*(bulkfun_type3)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2]); - continue; - case 4: - sidx -= 3; - Stack[sidx] = (*(bulkfun_type4)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3]); - continue; - case 5: - sidx -= 4; - Stack[sidx] = (*(bulkfun_type5)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4]); - continue; - case 6: - sidx -= 5; - Stack[sidx] = (*(bulkfun_type6)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5]); - continue; - case 7: - sidx -= 6; - Stack[sidx] = (*(bulkfun_type7)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]); - continue; - case 8: - sidx -= 7; - Stack[sidx] = (*(bulkfun_type8)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], - Stack[sidx + 7]); - continue; - case 9: - sidx -= 8; - Stack[sidx] = (*(bulkfun_type9)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], - Stack[sidx + 7], Stack[sidx + 8]); - continue; - case 10: - sidx -= 9; - Stack[sidx] = (*(bulkfun_type10)pTok->Fun.ptr)( - nOffset, nThreadID, Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], - Stack[sidx + 7], Stack[sidx + 8], Stack[sidx + 9]); - continue; - default: - assert(0 && "muParser internal error"); - continue; - } - } - default: assert(0 && "muParser internal error"); return 0; @@ -1300,8 +1208,7 @@ void ParserBase::CreateRPN() const { if (iArgCount > 1 && (stOpt.size() == 0 || - (stOpt.top().GetCode() != cmFUNC && stOpt.top().GetCode() != cmFUNC_BULK && - stOpt.top().GetCode() != cmFUNC_STR))) + (stOpt.top().GetCode() != cmFUNC && stOpt.top().GetCode() != cmFUNC_STR))) Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); // The opening bracket was popped from the stack now check if there @@ -1379,7 +1286,6 @@ void ParserBase::CreateRPN() const { case cmOPRT_INFIX: case cmFUNC: - case cmFUNC_BULK: case cmFUNC_STR: stOpt.push(opt); break; @@ -1624,9 +1530,6 @@ void ParserBase::StackDump(const ParserStack &a_stVal, case cmFUNC: mu::console() << _T("FUNC \"") << stOprt.top().GetAsString() << _T("\"\n"); break; - case cmFUNC_BULK: - mu::console() << _T("FUNC_BULK \"") << stOprt.top().GetAsString() << _T("\"\n"); - break; case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"") << stOprt.top().GetAsString() << _T("\"\n"); @@ -1712,23 +1615,4 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; } */ value_type ParserBase::Eval() const { return (this->*m_pParseFormula)(); } -//--------------------------------------------------------------------------- -void ParserBase::Eval(value_type *results, int nBulkSize) { - /* Commented because it is making a unit test impossible - - // Parallelization does not make sense for fewer than 10000 computations - // due to thread creation overhead. If the bulk size is below 2000 - // computation is refused. - if (nBulkSize<2000) - { - throw ParserError(ecUNREASONABLE_NUMBER_OF_COMPUTATIONS); - } - */ - CreateRPN(); - - int i = 0; - for (i = 0; i < nBulkSize; ++i) { - results[i] = ParseCmdCodeBulk(i, 0); - } -} } // namespace mu diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index b181f0021..b649fdd7e 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -380,24 +380,7 @@ void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) { } //--------------------------------------------------------------------------- -/** \brief Add a bulk function to bytecode. - - \param a_iArgc Number of arguments, negative numbers indicate multiarg functions. - \param a_pFun Pointer to function callback. -*/ -void ParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) { - m_iStackPos = m_iStackPos - a_iArgc + 1; - m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - - SToken tok; - tok.Cmd = cmFUNC_BULK; - tok.Fun.argc = a_iArgc; - tok.Fun.ptr = a_pFun; - m_vRPN.push_back(tok); -} - -//--------------------------------------------------------------------------- -/** \brief Add Strung function entry to the parser bytecode. +/** \brief Add String function entry to the parser bytecode. \throw nothrow A string function entry consists of the stack position of the return value, diff --git a/muparser-2.2.5/src/muParserCallback.cpp b/muparser-2.2.5/src/muParserCallback.cpp index 50d988e66..478a464f8 100644 --- a/muparser-2.2.5/src/muParserCallback.cpp +++ b/muparser-2.2.5/src/muParserCallback.cpp @@ -161,119 +161,6 @@ ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) m_iType(tpDBL), m_bAllowOpti(a_bAllowOpti) {} -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type0 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(0), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type1 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(1), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -/** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow -*/ -ParserCallback::ParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(2), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type3 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(3), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type4 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(4), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type5 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(5), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type6 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(6), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type7 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(7), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type8 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(8), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type9 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(9), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti) - : m_pFun((void*)a_pFun), - m_iArgc(10), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC_BULK), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} - //--------------------------------------------------------------------------- ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) : m_pFun((void*)a_pFun), diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 7d361c3ba..7fd891c35 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -213,14 +213,6 @@ API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) { return 0; } -//--------------------------------------------------------------------------- -API_EXPORT(void) mupEvalBulk(muParserHandle_t a_hParser, muFloat_t* a_res, int nSize) { - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->Eval(a_res, nSize); - MU_CATCH -} - //--------------------------------------------------------------------------- API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) { MU_TRY @@ -388,105 +380,6 @@ mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a MU_CATCH } -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun0_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun1_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun2_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun3_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun4_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun5_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun6_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun7_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun8_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun9_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muBulkFun10_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); - MU_CATCH -} - //--------------------------------------------------------------------------- API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) { diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index c63b7d41a..54a753d4e 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -57,7 +57,6 @@ ParserTester::ParserTester() : m_vTestFun() { AddTest(&ParserTester::TestBinOprt); AddTest(&ParserTester::TestException); AddTest(&ParserTester::TestStrArg); - AddTest(&ParserTester::TestBulkMode); ParserTester::c_iCount = 0; } @@ -142,39 +141,6 @@ int ParserTester::TestStrArg() { return iStat; } -//--------------------------------------------------------------------------------------------- -int ParserTester::TestBulkMode() { - int iStat = 0; - mu::console() << _T("testing bulkmode..."); - -#define EQN_TEST_BULK(EXPR, R1, R2, R3, R4, PASS) \ - { \ - double res[] = {R1, R2, R3, R4}; \ - iStat += EqnTestBulk(_T(EXPR), res, (PASS)); \ - } - - // Bulk Variables for the test: - // a: 1,2,3,4 - // b: 2,2,2,2 - // c: 3,3,3,3 - // d: 5,4,3,2 - EQN_TEST_BULK("a", 1, 1, 1, 1, false) - EQN_TEST_BULK("a", 1, 2, 3, 4, true) - EQN_TEST_BULK("b=a", 1, 2, 3, 4, true) - EQN_TEST_BULK("b=a, b*10", 10, 20, 30, 40, true) - EQN_TEST_BULK("b=a, b*10, a", 1, 2, 3, 4, true) - EQN_TEST_BULK("a+b", 3, 4, 5, 6, true) - EQN_TEST_BULK("c*(a+b)", 9, 12, 15, 18, true) -#undef EQN_TEST_BULK - - if (iStat == 0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; -} - //--------------------------------------------------------------------------------------------- int ParserTester::TestBinOprt() { int iStat = 0; @@ -1388,56 +1354,6 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa return iRet; } -//--------------------------------------------------------------------------- -/** \brief Test an expression in Bulk Mode. */ -int ParserTester::EqnTestBulk(const string_type &a_str, double a_fRes[4], bool a_fPass) { - ParserTester::c_iCount++; - - // Define Bulk Variables - int nBulkSize = 4; - value_type vVariableA[] = {1, 2, 3, 4}; // variable values - value_type vVariableB[] = {2, 2, 2, 2}; // variable values - value_type vVariableC[] = {3, 3, 3, 3}; // variable values - value_type vResults[] = {0, 0, 0, 0}; // variable values - int iRet(0); - - try { - Parser p; - p.DefineConst(_T("const1"), 1); - p.DefineConst(_T("const2"), 2); - p.DefineVar(_T("a"), vVariableA); - p.DefineVar(_T("b"), vVariableB); - p.DefineVar(_T("c"), vVariableC); - - p.SetExpr(a_str); - p.Eval(vResults, nBulkSize); - - bool bCloseEnough(true); - for (int i = 0; i < nBulkSize; ++i) { - bCloseEnough &= (fabs(a_fRes[i] - vResults[i]) <= fabs(a_fRes[i] * 0.00001)); - } - - iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1; - if (iRet == 1) { - mu::console() << _T("\n fail: ") << a_str.c_str() - << _T(" (incorrect result; expected: {") << a_fRes[0] << _T(",") - << a_fRes[1] << _T(",") << a_fRes[2] << _T(",") << a_fRes[3] << _T("}") - << _T(" ;calculated: ") << vResults[0] << _T(",") << vResults[1] - << _T(",") << vResults[2] << _T(",") << vResults[3] << _T("}"); - } - } catch (Parser::exception_type &e) { - if (a_fPass) { - mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); - iRet = 1; - } - } catch (...) { - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)"); - iRet = 1; // exceptions other than ParserException are not allowed - } - - return iRet; -} - //--------------------------------------------------------------------------- /** \brief Internal error in test class Test is going to be aborted. */ void ParserTester::Abort() const { From a7f610549787537896cb4c2fc8b4bebe1dedcf51 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 10:48:09 -0800 Subject: [PATCH 11/62] [muparser] Remove the optimizer The optimizer adds a fair amount of complexity in muparser with no benefit to fish, since fish is not going to use complicated expressions or cache parsed expressions. --- muparser-2.2.5/include/muParserBase.h | 1 - muparser-2.2.5/include/muParserBytecode.h | 4 - muparser-2.2.5/samples/example1/example1.cpp | 12 +- muparser-2.2.5/src/muParserBase.cpp | 10 -- muparser-2.2.5/src/muParserBytecode.cpp | 136 +------------------ muparser-2.2.5/src/muParserTest.cpp | 2 - 6 files changed, 6 insertions(+), 159 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index a613e59c5..06e82e627 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -109,7 +109,6 @@ class ParserBase { void SetThousandsSep(char_type cThousandsSep = 0); void ResetLocale(); - void EnableOptimizer(bool a_bIsOn = true); void EnableBuiltInOprt(bool a_bIsOn = true); bool HasBuiltInOprt() const; diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index 7ea808ff2..d3509364e 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -95,8 +95,6 @@ class ParserByteCode { /** \brief The actual rpn storage. */ rpn_type m_vRPN; - bool m_bEnableOptimizer; - void ConstantFolding(ECmdCode a_Oprt); public: @@ -113,8 +111,6 @@ class ParserByteCode { void AddFun(generic_fun_type a_pFun, int a_iArgc); void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx); - void EnableOptimizer(bool bStat); - void Finalize(); void clear(); std::size_t GetMaxStackSize() const; diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index dc7005e34..f5decefca 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -176,8 +176,6 @@ value_type Help() { mu::console() << _T( " list var - list parser variables\n"); mu::console() << _T( " list exprvar - list expression variables\n"); mu::console() << _T( " list const - list all numeric parser constants\n"); - mu::console() << _T( " opt on - enable optimizer (default)\n"); - mu::console() << _T( " opt off - disable optimizer\n"); mu::console() << _T( " locale de - switch to german locale\n"); mu::console() << _T( " locale en - switch to english locale\n"); mu::console() << _T( " locale reset - reset locale\n"); @@ -310,14 +308,6 @@ int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) { } else if (sLine == _T("list var")) { ListVar(a_Parser); return 1; - } else if (sLine == _T("opt on")) { - a_Parser.EnableOptimizer(true); - mu::console() << _T("Optimizer enabled\n"); - return 1; - } else if (sLine == _T("opt off")) { - a_Parser.EnableOptimizer(false); - mu::console() << _T("Optimizer disabled\n"); - return 1; } else if (sLine == _T("list const")) { ListConst(a_Parser); return 1; @@ -382,7 +372,7 @@ void Calc() { parser.DefineFun(_T("strfun0"), StrFun0); parser.DefineFun(_T("strfun2"), StrFun2); parser.DefineFun(_T("ping"), Ping); - parser.DefineFun(_T("rnd"), Rnd); // Add an unoptimizeable function + parser.DefineFun(_T("rnd"), Rnd); parser.DefineFun(_T("throw"), ThrowAnException); parser.DefineOprt(_T("add"), Add, 0); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index c6762c56e..100fd3e54 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1441,16 +1441,6 @@ void ParserBase::ClearInfixOprt() { ReInit(); } -//------------------------------------------------------------------------------ -/** \brief Enable or disable the formula optimization feature. - \post Resets the parser to string parser mode. - \throw nothrow -*/ -void ParserBase::EnableOptimizer(bool a_bIsOn) { - m_vRPN.EnableOptimizer(a_bIsOn); - ReInit(); -} - //--------------------------------------------------------------------------- /** \brief Enable the dumping of bytecode and stack content on the console. \param bDumpCmd Flag to enable dumping of the current bytecode to the console. diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index b649fdd7e..bf7b34f36 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -39,8 +39,7 @@ namespace mu { //--------------------------------------------------------------------------- /** \brief Bytecode default constructor. */ -ParserByteCode::ParserByteCode() - : m_iStackPos(0), m_iMaxStackSize(0), m_vRPN(), m_bEnableOptimizer(true) { +ParserByteCode::ParserByteCode() : m_iStackPos(0), m_iMaxStackSize(0), m_vRPN() { m_vRPN.reserve(50); } @@ -61,9 +60,6 @@ ParserByteCode &ParserByteCode::operator=(const ParserByteCode &a_ByteCode) { return *this; } -//--------------------------------------------------------------------------- -void ParserByteCode::EnableOptimizer(bool bStat) { m_bEnableOptimizer = bStat; } - //--------------------------------------------------------------------------- /** \brief Copy state of another object to this. @@ -75,7 +71,6 @@ void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) { m_iStackPos = a_ByteCode.m_iStackPos; m_vRPN = a_ByteCode.m_vRPN; m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; - m_bEnableOptimizer = a_ByteCode.m_bEnableOptimizer; } //--------------------------------------------------------------------------- @@ -203,131 +198,10 @@ void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) { \sa ParserToken::ECmdCode */ void ParserByteCode::AddOp(ECmdCode a_Oprt) { - bool bOptimized = false; - - if (m_bEnableOptimizer) { - std::size_t sz = m_vRPN.size(); - - // Check for foldable constants like: - // cmVAL cmVAL cmADD - // where cmADD can stand fopr any binary operator applied to - // two constant values. - if (sz >= 2 && m_vRPN[sz - 2].Cmd == cmVAL && m_vRPN[sz - 1].Cmd == cmVAL) { - ConstantFolding(a_Oprt); - bOptimized = true; - } else { - switch (a_Oprt) { - case cmPOW: - // Optimization for polynomials of low order - if (m_vRPN[sz - 2].Cmd == cmVAR && m_vRPN[sz - 1].Cmd == cmVAL) { - if (m_vRPN[sz - 1].Val.data2 == 2) - m_vRPN[sz - 2].Cmd = cmVARPOW2; - else if (m_vRPN[sz - 1].Val.data2 == 3) - m_vRPN[sz - 2].Cmd = cmVARPOW3; - else if (m_vRPN[sz - 1].Val.data2 == 4) - m_vRPN[sz - 2].Cmd = cmVARPOW4; - else - break; - - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmSUB: - case cmADD: - // Simple optimization based on pattern recognition for a shitload of different - // bytecode combinations of addition/subtraction - if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) || - (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR) || - (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) || - (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL) || - (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && - m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || - (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVARMUL && - m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || - (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAR && - m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr) || - (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVARMUL && - m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)) { - assert((m_vRPN[sz - 2].Val.ptr == NULL && m_vRPN[sz - 1].Val.ptr != NULL) || - (m_vRPN[sz - 2].Val.ptr != NULL && m_vRPN[sz - 1].Val.ptr == NULL) || - (m_vRPN[sz - 2].Val.ptr == m_vRPN[sz - 1].Val.ptr)); - - m_vRPN[sz - 2].Cmd = cmVARMUL; - m_vRPN[sz - 2].Val.ptr = - (value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) | - (long long)(m_vRPN[sz - 1].Val.ptr)); // variable - m_vRPN[sz - 2].Val.data2 += - ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data2; // offset - m_vRPN[sz - 2].Val.data += - ((a_Oprt == cmSUB) ? -1 : 1) * m_vRPN[sz - 1].Val.data; // multiplicand - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmMUL: - if ((m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAL) || - (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVAR)) { - m_vRPN[sz - 2].Cmd = cmVARMUL; - m_vRPN[sz - 2].Val.ptr = - (value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) | - (long long)(m_vRPN[sz - 1].Val.ptr)); - m_vRPN[sz - 2].Val.data = - m_vRPN[sz - 2].Val.data2 + m_vRPN[sz - 1].Val.data2; - m_vRPN[sz - 2].Val.data2 = 0; - m_vRPN.pop_back(); - bOptimized = true; - } else if ((m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL) || - (m_vRPN[sz - 1].Cmd == cmVARMUL && m_vRPN[sz - 2].Cmd == cmVAL)) { - // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 - m_vRPN[sz - 2].Cmd = cmVARMUL; - m_vRPN[sz - 2].Val.ptr = - (value_type *)((long long)(m_vRPN[sz - 2].Val.ptr) | - (long long)(m_vRPN[sz - 1].Val.ptr)); - if (m_vRPN[sz - 1].Cmd == cmVAL) { - m_vRPN[sz - 2].Val.data *= m_vRPN[sz - 1].Val.data2; - m_vRPN[sz - 2].Val.data2 *= m_vRPN[sz - 1].Val.data2; - } else { - m_vRPN[sz - 2].Val.data = - m_vRPN[sz - 1].Val.data * m_vRPN[sz - 2].Val.data2; - m_vRPN[sz - 2].Val.data2 = - m_vRPN[sz - 1].Val.data2 * m_vRPN[sz - 2].Val.data2; - } - m_vRPN.pop_back(); - bOptimized = true; - } else if (m_vRPN[sz - 1].Cmd == cmVAR && m_vRPN[sz - 2].Cmd == cmVAR && - m_vRPN[sz - 1].Val.ptr == m_vRPN[sz - 2].Val.ptr) { - // Optimization: a*a -> a^2 - m_vRPN[sz - 2].Cmd = cmVARPOW2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - case cmDIV: - if (m_vRPN[sz - 1].Cmd == cmVAL && m_vRPN[sz - 2].Cmd == cmVARMUL && - m_vRPN[sz - 1].Val.data2 != 0) { - // Optimization: 4*a/2 -> 2*a - m_vRPN[sz - 2].Val.data /= m_vRPN[sz - 1].Val.data2; - m_vRPN[sz - 2].Val.data2 /= m_vRPN[sz - 1].Val.data2; - m_vRPN.pop_back(); - bOptimized = true; - } - break; - - } // switch a_Oprt - } - } - - // If optimization can't be applied just write the value - if (!bOptimized) { - --m_iStackPos; - SToken tok; - tok.Cmd = a_Oprt; - m_vRPN.push_back(tok); - } + --m_iStackPos; + SToken tok; + tok.Cmd = a_Oprt; + m_vRPN.push_back(tok); } //--------------------------------------------------------------------------- diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 54a753d4e..6c1c57188 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -1253,10 +1253,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) fVal[2] = p2.Eval(); // Test assignment operator - // additionally disable Optimizer this time mu::Parser p3; p3 = p2; - p3.EnableOptimizer(false); fVal[3] = p3.Eval(); // Test Eval function for multiple return values From fc110d2c0e6c0fd688adcbcea9316e265eed377e Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 10:51:35 -0800 Subject: [PATCH 12/62] [muparser] Fix "enumeration value not handled in switch" warning It's unclear whether the default behavior is ever executed. Add an assertion to find out the hard way. --- muparser-2.2.5/src/muParserBase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 100fd3e54..71a27482a 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -775,6 +775,9 @@ void ParserBase::ApplyFunc(ParserStack &a_stOpt, ParserStack Date: Wed, 22 Nov 2017 10:52:23 -0800 Subject: [PATCH 13/62] [muparser] Fix "backslash and newline separated by space" warning ASCII art is serious business. --- muparser-2.2.5/samples/example1/example1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index f5decefca..aa77d0510 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -2,7 +2,7 @@ // // __________ // _____ __ __\______ \_____ _______ ______ ____ _______ -// / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ +// / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ | // | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ // |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| // \/ \/ \/ \/ From 5655f255eff8f90be93e50f8663c374e748132c8 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 18 Nov 2017 14:36:14 -0800 Subject: [PATCH 14/62] [muparser] Add a muParser ValueOrError type First steps towards removing exceptions from muParser. --- muparser-2.2.5/include/muParser.h | 58 ++++----- muparser-2.2.5/include/muParserDLL.h | 39 +++--- muparser-2.2.5/include/muParserDef.h | 121 +++++++++++++++---- muparser-2.2.5/include/muParserInt.h | 54 ++++----- muparser-2.2.5/include/muParserTest.h | 74 ++++++------ muparser-2.2.5/samples/example1/example1.cpp | 27 +++-- muparser-2.2.5/src/muParser.cpp | 56 ++++----- muparser-2.2.5/src/muParserBase.cpp | 67 ++++++---- muparser-2.2.5/src/muParserInt.cpp | 52 ++++---- src/builtin_math.cpp | 2 +- 10 files changed, 324 insertions(+), 226 deletions(-) diff --git a/muparser-2.2.5/include/muParser.h b/muparser-2.2.5/include/muParser.h index 42e0cbe1c..3b8ad7120 100644 --- a/muparser-2.2.5/include/muParser.h +++ b/muparser-2.2.5/include/muParser.h @@ -57,49 +57,49 @@ namespace mu { virtual void InitOprt(); virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - value_type Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon = 0) const; + ValueOrError Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon = 0) const; protected: // Trigonometric functions - static value_type Sin(value_type); - static value_type Cos(value_type); - static value_type Tan(value_type); - static value_type Tan2(value_type, value_type); + static ValueOrError Sin(value_type); + static ValueOrError Cos(value_type); + static ValueOrError Tan(value_type); + static ValueOrError Tan2(value_type, value_type); // arcus functions - static value_type ASin(value_type); - static value_type ACos(value_type); - static value_type ATan(value_type); - static value_type ATan2(value_type, value_type); + static ValueOrError ASin(value_type); + static ValueOrError ACos(value_type); + static ValueOrError ATan(value_type); + static ValueOrError ATan2(value_type, value_type); // hyperbolic functions - static value_type Sinh(value_type); - static value_type Cosh(value_type); - static value_type Tanh(value_type); + static ValueOrError Sinh(value_type); + static ValueOrError Cosh(value_type); + static ValueOrError Tanh(value_type); // arcus hyperbolic functions - static value_type ASinh(value_type); - static value_type ACosh(value_type); - static value_type ATanh(value_type); + static ValueOrError ASinh(value_type); + static ValueOrError ACosh(value_type); + static ValueOrError ATanh(value_type); // Logarithm functions - static value_type Log2(value_type); // Logarithm Base 2 - static value_type Log10(value_type); // Logarithm Base 10 - static value_type Ln(value_type); // Logarithm Base e (natural logarithm) + static ValueOrError Log2(value_type); // Logarithm Base 2 + static ValueOrError Log10(value_type); // Logarithm Base 10 + static ValueOrError Ln(value_type); // Logarithm Base e (natural logarithm) // misc - static value_type Exp(value_type); - static value_type Abs(value_type); - static value_type Sqrt(value_type); - static value_type Rint(value_type); - static value_type Sign(value_type); + static ValueOrError Exp(value_type); + static ValueOrError Abs(value_type); + static ValueOrError Sqrt(value_type); + static ValueOrError Rint(value_type); + static ValueOrError Sign(value_type); // Prefix operators // !!! Unary Minus is a MUST if you want to use negative signs !!! - static value_type UnaryMinus(value_type); - static value_type UnaryPlus(value_type); + static ValueOrError UnaryMinus(value_type); + static ValueOrError UnaryPlus(value_type); // Functions with variable number of arguments - static value_type Sum(const value_type *, int); // sum - static value_type Avg(const value_type *, int); // mean value - static value_type Min(const value_type *, int); // minimum - static value_type Max(const value_type *, int); // maximum + static ValueOrError Sum(const value_type *, int); // sum + static ValueOrError Avg(const value_type *, int); // mean value + static ValueOrError Min(const value_type *, int); // minimum + static ValueOrError Max(const value_type *, int); // maximum static int IsVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fVal); }; diff --git a/muparser-2.2.5/include/muParserDLL.h b/muparser-2.2.5/include/muParserDLL.h index 7dae903f4..caaccd9d2 100644 --- a/muparser-2.2.5/include/muParserDLL.h +++ b/muparser-2.2.5/include/muParserDLL.h @@ -55,28 +55,29 @@ typedef wchar_t muChar_t; // character type typedef int muBool_t; // boolean type typedef int muInt_t; // integer type typedef double muFloat_t; // floating point type +using mu::ValueOrError; // function types for calculation -typedef muFloat_t (*muFun0_t)(); -typedef muFloat_t (*muFun1_t)(muFloat_t); -typedef muFloat_t (*muFun2_t)(muFloat_t, muFloat_t); -typedef muFloat_t (*muFun3_t)(muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun4_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun5_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun6_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun7_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t); -typedef muFloat_t (*muFun8_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t); -typedef muFloat_t (*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef ValueOrError (*muFun0_t)(); +typedef ValueOrError (*muFun1_t)(muFloat_t); +typedef ValueOrError (*muFun2_t)(muFloat_t, muFloat_t); +typedef ValueOrError (*muFun3_t)(muFloat_t, muFloat_t, muFloat_t); +typedef ValueOrError (*muFun4_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef ValueOrError (*muFun5_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef ValueOrError (*muFun6_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); +typedef ValueOrError (*muFun7_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t); +typedef ValueOrError (*muFun8_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t); +typedef ValueOrError (*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t); +typedef ValueOrError (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, + muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef muFloat_t (*muMultFun_t)(const muFloat_t *, muInt_t); -typedef muFloat_t (*muStrFun1_t)(const muChar_t *); -typedef muFloat_t (*muStrFun2_t)(const muChar_t *, muFloat_t); -typedef muFloat_t (*muStrFun3_t)(const muChar_t *, muFloat_t, muFloat_t); +typedef ValueOrError (*muMultFun_t)(const muFloat_t *, muInt_t); +typedef ValueOrError (*muStrFun1_t)(const muChar_t *); +typedef ValueOrError (*muStrFun2_t)(const muChar_t *, muFloat_t); +typedef ValueOrError (*muStrFun3_t)(const muChar_t *, muFloat_t, muFloat_t); // Functions for parser management typedef void (*muErrorHandler_t)( diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 6666df808..712dc67d8 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -25,8 +25,10 @@ #ifndef MUP_DEF_H #define MUP_DEF_H +#include #include #include +#include #include #include #include @@ -352,60 +354,137 @@ class ParserError { EErrorCodes m_iErrc; ///< Error code }; +// Compatibility with non-clang compilers. +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +// Define a type-level attribute declaring that this type, when used as the return value +// of a function, should produce warnings. +#if __has_attribute(warn_unused_result) +#define MUPARSER_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define MUPARSER_ATTR_WARN_UNUSED_RESULT +#endif + +// OptionalError is used to optionally encapsulate an error. +class OptionalError { + std::unique_ptr error_{}; + + public: + /// Create an OptionalError that represents no error. + OptionalError() {} + + /// Create an OptionalError for the given error. + /* implicit */ OptionalError(ParserError err) : error_(new ParserError(std::move(err))) {} + + /// \return whether an error is present. + bool has_error() const { return bool(error_); } + + /// \return the error. asserts if this is not an error. + const ParserError &error() const { + assert(error_ && "Value did not error"); + return *error_; + } +} MUPARSER_ATTR_WARN_UNUSED_RESULT; + +// ValueOrError is used to propagate failures to callers. +class ValueOrError { + value_type value_{0}; + OptionalError error_{}; + + public: + /// \return true if this has a value, false if it is an error. + bool has_value() const { return !error_.has_error(); } + + /// \return false if this has a value,true if it is an error. + bool has_error() const { return error_.has_error(); } + + /// Construct from a value. + /* implicit */ ValueOrError(value_type value) : value_(value) {} + + /// Construct from an error. + /* implicit */ ValueOrError(ParserError err) : error_(std::move(err)) {} + + /// \return the error. asserts if this is not an error. + const ParserError &error() const { return error_.error(); } + + /// \return the value. asserts if this is an error. + value_type value() const { + assert(has_value() && "Value is an error"); + return value_; + } + + /// \return the value or throw the error + value_type getOrThrow() const { + if (has_error()) throw error(); + return value(); + } + + /// \return whether this has a value. + explicit operator bool() const { return has_value(); } + + value_type operator*() const { + assert(has_value() && "Cannot access value with error"); + return value_; + } + +} MUPARSER_ATTR_WARN_UNUSED_RESULT; + // Parser callbacks /** \brief Callback type used for functions without arguments. */ -typedef value_type (*generic_fun_type)(); +typedef ValueOrError (*generic_fun_type)(); /** \brief Callback type used for functions without arguments. */ -typedef value_type (*fun_type0)(); +typedef ValueOrError (*fun_type0)(); /** \brief Callback type used for functions with a single arguments. */ -typedef value_type (*fun_type1)(value_type); +typedef ValueOrError (*fun_type1)(value_type); /** \brief Callback type used for functions with two arguments. */ -typedef value_type (*fun_type2)(value_type, value_type); +typedef ValueOrError (*fun_type2)(value_type, value_type); /** \brief Callback type used for functions with three arguments. */ -typedef value_type (*fun_type3)(value_type, value_type, value_type); +typedef ValueOrError (*fun_type3)(value_type, value_type, value_type); /** \brief Callback type used for functions with four arguments. */ -typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type); +typedef ValueOrError (*fun_type4)(value_type, value_type, value_type, value_type); /** \brief Callback type used for functions with five arguments. */ -typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type); +typedef ValueOrError (*fun_type5)(value_type, value_type, value_type, value_type, value_type); /** \brief Callback type used for functions with five arguments. */ -typedef value_type (*fun_type6)(value_type, value_type, value_type, value_type, value_type, - value_type); +typedef ValueOrError (*fun_type6)(value_type, value_type, value_type, value_type, value_type, + value_type); /** \brief Callback type used for functions with five arguments. */ -typedef value_type (*fun_type7)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type); +typedef ValueOrError (*fun_type7)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type); /** \brief Callback type used for functions with five arguments. */ -typedef value_type (*fun_type8)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type, value_type); +typedef ValueOrError (*fun_type8)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type, value_type); /** \brief Callback type used for functions with five arguments. */ -typedef value_type (*fun_type9)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type); +typedef ValueOrError (*fun_type9)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type); /** \brief Callback type used for functions with five arguments. */ -typedef value_type (*fun_type10)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type, value_type); +typedef ValueOrError (*fun_type10)(value_type, value_type, value_type, value_type, value_type, + value_type, value_type, value_type, value_type, value_type); /** \brief Callback type used for functions with a variable argument list. */ -typedef value_type (*multfun_type)(const value_type *, int); +typedef ValueOrError (*multfun_type)(const value_type *, int); /** \brief Callback type used for functions taking a string as an argument. */ -typedef value_type (*strfun_type1)(const char_type *); +typedef ValueOrError (*strfun_type1)(const char_type *); /** \brief Callback type used for functions taking a string and a value as arguments. */ -typedef value_type (*strfun_type2)(const char_type *, value_type); +typedef ValueOrError (*strfun_type2)(const char_type *, value_type); /** \brief Callback type used for functions taking a string and two values as arguments. */ -typedef value_type (*strfun_type3)(const char_type *, value_type, value_type); +typedef ValueOrError (*strfun_type3)(const char_type *, value_type, value_type); /** \brief Callback used for functions that identify values in a string. */ typedef int (*identfun_type)(const char_type *sExpr, int *nPos, value_type *fVal); diff --git a/muparser-2.2.5/include/muParserInt.h b/muparser-2.2.5/include/muParserInt.h index 6869fd67e..c1f687669 100644 --- a/muparser-2.2.5/include/muParserInt.h +++ b/muparser-2.2.5/include/muParserInt.h @@ -45,36 +45,36 @@ class ParserInt : public ParserBase { private: static int Round(value_type v) { return (int)(v + ((v >= 0) ? 0.5 : -0.5)); }; - static value_type Abs(value_type); - static value_type Sign(value_type); - static value_type Ite(value_type, value_type, value_type); + static ValueOrError Abs(value_type); + static ValueOrError Sign(value_type); + static ValueOrError Ite(value_type, value_type, value_type); // !! The unary Minus is a MUST, otherwise you cant use negative signs !! - static value_type UnaryMinus(value_type); + static ValueOrError UnaryMinus(value_type); // Functions with variable number of arguments - static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum - static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum - static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum + static ValueOrError Sum(const value_type* a_afArg, int a_iArgc); // sum + static ValueOrError Min(const value_type* a_afArg, int a_iArgc); // minimum + static ValueOrError Max(const value_type* a_afArg, int a_iArgc); // maximum // binary operator callbacks - static value_type Add(value_type v1, value_type v2); - static value_type Sub(value_type v1, value_type v2); - static value_type Mul(value_type v1, value_type v2); - static value_type Div(value_type v1, value_type v2); - static value_type Mod(value_type v1, value_type v2); - static value_type Pow(value_type v1, value_type v2); - static value_type Shr(value_type v1, value_type v2); - static value_type Shl(value_type v1, value_type v2); - static value_type LogAnd(value_type v1, value_type v2); - static value_type LogOr(value_type v1, value_type v2); - static value_type And(value_type v1, value_type v2); - static value_type Or(value_type v1, value_type v2); - static value_type Xor(value_type v1, value_type v2); - static value_type Less(value_type v1, value_type v2); - static value_type Greater(value_type v1, value_type v2); - static value_type LessEq(value_type v1, value_type v2); - static value_type GreaterEq(value_type v1, value_type v2); - static value_type Equal(value_type v1, value_type v2); - static value_type NotEqual(value_type v1, value_type v2); - static value_type Not(value_type v1); + static ValueOrError Add(value_type v1, value_type v2); + static ValueOrError Sub(value_type v1, value_type v2); + static ValueOrError Mul(value_type v1, value_type v2); + static ValueOrError Div(value_type v1, value_type v2); + static ValueOrError Mod(value_type v1, value_type v2); + static ValueOrError Pow(value_type v1, value_type v2); + static ValueOrError Shr(value_type v1, value_type v2); + static ValueOrError Shl(value_type v1, value_type v2); + static ValueOrError LogAnd(value_type v1, value_type v2); + static ValueOrError LogOr(value_type v1, value_type v2); + static ValueOrError And(value_type v1, value_type v2); + static ValueOrError Or(value_type v1, value_type v2); + static ValueOrError Xor(value_type v1, value_type v2); + static ValueOrError Less(value_type v1, value_type v2); + static ValueOrError Greater(value_type v1, value_type v2); + static ValueOrError LessEq(value_type v1, value_type v2); + static ValueOrError GreaterEq(value_type v1, value_type v2); + static ValueOrError Equal(value_type v1, value_type v2); + static ValueOrError NotEqual(value_type v1, value_type v2); + static ValueOrError Not(value_type v1); static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); static int IsBinVal(const char_type* a_szExpr, int* a_iPos, value_type* a_iVal); diff --git a/muparser-2.2.5/include/muParserTest.h b/muparser-2.2.5/include/muParserTest.h index 2ad907b80..ff6738784 100644 --- a/muparser-2.2.5/include/muParserTest.h +++ b/muparser-2.2.5/include/muParserTest.h @@ -50,65 +50,65 @@ class ParserTester // final static int c_iCount; // Multiarg callbacks - static value_type f1of1(value_type v) { return v; }; + static ValueOrError f1of1(value_type v) { return v; }; - static value_type f1of2(value_type v, value_type) { return v; }; - static value_type f2of2(value_type, value_type v) { return v; }; + static ValueOrError f1of2(value_type v, value_type) { return v; }; + static ValueOrError f2of2(value_type, value_type v) { return v; }; - static value_type f1of3(value_type v, value_type, value_type) { return v; }; - static value_type f2of3(value_type, value_type v, value_type) { return v; }; - static value_type f3of3(value_type, value_type, value_type v) { return v; }; + static ValueOrError f1of3(value_type v, value_type, value_type) { return v; }; + static ValueOrError f2of3(value_type, value_type v, value_type) { return v; }; + static ValueOrError f3of3(value_type, value_type, value_type v) { return v; }; - static value_type f1of4(value_type v, value_type, value_type, value_type) { return v; } - static value_type f2of4(value_type, value_type v, value_type, value_type) { return v; } - static value_type f3of4(value_type, value_type, value_type v, value_type) { return v; } - static value_type f4of4(value_type, value_type, value_type, value_type v) { return v; } + static ValueOrError f1of4(value_type v, value_type, value_type, value_type) { return v; } + static ValueOrError f2of4(value_type, value_type v, value_type, value_type) { return v; } + static ValueOrError f3of4(value_type, value_type, value_type v, value_type) { return v; } + static ValueOrError f4of4(value_type, value_type, value_type, value_type v) { return v; } - static value_type f1of5(value_type v, value_type, value_type, value_type, value_type) { + static ValueOrError f1of5(value_type v, value_type, value_type, value_type, value_type) { return v; } - static value_type f2of5(value_type, value_type v, value_type, value_type, value_type) { + static ValueOrError f2of5(value_type, value_type v, value_type, value_type, value_type) { return v; } - static value_type f3of5(value_type, value_type, value_type v, value_type, value_type) { + static ValueOrError f3of5(value_type, value_type, value_type v, value_type, value_type) { return v; } - static value_type f4of5(value_type, value_type, value_type, value_type v, value_type) { + static ValueOrError f4of5(value_type, value_type, value_type, value_type v, value_type) { return v; } - static value_type f5of5(value_type, value_type, value_type, value_type, value_type v) { + static ValueOrError f5of5(value_type, value_type, value_type, value_type, value_type v) { return v; } - static value_type Min(value_type a_fVal1, value_type a_fVal2) { + static ValueOrError Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 < a_fVal2) ? a_fVal1 : a_fVal2; } - static value_type Max(value_type a_fVal1, value_type a_fVal2) { + static ValueOrError Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 > a_fVal2) ? a_fVal1 : a_fVal2; } - static value_type plus2(value_type v1) { return v1 + 2; } - static value_type times3(value_type v1) { return v1 * 3; } - static value_type sqr(value_type v1) { return v1 * v1; } - static value_type sign(value_type v) { return -v; } - static value_type add(value_type v1, value_type v2) { return v1 + v2; } - static value_type land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } + static ValueOrError plus2(value_type v1) { return v1 + 2; } + static ValueOrError times3(value_type v1) { return v1 * 3; } + static ValueOrError sqr(value_type v1) { return v1 * v1; } + static ValueOrError sign(value_type v) { return -v; } + static ValueOrError add(value_type v1, value_type v2) { return v1 + v2; } + static ValueOrError land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } - static value_type FirstArg(const value_type* a_afArg, int a_iArgc) { + static ValueOrError FirstArg(const value_type* a_afArg, int a_iArgc) { if (!a_iArgc) throw mu::Parser::exception_type(_T("too few arguments for function FirstArg.")); return a_afArg[0]; } - static value_type LastArg(const value_type* a_afArg, int a_iArgc) { + static ValueOrError LastArg(const value_type* a_afArg, int a_iArgc) { if (!a_iArgc) throw mu::Parser::exception_type(_T("too few arguments for function LastArg.")); return a_afArg[a_iArgc - 1]; } - static value_type Sum(const value_type* a_afArg, int a_iArgc) { + static ValueOrError Sum(const value_type* a_afArg, int a_iArgc) { if (!a_iArgc) throw mu::Parser::exception_type(_T("too few arguments for function sum.")); value_type fRes = 0; @@ -116,46 +116,46 @@ class ParserTester // final return fRes; } - static value_type Rnd(value_type v) { + static ValueOrError Rnd(value_type v) { return (value_type)(1 + (v * std::rand() / (RAND_MAX + 1.0))); } - static value_type RndWithString(const char_type*) { + static ValueOrError RndWithString(const char_type*) { return (value_type)(1 + (1000.0f * std::rand() / (RAND_MAX + 1.0))); } - static value_type Ping() { return 10; } + static ValueOrError Ping() { return 10; } - static value_type ValueOf(const char_type*) { return 123; } + static ValueOrError ValueOf(const char_type*) { return 123; } - static value_type StrFun1(const char_type* v1) { + static ValueOrError StrFun1(const char_type* v1) { int val(0); stringstream_type(v1) >> val; return (value_type)val; } - static value_type StrFun2(const char_type* v1, value_type v2) { + static ValueOrError StrFun2(const char_type* v1, value_type v2) { int val(0); stringstream_type(v1) >> val; return (value_type)(val + v2); } - static value_type StrFun3(const char_type* v1, value_type v2, value_type v3) { + static ValueOrError StrFun3(const char_type* v1, value_type v2, value_type v3) { int val(0); stringstream_type(v1) >> val; return val + v2 + v3; } - static value_type StrToFloat(const char_type* a_szMsg) { + static ValueOrError StrToFloat(const char_type* a_szMsg) { value_type val(0); stringstream_type(a_szMsg) >> val; return val; } // postfix operator callback - static value_type Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; } - static value_type Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; } - static value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } + static ValueOrError Mega(value_type a_fVal) { return a_fVal * (value_type)1e6; } + static ValueOrError Micro(value_type a_fVal) { return a_fVal * (value_type)1e-6; } + static ValueOrError Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } // Custom value recognition static int IsHexVal(const char_type* a_szExpr, int* a_iPos, value_type* a_fVal); diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index aa77d0510..c54ad3e1e 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -56,39 +56,40 @@ struct DumpLeaks { #endif // Operator callback functions -value_type Mega(value_type a_fVal) { return a_fVal * 1e6; } -value_type Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } -value_type Rnd(value_type v) { return v * std::rand() / (value_type)(RAND_MAX + 1.0); } -value_type Not(value_type v) { return v == 0; } -value_type Add(value_type v1, value_type v2) { return v1 + v2; } -value_type Mul(value_type v1, value_type v2) { return v1 * v2; } +ValueOrError Mega(value_type a_fVal) { return a_fVal * 1e6; } +ValueOrError Milli(value_type a_fVal) { return a_fVal / (value_type)1e3; } +ValueOrError Rnd(value_type v) { return v * std::rand() / (value_type)(RAND_MAX + 1.0); } +ValueOrError Not(value_type v) { return v == 0; } +ValueOrError Add(value_type v1, value_type v2) { return v1 + v2; } +ValueOrError Mul(value_type v1, value_type v2) { return v1 * v2; } //--------------------------------------------------------------------------- -value_type ThrowAnException(value_type) { +ValueOrError ThrowAnException(value_type) { throw std::runtime_error("This function does throw an exception."); } //--------------------------------------------------------------------------- -value_type Ping() { +//--------------------------------------------------------------------------- +ValueOrError Ping() { mu::console() << "ping\n"; return 0; } //--------------------------------------------------------------------------- -value_type StrFun0(const char_type *szMsg) { +ValueOrError StrFun0(const char_type *szMsg) { if (szMsg) mu::console() << szMsg << std::endl; return 999; } //--------------------------------------------------------------------------- -value_type StrFun2(const char_type *v1, value_type v2, value_type v3) { +ValueOrError StrFun2(const char_type *v1, value_type v2, value_type v3) { mu::console() << v1 << std::endl; return v2 + v3; } //--------------------------------------------------------------------------- -value_type Debug(mu::value_type v1, mu::value_type v2) { +ValueOrError Debug(mu::value_type v1, mu::value_type v2) { ParserBase::EnableDebugDump(v1 != 0, v2 != 0); mu::console() << _T("Bytecode dumping ") << ((v1 != 0) ? _T("active") : _T("inactive")) << _T("\n"); @@ -153,7 +154,7 @@ void Splash() { } //--------------------------------------------------------------------------- -value_type SelfTest() { +ValueOrError SelfTest() { mu::console() << _T( "-----------------------------------------------------------\n"); mu::console() << _T( "Running test suite:\n\n"); @@ -170,7 +171,7 @@ value_type SelfTest() { } //--------------------------------------------------------------------------- -value_type Help() { +ValueOrError Help() { mu::console() << _T( "-----------------------------------------------------------\n"); mu::console() << _T( "Commands:\n\n"); mu::console() << _T( " list var - list parser variables\n"); diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 74b355567..bbd0097f7 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -48,27 +48,27 @@ namespace mu { //--------------------------------------------------------------------------- // Trigonometric function -value_type Parser::Sin(value_type v) { return MathImpl::Sin(v); } -value_type Parser::Cos(value_type v) { return MathImpl::Cos(v); } -value_type Parser::Tan(value_type v) { return MathImpl::Tan(v); } -value_type Parser::ASin(value_type v) { return MathImpl::ASin(v); } -value_type Parser::ACos(value_type v) { return MathImpl::ACos(v); } -value_type Parser::ATan(value_type v) { return MathImpl::ATan(v); } -value_type Parser::ATan2(value_type v1, value_type v2) { +ValueOrError Parser::Sin(value_type v) { return MathImpl::Sin(v); } +ValueOrError Parser::Cos(value_type v) { return MathImpl::Cos(v); } +ValueOrError Parser::Tan(value_type v) { return MathImpl::Tan(v); } +ValueOrError Parser::ASin(value_type v) { return MathImpl::ASin(v); } +ValueOrError Parser::ACos(value_type v) { return MathImpl::ACos(v); } +ValueOrError Parser::ATan(value_type v) { return MathImpl::ATan(v); } +ValueOrError Parser::ATan2(value_type v1, value_type v2) { return MathImpl::ATan2(v1, v2); } -value_type Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } -value_type Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } -value_type Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } -value_type Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } -value_type Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } -value_type Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } +ValueOrError Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } +ValueOrError Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } +ValueOrError Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } +ValueOrError Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } +ValueOrError Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } +ValueOrError Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } //--------------------------------------------------------------------------- // Logarithm functions // Logarithm base 2 -value_type Parser::Log2(value_type v) { +ValueOrError Parser::Log2(value_type v) { #ifdef MUP_MATH_EXCEPTIONS if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Log2")); #endif @@ -77,7 +77,7 @@ value_type Parser::Log2(value_type v) { } // Logarithm base 10 -value_type Parser::Log10(value_type v) { +ValueOrError Parser::Log10(value_type v) { #ifdef MUP_MATH_EXCEPTIONS if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Log10")); #endif @@ -86,7 +86,7 @@ value_type Parser::Log10(value_type v) { } // Logarithm base e (natural logarithm) -value_type Parser::Ln(value_type v) { +ValueOrError Parser::Ln(value_type v) { #ifdef MUP_MATH_EXCEPTIONS if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Ln")); #endif @@ -96,38 +96,38 @@ value_type Parser::Ln(value_type v) { //--------------------------------------------------------------------------- // misc -value_type Parser::Exp(value_type v) { return MathImpl::Exp(v); } -value_type Parser::Abs(value_type v) { return MathImpl::Abs(v); } -value_type Parser::Sqrt(value_type v) { +ValueOrError Parser::Exp(value_type v) { return MathImpl::Exp(v); } +ValueOrError Parser::Abs(value_type v) { return MathImpl::Abs(v); } +ValueOrError Parser::Sqrt(value_type v) { #ifdef MUP_MATH_EXCEPTIONS if (v < 0) throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); #endif return MathImpl::Sqrt(v); } -value_type Parser::Rint(value_type v) { return MathImpl::Rint(v); } -value_type Parser::Sign(value_type v) { return MathImpl::Sign(v); } +ValueOrError Parser::Rint(value_type v) { return MathImpl::Rint(v); } +ValueOrError Parser::Sign(value_type v) { return MathImpl::Sign(v); } //--------------------------------------------------------------------------- /** \brief Callback for the unary minus operator. \param v The value to negate \return -v */ -value_type Parser::UnaryMinus(value_type v) { return -v; } +ValueOrError Parser::UnaryMinus(value_type v) { return -v; } //--------------------------------------------------------------------------- /** \brief Callback for the unary minus operator. \param v The value to negate \return -v */ -value_type Parser::UnaryPlus(value_type v) { return v; } +ValueOrError Parser::UnaryPlus(value_type v) { return v; } //--------------------------------------------------------------------------- /** \brief Callback for adding multiple values. \param [in] a_afArg Vector with the function arguments \param [in] a_iArgc The size of a_afArg */ -value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) { +ValueOrError Parser::Sum(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw exception_type(_T("too few arguments for function sum.")); value_type fRes = 0; @@ -140,7 +140,7 @@ value_type Parser::Sum(const value_type *a_afArg, int a_iArgc) { \param [in] a_afArg Vector with the function arguments \param [in] a_iArgc The size of a_afArg */ -value_type Parser::Avg(const value_type *a_afArg, int a_iArgc) { +ValueOrError Parser::Avg(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw exception_type(_T("too few arguments for function sum.")); value_type fRes = 0; @@ -153,7 +153,7 @@ value_type Parser::Avg(const value_type *a_afArg, int a_iArgc) { \param [in] a_afArg Vector with the function arguments \param [in] a_iArgc The size of a_afArg */ -value_type Parser::Min(const value_type *a_afArg, int a_iArgc) { +ValueOrError Parser::Min(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw exception_type(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; @@ -167,7 +167,7 @@ value_type Parser::Min(const value_type *a_afArg, int a_iArgc) { \param [in] a_afArg Vector with the function arguments \param [in] a_iArgc The size of a_afArg */ -value_type Parser::Max(const value_type *a_afArg, int a_iArgc) { +ValueOrError Parser::Max(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw exception_type(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; @@ -330,7 +330,7 @@ void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 */ -value_type Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const { +ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const { value_type fRes(0), fBuf(*a_Var), f[4] = {0, 0, 0, 0}, fEpsilon(a_fEpsilon); // Backwards compatible calculation of epsilon inc case the user doesn't provide diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 71a27482a..d863ed88f 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1025,62 +1025,74 @@ value_type ParserBase::ParseCmdCode() const { switch (iArgCount) { case 0: sidx += 1; - Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)(); + Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)().getOrThrow(); continue; case 1: - Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]); + Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]).getOrThrow(); continue; case 2: sidx -= 1; - Stack[sidx] = (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1]); + Stack[sidx] = + (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1]).getOrThrow(); continue; case 3: sidx -= 2; Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2]); + Stack[sidx + 2]) + .getOrThrow(); continue; case 4: sidx -= 3; Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3]); + Stack[sidx + 2], Stack[sidx + 3]) + .getOrThrow(); continue; case 5: sidx -= 4; Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4]); + Stack[sidx + 4]) + .getOrThrow(); continue; case 6: sidx -= 5; Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5]); + Stack[sidx + 4], Stack[sidx + 5]) + .getOrThrow(); continue; case 7: sidx -= 6; - Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)( - Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6]); + Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], + Stack[sidx + 6]) + .getOrThrow(); continue; case 8: sidx -= 7; - Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)( - Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7]); + Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], + Stack[sidx + 6], Stack[sidx + 7]) + .getOrThrow(); continue; case 9: sidx -= 8; Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)( - Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], - Stack[sidx + 8]); + Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], + Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], + Stack[sidx + 6], Stack[sidx + 7], Stack[sidx + 8]) + .getOrThrow(); continue; case 10: sidx -= 9; - Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)( - Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], Stack[sidx + 6], Stack[sidx + 7], - Stack[sidx + 8], Stack[sidx + 9]); + Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], + Stack[sidx + 2], Stack[sidx + 3], + Stack[sidx + 4], Stack[sidx + 5], + Stack[sidx + 6], Stack[sidx + 7], + Stack[sidx + 8], Stack[sidx + 9]) + .getOrThrow(); continue; default: if (iArgCount > 0) // function with variable arguments store the number as @@ -1088,7 +1100,8 @@ value_type ParserBase::ParseCmdCode() const { assert(0 && "muParser internal error"); sidx -= -iArgCount - 1; - Stack[sidx] = (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); + Stack[sidx] = + (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount).getOrThrow(); continue; } } @@ -1105,15 +1118,19 @@ value_type ParserBase::ParseCmdCode() const { { case 0: Stack[sidx] = - (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); + (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()) + .getOrThrow(); continue; case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)( - m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); + m_vStringBuf[iIdxStack].c_str(), Stack[sidx]) + .getOrThrow(); continue; case 2: - Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)( - m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx + 1]); + Stack[sidx] = + (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), + Stack[sidx], Stack[sidx + 1]) + .getOrThrow(); continue; } diff --git a/muparser-2.2.5/src/muParserInt.cpp b/muparser-2.2.5/src/muParserInt.cpp index 3d40f8179..10bbb1a18 100644 --- a/muparser-2.2.5/src/muParserInt.cpp +++ b/muparser-2.2.5/src/muParserInt.cpp @@ -37,40 +37,40 @@ using namespace std; /** \brief Namespace for mathematical applications. */ namespace mu { -value_type ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } -value_type ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; } -value_type ParserInt::Ite(value_type v1, value_type v2, value_type v3) { +ValueOrError ParserInt::Abs(value_type v) { return (value_type)Round(fabs((double)v)); } +ValueOrError ParserInt::Sign(value_type v) { return (Round(v) < 0) ? -1 : (Round(v) > 0) ? 1 : 0; } +ValueOrError ParserInt::Ite(value_type v1, value_type v2, value_type v3) { return (Round(v1) == 1) ? Round(v2) : Round(v3); } -value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } -value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } -value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } -value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } -value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } -value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } -value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } -value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } -value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } -value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } -value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } -value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } -value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } -value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } -value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } -value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } -value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } -value_type ParserInt::Not(value_type v) { return !Round(v); } +ValueOrError ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); } +ValueOrError ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); } +ValueOrError ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); } +ValueOrError ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); } +ValueOrError ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); } +ValueOrError ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); } +ValueOrError ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); } +ValueOrError ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); } +ValueOrError ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); } +ValueOrError ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); } +ValueOrError ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); } +ValueOrError ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); } +ValueOrError ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); } +ValueOrError ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); } +ValueOrError ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); } +ValueOrError ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); } +ValueOrError ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); } +ValueOrError ParserInt::Not(value_type v) { return !Round(v); } -value_type ParserInt::Pow(value_type v1, value_type v2) { +ValueOrError ParserInt::Pow(value_type v1, value_type v2) { return std::pow((double)Round(v1), (double)Round(v2)); } //--------------------------------------------------------------------------- // Unary operator Callbacks: Infix operators -value_type ParserInt::UnaryMinus(value_type v) { return -Round(v); } +ValueOrError ParserInt::UnaryMinus(value_type v) { return -Round(v); } //--------------------------------------------------------------------------- -value_type ParserInt::Sum(const value_type *a_afArg, int a_iArgc) { +ValueOrError ParserInt::Sum(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw ParserError(_T("too few arguments for function sum.")); value_type fRes = 0; @@ -80,7 +80,7 @@ value_type ParserInt::Sum(const value_type *a_afArg, int a_iArgc) { } //--------------------------------------------------------------------------- -value_type ParserInt::Min(const value_type *a_afArg, int a_iArgc) { +ValueOrError ParserInt::Min(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw ParserError(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; @@ -90,7 +90,7 @@ value_type ParserInt::Min(const value_type *a_afArg, int a_iArgc) { } //--------------------------------------------------------------------------- -value_type ParserInt::Max(const value_type *a_afArg, int a_iArgc) { +ValueOrError ParserInt::Max(const value_type *a_afArg, int a_iArgc) { if (!a_iArgc) throw ParserError(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; diff --git a/src/builtin_math.cpp b/src/builtin_math.cpp index 8e733b1cb..2a2325b5c 100644 --- a/src/builtin_math.cpp +++ b/src/builtin_math.cpp @@ -116,7 +116,7 @@ static const wchar_t *math_get_arg(int *argidx, wchar_t **argv, wcstring *storag } /// Implement integer modulo math operator. -static double moduloOperator(double v, double w) { return (int)v % std::max(1, (int)w); }; +static mu::ValueOrError moduloOperator(double v, double w) { return (int)v % std::max(1, (int)w); }; /// Evaluate math expressions. static int evaluate_expression(wchar_t *cmd, parser_t &parser, io_streams_t &streams, From bfd70880a53f6360aac4740d08b831c9dbc0ab2d Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 10:25:52 -0800 Subject: [PATCH 15/62] [muparser] Begin adopting ValueOrError Switch custom function types to return ValueOrError, which will enable us to remove exceptions. --- muparser-2.2.5/include/muParserBase.h | 9 +- muparser-2.2.5/src/muParserBase.cpp | 164 ++++++++++---------------- 2 files changed, 68 insertions(+), 105 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 06e82e627..8be20cee6 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -65,7 +65,7 @@ class ParserBase { the function pointer to the parser function depending on which state it is in. (i.e. bytecode parser vs. string parser) */ - typedef value_type (ParserBase::*ParseFunction)() const; + typedef ValueOrError (ParserBase::*ParseFunction)() const; /** \brief Type used for storing an array of values. */ typedef std::vector valbuf_type; @@ -236,9 +236,10 @@ class ParserBase { void CreateRPN() const; - value_type ParseString() const; - value_type ParseCmdCode() const; - value_type ParseCmdCodeBulk(int nOffset, int nThreadID) const; + ValueOrError ParseString() const; + ValueOrError ParseCmdCode() const; + ValueOrError ParseCmdCodeBulk(int nOffset, int nThreadID) const; + ValueOrError InvokeFunction(generic_fun_type func, const value_type *args, int argCount) const; void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; void CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index d863ed88f..47a5e5e42 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -886,6 +886,44 @@ void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, } } +/// Invoke the function \p func as the fun_typeN given argCount, passing in \p argCount arguments +/// starting at \p args. +ValueOrError ParserBase::InvokeFunction(generic_fun_type func, const value_type *args, + int argCount) const { + assert(0 <= argCount && argCount <= 10 && "Invalid arg count"); + switch (argCount) { + case 0: + return ((fun_type0)func)(); + case 1: + return ((fun_type1)func)(args[0]); + case 2: + return ((fun_type2)func)(args[0], args[1]); + case 3: + return ((fun_type3)func)(args[0], args[1], args[2]); + case 4: + return ((fun_type4)func)(args[0], args[1], args[2], args[3]); + case 5: + return ((fun_type5)func)(args[0], args[1], args[2], args[3], args[4]); + case 6: + return ((fun_type6)func)(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: + return ((fun_type7)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: + return ((fun_type8)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7]); + case 9: + return ((fun_type9)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8]); + case 10: + return ((fun_type10)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9]); + default: + // Unreachable. + assert(0 && "Internal error"); + return 0; + } +} + //--------------------------------------------------------------------------- /** \brief Parse the command code. \sa ParseString(...) @@ -894,7 +932,7 @@ void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, associated operators. The Stack is filled beginning from index one the value at index zero is not used at all. */ -value_type ParserBase::ParseCmdCode() const { +ValueOrError ParserBase::ParseCmdCode() const { value_type *Stack = &m_vStackBuffer[0]; value_type buf; int sidx(0); @@ -1020,90 +1058,18 @@ value_type ParserBase::ParseCmdCode() const { // Next is treatment of numeric functions case cmFUNC: { int iArgCount = pTok->Fun.argc; - - // switch according to argument count - switch (iArgCount) { - case 0: - sidx += 1; - Stack[sidx] = (*(fun_type0)pTok->Fun.ptr)().getOrThrow(); - continue; - case 1: - Stack[sidx] = (*(fun_type1)pTok->Fun.ptr)(Stack[sidx]).getOrThrow(); - continue; - case 2: - sidx -= 1; - Stack[sidx] = - (*(fun_type2)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1]).getOrThrow(); - continue; - case 3: - sidx -= 2; - Stack[sidx] = (*(fun_type3)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2]) - .getOrThrow(); - continue; - case 4: - sidx -= 3; - Stack[sidx] = (*(fun_type4)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3]) - .getOrThrow(); - continue; - case 5: - sidx -= 4; - Stack[sidx] = (*(fun_type5)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4]) - .getOrThrow(); - continue; - case 6: - sidx -= 5; - Stack[sidx] = (*(fun_type6)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5]) - .getOrThrow(); - continue; - case 7: - sidx -= 6; - Stack[sidx] = (*(fun_type7)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], - Stack[sidx + 6]) - .getOrThrow(); - continue; - case 8: - sidx -= 7; - Stack[sidx] = (*(fun_type8)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], - Stack[sidx + 6], Stack[sidx + 7]) - .getOrThrow(); - continue; - case 9: - sidx -= 8; - Stack[sidx] = (*(fun_type9)pTok->Fun.ptr)( - Stack[sidx], Stack[sidx + 1], Stack[sidx + 2], - Stack[sidx + 3], Stack[sidx + 4], Stack[sidx + 5], - Stack[sidx + 6], Stack[sidx + 7], Stack[sidx + 8]) - .getOrThrow(); - continue; - case 10: - sidx -= 9; - Stack[sidx] = (*(fun_type10)pTok->Fun.ptr)(Stack[sidx], Stack[sidx + 1], - Stack[sidx + 2], Stack[sidx + 3], - Stack[sidx + 4], Stack[sidx + 5], - Stack[sidx + 6], Stack[sidx + 7], - Stack[sidx + 8], Stack[sidx + 9]) - .getOrThrow(); - continue; - default: - if (iArgCount > 0) // function with variable arguments store the number as - // a negative value - assert(0 && "muParser internal error"); - - sidx -= -iArgCount - 1; - Stack[sidx] = - (*(multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount).getOrThrow(); - continue; + ValueOrError funcResult{0.0}; + if (iArgCount >= 0) { + sidx -= iArgCount - 1; + funcResult = InvokeFunction(pTok->Fun.ptr, &Stack[sidx], iArgCount); + } else { + // function with variable arguments store the number as a negative value + sidx -= -iArgCount - 1; + funcResult = ((multfun_type)pTok->Fun.ptr)(&Stack[sidx], -iArgCount); } + if (!funcResult) return funcResult; + Stack[sidx] = *funcResult; + continue; } // Next is treatment of string functions @@ -1113,27 +1079,23 @@ value_type ParserBase::ParseCmdCode() const { // The index of the string argument in the string table int iIdxStack = pTok->Fun.idx; MUP_ASSERT(iIdxStack >= 0 && iIdxStack < (int)m_vStringBuf.size()); - + ValueOrError funcResult{0.0}; switch (pTok->Fun.argc) // switch according to argument count { case 0: - Stack[sidx] = - (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()) - .getOrThrow(); - continue; + funcResult = ((strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); + break; case 1: - Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)( - m_vStringBuf[iIdxStack].c_str(), Stack[sidx]) - .getOrThrow(); - continue; + funcResult = ((strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), + Stack[sidx]); + break; case 2: - Stack[sidx] = - (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), - Stack[sidx], Stack[sidx + 1]) - .getOrThrow(); - continue; + funcResult = ((strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), + Stack[sidx], Stack[sidx + 1]); + break; } - + if (!funcResult) return funcResult; + Stack[sidx] = *funcResult; continue; } @@ -1357,7 +1319,7 @@ void ParserBase::CreateRPN() const { pointer #m_pParseFormula will be changed to the second parse routine the uses bytecode instead of string parsing. */ -value_type ParserBase::ParseString() const { +ValueOrError ParserBase::ParseString() const { try { CreateRPN(); m_pParseFormula = &ParserBase::ParseCmdCode; @@ -1623,6 +1585,6 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; } \return The evaluation result \throw ParseException if no Formula is set or in case of any other error related to the formula. */ -value_type ParserBase::Eval() const { return (this->*m_pParseFormula)(); } +value_type ParserBase::Eval() const { return (this->*m_pParseFormula)().getOrThrow(); } } // namespace mu From 9649b132bd31deca799a2bfea68b887e3e25fd8f Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 12:27:10 -0800 Subject: [PATCH 16/62] [muparser] Continue adopting ValueOrError --- muparser-2.2.5/include/muParserBase.h | 4 +-- muparser-2.2.5/include/muParserDLL.h | 1 - muparser-2.2.5/samples/example1/example1.cpp | 13 +++++---- muparser-2.2.5/src/muParser.cpp | 10 +++++-- muparser-2.2.5/src/muParserBase.cpp | 8 +++--- muparser-2.2.5/src/muParserDLL.cpp | 14 +--------- muparser-2.2.5/src/muParserTest.cpp | 29 ++++++++++---------- src/builtin_math.cpp | 10 +++---- 8 files changed, 40 insertions(+), 49 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 8be20cee6..57564eb09 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -97,8 +97,8 @@ class ParserBase { virtual ~ParserBase(); - value_type Eval() const; - value_type *Eval(int &nStackSize) const; + ValueOrError Eval() const; + void Eval(std::vector *results) const; int GetNumResults() const; diff --git a/muparser-2.2.5/include/muParserDLL.h b/muparser-2.2.5/include/muParserDLL.h index caaccd9d2..ccc79ff1f 100644 --- a/muparser-2.2.5/include/muParserDLL.h +++ b/muparser-2.2.5/include/muParserDLL.h @@ -112,7 +112,6 @@ API_EXPORT(void) mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData); API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser); API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); -API_EXPORT(muFloat_t *) mupEvalMulti(muParserHandle_t a_hParser, int *nNum); // Defining callbacks / variables / constants API_EXPORT(void) diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index c54ad3e1e..e4f48839a 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -416,7 +416,7 @@ void Calc() { // 1.) If you know there is only a single return value or in case you only need the last // result of an expression consisting of comma separated subexpressions you can // simply use: - mu::console() << _T("ans=") << parser.Eval() << _T("\n"); + mu::console() << _T("ans=") << *parser.Eval() << _T("\n"); // 2.) As an alternative you can also retrieve multiple return values using this API: int nNum = parser.GetNumResults(); @@ -425,10 +425,11 @@ void Calc() { // this is the hard way if you need to retrieve multiple subexpression // results - value_type *v = parser.Eval(nNum); + std::vector vs; + parser.Eval(&vs); mu::console() << std::setprecision(12); - for (int i = 0; i < nNum; ++i) { - mu::console() << v[i] << _T("\n"); + for (const ValueOrError &v : vs) { + mu::console() << *v << _T("\n"); } } } catch (mu::Parser::exception_type &e) { @@ -446,8 +447,8 @@ void Calc() { //--------------------------------------------------------------------------- int main(int, char **) { Splash(); - SelfTest(); - Help(); + (void)SelfTest(); + (void)Help(); // CheckLocale(); // CheckDiff(); diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index bbd0097f7..6d19b9f25 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -331,9 +331,10 @@ void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 */ ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const { - value_type fRes(0), fBuf(*a_Var), f[4] = {0, 0, 0, 0}, fEpsilon(a_fEpsilon); + value_type fRes(0), fBuf(*a_Var), fEpsilon(a_fEpsilon); + ValueOrError f[4] = {0, 0, 0, 0}; - // Backwards compatible calculation of epsilon inc case the user doesn't provide + // Backwards compatible calculation of epsilon in case the user doesn't provide // his own epsilon if (fEpsilon == 0) fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; @@ -347,7 +348,10 @@ ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEp f[3] = Eval(); *a_Var = fBuf; // restore variable - fRes = (-f[0] + 8 * f[1] - 8 * f[2] + f[3]) / (12 * fEpsilon); + for (ValueOrError &v : f) { + if (!v) return std::move(v); + } + fRes = (-*f[0] + 8 * *f[1] - 8 * *f[2] + *f[3]) / (12 * fEpsilon); return fRes; } } // namespace mu diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 47a5e5e42..f335cdf00 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1552,12 +1552,12 @@ void ParserBase::StackDump(const ParserStack &a_stVal, This member function can be used to retrieve all results of an expression made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") */ -value_type *ParserBase::Eval(int &nStackSize) const { +void ParserBase::Eval(std::vector *outResult) const { (this->*m_pParseFormula)(); - nStackSize = m_nFinalResultIdx; + int stackSize = m_nFinalResultIdx; // (for historic reasons the stack starts at position 1) - return &m_vStackBuffer[1]; + outResult->assign(&m_vStackBuffer[1], &m_vStackBuffer[1 + stackSize]); } //--------------------------------------------------------------------------- @@ -1585,6 +1585,6 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; } \return The evaluation result \throw ParseException if no Formula is set or in case of any other error related to the formula. */ -value_type ParserBase::Eval() const { return (this->*m_pParseFormula)().getOrThrow(); } +ValueOrError ParserBase::Eval() const { return (this->*m_pParseFormula)(); } } // namespace mu diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 7fd891c35..6b196b5a2 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -195,19 +195,7 @@ API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) { API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - return p->Eval(); - MU_CATCH - - return 0; -} - -//--------------------------------------------------------------------------- -API_EXPORT(muFloat_t*) mupEvalMulti(muParserHandle_t a_hParser, int* nNum) { - MU_TRY - assert(nNum != NULL); - - muParser_t* const p(AsParser(a_hParser)); - return p->Eval(*nNum); + return *p->Eval(); MU_CATCH return 0; diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 6c1c57188..8ef1f167d 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -94,14 +94,14 @@ int ParserTester::TestInterface() { p.DefineVar(_T("b"), &afVal[1]); p.DefineVar(_T("c"), &afVal[2]); p.SetExpr(_T("a+b+c")); - p.Eval(); + (void)p.Eval(); } catch (...) { iStat += 1; // this is not supposed to happen } try { p.RemoveVar(_T("c")); - p.Eval(); + (void)p.Eval(); iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... } catch (...) { // failure is expected... @@ -1075,7 +1075,7 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) p.DefineFun(_T("strfun2"), StrFun2); p.DefineFun(_T("strfun3"), StrFun3); p.SetExpr(a_str); - p.Eval(); + (void)p.Eval(); } catch (ParserError &e) { // output the formula in case of an failed test if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) { @@ -1119,10 +1119,10 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1, p.SetExpr(a_str); var = a_fVar1; - fVal[0] = p.Eval(); + fVal[0] = *p.Eval(); var = a_fVar2; - fVal[1] = p.Eval(); + fVal[1] = *p.Eval(); if (fabs(a_fRes1 - fVal[0]) > 0.0000000001) throw std::runtime_error("incorrect result (first pass)"); @@ -1234,8 +1234,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) // Test bytecode integrity // String parsing and bytecode parsing must yield the same result - fVal[0] = p1->Eval(); // result from stringparsing - fVal[1] = p1->Eval(); // result from bytecode + fVal[0] = *p1->Eval(); // result from stringparsing + fVal[1] = *p1->Eval(); // result from bytecode if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); @@ -1250,18 +1250,17 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) vParser.clear(); // delete the vector p1.reset(0); - fVal[2] = p2.Eval(); + fVal[2] = *p2.Eval(); // Test assignment operator mu::Parser p3; p3 = p2; - fVal[3] = p3.Eval(); + fVal[3] = *p3.Eval(); // Test Eval function for multiple return values - // use p2 since it has the optimizer enabled! - int nNum; - value_type *v = p2.Eval(nNum); - fVal[4] = v[nNum - 1]; + std::vector v; + p2.Eval(&v); + fVal[4] = *v.back(); } catch (std::exception &e) { mu::console() << _T("\n ") << e.what() << _T("\n"); } @@ -1328,8 +1327,8 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa p.DefineVar(_T("c"), &vVarVal[2]); p.SetExpr(a_str); - fVal[0] = p.Eval(); // result from stringparsing - fVal[1] = p.Eval(); // result from bytecode + fVal[0] = *p.Eval(); // result from stringparsing + fVal[1] = *p.Eval(); // result from bytecode if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt.")); diff --git a/src/builtin_math.cpp b/src/builtin_math.cpp index 2a2325b5c..196ce32ad 100644 --- a/src/builtin_math.cpp +++ b/src/builtin_math.cpp @@ -131,13 +131,13 @@ static int evaluate_expression(wchar_t *cmd, parser_t &parser, io_streams_t &str p.DefineOprt(L"%", moduloOperator, mu::prINFIX); p.SetExpr(expression); - int nNum; - mu::value_type *v = p.Eval(nNum); - for (int i = 0; i < nNum; ++i) { + std::vector vs; + p.Eval(&vs); + for (const mu::ValueOrError &v : vs) { if (opts.scale == 0) { - streams.out.append_format(L"%ld\n", static_cast(v[i])); + streams.out.append_format(L"%ld\n", static_cast(*v)); } else { - streams.out.append_format(L"%.*lf\n", opts.scale, v[i]); + streams.out.append_format(L"%.*lf\n", opts.scale, *v); } } return STATUS_CMD_OK; From f05b55c84c10ab68bf8a893aca03f136e5548007 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 12:49:06 -0800 Subject: [PATCH 17/62] [muparser] Remove \throw nothrow comments Soon it will all be nothrow! --- muparser-2.2.5/include/muParserToken.h | 10 ---------- muparser-2.2.5/src/muParserBase.cpp | 13 ------------- muparser-2.2.5/src/muParserBytecode.cpp | 7 ------- muparser-2.2.5/src/muParserCallback.cpp | 13 ++----------- muparser-2.2.5/src/muParserDLL.cpp | 2 -- muparser-2.2.5/src/muParserTokenReader.cpp | 11 ----------- 6 files changed, 2 insertions(+), 54 deletions(-) diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index 36222c622..8c690ef49 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -72,7 +72,6 @@ class ParserToken { /** \brief Constructor (default). Sets token to an neutral state of type cmUNKNOWN. - \throw nothrow \sa ECmdCode */ ParserToken() @@ -89,7 +88,6 @@ class ParserToken { /** \brief Create token from another one. Implemented by calling Assign(...) - \throw nothrow \post m_iType==cmUNKNOWN \sa #Assign */ @@ -100,7 +98,6 @@ class ParserToken { Copy token state from another token and return this. Implemented by calling Assign(...). - \throw nothrow */ ParserToken &operator=(const ParserToken &a_Tok) { Assign(a_Tok); @@ -109,8 +106,6 @@ class ParserToken { //------------------------------------------------------------------------------ /** \brief Copy token information from argument. - - \throw nothrow */ void Assign(const ParserToken &a_Tok) { m_iCode = a_Tok.m_iCode; @@ -170,7 +165,6 @@ class ParserToken { /** \brief Make this token a value token. Member variables not necessary for value tokens will be invalidated. - \throw nothrow */ ParserToken &SetVal(TBase a_fVal, const TString &a_strTok = TString()) { m_iCode = cmVAL; @@ -189,7 +183,6 @@ class ParserToken { /** \brief make this token a variable token. Member variables not necessary for variable tokens will be invalidated. - \throw nothrow */ ParserToken &SetVar(TBase *a_pVar, const TString &a_strTok) { m_iCode = cmVAR; @@ -205,7 +198,6 @@ class ParserToken { /** \brief Make this token a variable token. Member variables not necessary for variable tokens will be invalidated. - \throw nothrow */ ParserToken &SetString(const TString &a_strTok, std::size_t a_iSize) { m_iCode = cmSTRING; @@ -249,7 +241,6 @@ class ParserToken { /** \brief Return the token type. \return #m_iType - \throw nothrow */ ECmdCode GetCode() const { if (m_pCallback.get()) { @@ -353,7 +344,6 @@ class ParserToken { If #m_iType is cmSTRING the token identifier is the value of the string argument for a string function. \return #m_strTok - \throw nothrow \sa m_strTok */ const TString &GetAsString() const { return m_strTok; } diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index f335cdf00..0398557e0 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -122,7 +122,6 @@ ParserBase::~ParserBase() {} Implemented by calling Assign(a_Parser). Self assignment is suppressed. \param a_Parser Object to copy to this. \return *this - \throw nothrow */ ParserBase &ParserBase::operator=(const ParserBase &a_Parser) { Assign(a_Parser); @@ -211,7 +210,6 @@ void ParserBase::ResetLocale() { constant and variable definitions. \post m_pTokenReader.get()!=0 - \throw nothrow */ void ParserBase::InitTokenReader() { m_pTokenReader.reset(new token_reader_type(this)); } @@ -219,7 +217,6 @@ void ParserBase::InitTokenReader() { m_pTokenReader.reset(new token_reader_type( /** \brief Reset parser to string parsing mode and clear internal buffers. Clear bytecode, reset the token reader. - \throw nothrow */ void ParserBase::ReInit() const { m_pParseFormula = &ParserBase::ParseString; @@ -646,7 +643,6 @@ const valmap_type &ParserBase::GetConst() const { return m_ConstDef; } /** \brief Return prototypes of all parser functions. \return #m_FunDef \sa FunProt - \throw nothrow The return type is a map of the public type #funmap_type containing the prototype definitions for all numerical parser functions. String functions are not part of @@ -1347,7 +1343,6 @@ void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTo //------------------------------------------------------------------------------ /** \brief Clear all user defined variables. - \throw nothrow Resets the parser to string parsing mode by calling #ReInit. */ @@ -1358,7 +1353,6 @@ void ParserBase::ClearVar() { //------------------------------------------------------------------------------ /** \brief Remove a variable from internal storage. - \throw nothrow Removes a variable if it exists. If the Variable does not exist nothing will be done. */ @@ -1373,7 +1367,6 @@ void ParserBase::RemoveVar(const string_type &a_strVarName) { //------------------------------------------------------------------------------ /** \brief Clear all functions. \post Resets the parser to string parsing mode. - \throw nothrow */ void ParserBase::ClearFun() { m_FunDef.clear(); @@ -1385,7 +1378,6 @@ void ParserBase::ClearFun() { Both numeric and string constants will be removed from the internal storage. \post Resets the parser to string parsing mode. - \throw nothrow */ void ParserBase::ClearConst() { m_ConstDef.clear(); @@ -1396,7 +1388,6 @@ void ParserBase::ClearConst() { //------------------------------------------------------------------------------ /** \brief Clear all user defined postfix operators. \post Resets the parser to string parsing mode. - \throw nothrow */ void ParserBase::ClearPostfixOprt() { m_PostOprtDef.clear(); @@ -1406,7 +1397,6 @@ void ParserBase::ClearPostfixOprt() { //------------------------------------------------------------------------------ /** \brief Clear all user defined binary operators. \post Resets the parser to string parsing mode. - \throw nothrow */ void ParserBase::ClearOprt() { m_OprtDef.clear(); @@ -1416,7 +1406,6 @@ void ParserBase::ClearOprt() { //------------------------------------------------------------------------------ /** \brief Clear the user defined Prefix operators. \post Resets the parser to string parser mode. - \throw nothrow */ void ParserBase::ClearInfixOprt() { m_InfixOprtDef.clear(); @@ -1437,7 +1426,6 @@ void ParserBase::EnableDebugDump(bool bDumpCmd, bool bDumpStack) { //------------------------------------------------------------------------------ /** \brief Enable or disable the built in binary operators. - \throw nothrow \sa m_bBuiltInOp, ReInit() If you disable the built in binary operators there will be no binary operators @@ -1453,7 +1441,6 @@ void ParserBase::EnableBuiltInOprt(bool a_bIsOn) { //------------------------------------------------------------------------------ /** \brief Query status of built in variables. \return #m_bBuiltInOp; true if built in operators are enabled. - \throw nothrow */ bool ParserBase::HasBuiltInOprt() const { return m_bBuiltInOp; } diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index bf7b34f36..8bffa8b8d 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -76,7 +76,6 @@ void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) { //--------------------------------------------------------------------------- /** \brief Add a Variable pointer to bytecode. \param a_pVar Pointer to be added. - \throw nothrow */ void ParserByteCode::AddVar(value_type *a_pVar) { ++m_iStackPos; @@ -102,7 +101,6 @@ void ParserByteCode::AddVar(value_type *a_pVar) { \param a_pVal Value to be added. - \throw nothrow */ void ParserByteCode::AddVal(value_type a_fVal) { ++m_iStackPos; @@ -255,7 +253,6 @@ void ParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) { //--------------------------------------------------------------------------- /** \brief Add String function entry to the parser bytecode. - \throw nothrow A string function entry consists of the stack position of the return value, followed by a cmSTRFUNC code, the function pointer and an index into the @@ -276,8 +273,6 @@ void ParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) //--------------------------------------------------------------------------- /** \brief Add end marker to bytecode. - - \throw nothrow */ void ParserByteCode::Finalize() { SToken tok; @@ -327,8 +322,6 @@ std::size_t ParserByteCode::GetSize() const { return m_vRPN.size(); } //--------------------------------------------------------------------------- /** \brief Delete the bytecode. - \throw nothrow - The name of this function is a violation of my own coding guidelines but this way it's more in line with the STL functions thus more intuitive. diff --git a/muparser-2.2.5/src/muParserCallback.cpp b/muparser-2.2.5/src/muParserCallback.cpp index 478a464f8..fb0d544b3 100644 --- a/muparser-2.2.5/src/muParserCallback.cpp +++ b/muparser-2.2.5/src/muParserCallback.cpp @@ -52,7 +52,6 @@ ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, //--------------------------------------------------------------------------- /** \brief Constructor for constructing function callbacks taking two arguments. - \throw nothrow */ ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) : m_pFun((void*)a_pFun), @@ -69,7 +68,6 @@ ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) \param a_bAllowOpti A flag indicating this function can be optimized \param a_iPrec The operator precedence \param a_eOprtAsct The operators associativity - \throw nothrow */ ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, EOprtAssociativity a_eOprtAsct) @@ -203,7 +201,6 @@ ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) //--------------------------------------------------------------------------- /** \brief Default constructor. - \throw nothrow */ ParserCallback::ParserCallback() : m_pFun(0), @@ -216,7 +213,6 @@ ParserCallback::ParserCallback() //--------------------------------------------------------------------------- /** \brief Copy constructor. - \throw nothrow */ ParserCallback::ParserCallback(const ParserCallback& ref) { m_pFun = ref.m_pFun; @@ -236,7 +232,6 @@ ParserCallback* ParserCallback::Clone() const { return new ParserCallback(*this) /** \brief Return tru if the function is conservative. Conservative functions return always the same result for the same argument. - \throw nothrow */ bool ParserCallback::IsOptimizable() const { return m_bAllowOpti; } @@ -245,8 +240,6 @@ bool ParserCallback::IsOptimizable() const { return m_bAllowOpti; } The type of the address is void. It needs to be recasted according to the argument number to the right type. - - \throw nothrow \return #pFun */ void* ParserCallback::GetAddr() const { return m_pFun; } @@ -259,16 +252,14 @@ ECmdCode ParserCallback::GetCode() const { return m_iCode; } ETypeCode ParserCallback::GetType() const { return m_iType; } //--------------------------------------------------------------------------- -/** \brief Return the operator precedence. - \throw nothrown +/** \brief Return the operator precedence.n Only valid if the callback token is an operator token (binary or infix). */ int ParserCallback::GetPri() const { return m_iPri; } //--------------------------------------------------------------------------- -/** \brief Return the operators associativity. - \throw nothrown +/** \brief Return the operators associativity.n Only valid if the callback token is a binary operator token. */ diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 6b196b5a2..be69afc85 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -532,7 +532,6 @@ API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) { \param a_iVar [in] The index of the variable to return. \param a_szName [out] Pointer to the variable name. \param a_pVar [out] Pointer to the variable. - \throw nothrow Prior to calling this function call mupGetExprVarNum in order to get the number of variables in the expression. If the parameter a_iVar is greater @@ -612,7 +611,6 @@ API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) { \param a_iVar [in] The index of the variable to return. \param a_szName [out] Pointer to the variable name. \param a_pVar [out] Pointer to the variable. - \throw nothrow */ API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 234d54a83..23af05444 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -45,7 +45,6 @@ class ParserBase; /** \brief Copy constructor. \sa Assign - \throw nothrow */ ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) { Assign(a_Reader); } @@ -55,7 +54,6 @@ ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) { Assign Self assignment will be suppressed otherwise #Assign is called. \param a_Reader Object to copy to this token reader. - \throw nothrow */ ParserTokenReader &ParserTokenReader::operator=(const ParserTokenReader &a_Reader) { if (&a_Reader != this) Assign(a_Reader); @@ -67,7 +65,6 @@ ParserTokenReader &ParserTokenReader::operator=(const ParserTokenReader &a_Reade /** \brief Assign state of a token reader to this token reader. \param a_Reader Object from which the state should be copied. - \throw nothrow */ void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) { m_pParser = a_Reader.m_pParser; @@ -134,7 +131,6 @@ ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) This is a factory method the calling function must take care of the object destruction. \return A new ParserTokenReader object. - \throw nothrow */ ParserTokenReader *ParserTokenReader::Clone(ParserBase *a_pParent) const { std::auto_ptr ptr(new ParserTokenReader(*this)); @@ -169,7 +165,6 @@ void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData) { /** \brief Return the current position of the token reader in the formula string. \return #m_iPos - \throw nothrow */ int ParserTokenReader::GetPos() const { return m_iPos; } @@ -177,7 +172,6 @@ int ParserTokenReader::GetPos() const { return m_iPos; } /** \brief Return a reference to the formula. \return #m_strFormula - \throw nothrow */ const string_type &ParserTokenReader::GetExpr() const { return m_strFormula; } @@ -214,7 +208,6 @@ void ParserTokenReader::IgnoreUndefVar(bool bIgnore) { m_bIgnoreUndefVar = bIgno The syntax flags will be reset to a value appropriate for the start of a formula. \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR - \throw nothrow \sa ESynCodes */ void ParserTokenReader::ReInit() { @@ -288,7 +281,6 @@ void ParserTokenReader::SetParent(ParserBase *a_pParent) { \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. \param a_iPos [in] Position in the string from where to start reading. \return The Position of the first character not listed in a_szCharSet. - \throw nothrow */ int ParserTokenReader::ExtractToken(const char_type *a_szCharSet, string_type &a_sTok, int a_iPos) const { @@ -454,7 +446,6 @@ bool ParserTokenReader::IsArgSep(token_type &a_Tok) { \return true if an end of formula is found false otherwise. \param a_Tok [out] If an eof is found the corresponding token will be stored there. - \throw nothrow \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok */ bool ParserTokenReader::IsEOF(token_type &a_Tok) { @@ -746,7 +737,6 @@ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) { \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. \return true if a variable token has been found. - \throw nothrow */ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) { string_type strTok; @@ -791,7 +781,6 @@ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) { \param a_Tok [out] If a variable token has been found it will be placed here. \return true if a string token has been found. \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok - \throw nothrow */ bool ParserTokenReader::IsString(token_type &a_Tok) { if (m_strFormula[m_iPos] != '"') return false; From 65f49635423eefd7be8f557bbd6998a9e1d50f60 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 13:06:17 -0800 Subject: [PATCH 18/62] [muparser] Eliminate MUP_FAIL and MUP_ASSERT Replace MUP_ASSERT with assert(). MUP_FAIL was unused. --- muparser-2.2.5/include/muParserDef.h | 26 -------------------------- muparser-2.2.5/src/muParserBase.cpp | 17 +++++++++-------- 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 712dc67d8..24bcbc801 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -71,32 +71,6 @@ #define MUP_STRING_TYPE std::string #endif -#if defined(_DEBUG) -/** \brief Debug macro to force an abortion of the programm with a certain message. -*/ -#define MUP_FAIL(MSG) \ - { \ - bool MSG = false; \ - assert(MSG); \ - } - -/** \brief An assertion that does not kill the program. - - This macro is neutralised in UNICODE builds. It's - too difficult to translate. -*/ -#define MUP_ASSERT(COND) \ - if (!(COND)) { \ - stringstream_type ss; \ - ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") << __FILE__ << _T(" line ") \ - << __LINE__ << _T("."); \ - throw ParserError(ss.str()); \ - } -#else -#define MUP_FAIL(MSG) -#define MUP_ASSERT(COND) -#endif - namespace mu { #if defined(_UNICODE) diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 0398557e0..35fbdb991 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -788,13 +788,13 @@ void ParserBase::ApplyIfElse(ParserStack &a_stOpt, // Check if there is an if Else clause to be calculated while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE) { token_type opElse = a_stOpt.pop(); - MUP_ASSERT(a_stOpt.size() > 0); + assert(a_stOpt.size() > 0 && "Invalid if/else clause"); // Take the value associated with the else branch from the value stack token_type vVal2 = a_stVal.pop(); - MUP_ASSERT(a_stOpt.size() > 0); - MUP_ASSERT(a_stVal.size() >= 2); + assert(a_stOpt.size() > 0 && "Invalid if/else clause"); + assert(a_stVal.size() >= 2 && "Invalid if/else clause"); // it then else is a ternary operator Pop all three values from the value s // tack and just return the right value @@ -804,8 +804,8 @@ void ParserBase::ApplyIfElse(ParserStack &a_stOpt, a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2); token_type opIf = a_stOpt.pop(); - MUP_ASSERT(opElse.GetCode() == cmELSE); - MUP_ASSERT(opIf.GetCode() == cmIF); + assert(opElse.GetCode() == cmELSE && "Invalid if/else clause"); + assert(opIf.GetCode() == cmIF && "Invalid if/else clause"); m_vRPN.AddIfElse(cmENDIF); } // while pending if-else-clause found @@ -821,7 +821,7 @@ void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, if (a_stOpt.top().GetCode() == cmOPRT_BIN) { ApplyFunc(a_stOpt, a_stVal, 2); } else { - MUP_ASSERT(a_stVal.size() >= 2); + assert(a_stVal.size() >= 2 && "Too few arguments for binary operator"); token_type valTok1 = a_stVal.pop(), valTok2 = a_stVal.pop(), optTok = a_stOpt.pop(), resTok; if (valTok1.GetType() != valTok2.GetType() || @@ -1074,7 +1074,8 @@ ValueOrError ParserBase::ParseCmdCode() const { // The index of the string argument in the string table int iIdxStack = pTok->Fun.idx; - MUP_ASSERT(iIdxStack >= 0 && iIdxStack < (int)m_vStringBuf.size()); + assert(iIdxStack >= 0 && iIdxStack < (int)m_vStringBuf.size() && + "Invalid string index"); ValueOrError funcResult{0.0}; switch (pTok->Fun.argc) // switch according to argument count { @@ -1295,7 +1296,7 @@ void ParserBase::CreateRPN() const { if (m_nIfElseCounter > 0) Error(ecMISSING_ELSE_CLAUSE); // get the last value (= final result) from the stack - MUP_ASSERT(stArgCount.size() == 1); + assert(stArgCount.size() == 1 && "Expected arg count of 1"); m_nFinalResultIdx = stArgCount.top(); if (m_nFinalResultIdx == 0) assert(0 && "muParser internal error"); From 9443a4bf2d1d390c455ea3b83e7e9a31f56a8dc4 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 13:27:09 -0800 Subject: [PATCH 19/62] [muparser] Remove copy and assignment There is no reason for muParsers to be copyable or assignable. Also remove some dead code and switch an auto_ptr to unique_ptr. --- muparser-2.2.5/include/muParserBase.h | 5 +- muparser-2.2.5/include/muParserBytecode.h | 7 +- muparser-2.2.5/include/muParserToken.h | 2 +- muparser-2.2.5/src/muParserBase.cpp | 79 +----------------- muparser-2.2.5/src/muParserBytecode.cpp | 99 ----------------------- muparser-2.2.5/src/muParserTest.cpp | 39 ++------- 6 files changed, 13 insertions(+), 218 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 57564eb09..d90490990 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -92,8 +92,8 @@ class ParserBase { static void EnableDebugDump(bool bDumpCmd, bool bDumpStack); ParserBase(); - ParserBase(const ParserBase &a_Parser); - ParserBase &operator=(const ParserBase &a_Parser); + ParserBase(const ParserBase &a_Parser) = delete; + ParserBase &operator=(const ParserBase &a_Parser) = delete; virtual ~ParserBase(); @@ -212,7 +212,6 @@ class ParserBase { }; private: - void Assign(const ParserBase &a_Parser); void InitTokenReader(); void ReInit() const; diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index d3509364e..ac70842af 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -95,13 +95,10 @@ class ParserByteCode { /** \brief The actual rpn storage. */ rpn_type m_vRPN; - void ConstantFolding(ECmdCode a_Oprt); - public: ParserByteCode(); - ParserByteCode(const ParserByteCode &a_ByteCode); - ParserByteCode &operator=(const ParserByteCode &a_ByteCode); - void Assign(const ParserByteCode &a_ByteCode); + ParserByteCode(const ParserByteCode &a_ByteCode) = default; + ParserByteCode &operator=(const ParserByteCode &a_ByteCode) = default; void AddVar(value_type *a_pVar); void AddVal(value_type a_fVal); diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index 8c690ef49..5f268c529 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -65,7 +65,7 @@ class ParserToken { TString m_strTok; ///< Token string TString m_strVal; ///< Value for string variables value_type m_fVal; ///< the value - std::auto_ptr m_pCallback; + std::unique_ptr m_pCallback; public: //--------------------------------------------------------------------------- diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 35fbdb991..3a8deb1df 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -87,84 +87,7 @@ ParserBase::ParserBase() } //--------------------------------------------------------------------------- -/** \brief Copy constructor. - - The parser can be safely copy constructed but the bytecode is reset during - copy construction. -*/ -ParserBase::ParserBase(const ParserBase &a_Parser) - : m_pParseFormula(&ParserBase::ParseString), - m_vRPN(), - m_vStringBuf(), - m_pTokenReader(), - m_FunDef(), - m_PostOprtDef(), - m_InfixOprtDef(), - m_OprtDef(), - m_ConstDef(), - m_StrVarDef(), - m_VarDef(), - m_bBuiltInOp(true), - m_sNameChars(), - m_sOprtChars(), - m_sInfixOprtChars(), - m_nIfElseCounter(0) { - m_pTokenReader.reset(new token_reader_type(this)); - Assign(a_Parser); -} - -//--------------------------------------------------------------------------- -ParserBase::~ParserBase() {} - -//--------------------------------------------------------------------------- -/** \brief Assignment operator. - - Implemented by calling Assign(a_Parser). Self assignment is suppressed. - \param a_Parser Object to copy to this. - \return *this -*/ -ParserBase &ParserBase::operator=(const ParserBase &a_Parser) { - Assign(a_Parser); - return *this; -} - -//--------------------------------------------------------------------------- -/** \brief Copy state of a parser object to this. - - Clears Variables and Functions of this parser. - Copies the states of all internal variables. - Resets parse function to string parse mode. - - \param a_Parser the source object. -*/ -void ParserBase::Assign(const ParserBase &a_Parser) { - if (&a_Parser == this) return; - - // Don't copy bytecode instead cause the parser to create new bytecode - // by resetting the parse function. - ReInit(); - - m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants - m_VarDef = a_Parser.m_VarDef; // Copy user defined variables - m_bBuiltInOp = a_Parser.m_bBuiltInOp; - m_vStringBuf = a_Parser.m_vStringBuf; - m_vStackBuffer = a_Parser.m_vStackBuffer; - m_nFinalResultIdx = a_Parser.m_nFinalResultIdx; - m_StrVarDef = a_Parser.m_StrVarDef; - m_vStringVarBuf = a_Parser.m_vStringVarBuf; - m_nIfElseCounter = a_Parser.m_nIfElseCounter; - m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this)); - - // Copy function and operator callbacks - m_FunDef = a_Parser.m_FunDef; // Copy function definitions - m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators - m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation - m_OprtDef = a_Parser.m_OprtDef; // binary operators - - m_sNameChars = a_Parser.m_sNameChars; - m_sOprtChars = a_Parser.m_sOprtChars; - m_sInfixOprtChars = a_Parser.m_sInfixOprtChars; -} +ParserBase::~ParserBase() = default; //--------------------------------------------------------------------------- /** \brief Set the decimal separator. diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index 8bffa8b8d..f2dd8c0c5 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -43,36 +43,6 @@ ParserByteCode::ParserByteCode() : m_iStackPos(0), m_iMaxStackSize(0), m_vRPN() m_vRPN.reserve(50); } -//--------------------------------------------------------------------------- -/** \brief Copy constructor. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) -*/ -ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode) { Assign(a_ByteCode); } - -//--------------------------------------------------------------------------- -/** \brief Assignment operator. - - Implemented in Terms of Assign(const ParserByteCode &a_ByteCode) -*/ -ParserByteCode &ParserByteCode::operator=(const ParserByteCode &a_ByteCode) { - Assign(a_ByteCode); - return *this; -} - -//--------------------------------------------------------------------------- -/** \brief Copy state of another object to this. - - \throw nowthrow -*/ -void ParserByteCode::Assign(const ParserByteCode &a_ByteCode) { - if (this == &a_ByteCode) return; - - m_iStackPos = a_ByteCode.m_iStackPos; - m_vRPN = a_ByteCode.m_vRPN; - m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; -} - //--------------------------------------------------------------------------- /** \brief Add a Variable pointer to bytecode. \param a_pVar Pointer to be added. @@ -115,75 +85,6 @@ void ParserByteCode::AddVal(value_type a_fVal) { m_vRPN.push_back(tok); } -//--------------------------------------------------------------------------- -void ParserByteCode::ConstantFolding(ECmdCode a_Oprt) { - std::size_t sz = m_vRPN.size(); - value_type &x = m_vRPN[sz - 2].Val.data2, &y = m_vRPN[sz - 1].Val.data2; - switch (a_Oprt) { - case cmLAND: - x = (int)x && (int)y; - m_vRPN.pop_back(); - break; - case cmLOR: - x = (int)x || (int)y; - m_vRPN.pop_back(); - break; - case cmLT: - x = x < y; - m_vRPN.pop_back(); - break; - case cmGT: - x = x > y; - m_vRPN.pop_back(); - break; - case cmLE: - x = x <= y; - m_vRPN.pop_back(); - break; - case cmGE: - x = x >= y; - m_vRPN.pop_back(); - break; - case cmNEQ: - x = x != y; - m_vRPN.pop_back(); - break; - case cmEQ: - x = x == y; - m_vRPN.pop_back(); - break; - case cmADD: - x = x + y; - m_vRPN.pop_back(); - break; - case cmSUB: - x = x - y; - m_vRPN.pop_back(); - break; - case cmMUL: - x = x * y; - m_vRPN.pop_back(); - break; - case cmDIV: - -#if defined(MUP_MATH_EXCEPTIONS) - if (y == 0) throw ParserError(ecDIV_BY_ZERO, _T("0")); -#endif - - x = x / y; - m_vRPN.pop_back(); - break; - - case cmPOW: - x = MathImpl::Pow(x, y); - m_vRPN.pop_back(); - break; - - default: - break; - } // switch opcode -} - //--------------------------------------------------------------------------- /** \brief Add an operator identifier to bytecode. diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 8ef1f167d..4a5920350 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -1151,7 +1151,7 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1, int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) { ParserTester::c_iCount++; int iRet(0); - value_type fVal[5] = {-999, -998, -997, -996, -995}; // initially should be different + value_type fVal[] = {-999, -998, -997}; // initially should be different try { std::auto_ptr p1; @@ -1239,31 +1239,10 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); - // Test copy and assignment operators - try { - // Test copy constructor - std::vector vParser; - vParser.push_back(*(p1.get())); - mu::Parser p2 = vParser[0]; // take parser from vector - - // destroy the originals from p2 - vParser.clear(); // delete the vector - p1.reset(0); - - fVal[2] = *p2.Eval(); - - // Test assignment operator - mu::Parser p3; - p3 = p2; - fVal[3] = *p3.Eval(); - - // Test Eval function for multiple return values - std::vector v; - p2.Eval(&v); - fVal[4] = *v.back(); - } catch (std::exception &e) { - mu::console() << _T("\n ") << e.what() << _T("\n"); - } + // Test Eval function for multiple return values. + std::vector v; + p1->Eval(&v); + fVal[2] = *v.back(); // limited floating point accuracy requires the following test bool bCloseEnough(true); @@ -1288,15 +1267,11 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (incorrect result; expected: ") << a_fRes << _T(" ;calculated: ") << fVal[0] << _T(",") << fVal[1] << _T(",") << fVal[2] << _T(",") - << fVal[3] << _T(",") << fVal[4] << _T(")."); + << _T(")."); } } catch (Parser::exception_type &e) { if (a_fPass) { - if (fVal[0] != fVal[2] && fVal[0] != -999 && fVal[1] != -998) - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (copy construction)"); - else - mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() - << _T(")"); + mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")"); return 1; } } catch (std::exception &e) { From c4c89dff4ec9512c977d46509916c09e645001e0 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 13:40:49 -0800 Subject: [PATCH 20/62] [muparser] Clean up ParserCallback interface Remove Clone() method and mark some functions as defaulted. --- muparser-2.2.5/include/muParserCallback.h | 4 +--- muparser-2.2.5/include/muParserToken.h | 2 +- muparser-2.2.5/src/muParserCallback.cpp | 14 +------------- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/muparser-2.2.5/include/muParserCallback.h b/muparser-2.2.5/include/muParserCallback.h index e153165af..83417f27b 100644 --- a/muparser-2.2.5/include/muParserCallback.h +++ b/muparser-2.2.5/include/muParserCallback.h @@ -46,7 +46,7 @@ namespace mu { \author (C) 2004-2011 Ingo Berg */ -class ParserCallback { +class ParserCallback final { public: ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, @@ -70,8 +70,6 @@ class ParserCallback { ParserCallback(); ParserCallback(const ParserCallback& a_Fun); - ParserCallback* Clone() const; - bool IsOptimizable() const; void* GetAddr() const; ECmdCode GetCode() const; diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index 5f268c529..111e3e7fe 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -116,7 +116,7 @@ class ParserToken { m_iType = a_Tok.m_iType; m_fVal = a_Tok.m_fVal; // create new callback object if a_Tok has one - m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0); + m_pCallback.reset(a_Tok.m_pCallback ? new ParserCallback(*a_Tok.m_pCallback) : nullptr); } //------------------------------------------------------------------------------ diff --git a/muparser-2.2.5/src/muParserCallback.cpp b/muparser-2.2.5/src/muParserCallback.cpp index fb0d544b3..abb2c594f 100644 --- a/muparser-2.2.5/src/muParserCallback.cpp +++ b/muparser-2.2.5/src/muParserCallback.cpp @@ -214,19 +214,7 @@ ParserCallback::ParserCallback() //--------------------------------------------------------------------------- /** \brief Copy constructor. */ -ParserCallback::ParserCallback(const ParserCallback& ref) { - m_pFun = ref.m_pFun; - m_iArgc = ref.m_iArgc; - m_bAllowOpti = ref.m_bAllowOpti; - m_iCode = ref.m_iCode; - m_iType = ref.m_iType; - m_iPri = ref.m_iPri; - m_eOprtAsct = ref.m_eOprtAsct; -} - -//--------------------------------------------------------------------------- -/** \brief Clone this instance and return a pointer to the new instance. */ -ParserCallback* ParserCallback::Clone() const { return new ParserCallback(*this); } +ParserCallback::ParserCallback(const ParserCallback& ref) = default; //--------------------------------------------------------------------------- /** \brief Return tru if the function is conservative. From 3b1b5b30ca9fd0dd96607011e32f292056103527 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 13:46:29 -0800 Subject: [PATCH 21/62] [muparser] Clean up ParserToken::GetFuncAddr --- muparser-2.2.5/include/muParserToken.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index 111e3e7fe..b98c4cb89 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -282,18 +282,9 @@ class ParserToken { function and operator tokens. \return The pointer stored in #m_pTok. - \throw exception_type if token type is non of: -
    -
  • cmFUNC
  • -
  • cmSTRFUNC
  • -
  • cmPOSTOP
  • -
  • cmINFIXOP
  • -
  • cmOPRT_BIN
  • -
- \sa ECmdCode */ generic_fun_type GetFuncAddr() const { - return (m_pCallback.get()) ? (generic_fun_type)m_pCallback->GetAddr() : 0; + return m_pCallback ? (generic_fun_type)m_pCallback->GetAddr() : nullptr; } //------------------------------------------------------------------------------ From 83799832bc3f49a8d7c452cb360af4739ebb43cb Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 13:54:53 -0800 Subject: [PATCH 22/62] [muparser] Make ParserTokenReader non-copyable There's no reason to copy these. --- muparser-2.2.5/include/muParserTokenReader.h | 9 +-- muparser-2.2.5/src/muParserTokenReader.cpp | 66 -------------------- 2 files changed, 3 insertions(+), 72 deletions(-) diff --git a/muparser-2.2.5/include/muParserTokenReader.h b/muparser-2.2.5/include/muParserTokenReader.h index 143069b43..d91766a8b 100644 --- a/muparser-2.2.5/include/muParserTokenReader.h +++ b/muparser-2.2.5/include/muParserTokenReader.h @@ -47,15 +47,13 @@ namespace mu { class ParserBase; /** \brief Token reader for the ParserBase class. - */ -class ParserTokenReader { +class ParserTokenReader final { private: typedef ParserToken token_type; public: ParserTokenReader(ParserBase *a_pParent); - ParserTokenReader *Clone(ParserBase *a_pParent) const; void AddValIdent(identfun_type a_pCallback); void SetVarCreator(facfun_type a_pFactory, void *pUserData); @@ -97,9 +95,8 @@ class ParserTokenReader { noANY = ~0 ///< All of he above flags set }; - ParserTokenReader(const ParserTokenReader &a_Reader); - ParserTokenReader &operator=(const ParserTokenReader &a_Reader); - void Assign(const ParserTokenReader &a_Reader); + ParserTokenReader(const ParserTokenReader &a_Reader) = delete; + ParserTokenReader &operator=(const ParserTokenReader &a_Reader) = delete; void SetParent(ParserBase *a_pParent); int ExtractToken(const char_type *a_szCharSet, string_type &a_strTok, int a_iPos) const; diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 23af05444..57ead44e3 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -38,58 +38,6 @@ namespace mu { -// Forward declaration -class ParserBase; - -//--------------------------------------------------------------------------- -/** \brief Copy constructor. - - \sa Assign -*/ -ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader) { Assign(a_Reader); } - -//--------------------------------------------------------------------------- -/** \brief Assignment operator. - - Self assignment will be suppressed otherwise #Assign is called. - - \param a_Reader Object to copy to this token reader. -*/ -ParserTokenReader &ParserTokenReader::operator=(const ParserTokenReader &a_Reader) { - if (&a_Reader != this) Assign(a_Reader); - - return *this; -} - -//--------------------------------------------------------------------------- -/** \brief Assign state of a token reader to this token reader. - - \param a_Reader Object from which the state should be copied. -*/ -void ParserTokenReader::Assign(const ParserTokenReader &a_Reader) { - m_pParser = a_Reader.m_pParser; - m_strFormula = a_Reader.m_strFormula; - m_iPos = a_Reader.m_iPos; - m_iSynFlags = a_Reader.m_iSynFlags; - - m_UsedVar = a_Reader.m_UsedVar; - m_pFunDef = a_Reader.m_pFunDef; - m_pConstDef = a_Reader.m_pConstDef; - m_pVarDef = a_Reader.m_pVarDef; - m_pStrVarDef = a_Reader.m_pStrVarDef; - m_pPostOprtDef = a_Reader.m_pPostOprtDef; - m_pInfixOprtDef = a_Reader.m_pInfixOprtDef; - m_pOprtDef = a_Reader.m_pOprtDef; - m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar; - m_vIdentFun = a_Reader.m_vIdentFun; - m_pFactory = a_Reader.m_pFactory; - m_pFactoryData = a_Reader.m_pFactoryData; - m_iBrackets = a_Reader.m_iBrackets; - m_cArgSep = a_Reader.m_cArgSep; - m_fZero = a_Reader.m_fZero; - m_lastTok = a_Reader.m_lastTok; -} - //--------------------------------------------------------------------------- /** \brief Constructor. @@ -124,20 +72,6 @@ ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) SetParent(m_pParser); } -//--------------------------------------------------------------------------- -/** \brief Create instance of a ParserTokenReader identical with this - and return its pointer. - - This is a factory method the calling function must take care of the object destruction. - - \return A new ParserTokenReader object. -*/ -ParserTokenReader *ParserTokenReader::Clone(ParserBase *a_pParent) const { - std::auto_ptr ptr(new ParserTokenReader(*this)); - ptr->SetParent(a_pParent); - return ptr.release(); -} - //--------------------------------------------------------------------------- ParserTokenReader::token_type &ParserTokenReader::SaveBeforeReturn(const token_type &tok) { m_lastTok = tok; From d97bb3425ff74653d0df7dbb2c8ffbb4e99e7fe6 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 22 Nov 2017 13:57:28 -0800 Subject: [PATCH 23/62] [muparser] Clean up ParserTokenReader constructor --- muparser-2.2.5/include/muParserTokenReader.h | 30 ++++++++++---------- muparser-2.2.5/src/muParserTokenReader.cpp | 26 ++--------------- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/muparser-2.2.5/include/muParserTokenReader.h b/muparser-2.2.5/include/muParserTokenReader.h index d91766a8b..597c9809f 100644 --- a/muparser-2.2.5/include/muParserTokenReader.h +++ b/muparser-2.2.5/include/muParserTokenReader.h @@ -121,25 +121,25 @@ class ParserTokenReader final { ParserBase *m_pParser; string_type m_strFormula; - int m_iPos; - int m_iSynFlags; - bool m_bIgnoreUndefVar; + int m_iPos = 0; + int m_iSynFlags = 0; + bool m_bIgnoreUndefVar = false; - const funmap_type *m_pFunDef; - const funmap_type *m_pPostOprtDef; - const funmap_type *m_pInfixOprtDef; - const funmap_type *m_pOprtDef; - const valmap_type *m_pConstDef; - const strmap_type *m_pStrVarDef; - varmap_type *m_pVarDef; ///< The only non const pointer to parser internals - facfun_type m_pFactory; - void *m_pFactoryData; + const funmap_type *m_pFunDef = nullptr; + const funmap_type *m_pPostOprtDef = nullptr; + const funmap_type *m_pInfixOprtDef = nullptr; + const funmap_type *m_pOprtDef = nullptr; + const valmap_type *m_pConstDef = nullptr; + const strmap_type *m_pStrVarDef = nullptr; + varmap_type *m_pVarDef = nullptr; ///< The only non const pointer to parser internals + facfun_type m_pFactory = nullptr; + void *m_pFactoryData = nullptr; std::list m_vIdentFun; ///< Value token identification function varmap_type m_UsedVar; - value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables - int m_iBrackets; + value_type m_fZero = 0; ///< Dummy value of zero, referenced by undefined variables + int m_iBrackets = 0; token_type m_lastTok; - char_type m_cArgSep; ///< The character used for separating function arguments + char_type m_cArgSep = ','; ///< The character used for separating function arguments }; } // namespace mu diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 57ead44e3..3471e8fa4 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -47,29 +47,9 @@ namespace mu { \post #m_pParser==a_pParser \param a_pParent Parent parser object of the token reader. */ -ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) - : m_pParser(a_pParent), - m_strFormula(), - m_iPos(0), - m_iSynFlags(0), - m_bIgnoreUndefVar(false), - m_pFunDef(NULL), - m_pPostOprtDef(NULL), - m_pInfixOprtDef(NULL), - m_pOprtDef(NULL), - m_pConstDef(NULL), - m_pStrVarDef(NULL), - m_pVarDef(NULL), - m_pFactory(NULL), - m_pFactoryData(NULL), - m_vIdentFun(), - m_UsedVar(), - m_fZero(0), - m_iBrackets(0), - m_lastTok(), - m_cArgSep(',') { - assert(m_pParser); - SetParent(m_pParser); +ParserTokenReader::ParserTokenReader(ParserBase *a_pParent) { + assert(a_pParent && "Missing parent"); + SetParent(a_pParent); } //--------------------------------------------------------------------------- From 60d9c9fa00855af4dd69a645ffb8b6445d4ddf45 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Nov 2017 15:12:04 -0800 Subject: [PATCH 24/62] [muparser] More functions to return errors Return OptionalError for more functions, allowing for explicit error handling. --- muparser-2.2.5/include/muParserBase.h | 16 ++-- muparser-2.2.5/include/muParserToken.h | 3 +- muparser-2.2.5/src/muParserBase.cpp | 124 ++++++++++++++----------- 3 files changed, 80 insertions(+), 63 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index d90490990..93c00969b 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -220,20 +220,22 @@ class ParserBase { void ApplyRemainingOprt(ParserStack &a_stOpt, ParserStack &a_stVal) const; - void ApplyBinOprt(ParserStack &a_stOpt, ParserStack &a_stVal) const; + OptionalError ApplyBinOprt(ParserStack &a_stOpt, + ParserStack &a_stVal) const; - void ApplyIfElse(ParserStack &a_stOpt, ParserStack &a_stVal) const; + OptionalError ApplyIfElse(ParserStack &a_stOpt, + ParserStack &a_stVal) const; - void ApplyFunc(ParserStack &a_stOpt, ParserStack &a_stVal, - int iArgCount) const; + OptionalError ApplyFunc(ParserStack &a_stOpt, ParserStack &a_stVal, + int iArgCount) const; - token_type ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const; + OptionalError ApplyStrFunc(const token_type &a_FunTok, + const std::vector &a_vArg) const; int GetOprtPrecedence(const token_type &a_Tok) const; EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const; - void CreateRPN() const; + OptionalError CreateRPN() const; ValueOrError ParseString() const; ValueOrError ParseCmdCode() const; diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index b98c4cb89..aeb5397ed 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -291,9 +291,8 @@ class ParserToken { /** \biref Get value of the token. Only applicable to variable and value tokens. - \throw exception_type if token is no value/variable token. */ - TBase GetVal() const { + ValueOrError GetVal() const { switch (m_iCode) { case cmVAL: return m_fVal; diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 3a8deb1df..2bff4c172 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -538,9 +538,9 @@ EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) con const varmap_type &ParserBase::GetUsedVar() const { try { m_pTokenReader->IgnoreUndefVar(true); - CreateRPN(); // try to create bytecode, but don't use it for any further calculations since - // it - // may contain references to nonexisting variables. + // Try to create bytecode, but don't use it for any further calculations since it may + // contain references to nonexisting variables. + OptionalError err = CreateRPN(); m_pParseFormula = &ParserBase::ParseString; m_pTokenReader->IgnoreUndefVar(false); } catch (exception_type & /*e*/) { @@ -583,45 +583,42 @@ const string_type &ParserBase::GetExpr() const { return m_pTokenReader->GetExpr( \param a_FunTok Function token. \throw exception_type If the function token is not a string function */ -ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, - const std::vector &a_vArg) const { +OptionalError ParserBase::ApplyStrFunc(const token_type &a_FunTok, + const std::vector &a_vArg) const { if (a_vArg.back().GetCode() != cmSTRING) Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); token_type valTok; generic_fun_type pFunc = a_FunTok.GetFuncAddr(); assert(pFunc); - - try { - // Check function arguments; write dummy value into valtok to represent the result - switch (a_FunTok.GetArgCount()) { - case 0: - valTok.SetVal(1); - a_vArg[0].GetAsString(); - break; - case 1: - valTok.SetVal(1); - a_vArg[1].GetAsString(); - a_vArg[0].GetVal(); - break; - case 2: - valTok.SetVal(1); - a_vArg[2].GetAsString(); - a_vArg[1].GetVal(); - a_vArg[0].GetVal(); - break; - default: - assert(0 && "Unexpected arg count"); - } - } catch (ParserError &) { + bool errored = false; + // Check function arguments; write dummy value into valtok to represent the result + switch (a_FunTok.GetArgCount()) { + case 0: + valTok.SetVal(1); + a_vArg[0].GetAsString(); + break; + case 1: + valTok.SetVal(1); + a_vArg[1].GetAsString(); + errored |= a_vArg[0].GetVal().has_error(); + break; + case 2: + valTok.SetVal(1); + a_vArg[2].GetAsString(); + errored |= a_vArg[1].GetVal().has_error(); + errored |= a_vArg[0].GetVal().has_error(); + break; + default: + assert(0 && "Unexpected arg count"); + } + if (errored) { Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); } // string functions won't be optimized m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); - - // Push dummy value representing the function result to the stack - return valTok; + return {}; } //--------------------------------------------------------------------------- @@ -629,14 +626,14 @@ ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok, \param iArgCount Number of Arguments actually gathered used only for multiarg functions. \post The result is pushed to the value stack \post The function token is removed from the stack - \throw exception_type if Argument count does not match function requirements. + \return ParserError if Argument count does not match function requirements. */ -void ParserBase::ApplyFunc(ParserStack &a_stOpt, ParserStack &a_stVal, - int a_iArgCount) const { +OptionalError ParserBase::ApplyFunc(ParserStack &a_stOpt, + ParserStack &a_stVal, int a_iArgCount) const { assert(m_pTokenReader.get()); // Operator stack empty or does not contain tokens with callback functions - if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0) return; + if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr() == 0) return {}; token_type funTok = a_stOpt.pop(); assert(funTok.GetFuncAddr()); @@ -675,14 +672,16 @@ void ParserBase::ApplyFunc(ParserStack &a_stOpt, ParserStackGetPos(), funTok.GetAsString()); - ApplyStrFunc(funTok, stArg); + OptionalError err = ApplyStrFunc(funTok, stArg); + if (err.has_error()) return err; break; + } case cmOPRT_BIN: case cmOPRT_POSTFIX: @@ -703,11 +702,12 @@ void ParserBase::ApplyFunc(ParserStack &a_stOpt, ParserStack &a_stOpt, - ParserStack &a_stVal) const { +OptionalError ParserBase::ApplyIfElse(ParserStack &a_stOpt, + ParserStack &a_stVal) const { // Check if there is an if Else clause to be calculated while (a_stOpt.size() && a_stOpt.top().GetCode() == cmELSE) { token_type opElse = a_stOpt.pop(); @@ -724,7 +724,9 @@ void ParserBase::ApplyIfElse(ParserStack &a_stOpt, token_type vVal1 = a_stVal.pop(); token_type vExpr = a_stVal.pop(); - a_stVal.push((vExpr.GetVal() != 0) ? vVal1 : vVal2); + ValueOrError vExprValue = vExpr.GetVal(); + if (vExprValue.has_error()) return vExprValue.error(); + a_stVal.push((vExprValue.value() != 0) ? vVal1 : vVal2); token_type opIf = a_stOpt.pop(); assert(opElse.GetCode() == cmELSE && "Invalid if/else clause"); @@ -732,17 +734,18 @@ void ParserBase::ApplyIfElse(ParserStack &a_stOpt, m_vRPN.AddIfElse(cmENDIF); } // while pending if-else-clause found + return {}; } //--------------------------------------------------------------------------- /** \brief Performs the necessary steps to write code for the execution of binary operators into the bytecode. */ -void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const { +OptionalError ParserBase::ApplyBinOprt(ParserStack &a_stOpt, + ParserStack &a_stVal) const { // is it a user defined binary operator? if (a_stOpt.top().GetCode() == cmOPRT_BIN) { - ApplyFunc(a_stOpt, a_stVal, 2); + return ApplyFunc(a_stOpt, a_stVal, 2); } else { assert(a_stVal.size() >= 2 && "Too few arguments for binary operator"); token_type valTok1 = a_stVal.pop(), valTok2 = a_stVal.pop(), optTok = a_stOpt.pop(), resTok; @@ -761,6 +764,7 @@ void ParserBase::ApplyBinOprt(ParserStack &a_stOpt, resTok.SetVal(1); a_stVal.push(resTok); } + return {}; } //--------------------------------------------------------------------------- @@ -1029,8 +1033,8 @@ ValueOrError ParserBase::ParseCmdCode() const { } //--------------------------------------------------------------------------- -void ParserBase::CreateRPN() const { - if (!m_pTokenReader->GetExpr().length()) Error(ecUNEXPECTED_EOF, 0); +OptionalError ParserBase::CreateRPN() const { + if (!m_pTokenReader->GetExpr().length()) return ParserError(ecUNEXPECTED_EOF, 0); ParserStack stOpt, stVal; ParserStack stArgCount; @@ -1061,10 +1065,13 @@ void ParserBase::CreateRPN() const { m_vRPN.AddVar(static_cast(opt.GetVar())); break; - case cmVAL: + case cmVAL: { stVal.push(opt); - m_vRPN.AddVal(opt.GetVal()); + ValueOrError optVal = opt.GetVal(); + if (optVal.has_error()) throw optVal.error(); + m_vRPN.AddVal(optVal.value()); break; + } case cmELSE: m_nIfElseCounter--; @@ -1117,7 +1124,8 @@ void ParserBase::CreateRPN() const { // was a function before this bracket if (stOpt.size() && stOpt.top().GetCode() != cmOPRT_INFIX && stOpt.top().GetCode() != cmOPRT_BIN && stOpt.top().GetFuncAddr() != 0) { - ApplyFunc(stOpt, stVal, iArgCount); + OptionalError err = ApplyFunc(stOpt, stVal, iArgCount); + if (err.has_error()) return err.error(); } } } // if bracket content is evaluated @@ -1166,10 +1174,14 @@ void ParserBase::CreateRPN() const { break; } + OptionalError oerr; if (stOpt.top().GetCode() == cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); + oerr = ApplyFunc(stOpt, stVal, 1); else - ApplyBinOprt(stOpt, stVal); + oerr = ApplyBinOprt(stOpt, stVal); + if (oerr.has_error()) { + return oerr.error(); + } } // while ( ... ) if (opt.GetCode() == cmIF) m_vRPN.AddIfElse(opt.GetCode()); @@ -1192,10 +1204,12 @@ void ParserBase::CreateRPN() const { stOpt.push(opt); break; - case cmOPRT_POSTFIX: + case cmOPRT_POSTFIX: { stOpt.push(opt); - ApplyFunc(stOpt, stVal, 1); // this is the postfix operator + OptionalError oerr = ApplyFunc(stOpt, stVal, 1); // this is the postfix operator + if (oerr.has_error()) return oerr.error(); break; + } default: assert(0 && "muParser internal error"); @@ -1228,6 +1242,7 @@ void ParserBase::CreateRPN() const { if (stVal.top().GetType() != tpDBL) Error(ecSTR_RESULT); m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); + return {}; } //--------------------------------------------------------------------------- @@ -1241,7 +1256,8 @@ void ParserBase::CreateRPN() const { */ ValueOrError ParserBase::ParseString() const { try { - CreateRPN(); + OptionalError oerr = CreateRPN(); + if (oerr.has_error()) return oerr.error(); m_pParseFormula = &ParserBase::ParseCmdCode; return (this->*m_pParseFormula)(); } catch (ParserError &exc) { @@ -1394,7 +1410,7 @@ void ParserBase::StackDump(const ParserStack &a_stVal, if (val.GetType() == tpSTR) mu::console() << _T(" \"") << val.GetAsString() << _T("\" "); else - mu::console() << _T(" ") << val.GetVal() << _T(" "); + mu::console() << _T(" ") << val.GetVal().value() << _T(" "); } mu::console() << "\nOperator stack:\n"; From 234808bc32d7dd59ccc4912f8784511b3da5623e Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Nov 2017 15:54:00 -0800 Subject: [PATCH 25/62] [muparser] ApplyRemainingOprt to return explicit errors --- muparser-2.2.5/include/muParserBase.h | 4 ++-- muparser-2.2.5/src/muParserBase.cpp | 28 +++++++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 93c00969b..13af8a0bd 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -218,8 +218,8 @@ class ParserBase { void AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, funmap_type &a_Storage, const char_type *a_szCharSet); - void ApplyRemainingOprt(ParserStack &a_stOpt, - ParserStack &a_stVal) const; + OptionalError ApplyRemainingOprt(ParserStack &a_stOpt, + ParserStack &a_stVal) const; OptionalError ApplyBinOprt(ParserStack &a_stOpt, ParserStack &a_stVal) const; diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 2bff4c172..f5e22cf2c 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -540,7 +540,8 @@ const varmap_type &ParserBase::GetUsedVar() const { m_pTokenReader->IgnoreUndefVar(true); // Try to create bytecode, but don't use it for any further calculations since it may // contain references to nonexisting variables. - OptionalError err = CreateRPN(); + OptionalError oerr = CreateRPN(); + if (oerr.has_error()) throw oerr.error(); m_pParseFormula = &ParserBase::ParseString; m_pTokenReader->IgnoreUndefVar(false); } catch (exception_type & /*e*/) { @@ -772,9 +773,10 @@ OptionalError ParserBase::ApplyBinOprt(ParserStack &a_stOpt, \param a_stOpt The operator stack \param a_stVal The value stack */ -void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, - ParserStack &stVal) const { +OptionalError ParserBase::ApplyRemainingOprt(ParserStack &stOpt, + ParserStack &stVal) const { while (stOpt.size() && stOpt.top().GetCode() != cmBO && stOpt.top().GetCode() != cmIF) { + OptionalError oerr; token_type tok = stOpt.top(); switch (tok.GetCode()) { case cmOPRT_INFIX: @@ -794,19 +796,21 @@ void ParserBase::ApplyRemainingOprt(ParserStack &stOpt, case cmLOR: case cmASSIGN: if (stOpt.top().GetCode() == cmOPRT_INFIX) - ApplyFunc(stOpt, stVal, 1); + oerr = ApplyFunc(stOpt, stVal, 1); else - ApplyBinOprt(stOpt, stVal); + oerr = ApplyBinOprt(stOpt, stVal); break; case cmELSE: - ApplyIfElse(stOpt, stVal); + oerr = ApplyIfElse(stOpt, stVal); break; default: assert(0 && "muParser internal error"); } + if (oerr.has_error()) return oerr.error(); } + return {}; } /// Invoke the function \p func as the fun_typeN given argCount, passing in \p argCount arguments @@ -1049,6 +1053,7 @@ OptionalError ParserBase::CreateRPN() const { for (;;) { opt = m_pTokenReader->ReadNextToken(); + OptionalError oerr; switch (opt.GetCode()) { // @@ -1068,7 +1073,7 @@ OptionalError ParserBase::CreateRPN() const { case cmVAL: { stVal.push(opt); ValueOrError optVal = opt.GetVal(); - if (optVal.has_error()) throw optVal.error(); + if (optVal.has_error()) return optVal.error(); m_vRPN.AddVal(optVal.value()); break; } @@ -1077,7 +1082,8 @@ OptionalError ParserBase::CreateRPN() const { m_nIfElseCounter--; if (m_nIfElseCounter < 0) Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); - ApplyRemainingOprt(stOpt, stVal); + oerr = ApplyRemainingOprt(stOpt, stVal); + if (oerr.has_error()) return oerr.error(); m_vRPN.AddIfElse(cmELSE); stOpt.push(opt); break; @@ -1089,7 +1095,8 @@ OptionalError ParserBase::CreateRPN() const { // fallthrough intentional (no break!) case cmEND: - ApplyRemainingOprt(stOpt, stVal); + oerr = ApplyRemainingOprt(stOpt, stVal); + if (oerr.has_error()) return oerr.error(); break; case cmBC: { @@ -1099,7 +1106,8 @@ OptionalError ParserBase::CreateRPN() const { // was an opening bracket we know better... if (opta.GetCode() == cmBO) --stArgCount.top(); - ApplyRemainingOprt(stOpt, stVal); + oerr = ApplyRemainingOprt(stOpt, stVal); + if (oerr.has_error()) return oerr.error(); // Check if the bracket content has been evaluated completely if (stOpt.size() && stOpt.top().GetCode() == cmBO) { From 3faccc8b3ea3336da17d442c49bce8f9caf3ea62 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Nov 2017 18:49:00 -0800 Subject: [PATCH 26/62] [muparser] Remove querying variables and constants fish does not need to query variables and constants from muparser. This simplifies the code. --- muparser-2.2.5/include/muParserBase.h | 2 - muparser-2.2.5/include/muParserDLL.h | 8 - muparser-2.2.5/include/muParserTest.h | 1 - muparser-2.2.5/include/muParserTokenReader.h | 1 - muparser-2.2.5/samples/example1/example1.cpp | 64 ------ muparser-2.2.5/src/muParserBase.cpp | 33 +-- muparser-2.2.5/src/muParserDLL.cpp | 199 ------------------- muparser-2.2.5/src/muParserTest.cpp | 98 --------- muparser-2.2.5/src/muParserTokenReader.cpp | 4 - 9 files changed, 1 insertion(+), 409 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 13af8a0bd..52291748f 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -144,9 +144,7 @@ class ParserBase { void ClearOprt(); void RemoveVar(const string_type &a_strVarName); - const varmap_type &GetUsedVar() const; const varmap_type &GetVar() const; - const valmap_type &GetConst() const; const string_type &GetExpr() const; const funmap_type &GetFunDef() const; string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; diff --git a/muparser-2.2.5/include/muParserDLL.h b/muparser-2.2.5/include/muParserDLL.h index ccc79ff1f..396f63ccf 100644 --- a/muparser-2.2.5/include/muParserDLL.h +++ b/muparser-2.2.5/include/muParserDLL.h @@ -195,17 +195,9 @@ API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser); // Querying variables / expression variables / constants API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); -API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser); -API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser); API_EXPORT(void) mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, muFloat_t **a_pVar); -API_EXPORT(void) -mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, - muFloat_t **a_pVar); -API_EXPORT(void) -mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, - muFloat_t *a_pVar); API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); diff --git a/muparser-2.2.5/include/muParserTest.h b/muparser-2.2.5/include/muParserTest.h index ff6738784..71607d44c 100644 --- a/muparser-2.2.5/include/muParserTest.h +++ b/muparser-2.2.5/include/muParserTest.h @@ -167,7 +167,6 @@ class ParserTester // final int TestExpression(); int TestInfixOprt(); int TestBinOprt(); - int TestVarConst(); int TestInterface(); int TestException(); int TestStrArg(); diff --git a/muparser-2.2.5/include/muParserTokenReader.h b/muparser-2.2.5/include/muParserTokenReader.h index 597c9809f..c9e46c81b 100644 --- a/muparser-2.2.5/include/muParserTokenReader.h +++ b/muparser-2.2.5/include/muParserTokenReader.h @@ -62,7 +62,6 @@ class ParserTokenReader final { int GetPos() const; const string_type &GetExpr() const; - varmap_type &GetUsedVar(); char_type GetArgSep() const; void IgnoreUndefVar(bool bIgnore); diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index e4f48839a..fac5e253c 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -243,61 +243,6 @@ void CheckDiff() } */ -//--------------------------------------------------------------------------- -void ListVar(const mu::ParserBase &parser) { - // Query the used variables (must be done after calc) - mu::varmap_type variables = parser.GetVar(); - if (!variables.size()) return; - - cout << "\nParser variables:\n"; - cout << "-----------------\n"; - cout << "Number: " << (int)variables.size() << "\n"; - varmap_type::const_iterator item = variables.begin(); - for (; item != variables.end(); ++item) - mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second - << _T("]\n"); -} - -//--------------------------------------------------------------------------- -void ListConst(const mu::ParserBase &parser) { - mu::console() << _T("\nParser constants:\n"); - mu::console() << _T("-----------------\n"); - - mu::valmap_type cmap = parser.GetConst(); - if (!cmap.size()) { - mu::console() << _T("Expression does not contain constants\n"); - } else { - valmap_type::const_iterator item = cmap.begin(); - for (; item != cmap.end(); ++item) - mu::console() << _T(" ") << item->first << _T(" = ") << item->second << _T("\n"); - } -} - -//--------------------------------------------------------------------------- -void ListExprVar(const mu::ParserBase &parser) { - string_type sExpr = parser.GetExpr(); - if (sExpr.length() == 0) { - cout << _T("Expression string is empty\n"); - return; - } - - // Query the used variables (must be done after calc) - mu::console() << _T("\nExpression variables:\n"); - mu::console() << _T("---------------------\n"); - mu::console() << _T("Expression: ") << parser.GetExpr() << _T("\n"); - - varmap_type variables = parser.GetUsedVar(); - if (!variables.size()) { - mu::console() << _T("Expression does not contain variables\n"); - } else { - mu::console() << _T("Number: ") << (int)variables.size() << _T("\n"); - mu::varmap_type::const_iterator item = variables.begin(); - for (; item != variables.end(); ++item) - mu::console() << _T("Name: ") << item->first << _T(" Address: [0x") << item->second - << _T("]\n"); - } -} - //--------------------------------------------------------------------------- /** \brief Check for external keywords. */ @@ -306,15 +251,6 @@ int CheckKeywords(const mu::char_type *a_szLine, mu::Parser &a_Parser) { if (sLine == _T("quit")) { return -1; - } else if (sLine == _T("list var")) { - ListVar(a_Parser); - return 1; - } else if (sLine == _T("list const")) { - ListConst(a_Parser); - return 1; - } else if (sLine == _T("list exprvar")) { - ListExprVar(a_Parser); - return 1; } else if (sLine == _T("locale de")) { mu::console() << _T("Setting german locale: ArgSep=';' DecSep=',' ThousandsSep='.'\n"); a_Parser.SetArgSep(';'); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index f5e22cf2c..3a571d217 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -533,36 +533,6 @@ EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) con } } -//--------------------------------------------------------------------------- -/** \brief Return a map containing the used variables only. */ -const varmap_type &ParserBase::GetUsedVar() const { - try { - m_pTokenReader->IgnoreUndefVar(true); - // Try to create bytecode, but don't use it for any further calculations since it may - // contain references to nonexisting variables. - OptionalError oerr = CreateRPN(); - if (oerr.has_error()) throw oerr.error(); - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - } catch (exception_type & /*e*/) { - // Make sure to stay in string parse mode, dont call ReInit() - // because it deletes the array with the used variables - m_pParseFormula = &ParserBase::ParseString; - m_pTokenReader->IgnoreUndefVar(false); - throw; - } - - return m_pTokenReader->GetUsedVar(); -} - -//--------------------------------------------------------------------------- -/** \brief Return a map containing the used variables only. */ -const varmap_type &ParserBase::GetVar() const { return m_VarDef; } - -//--------------------------------------------------------------------------- -/** \brief Return a map containing all parser constants. */ -const valmap_type &ParserBase::GetConst() const { return m_ConstDef; } - //--------------------------------------------------------------------------- /** \brief Return prototypes of all parser functions. \return #m_FunDef @@ -1510,8 +1480,7 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; } A note on const correctness: I consider it important that Calc is a const function. Due to caching operations Calc changes only the state of internal variables with one exception - m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making - Calc non const GetUsedVar is non const because it explicitly calls Eval() forcing this update. + m_UsedVar this is reset during string parsing and accessible from the outside. \pre A formula must be set. \pre Variables must have been set (if needed) diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index be69afc85..6fca652a3 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -510,159 +510,6 @@ API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muCha p->DefineInfixOprtChars(a_szCharset); } -//--------------------------------------------------------------------------- -/** \brief Get the number of variables defined in the parser. - \param a_hParser [in] Must be a valid parser handle. - \return The number of used variables. - \sa mupGetExprVar - */ -API_EXPORT(int) mupGetVarNum(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetVar(); - return (int)VarMap.size(); - MU_CATCH - - return 0; // never reached -} - -//--------------------------------------------------------------------------- -/** \brief Return a variable that is used in an expression. - \param a_hParser [in] A valid parser handle. - \param a_iVar [in] The index of the variable to return. - \param a_szName [out] Pointer to the variable name. - \param a_pVar [out] Pointer to the variable. - - Prior to calling this function call mupGetExprVarNum in order to get the - number of variables in the expression. If the parameter a_iVar is greater - than the number of variables both a_szName and a_pVar will be set to zero. - As a side effect this function will trigger an internal calculation of the - expression undefined variables will be set to zero during this calculation. - During the calculation user defined callback functions present in the expression - will be called, this is unavoidable. - */ -API_EXPORT(void) -mupGetVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, - muFloat_t** a_pVar) { - // A static buffer is needed for the name since i cant return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetVar(); - - if (a_iVar >= VarMap.size()) { - *a_szName = 0; - *a_pVar = 0; - return; - } - mu::varmap_type::const_iterator item; - - item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), sizeof(szName)); -#else - wcsncpy(szName, item->first.c_str(), sizeof(szName)); -#endif - - szName[sizeof(szName) - 1] = 0; - - *a_szName = &szName[0]; - *a_pVar = item->second; - return; - - MU_CATCH - - *a_szName = 0; - *a_pVar = 0; -} - -//--------------------------------------------------------------------------- -/** \brief Get the number of variables used in the expression currently set in the parser. - \param a_hParser [in] Must be a valid parser handle. - \return The number of used variables. - \sa mupGetExprVar - */ -API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetUsedVar(); - return (int)VarMap.size(); - MU_CATCH - - return 0; // never reached -} - -//--------------------------------------------------------------------------- -/** \brief Return a variable that is used in an expression. - - Prior to calling this function call mupGetExprVarNum in order to get the - number of variables in the expression. If the parameter a_iVar is greater - than the number of variables both a_szName and a_pVar will be set to zero. - As a side effect this function will trigger an internal calculation of the - expression undefined variables will be set to zero during this calculation. - During the calculation user defined callback functions present in the expression - will be called, this is unavoidable. - - \param a_hParser [in] A valid parser handle. - \param a_iVar [in] The index of the variable to return. - \param a_szName [out] Pointer to the variable name. - \param a_pVar [out] Pointer to the variable. - */ -API_EXPORT(void) -mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_szName, - muFloat_t** a_pVar) { - // A static buffer is needed for the name since i cant return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::varmap_type VarMap = p->GetUsedVar(); - - if (a_iVar >= VarMap.size()) { - *a_szName = 0; - *a_pVar = 0; - return; - } - mu::varmap_type::const_iterator item; - - item = VarMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), sizeof(szName)); -#else - wcsncpy(szName, item->first.c_str(), sizeof(szName)); -#endif - - szName[sizeof(szName) - 1] = 0; - - *a_szName = &szName[0]; - *a_pVar = item->second; - return; - - MU_CATCH - - *a_szName = 0; - *a_pVar = 0; -} - -//--------------------------------------------------------------------------- -/** \brief Return the number of constants defined in a parser. */ -API_EXPORT(int) mupGetConstNum(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::valmap_type ValMap = p->GetConst(); - return (int)ValMap.size(); - MU_CATCH - - return 0; // never reached -} - //----------------------------------------------------------------------------------------------------- API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) { MU_TRY @@ -695,52 +542,6 @@ API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t c MU_CATCH } -//--------------------------------------------------------------------------- -/** \brief Retrieve name and value of a single parser constant. - \param a_hParser [in] a valid parser handle - \param a_iVar [in] Index of the constant to query - \param a_pszName [out] pointer to a null terminated string with the constant name - \param [out] The constant value - */ -API_EXPORT(void) -mupGetConst(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t** a_pszName, - muFloat_t* a_fVal) { - // A static buffer is needed for the name since i cant return the - // pointer from the map. - static muChar_t szName[1024]; - - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - const mu::valmap_type ValMap = p->GetConst(); - - if (a_iVar >= ValMap.size()) { - *a_pszName = 0; - *a_fVal = 0; - return; - } - - mu::valmap_type::const_iterator item; - item = ValMap.begin(); - for (unsigned i = 0; i < a_iVar; ++i) ++item; - -#ifndef _UNICODE - strncpy(szName, item->first.c_str(), sizeof(szName)); -#else - wcsncpy(szName, item->first.c_str(), sizeof(szName)); -#endif - - szName[sizeof(szName) - 1] = 0; - - *a_pszName = &szName[0]; - *a_fVal = item->second; - return; - - MU_CATCH - - *a_pszName = 0; - *a_fVal = 0; -} - //--------------------------------------------------------------------------- /** \brief Add a custom value recognition function. */ diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 4a5920350..3266a2cdd 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -49,7 +49,6 @@ ParserTester::ParserTester() : m_vTestFun() { AddTest(&ParserTester::TestSyntax); AddTest(&ParserTester::TestPostFix); AddTest(&ParserTester::TestInfixOprt); - AddTest(&ParserTester::TestVarConst); AddTest(&ParserTester::TestMultiArg); AddTest(&ParserTester::TestExpression); AddTest(&ParserTester::TestIfThenElse); @@ -427,103 +426,6 @@ int ParserTester::TestSyntax() { return iStat; } -//--------------------------------------------------------------------------- -int ParserTester::TestVarConst() { - int iStat = 0; - mu::console() << _T("testing variable/constant detection..."); - - // Test if the result changes when a variable changes - iStat += EqnTestWithVarChange(_T("a"), 1, 1, 2, 2); - iStat += EqnTestWithVarChange(_T("2*a"), 2, 4, 3, 6); - - // distinguish constants with same basename - iStat += EqnTest(_T("const"), 1, true); - iStat += EqnTest(_T("const1"), 2, true); - iStat += EqnTest(_T("const2"), 3, true); - iStat += EqnTest(_T("2*const"), 2, true); - iStat += EqnTest(_T("2*const1"), 4, true); - iStat += EqnTest(_T("2*const2"), 6, true); - iStat += EqnTest(_T("2*const+1"), 3, true); - iStat += EqnTest(_T("2*const1+1"), 5, true); - iStat += EqnTest(_T("2*const2+1"), 7, true); - iStat += EqnTest(_T("const"), 0, false); - iStat += EqnTest(_T("const1"), 0, false); - iStat += EqnTest(_T("const2"), 0, false); - - // distinguish variables with same basename - iStat += EqnTest(_T("a"), 1, true); - iStat += EqnTest(_T("aa"), 2, true); - iStat += EqnTest(_T("2*a"), 2, true); - iStat += EqnTest(_T("2*aa"), 4, true); - iStat += EqnTest(_T("2*a-1"), 1, true); - iStat += EqnTest(_T("2*aa-1"), 3, true); - - // custom value recognition - iStat += EqnTest(_T("0xff"), 255, true); - iStat += EqnTest(_T("0x97 + 0xff"), 406, true); - - // Finally test querying of used variables - try { - int idx; - mu::Parser p; - mu::value_type vVarVal[] = {1, 2, 3, 4, 5}; - p.DefineVar(_T("a"), &vVarVal[0]); - p.DefineVar(_T("b"), &vVarVal[1]); - p.DefineVar(_T("c"), &vVarVal[2]); - p.DefineVar(_T("d"), &vVarVal[3]); - p.DefineVar(_T("e"), &vVarVal[4]); - - // Test lookup of defined variables - // 4 used variables - p.SetExpr(_T("a+b+c+d")); - mu::varmap_type UsedVar = p.GetUsedVar(); - int iCount = (int)UsedVar.size(); - if (iCount != 4) throw false; - - // the next check will fail if the parser - // erroneously creates new variables internally - if (p.GetVar().size() != 5) throw false; - - mu::varmap_type::const_iterator item = UsedVar.begin(); - for (idx = 0; item != UsedVar.end(); ++item) { - if (&vVarVal[idx++] != item->second) throw false; - } - - // Test lookup of undefined variables - p.SetExpr(_T("undef1+undef2+undef3")); - UsedVar = p.GetUsedVar(); - iCount = (int)UsedVar.size(); - if (iCount != 3) throw false; - - // the next check will fail if the parser - // erroneously creates new variables internally - if (p.GetVar().size() != 5) throw false; - - for (item = UsedVar.begin(); item != UsedVar.end(); ++item) { - if (item->second != 0) throw false; // all pointers to undefined variables must be null - } - - // 1 used variables - p.SetExpr(_T("a+b")); - UsedVar = p.GetUsedVar(); - iCount = (int)UsedVar.size(); - if (iCount != 2) throw false; - item = UsedVar.begin(); - for (idx = 0; item != UsedVar.end(); ++item) - if (&vVarVal[idx++] != item->second) throw false; - - } catch (...) { - iStat += 1; - } - - if (iStat == 0) - mu::console() << _T("passed") << endl; - else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; - - return iStat; -} - //--------------------------------------------------------------------------- int ParserTester::TestMultiArg() { int iStat = 0; diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 3471e8fa4..34c6cd1f6 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -89,10 +89,6 @@ int ParserTokenReader::GetPos() const { return m_iPos; } */ const string_type &ParserTokenReader::GetExpr() const { return m_strFormula; } -//--------------------------------------------------------------------------- -/** \brief Return a map containing the used variables only. */ -varmap_type &ParserTokenReader::GetUsedVar() { return m_UsedVar; } - //--------------------------------------------------------------------------- /** \brief Initialize the token Reader. From 67a6f756f22d757b308333b42202a21c5f85fe63 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Nov 2017 23:04:44 -0800 Subject: [PATCH 27/62] Add some math tests for invalid inputs --- muparser-2.2.5/src/muParser.cpp | 2 +- tests/math.err | 7 +++++++ tests/math.in | 6 ++++++ tests/math.out | 3 +++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 6d19b9f25..5e4e7bb25 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -168,7 +168,7 @@ ValueOrError Parser::Min(const value_type *a_afArg, int a_iArgc) { \param [in] a_iArgc The size of a_afArg */ ValueOrError Parser::Max(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw exception_type(_T("too few arguments for function min.")); + if (!a_iArgc) throw exception_type(_T("too few arguments for function max.")); value_type fRes = a_afArg[0]; for (int i = 0; i < a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]); diff --git a/tests/math.err b/tests/math.err index 5a7ab5130..212b31850 100644 --- a/tests/math.err +++ b/tests/math.err @@ -4,3 +4,10 @@ #################### # Validate how variables in an expression are handled + +#################### +# Validate math error reporting +math: Invalid expression: Too few parameters for function "min" at expression position 5 +math: Invalid expression: String value used where a numerical argument is expected. +math: Invalid expression: Too few parameters for function "max" at expression position 5 +math: Invalid expression: Too few parameters for function "sum" at expression position 5 diff --git a/tests/math.in b/tests/math.in index 1e13114d7..8fa48595f 100644 --- a/tests/math.in +++ b/tests/math.in @@ -22,3 +22,9 @@ set x 3 set y 1.5 math "-$x * $y" math -s1 "-$x * $y" + +logmsg Validate math error reporting +not math 'min()' +not math 'min("abc")' +not math 'max()' +not math 'sum()' diff --git a/tests/math.out b/tests/math.out index df8607f71..7ddcac4a0 100644 --- a/tests/math.out +++ b/tests/math.out @@ -22,3 +22,6 @@ 2 -4 -4.5 + +#################### +# Validate math error reporting From bceef6c1250e586d070f9726781e56ca6903fa31 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Nov 2017 23:53:26 -0800 Subject: [PATCH 28/62] [muparser] ParserInt::IsBinVal to return false on overflow Instead of throwing an exception, simply return false. It is too complicated to thread the error return through this function and ParserInt is unused by fish anyways. --- muparser-2.2.5/src/muParserInt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/muparser-2.2.5/src/muParserInt.cpp b/muparser-2.2.5/src/muParserInt.cpp index 10bbb1a18..7523a636c 100644 --- a/muparser-2.2.5/src/muParserInt.cpp +++ b/muparser-2.2.5/src/muParserInt.cpp @@ -162,7 +162,8 @@ int ParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, value_type *a_fV if (i == 0) return 0; - if (i == iBits) throw exception_type(_T("Binary to integer conversion error (overflow).")); + // return false on overflow + if (i == iBits) return 0; *a_fVal = (unsigned)(iVal >> (iBits - i)); *a_iPos += i + 1; From 91c28449aab8196ea6a59f2990969bdec48f2e79 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Nov 2017 23:55:51 -0800 Subject: [PATCH 29/62] [muparser] Parser mathematical functions to return errors instead of throw Remove exceptions from Parser functions such as sqrt, min, and others. --- muparser-2.2.5/include/muParserBase.h | 31 +++--- muparser-2.2.5/include/muParserDef.h | 28 +++--- muparser-2.2.5/src/muParser.cpp | 25 +++-- muparser-2.2.5/src/muParserBase.cpp | 130 +++++++++++++++----------- muparser-2.2.5/src/muParserInt.cpp | 42 ++++----- src/builtin_math.cpp | 6 +- 6 files changed, 146 insertions(+), 116 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 52291748f..ec268779b 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -102,7 +102,7 @@ class ParserBase { int GetNumResults() const; - void SetExpr(const string_type &a_sExpr); + OptionalError SetExpr(const string_type &a_sExpr); void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL); void SetDecSep(char_type cDecSep); @@ -123,14 +123,17 @@ class ParserBase { */ template void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) { - AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars()); + auto oerr = + AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars()); + if (oerr.has_error()) throw oerr.error(); } - void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, - EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false); - void DefineConst(const string_type &a_sName, value_type a_fVal); - void DefineStrConst(const string_type &a_sName, const string_type &a_strVal); - void DefineVar(const string_type &a_sName, value_type *a_fVar); + OptionalError DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, + EOprtAssociativity a_eAssociativity = oaLEFT, + bool a_bAllowOpt = false); + OptionalError DefineConst(const string_type &a_sName, value_type a_fVal); + OptionalError DefineStrConst(const string_type &a_sName, const string_type &a_strVal); + OptionalError DefineVar(const string_type &a_sName, value_type *a_fVar); void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true); void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, bool a_bAllowOpt = true); @@ -161,8 +164,8 @@ class ParserBase { void SetArgSep(char_type cArgSep); char_type GetArgSep() const; - void Error(EErrorCodes a_iErrc, int a_iPos = (int)mu::string_type::npos, - const string_type &a_strTok = string_type()) const; + ParserError Error(EErrorCodes a_iErrc, int a_iPos = (int)mu::string_type::npos, + const string_type &a_strTok = string_type()) const; protected: void Init(); @@ -213,8 +216,8 @@ class ParserBase { void InitTokenReader(); void ReInit() const; - void AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, - funmap_type &a_Storage, const char_type *a_szCharSet); + OptionalError AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, + funmap_type &a_Storage, const char_type *a_szCharSet); OptionalError ApplyRemainingOprt(ParserStack &a_stOpt, ParserStack &a_stVal) const; @@ -240,9 +243,9 @@ class ParserBase { ValueOrError ParseCmdCodeBulk(int nOffset, int nThreadID) const; ValueOrError InvokeFunction(generic_fun_type func, const value_type *args, int argCount) const; - void CheckName(const string_type &a_strName, const string_type &a_CharSet) const; - void CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, - const string_type &a_szCharSet) const; + OptionalError CheckName(const string_type &a_strName, const string_type &a_CharSet) const; + OptionalError CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, + const string_type &a_szCharSet) const; void StackDump(const ParserStack &a_stVal, const ParserStack &a_stOprt) const; diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 24bcbc801..e309af55d 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -288,6 +288,19 @@ enum EErrorCodes { /// \return an error message for the given code. string_type parser_error_for_code(EErrorCodes code); +// Compatibility with non-clang compilers. +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +// Define a type-level attribute declaring that this type, when used as the return value +// of a function, should produce warnings. +#if __has_attribute(warn_unused_result) +#define MUPARSER_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +#define MUPARSER_ATTR_WARN_UNUSED_RESULT +#endif + //--------------------------------------------------------------------------- /** \brief Error class of the parser. \author Ingo Berg @@ -326,20 +339,7 @@ class ParserError { string_type m_strTok; ///< Token related with the error int m_iPos; ///< Formula position related to the error EErrorCodes m_iErrc; ///< Error code -}; - -// Compatibility with non-clang compilers. -#ifndef __has_attribute -#define __has_attribute(x) 0 -#endif - -// Define a type-level attribute declaring that this type, when used as the return value -// of a function, should produce warnings. -#if __has_attribute(warn_unused_result) -#define MUPARSER_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define MUPARSER_ATTR_WARN_UNUSED_RESULT -#endif +} MUPARSER_ATTR_WARN_UNUSED_RESULT; // OptionalError is used to optionally encapsulate an error. class OptionalError { diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 5e4e7bb25..96af93de9 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -70,7 +70,7 @@ ValueOrError Parser::ATanh(value_type v) { return MathImpl::ATanh(v) // Logarithm base 2 ValueOrError Parser::Log2(value_type v) { #ifdef MUP_MATH_EXCEPTIONS - if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Log2")); + if (v <= 0) return ParserError(ecDOMAIN_ERROR, _T("Log2")); #endif return MathImpl::Log2(v); @@ -79,7 +79,7 @@ ValueOrError Parser::Log2(value_type v) { // Logarithm base 10 ValueOrError Parser::Log10(value_type v) { #ifdef MUP_MATH_EXCEPTIONS - if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Log10")); + if (v <= 0) return ParserError(ecDOMAIN_ERROR, _T("Log10")); #endif return MathImpl::Log10(v); @@ -88,7 +88,7 @@ ValueOrError Parser::Log10(value_type v) { // Logarithm base e (natural logarithm) ValueOrError Parser::Ln(value_type v) { #ifdef MUP_MATH_EXCEPTIONS - if (v <= 0) throw ParserError(ecDOMAIN_ERROR, _T("Ln")); + if (v <= 0) return ParserError(ecDOMAIN_ERROR, _T("Ln")); #endif return MathImpl::Log(v); @@ -100,7 +100,7 @@ ValueOrError Parser::Exp(value_type v) { return MathImpl::Exp(v); } ValueOrError Parser::Abs(value_type v) { return MathImpl::Abs(v); } ValueOrError Parser::Sqrt(value_type v) { #ifdef MUP_MATH_EXCEPTIONS - if (v < 0) throw ParserError(ecDOMAIN_ERROR, _T("sqrt")); + if (v < 0) return ParserError(ecDOMAIN_ERROR, _T("sqrt")); #endif return MathImpl::Sqrt(v); @@ -128,7 +128,7 @@ ValueOrError Parser::UnaryPlus(value_type v) { return v; } \param [in] a_iArgc The size of a_afArg */ ValueOrError Parser::Sum(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw exception_type(_T("too few arguments for function sum.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function sum.")); value_type fRes = 0; for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; @@ -141,7 +141,7 @@ ValueOrError Parser::Sum(const value_type *a_afArg, int a_iArgc) { \param [in] a_iArgc The size of a_afArg */ ValueOrError Parser::Avg(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw exception_type(_T("too few arguments for function sum.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function sum.")); value_type fRes = 0; for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; @@ -154,7 +154,7 @@ ValueOrError Parser::Avg(const value_type *a_afArg, int a_iArgc) { \param [in] a_iArgc The size of a_afArg */ ValueOrError Parser::Min(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw exception_type(_T("too few arguments for function min.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; for (int i = 0; i < a_iArgc; ++i) fRes = std::min(fRes, a_afArg[i]); @@ -168,7 +168,7 @@ ValueOrError Parser::Min(const value_type *a_afArg, int a_iArgc) { \param [in] a_iArgc The size of a_afArg */ ValueOrError Parser::Max(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw exception_type(_T("too few arguments for function max.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function max.")); value_type fRes = a_afArg[0]; for (int i = 0; i < a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]); @@ -279,8 +279,13 @@ void Parser::InitFun() { number ("_e"). */ void Parser::InitConst() { - DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); - DefineConst(_T("_e"), (value_type)PARSER_CONST_E); + OptionalError oerr; + oerr = DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); + assert(!oerr.has_error() && "Error defining _pi constant"); + (void)oerr; + oerr = DefineConst(_T("_e"), (value_type)PARSER_CONST_E); + assert(!oerr.has_error() && "Error defining _e constant"); + (void)oerr; } //--------------------------------------------------------------------------- diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 3a571d217..ba0a2c893 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -219,30 +219,33 @@ void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData) { //--------------------------------------------------------------------------- /** \brief Add a function or operator callback to the parser. */ -void ParserBase::AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, - funmap_type &a_Storage, const char_type *a_szCharSet) { - if (a_Callback.GetAddr() == 0) Error(ecINVALID_FUN_PTR); +OptionalError ParserBase::AddCallback(const string_type &a_strName, + const ParserCallback &a_Callback, funmap_type &a_Storage, + const char_type *a_szCharSet) { + assert(a_Callback.GetAddr() && "Null callback"); const funmap_type *pFunMap = &a_Storage; // Check for conflicting operator or function names if (pFunMap != &m_FunDef && m_FunDef.find(a_strName) != m_FunDef.end()) - Error(ecNAME_CONFLICT, -1, a_strName); + return Error(ecNAME_CONFLICT, -1, a_strName); if (pFunMap != &m_PostOprtDef && m_PostOprtDef.find(a_strName) != m_PostOprtDef.end()) - Error(ecNAME_CONFLICT, -1, a_strName); + return Error(ecNAME_CONFLICT, -1, a_strName); if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_InfixOprtDef.find(a_strName) != m_InfixOprtDef.end()) - Error(ecNAME_CONFLICT, -1, a_strName); + return Error(ecNAME_CONFLICT, -1, a_strName); if (pFunMap != &m_InfixOprtDef && pFunMap != &m_OprtDef && m_OprtDef.find(a_strName) != m_OprtDef.end()) - Error(ecNAME_CONFLICT, -1, a_strName); + return Error(ecNAME_CONFLICT, -1, a_strName); - CheckOprt(a_strName, a_Callback, a_szCharSet); + OptionalError oerr = CheckOprt(a_strName, a_Callback, a_szCharSet); + if (oerr.has_error()) return oerr; a_Storage[a_strName] = a_Callback; ReInit(); + return {}; } //--------------------------------------------------------------------------- @@ -250,19 +253,20 @@ void ParserBase::AddCallback(const string_type &a_strName, const ParserCallback \throw ParserException if the name contains invalid characters. */ -void ParserBase::CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, - const string_type &a_szCharSet) const { +OptionalError ParserBase::CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, + const string_type &a_szCharSet) const { if (!a_sName.length() || (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) || (a_sName[0] >= '0' && a_sName[0] <= '9')) { switch (a_Callback.GetCode()) { case cmOPRT_POSTFIX: - Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); + return Error(ecINVALID_POSTFIX_IDENT, -1, a_sName); case cmOPRT_INFIX: - Error(ecINVALID_INFIX_IDENT, -1, a_sName); + return Error(ecINVALID_INFIX_IDENT, -1, a_sName); default: - Error(ecINVALID_NAME, -1, a_sName); + return Error(ecINVALID_NAME, -1, a_sName); } } + return {}; } //--------------------------------------------------------------------------- @@ -270,11 +274,13 @@ void ParserBase::CheckOprt(const string_type &a_sName, const ParserCallback &a_C \throw ParserException if the name contains invalid characters. */ -void ParserBase::CheckName(const string_type &a_sName, const string_type &a_szCharSet) const { +OptionalError ParserBase::CheckName(const string_type &a_sName, + const string_type &a_szCharSet) const { if (!a_sName.length() || (a_sName.find_first_not_of(a_szCharSet) != string_type::npos) || (a_sName[0] >= '0' && a_sName[0] <= '9')) { - Error(ecINVALID_NAME); + return Error(ecINVALID_NAME); } + return {}; } //--------------------------------------------------------------------------- @@ -285,11 +291,11 @@ void ParserBase::CheckName(const string_type &a_sName, const string_type &a_szCh Triggers first time calculation thus the creation of the bytecode and scanning of used variables. */ -void ParserBase::SetExpr(const string_type &a_sExpr) { +OptionalError ParserBase::SetExpr(const string_type &a_sExpr) { // Check locale compatibility std::locale loc; if (m_pTokenReader->GetArgSep() == std::use_facet >(loc).decimal_point()) - Error(ecLOCALE); + return Error(ecLOCALE); // 20060222: Bugfix for Borland-Kylix: // adding a space to the expression will keep Borlands KYLIX from going wild @@ -299,6 +305,7 @@ void ParserBase::SetExpr(const string_type &a_sExpr) { string_type sBuf(a_sExpr + _T(" ")); m_pTokenReader->SetFormula(sBuf); ReInit(); + return {}; } //--------------------------------------------------------------------------- @@ -359,8 +366,9 @@ const char_type *ParserBase::ValidInfixOprtChars() const { \post Will reset the Parser to string parsing mode. */ void ParserBase::DefinePostfixOprt(const string_type &a_sName, fun_type1 a_pFun, bool a_bAllowOpt) { - AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), - m_PostOprtDef, ValidOprtChars()); + auto oerr = AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), + m_PostOprtDef, ValidOprtChars()); + if (oerr.has_error()) throw oerr.error(); } //--------------------------------------------------------------------------- @@ -386,8 +394,9 @@ void ParserBase::Init() { */ void ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, int a_iPrec, bool a_bAllowOpt) { - AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, - ValidInfixOprtChars()); + auto oerr = AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), + m_InfixOprtDef, ValidInfixOprtChars()); + if (oerr.has_error()) throw oerr.error(); } //--------------------------------------------------------------------------- @@ -400,14 +409,14 @@ void ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, i Adds a new Binary operator the the parser instance. */ -void ParserBase::DefineOprt(const string_type &a_sName, fun_type2 a_pFun, unsigned a_iPrec, - EOprtAssociativity a_eAssociativity, bool a_bAllowOpt) { +OptionalError ParserBase::DefineOprt(const string_type &a_sName, fun_type2 a_pFun, unsigned a_iPrec, + EOprtAssociativity a_eAssociativity, bool a_bAllowOpt) { // Check for conflicts with built in operator names for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i) - if (a_sName == string_type(c_DefaultOprt[i])) Error(ecBUILTIN_OVERLOAD, -1, a_sName); + if (a_sName == string_type(c_DefaultOprt[i])) return Error(ecBUILTIN_OVERLOAD, -1, a_sName); - AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), m_OprtDef, - ValidOprtChars()); + return AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), + m_OprtDef, ValidOprtChars()); } //--------------------------------------------------------------------------- @@ -415,16 +424,19 @@ void ParserBase::DefineOprt(const string_type &a_sName, fun_type2 a_pFun, unsign \param [in] a_strName The name of the constant. \param [in] a_strVal the value of the constant. */ -void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal) { +OptionalError ParserBase::DefineStrConst(const string_type &a_strName, + const string_type &a_strVal) { // Test if a constant with that names already exists - if (m_StrVarDef.find(a_strName) != m_StrVarDef.end()) Error(ecNAME_CONFLICT); + if (m_StrVarDef.find(a_strName) != m_StrVarDef.end()) return Error(ecNAME_CONFLICT); - CheckName(a_strName, ValidNameChars()); + OptionalError oerr = CheckName(a_strName, ValidNameChars()); + if (oerr.has_error()) return oerr; m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer m_StrVarDef[a_strName] = m_vStringVarBuf.size() - 1; // bind buffer index to variable name ReInit(); + return {}; } //--------------------------------------------------------------------------- @@ -434,15 +446,18 @@ void ParserBase::DefineStrConst(const string_type &a_strName, const string_type \post Will reset the Parser to string parsing mode. \throw ParserException in case the name contains invalid signs or a_pVar is NULL. */ -void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar) { - if (a_pVar == 0) Error(ecINVALID_VAR_PTR); +OptionalError ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar) { + assert(a_pVar != nullptr && "Null variable pointer"); // Test if a constant with that names already exists - if (m_ConstDef.find(a_sName) != m_ConstDef.end()) Error(ecNAME_CONFLICT); + if (m_ConstDef.find(a_sName) != m_ConstDef.end()) return Error(ecNAME_CONFLICT); + + OptionalError oerr = CheckName(a_sName, ValidNameChars()); + if (oerr.has_error()) return oerr; - CheckName(a_sName, ValidNameChars()); m_VarDef[a_sName] = a_pVar; ReInit(); + return {}; } //--------------------------------------------------------------------------- @@ -452,10 +467,12 @@ void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar) { \post Will reset the Parser to string parsing mode. \throw ParserException in case the name contains invalid signs. */ -void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal) { - CheckName(a_sName, ValidNameChars()); +OptionalError ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal) { + OptionalError oerr = CheckName(a_sName, ValidNameChars()); + if (oerr.has_error()) return oerr; m_ConstDef[a_sName] = a_fVal; ReInit(); + return {}; } //--------------------------------------------------------------------------- @@ -557,7 +574,7 @@ const string_type &ParserBase::GetExpr() const { return m_pTokenReader->GetExpr( OptionalError ParserBase::ApplyStrFunc(const token_type &a_FunTok, const std::vector &a_vArg) const { if (a_vArg.back().GetCode() != cmSTRING) - Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + return Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); token_type valTok; generic_fun_type pFunc = a_FunTok.GetFuncAddr(); @@ -584,7 +601,7 @@ OptionalError ParserBase::ApplyStrFunc(const token_type &a_FunTok, assert(0 && "Unexpected arg count"); } if (errored) { - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); + return Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); } // string functions won't be optimized @@ -625,13 +642,13 @@ OptionalError ParserBase::ApplyFunc(ParserStack &a_stOpt, assert(0 && "muParser internal error"); if (funTok.GetArgCount() >= 0 && iArgCount > iArgRequired) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + return Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); if (funTok.GetCode() != cmOPRT_BIN && iArgCount < iArgRequired) - Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + return Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); if (funTok.GetCode() == cmFUNC_STR && iArgCount > iArgRequired) - Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); + return Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos() - 1, funTok.GetAsString()); // Collect the numeric function arguments from the value stack and store them // in a vector @@ -639,7 +656,7 @@ OptionalError ParserBase::ApplyFunc(ParserStack &a_stOpt, for (int i = 0; i < iArgNumerical; ++i) { stArg.push_back(a_stVal.pop()); if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR) - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + return Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); } switch (funTok.GetCode()) { @@ -647,7 +664,7 @@ OptionalError ParserBase::ApplyFunc(ParserStack &a_stOpt, stArg.push_back(a_stVal.pop()); if (stArg.back().GetType() == tpSTR && funTok.GetType() != tpSTR) - Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); + return Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString()); OptionalError err = ApplyStrFunc(funTok, stArg); if (err.has_error()) return err; @@ -659,7 +676,7 @@ OptionalError ParserBase::ApplyFunc(ParserStack &a_stOpt, case cmOPRT_INFIX: case cmFUNC: if (funTok.GetArgCount() == -1 && iArgCount == 0) - Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); + return Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos(), funTok.GetAsString()); m_vRPN.AddFun(funTok.GetFuncAddr(), (funTok.GetArgCount() == -1) ? -iArgNumerical : iArgNumerical); @@ -723,10 +740,10 @@ OptionalError ParserBase::ApplyBinOprt(ParserStack &a_stOpt, if (valTok1.GetType() != valTok2.GetType() || (valTok1.GetType() == tpSTR && valTok2.GetType() == tpSTR)) - Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); + return Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString()); if (optTok.GetCode() == cmASSIGN) { - if (valTok2.GetCode() != cmVAR) Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); + if (valTok2.GetCode() != cmVAR) return Error(ecUNEXPECTED_OPERATOR, -1, _T("=")); m_vRPN.AddAssignOp(valTok2.GetVar()); } else @@ -1023,8 +1040,8 @@ OptionalError ParserBase::CreateRPN() const { for (;;) { opt = m_pTokenReader->ReadNextToken(); - OptionalError oerr; + OptionalError oerr; switch (opt.GetCode()) { // // Next three are different kind of value entries @@ -1050,7 +1067,7 @@ OptionalError ParserBase::CreateRPN() const { case cmELSE: m_nIfElseCounter--; - if (m_nIfElseCounter < 0) Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + if (m_nIfElseCounter < 0) return Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); oerr = ApplyRemainingOprt(stOpt, stVal); if (oerr.has_error()) return oerr.error(); @@ -1059,7 +1076,8 @@ OptionalError ParserBase::CreateRPN() const { break; case cmARG_SEP: - if (stArgCount.empty()) Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); + if (stArgCount.empty()) + return Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); ++stArgCount.top(); // fallthrough intentional (no break!) @@ -1096,7 +1114,7 @@ OptionalError ParserBase::CreateRPN() const { if (iArgCount > 1 && (stOpt.size() == 0 || (stOpt.top().GetCode() != cmFUNC && stOpt.top().GetCode() != cmFUNC_STR))) - Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); + return Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos()); // The opening bracket was popped from the stack now check if there // was a function before this bracket @@ -1208,16 +1226,16 @@ OptionalError ParserBase::CreateRPN() const { if (ParserBase::g_DbgDumpCmdCode) m_vRPN.AsciiDump(); - if (m_nIfElseCounter > 0) Error(ecMISSING_ELSE_CLAUSE); + if (m_nIfElseCounter > 0) return Error(ecMISSING_ELSE_CLAUSE); // get the last value (= final result) from the stack assert(stArgCount.size() == 1 && "Expected arg count of 1"); m_nFinalResultIdx = stArgCount.top(); if (m_nFinalResultIdx == 0) assert(0 && "muParser internal error"); - if (stVal.size() == 0) Error(ecEMPTY_EXPRESSION); + if (stVal.size() == 0) return Error(ecEMPTY_EXPRESSION); - if (stVal.top().GetType() != tpDBL) Error(ecSTR_RESULT); + if (stVal.top().GetType() != tpDBL) return Error(ecSTR_RESULT); m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); return {}; @@ -1253,10 +1271,9 @@ ValueOrError ParserBase::ParseString() const { \param a_iErrc [in] The error code of type #EErrorCodes. \param a_iPos [in] The position where the error was detected. \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. */ -void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const { - throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); +ParserError ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const { + return ParserError(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); } //------------------------------------------------------------------------------ @@ -1458,7 +1475,8 @@ void ParserBase::StackDump(const ParserStack &a_stVal, made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") */ void ParserBase::Eval(std::vector *outResult) const { - (this->*m_pParseFormula)(); + ValueOrError v = (this->*m_pParseFormula)(); + if (v.has_error()) throw v.error(); int stackSize = m_nFinalResultIdx; // (for historic reasons the stack starts at position 1) diff --git a/muparser-2.2.5/src/muParserInt.cpp b/muparser-2.2.5/src/muParserInt.cpp index 7523a636c..aa9ee6a01 100644 --- a/muparser-2.2.5/src/muParserInt.cpp +++ b/muparser-2.2.5/src/muParserInt.cpp @@ -71,7 +71,7 @@ ValueOrError ParserInt::UnaryMinus(value_type v) { return -Round(v); } //--------------------------------------------------------------------------- ValueOrError ParserInt::Sum(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw ParserError(_T("too few arguments for function sum.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function sum.")); value_type fRes = 0; for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; @@ -81,7 +81,7 @@ ValueOrError ParserInt::Sum(const value_type *a_afArg, int a_iArgc) { //--------------------------------------------------------------------------- ValueOrError ParserInt::Min(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw ParserError(_T("too few arguments for function min.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; for (int i = 0; i < a_iArgc; ++i) fRes = std::min(fRes, a_afArg[i]); @@ -91,7 +91,7 @@ ValueOrError ParserInt::Min(const value_type *a_afArg, int a_iArgc) { //--------------------------------------------------------------------------- ValueOrError ParserInt::Max(const value_type *a_afArg, int a_iArgc) { - if (!a_iArgc) throw ParserError(_T("too few arguments for function min.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function min.")); value_type fRes = a_afArg[0]; for (int i = 0; i < a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]); @@ -219,28 +219,28 @@ void ParserInt::InitOprt() { DefineInfixOprt(_T("-"), UnaryMinus); DefineInfixOprt(_T("!"), Not); - DefineOprt(_T("&"), LogAnd, prLOGIC); - DefineOprt(_T("|"), LogOr, prLOGIC); - DefineOprt(_T("&&"), And, prLOGIC); - DefineOprt(_T("||"), Or, prLOGIC); + (void)DefineOprt(_T("&"), LogAnd, prLOGIC); + (void)DefineOprt(_T("|"), LogOr, prLOGIC); + (void)DefineOprt(_T("&&"), And, prLOGIC); + (void)DefineOprt(_T("||"), Or, prLOGIC); - DefineOprt(_T("<"), Less, prCMP); - DefineOprt(_T(">"), Greater, prCMP); - DefineOprt(_T("<="), LessEq, prCMP); - DefineOprt(_T(">="), GreaterEq, prCMP); - DefineOprt(_T("=="), Equal, prCMP); - DefineOprt(_T("!="), NotEqual, prCMP); + (void)DefineOprt(_T("<"), Less, prCMP); + (void)DefineOprt(_T(">"), Greater, prCMP); + (void)DefineOprt(_T("<="), LessEq, prCMP); + (void)DefineOprt(_T(">="), GreaterEq, prCMP); + (void)DefineOprt(_T("=="), Equal, prCMP); + (void)DefineOprt(_T("!="), NotEqual, prCMP); - DefineOprt(_T("+"), Add, prADD_SUB); - DefineOprt(_T("-"), Sub, prADD_SUB); + (void)DefineOprt(_T("+"), Add, prADD_SUB); + (void)DefineOprt(_T("-"), Sub, prADD_SUB); - DefineOprt(_T("*"), Mul, prMUL_DIV); - DefineOprt(_T("/"), Div, prMUL_DIV); - DefineOprt(_T("%"), Mod, prMUL_DIV); + (void)DefineOprt(_T("*"), Mul, prMUL_DIV); + (void)DefineOprt(_T("/"), Div, prMUL_DIV); + (void)DefineOprt(_T("%"), Mod, prMUL_DIV); - DefineOprt(_T("^"), Pow, prPOW, oaRIGHT); - DefineOprt(_T(">>"), Shr, prMUL_DIV + 1); - DefineOprt(_T("<<"), Shl, prMUL_DIV + 1); + (void)DefineOprt(_T("^"), Pow, prPOW, oaRIGHT); + (void)DefineOprt(_T(">>"), Shr, prMUL_DIV + 1); + (void)DefineOprt(_T("<<"), Shl, prMUL_DIV + 1); } } // namespace mu diff --git a/src/builtin_math.cpp b/src/builtin_math.cpp index 196ce32ad..ba61af8fb 100644 --- a/src/builtin_math.cpp +++ b/src/builtin_math.cpp @@ -130,9 +130,13 @@ static int evaluate_expression(wchar_t *cmd, parser_t &parser, io_streams_t &str p.DefineOprtChars(L"%"); p.DefineOprt(L"%", moduloOperator, mu::prINFIX); - p.SetExpr(expression); + mu::OptionalError oerr = p.SetExpr(expression); + if (oerr.has_error()) throw oerr.error(); std::vector vs; p.Eval(&vs); + for (const mu::ValueOrError &v : vs) { + if (v.has_error()) throw v.error(); + } for (const mu::ValueOrError &v : vs) { if (opts.scale == 0) { streams.out.append_format(L"%ld\n", static_cast(*v)); From 62bedde23d2229f722d382075f32ce8a577bd627 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 25 Nov 2017 01:07:56 -0800 Subject: [PATCH 30/62] [muparser] Clean up error handling in ParserTokenReader --- muparser-2.2.5/include/muParserTokenReader.h | 11 +++++++++-- muparser-2.2.5/src/muParserBase.cpp | 3 ++- muparser-2.2.5/src/muParserTokenReader.cpp | 17 +++++++++-------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/muparser-2.2.5/include/muParserTokenReader.h b/muparser-2.2.5/include/muParserTokenReader.h index c9e46c81b..9277c06a5 100644 --- a/muparser-2.2.5/include/muParserTokenReader.h +++ b/muparser-2.2.5/include/muParserTokenReader.h @@ -68,6 +68,13 @@ class ParserTokenReader final { void ReInit(); token_type ReadNextToken(); + /// \return the first error (if any), clearing it. + OptionalError acquireFirstError() { + OptionalError ret = std::move(firstError_); + firstError_ = OptionalError{}; + return ret; + } + private: /** \brief Syntax codes. @@ -113,8 +120,7 @@ class ParserTokenReader final { bool IsStrVarTok(token_type &a_Tok); bool IsUndefVarTok(token_type &a_Tok); bool IsString(token_type &a_Tok); - void Error(EErrorCodes a_iErrc, int a_iPos = -1, - const string_type &a_sTok = string_type()) const; + bool Error(EErrorCodes a_iErrc, int a_iPos = -1, const string_type &a_sTok = string_type()); token_type &SaveBeforeReturn(const token_type &tok); @@ -124,6 +130,7 @@ class ParserTokenReader final { int m_iSynFlags = 0; bool m_bIgnoreUndefVar = false; + OptionalError firstError_; /// The first error reported during parsing. const funmap_type *m_pFunDef = nullptr; const funmap_type *m_pPostOprtDef = nullptr; const funmap_type *m_pInfixOprtDef = nullptr; diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index ba0a2c893..a617b0544 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1040,8 +1040,9 @@ OptionalError ParserBase::CreateRPN() const { for (;;) { opt = m_pTokenReader->ReadNextToken(); + OptionalError oerr = m_pTokenReader->acquireFirstError(); + if (oerr.has_error()) return oerr; - OptionalError oerr; switch (opt.GetCode()) { // // Next three are different kind of value entries diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 34c6cd1f6..67a1b0b37 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -162,14 +162,14 @@ ParserTokenReader::token_type ParserTokenReader::ReadNextToken() { // Check for unknown token // - // !!! From this point on there is no exit without an exception possible... + // !!! From this point on there is no exit without an error possible... // string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); if (iEnd != m_iPos) Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); - return token_type(); // never reached + return token_type(); } //--------------------------------------------------------------------------- @@ -723,17 +723,18 @@ bool ParserTokenReader::IsString(token_type &a_Tok) { } //--------------------------------------------------------------------------- -/** \brief Create an error containing the parse error position. - - This function will create an Parser Exception object containing the error text and its position. +/** \brief Create an error containing the parse error position. Store it in parseError_, if not + already set. \param a_iErrc [in] The error code of type #EErrorCodes. \param a_iPos [in] The position where the error was detected. \param a_strTok [in] The token string representation associated with the error. - \throw ParserException always throws thats the only purpose of this function. */ -void ParserTokenReader::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const { - m_pParser->Error(a_iErrc, a_iPos, a_sTok); +bool ParserTokenReader::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) { + if (!firstError_.has_error()) { + firstError_ = m_pParser->Error(a_iErrc, a_iPos, a_sTok); + } + return false; } //--------------------------------------------------------------------------- From f3a9773849a17eaffbab9e325ba5aa7e27b29dc1 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 25 Nov 2017 02:30:18 -0800 Subject: [PATCH 31/62] [muparser] Make some error handling in ParserBase explicit Return ParserError instead of throwing exceptions --- muparser-2.2.5/src/muParserBase.cpp | 1 - muparser-2.2.5/src/muParserDLL.cpp | 17 ++++--- muparser-2.2.5/src/muParserTest.cpp | 26 +++++----- muparser-2.2.5/src/muParserTokenReader.cpp | 55 +++++++++++++--------- 4 files changed, 58 insertions(+), 41 deletions(-) diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index a617b0544..3144a6eb2 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1079,7 +1079,6 @@ OptionalError ParserBase::CreateRPN() const { case cmARG_SEP: if (stArgCount.empty()) return Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); - ++stArgCount.top(); // fallthrough intentional (no break!) diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 6fca652a3..59d8e286a 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -42,6 +42,10 @@ #include "muParserDLL.h" #include "muParserInt.h" +static void throwIfError(mu::OptionalError oerr) { + if (oerr.has_error()) throw oerr.error(); +} + #define MU_TRY try { #define MU_CATCH \ } \ @@ -205,7 +209,7 @@ API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) { API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->SetExpr(a_szExpr); + throwIfError(p->SetExpr(a_szExpr)); MU_CATCH } @@ -411,7 +415,8 @@ mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_p muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0); + throwIfError(p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, + a_bAllowOpt != 0)); MU_CATCH } @@ -420,7 +425,7 @@ API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); + throwIfError(p->DefineVar(a_szName, a_pVar)); MU_CATCH } @@ -429,7 +434,7 @@ API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); + throwIfError(p->DefineVar(a_szName, a_pVar)); MU_CATCH } @@ -438,7 +443,7 @@ API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineConst(a_szName, a_fVal); + throwIfError(p->DefineConst(a_szName, a_fVal)); MU_CATCH } @@ -447,7 +452,7 @@ API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineStrConst(a_szName, a_szVal); + throwIfError(p->DefineStrConst(a_szName, a_szVal)); MU_CATCH } diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 3266a2cdd..ac0b2ce83 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -41,6 +41,12 @@ using namespace std; namespace mu { namespace Test { + +static value_type getOrThrow(mu::ValueOrError voerr) { + if (voerr.has_error()) throw voerr.error(); + return *voerr; +} + int ParserTester::c_iCount = 0; //--------------------------------------------------------------------------------------------- @@ -93,14 +99,14 @@ int ParserTester::TestInterface() { p.DefineVar(_T("b"), &afVal[1]); p.DefineVar(_T("c"), &afVal[2]); p.SetExpr(_T("a+b+c")); - (void)p.Eval(); + getOrThrow(p.Eval()); } catch (...) { iStat += 1; // this is not supposed to happen } try { p.RemoveVar(_T("c")); - (void)p.Eval(); + getOrThrow(p.Eval()); iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... } catch (...) { // failure is expected... @@ -323,12 +329,10 @@ int ParserTester::TestNames() { PARSER_THROWCHECK(Var, true, _T("a_min"), &a) PARSER_THROWCHECK(Var, true, _T("a_min0"), &a) PARSER_THROWCHECK(Var, true, _T("a_min9"), &a) - PARSER_THROWCHECK(Var, false, _T("a_min9"), 0) // Postfix operators // fail PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1) PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1) - PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0) // pass PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1) PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1) @@ -977,7 +981,7 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) p.DefineFun(_T("strfun2"), StrFun2); p.DefineFun(_T("strfun3"), StrFun3); p.SetExpr(a_str); - (void)p.Eval(); + getOrThrow(p.Eval()); } catch (ParserError &e) { // output the formula in case of an failed test if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) { @@ -1021,10 +1025,10 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1, p.SetExpr(a_str); var = a_fVar1; - fVal[0] = *p.Eval(); + fVal[0] = getOrThrow(p.Eval()); var = a_fVar2; - fVal[1] = *p.Eval(); + fVal[1] = getOrThrow(p.Eval()); if (fabs(a_fRes1 - fVal[0]) > 0.0000000001) throw std::runtime_error("incorrect result (first pass)"); @@ -1136,8 +1140,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) // Test bytecode integrity // String parsing and bytecode parsing must yield the same result - fVal[0] = *p1->Eval(); // result from stringparsing - fVal[1] = *p1->Eval(); // result from bytecode + fVal[0] = getOrThrow(p1->Eval()); // result from stringparsing + fVal[1] = getOrThrow(p1->Eval()); // result from bytecode if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); @@ -1204,8 +1208,8 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa p.DefineVar(_T("c"), &vVarVal[2]); p.SetExpr(a_str); - fVal[0] = *p.Eval(); // result from stringparsing - fVal[1] = *p.Eval(); // result from bytecode + fVal[0] = getOrThrow(p.Eval()); // result from stringparsing + fVal[1] = getOrThrow(p.Eval()); // result from bytecode if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt.")); diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 67a1b0b37..2dff4aed2 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -166,10 +166,13 @@ ParserTokenReader::token_type ParserTokenReader::ReadNextToken() { // string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd != m_iPos) Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + if (iEnd != m_iPos) { + Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + return {}; + } Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); - return token_type(); + return {}; } //--------------------------------------------------------------------------- @@ -267,7 +270,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { // The assignment operator need special treatment if (i == cmASSIGN && m_iSynFlags & noASSIGN) - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + return Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); if (!m_pParser->HasBuiltInOprt()) continue; if (m_iSynFlags & noOPT) { @@ -276,7 +279,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { // their identifiers if (IsInfixOpTok(a_Tok)) return true; - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + return Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); } m_iSynFlags = @@ -284,7 +287,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { break; case cmBO: - if (m_iSynFlags & noBO) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noBO) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); if (m_lastTok.GetCode() == cmFUNC) m_iSynFlags = @@ -297,21 +300,23 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { break; case cmBC: - if (m_iSynFlags & noBC) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noBC) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; - if (--m_iBrackets < 0) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + if (--m_iBrackets < 0) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); break; case cmELSE: - if (m_iSynFlags & noELSE) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noELSE) + return Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; break; case cmIF: - if (m_iSynFlags & noIF) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noIF) + return Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; break; @@ -340,7 +345,7 @@ bool ParserTokenReader::IsArgSep(token_type &a_Tok) { szSep[0] = m_cArgSep; szSep[1] = 0; - if (m_iSynFlags & noARG_SEP) Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); + if (m_iSynFlags & noARG_SEP) return Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; m_iPos++; @@ -363,9 +368,9 @@ bool ParserTokenReader::IsEOF(token_type &a_Tok) { // check for EOF if (!szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) { - if (m_iSynFlags & noEND) Error(ecUNEXPECTED_EOF, m_iPos); + if (m_iSynFlags & noEND) return Error(ecUNEXPECTED_EOF, m_iPos); - if (m_iBrackets > 0) Error(ecMISSING_PARENS, m_iPos, _T(")")); + if (m_iBrackets > 0) return Error(ecMISSING_PARENS, m_iPos, _T(")")); m_iSynFlags = 0; a_Tok.Set(cmEND); @@ -392,7 +397,8 @@ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) { a_Tok.Set(it->second, it->first); m_iPos += (int)it->first.length(); - if (m_iSynFlags & noINFIXOP) Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + if (m_iSynFlags & noINFIXOP) + return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; return true; @@ -405,7 +411,7 @@ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) { m_iPos = (int)iEnd; if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; return true; @@ -435,7 +441,8 @@ bool ParserTokenReader::IsFunTok(token_type &a_Tok) { m_iPos = (int)iEnd; if (m_iSynFlags & noFUN) - Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); + return Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), + a_Tok.GetAsString()); m_iSynFlags = noANY ^ noBO; return true; @@ -483,7 +490,7 @@ bool ParserTokenReader::IsOprt(token_type &a_Tok) { else { // nope, no infix operator return false; - // Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + // return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); } } @@ -562,7 +569,8 @@ bool ParserTokenReader::IsValTok(token_type &a_Tok) { m_iPos = iEnd; a_Tok.SetVal(item->second, strTok); - if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + if (m_iSynFlags & noVAL) + return Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; return true; @@ -578,7 +586,8 @@ bool ParserTokenReader::IsValTok(token_type &a_Tok) { // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 strTok.assign(m_strFormula.c_str(), iStart, m_iPos - iStart); - if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + if (m_iSynFlags & noVAL) + return Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); a_Tok.SetVal(fVal, strTok); m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; @@ -604,7 +613,7 @@ bool ParserTokenReader::IsVarTok(token_type &a_Tok) { varmap_type::const_iterator item = m_pVarDef->find(strTok); if (item == m_pVarDef->end()) return false; - if (m_iSynFlags & noVAR) Error(ecUNEXPECTED_VAR, m_iPos, strTok); + if (m_iSynFlags & noVAR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok); m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); @@ -630,7 +639,7 @@ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) { strmap_type::const_iterator item = m_pStrVarDef->find(strTok); if (item == m_pStrVarDef->end()) return false; - if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_VAR, m_iPos, strTok); + if (m_iSynFlags & noSTR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok); m_iPos = iEnd; if (!m_pParser->m_vStringVarBuf.size()) assert(0 && "muParser internal error"); @@ -658,7 +667,7 @@ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) { // token identifier. // related bug report: // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 - Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); + return Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); } // If a factory is available implicitely create new variables @@ -706,11 +715,11 @@ bool ParserTokenReader::IsString(token_type &a_Tok) { iSkip++; } - if (iEnd == string_type::npos) Error(ecUNTERMINATED_STRING, m_iPos, _T("\"")); + if (iEnd == string_type::npos) return Error(ecUNTERMINATED_STRING, m_iPos, _T("\"")); string_type strTok(strBuf.begin(), strBuf.begin() + iEnd); - if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_STR, m_iPos, strTok); + if (m_iSynFlags & noSTR) return Error(ecUNEXPECTED_STR, m_iPos, strTok); m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size()); From 0be08e46836e228b57d1dac7f458f22d8ed69975 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 16 Dec 2017 12:59:04 -0800 Subject: [PATCH 32/62] [muparser] DefinePostfixOprt and DefineInfixOprt to return errors Return errors explicitly instead of throwing. --- muparser-2.2.5/include/muParserBase.h | 7 ++++--- muparser-2.2.5/src/muParserBase.cpp | 17 ++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index ec268779b..6e57ad57f 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -134,9 +134,10 @@ class ParserBase { OptionalError DefineConst(const string_type &a_sName, value_type a_fVal); OptionalError DefineStrConst(const string_type &a_sName, const string_type &a_strVal); OptionalError DefineVar(const string_type &a_sName, value_type *a_fVar); - void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt = true); - void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX, - bool a_bAllowOpt = true); + OptionalError DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, + bool a_bAllowOpt = true); + OptionalError DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, + int a_iPrec = prINFIX, bool a_bAllowOpt = true); // Clear user defined variables, constants or functions void ClearVar(); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 3144a6eb2..a10e49f8c 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -365,10 +365,10 @@ const char_type *ParserBase::ValidInfixOprtChars() const { /** \brief Add a user defined operator. \post Will reset the Parser to string parsing mode. */ -void ParserBase::DefinePostfixOprt(const string_type &a_sName, fun_type1 a_pFun, bool a_bAllowOpt) { - auto oerr = AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), - m_PostOprtDef, ValidOprtChars()); - if (oerr.has_error()) throw oerr.error(); +OptionalError ParserBase::DefinePostfixOprt(const string_type &a_sName, fun_type1 a_pFun, + bool a_bAllowOpt) { + return AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), + m_PostOprtDef, ValidOprtChars()); } //--------------------------------------------------------------------------- @@ -392,11 +392,10 @@ void ParserBase::Init() { \param [in] a_bAllowOpt True if operator is volatile (default=false) \sa EPrec */ -void ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, int a_iPrec, - bool a_bAllowOpt) { - auto oerr = AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), - m_InfixOprtDef, ValidInfixOprtChars()); - if (oerr.has_error()) throw oerr.error(); +OptionalError ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, int a_iPrec, + bool a_bAllowOpt) { + return AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), + m_InfixOprtDef, ValidInfixOprtChars()); } //--------------------------------------------------------------------------- From d3822e4cb3ff978b66fc95c240e57f4474f1637f Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 16 Dec 2017 13:45:48 -0800 Subject: [PATCH 33/62] [muparser] Propogate and check for lots more errors --- muparser-2.2.5/src/muParser.cpp | 21 ++--- muparser-2.2.5/src/muParserInt.cpp | 48 +++++++----- muparser-2.2.5/src/muParserTest.cpp | 114 ++++++++++++++-------------- 3 files changed, 98 insertions(+), 85 deletions(-) diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 96af93de9..9b6271b94 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -272,6 +272,14 @@ void Parser::InitFun() { } } +/// assert that the given optional error \p oerr is not an error. +/// This is used only during initialization, when it ought to be impossible +/// to generate an error. +static void assertNoError(OptionalError oerr) { + assert(!oerr.has_error() && "Unexpected error during initialization"); + (void)oerr; +} + //--------------------------------------------------------------------------- /** \brief Initialize constants. @@ -279,13 +287,8 @@ void Parser::InitFun() { number ("_e"). */ void Parser::InitConst() { - OptionalError oerr; - oerr = DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI); - assert(!oerr.has_error() && "Error defining _pi constant"); - (void)oerr; - oerr = DefineConst(_T("_e"), (value_type)PARSER_CONST_E); - assert(!oerr.has_error() && "Error defining _e constant"); - (void)oerr; + assertNoError(DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI)); + assertNoError(DefineConst(_T("_e"), (value_type)PARSER_CONST_E)); } //--------------------------------------------------------------------------- @@ -294,8 +297,8 @@ void Parser::InitConst() { By default only the unary minus operator is added. */ void Parser::InitOprt() { - DefineInfixOprt(_T("-"), UnaryMinus); - DefineInfixOprt(_T("+"), UnaryPlus); + assertNoError(DefineInfixOprt(_T("-"), UnaryMinus)); + assertNoError(DefineInfixOprt(_T("+"), UnaryPlus)); } //--------------------------------------------------------------------------- diff --git a/muparser-2.2.5/src/muParserInt.cpp b/muparser-2.2.5/src/muParserInt.cpp index aa9ee6a01..d5c47380e 100644 --- a/muparser-2.2.5/src/muParserInt.cpp +++ b/muparser-2.2.5/src/muParserInt.cpp @@ -207,6 +207,14 @@ void ParserInt::InitFun() { DefineFun(_T("max"), Max); } +/// assert that the given optional error \p oerr is not an error. +/// This is used only during initialization, when it ought to be impossible +/// to generate an error. +static void assertNoError(OptionalError oerr) { + assert(!oerr.has_error() && "Unexpected error during initialization"); + (void)oerr; +} + //--------------------------------------------------------------------------- /** \brief Initialize operators. */ void ParserInt::InitOprt() { @@ -216,31 +224,31 @@ void ParserInt::InitOprt() { // Disable all built in operators, they wont work with integer numbers // since they are designed for floating point numbers - DefineInfixOprt(_T("-"), UnaryMinus); - DefineInfixOprt(_T("!"), Not); + assertNoError(DefineInfixOprt(_T("-"), UnaryMinus)); + assertNoError(DefineInfixOprt(_T("!"), Not)); - (void)DefineOprt(_T("&"), LogAnd, prLOGIC); - (void)DefineOprt(_T("|"), LogOr, prLOGIC); - (void)DefineOprt(_T("&&"), And, prLOGIC); - (void)DefineOprt(_T("||"), Or, prLOGIC); + assertNoError(DefineOprt(_T("&"), LogAnd, prLOGIC)); + assertNoError(DefineOprt(_T("|"), LogOr, prLOGIC)); + assertNoError(DefineOprt(_T("&&"), And, prLOGIC)); + assertNoError(DefineOprt(_T("||"), Or, prLOGIC)); - (void)DefineOprt(_T("<"), Less, prCMP); - (void)DefineOprt(_T(">"), Greater, prCMP); - (void)DefineOprt(_T("<="), LessEq, prCMP); - (void)DefineOprt(_T(">="), GreaterEq, prCMP); - (void)DefineOprt(_T("=="), Equal, prCMP); - (void)DefineOprt(_T("!="), NotEqual, prCMP); + assertNoError(DefineOprt(_T("<"), Less, prCMP)); + assertNoError(DefineOprt(_T(">"), Greater, prCMP)); + assertNoError(DefineOprt(_T("<="), LessEq, prCMP)); + assertNoError(DefineOprt(_T(">="), GreaterEq, prCMP)); + assertNoError(DefineOprt(_T("=="), Equal, prCMP)); + assertNoError(DefineOprt(_T("!="), NotEqual, prCMP)); - (void)DefineOprt(_T("+"), Add, prADD_SUB); - (void)DefineOprt(_T("-"), Sub, prADD_SUB); + assertNoError(DefineOprt(_T("+"), Add, prADD_SUB)); + assertNoError(DefineOprt(_T("-"), Sub, prADD_SUB)); - (void)DefineOprt(_T("*"), Mul, prMUL_DIV); - (void)DefineOprt(_T("/"), Div, prMUL_DIV); - (void)DefineOprt(_T("%"), Mod, prMUL_DIV); + assertNoError(DefineOprt(_T("*"), Mul, prMUL_DIV)); + assertNoError(DefineOprt(_T("/"), Div, prMUL_DIV)); + assertNoError(DefineOprt(_T("%"), Mod, prMUL_DIV)); - (void)DefineOprt(_T("^"), Pow, prPOW, oaRIGHT); - (void)DefineOprt(_T(">>"), Shr, prMUL_DIV + 1); - (void)DefineOprt(_T("<<"), Shl, prMUL_DIV + 1); + assertNoError(DefineOprt(_T("^"), Pow, prPOW, oaRIGHT)); + assertNoError(DefineOprt(_T(">>"), Shr, prMUL_DIV + 1)); + assertNoError(DefineOprt(_T("<<"), Shl, prMUL_DIV + 1)); } } // namespace mu diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index ac0b2ce83..188759657 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -47,6 +47,12 @@ static value_type getOrThrow(mu::ValueOrError voerr) { return *voerr; } +static void throwIfError(mu::OptionalError oerr) { + if (oerr.has_error()) { + throw oerr.error(); + } +} + int ParserTester::c_iCount = 0; //--------------------------------------------------------------------------------------------- @@ -95,10 +101,10 @@ int ParserTester::TestInterface() { Parser p; try { - p.DefineVar(_T("a"), &afVal[0]); - p.DefineVar(_T("b"), &afVal[1]); - p.DefineVar(_T("c"), &afVal[2]); - p.SetExpr(_T("a+b+c")); + throwIfError(p.DefineVar(_T("a"), &afVal[0])); + throwIfError(p.DefineVar(_T("b"), &afVal[1])); + throwIfError(p.DefineVar(_T("c"), &afVal[2])); + throwIfError(p.SetExpr(_T("a+b+c"))); getOrThrow(p.Eval()); } catch (...) { iStat += 1; // this is not supposed to happen @@ -283,21 +289,17 @@ int ParserTester::TestBinOprt() { //--------------------------------------------------------------------------------------------- /** \brief Check muParser name restriction enforcement. */ int ParserTester::TestNames() { - int iStat = 0, iErr = 0; + int failures = 0; mu::console() << "testing name restriction enforcement..."; Parser p; + OptionalError oerr; -#define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \ - iErr = 0; \ - ParserTester::c_iCount++; \ - try { \ - p.Define##DOMAIN(EXPR, ARG); \ - } catch (Parser::exception_type &) { \ - iErr = (FAIL == false) ? 0 : 1; \ - } \ - iStat += iErr; +#define PARSER_THROWCHECK(DOMAIN, SHOULDPASS, EXPR, ARG) \ + ParserTester::c_iCount++; \ + oerr = p.Define##DOMAIN(EXPR, ARG); \ + failures += (oerr.has_error() == SHOULDPASS); // constant names PARSER_THROWCHECK(Const, false, _T("0a"), 1) @@ -374,12 +376,12 @@ int ParserTester::TestNames() { PARSER_THROWCHECK(Oprt, true, _T("||"), f1of2) #undef PARSER_THROWCHECK - if (iStat == 0) + if (failures == 0) mu::console() << _T("passed") << endl; else - mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl; + mu::console() << _T("\n failed with ") << failures << _T(" errors") << endl; - return iStat; + return failures; } //--------------------------------------------------------------------------- @@ -970,17 +972,17 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) value_type fVal[] = {1, 1, 1}; Parser p; - p.DefineVar(_T("a"), &fVal[0]); - p.DefineVar(_T("b"), &fVal[1]); - p.DefineVar(_T("c"), &fVal[2]); - p.DefinePostfixOprt(_T("{m}"), Milli); - p.DefinePostfixOprt(_T("m"), Milli); + throwIfError(p.DefineVar(_T("a"), &fVal[0])); + throwIfError(p.DefineVar(_T("b"), &fVal[1])); + throwIfError(p.DefineVar(_T("c"), &fVal[2])); + throwIfError(p.DefinePostfixOprt(_T("{m}"), Milli)); + throwIfError(p.DefinePostfixOprt(_T("m"), Milli)); p.DefineFun(_T("ping"), Ping); p.DefineFun(_T("valueof"), ValueOf); p.DefineFun(_T("strfun1"), StrFun1); p.DefineFun(_T("strfun2"), StrFun2); p.DefineFun(_T("strfun3"), StrFun3); - p.SetExpr(a_str); + throwIfError(p.SetExpr(a_str)); getOrThrow(p.Eval()); } catch (ParserError &e) { // output the formula in case of an failed test @@ -1021,8 +1023,8 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1, value_type var = 0; // variable - p.DefineVar(_T("a"), &var); - p.SetExpr(a_str); + throwIfError(p.DefineVar(_T("a"), &var)); + throwIfError(p.SetExpr(a_str)); var = a_fVar1; fVal[0] = getOrThrow(p.Eval()); @@ -1069,21 +1071,21 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) p1.reset(new mu::Parser()); // Add constants - p1->DefineConst(_T("pi"), (value_type)PARSER_CONST_PI); - p1->DefineConst(_T("e"), (value_type)PARSER_CONST_E); - p1->DefineConst(_T("const"), 1); - p1->DefineConst(_T("const1"), 2); - p1->DefineConst(_T("const2"), 3); + throwIfError(p1->DefineConst(_T("pi"), (value_type)PARSER_CONST_PI)); + throwIfError(p1->DefineConst(_T("e"), (value_type)PARSER_CONST_E)); + throwIfError(p1->DefineConst(_T("const"), 1)); + throwIfError(p1->DefineConst(_T("const1"), 2)); + throwIfError(p1->DefineConst(_T("const2"), 3)); // string constants - p1->DefineStrConst(_T("str1"), _T("1.11")); - p1->DefineStrConst(_T("str2"), _T("2.22")); + throwIfError(p1->DefineStrConst(_T("str1"), _T("1.11"))); + throwIfError(p1->DefineStrConst(_T("str2"), _T("2.22"))); // variables value_type vVarVal[] = {1, 2, 3, -2}; - p1->DefineVar(_T("a"), &vVarVal[0]); - p1->DefineVar(_T("aa"), &vVarVal[1]); - p1->DefineVar(_T("b"), &vVarVal[1]); - p1->DefineVar(_T("c"), &vVarVal[2]); - p1->DefineVar(_T("d"), &vVarVal[3]); + throwIfError(p1->DefineVar(_T("a"), &vVarVal[0])); + throwIfError(p1->DefineVar(_T("aa"), &vVarVal[1])); + throwIfError(p1->DefineVar(_T("b"), &vVarVal[1])); + throwIfError(p1->DefineVar(_T("c"), &vVarVal[2])); + throwIfError(p1->DefineVar(_T("d"), &vVarVal[3])); // custom value ident functions p1->AddValIdent(&ParserTester::IsHexVal); @@ -1107,9 +1109,9 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) p1->DefineFun(_T("f5of5"), f5of5); // binary operators - p1->DefineOprt(_T("add"), add, 0); - p1->DefineOprt(_T("++"), add, 0); - p1->DefineOprt(_T("&"), land, prLAND); + throwIfError(p1->DefineOprt(_T("add"), add, 0)); + throwIfError(p1->DefineOprt(_T("++"), add, 0)); + throwIfError(p1->DefineOprt(_T("&"), land, prLAND)); // sample functions p1->DefineFun(_T("min"), Min); @@ -1127,16 +1129,16 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) // infix / postfix operator // Note: Identifiers used here do not have any meaning // they are mere placeholders to test certain features. - p1->DefineInfixOprt(_T("$"), sign, prPOW + 1); // sign with high priority - p1->DefineInfixOprt(_T("~"), plus2); // high priority - p1->DefineInfixOprt(_T("~~"), plus2); - p1->DefinePostfixOprt(_T("{m}"), Milli); - p1->DefinePostfixOprt(_T("{M}"), Mega); - p1->DefinePostfixOprt(_T("m"), Milli); - p1->DefinePostfixOprt(_T("meg"), Mega); - p1->DefinePostfixOprt(_T("#"), times3); - p1->DefinePostfixOprt(_T("'"), sqr); - p1->SetExpr(a_str); + throwIfError(p1->DefineInfixOprt(_T("$"), sign, prPOW + 1)); // sign with high priority + throwIfError(p1->DefineInfixOprt(_T("~"), plus2)); // high priority + throwIfError(p1->DefineInfixOprt(_T("~~"), plus2)); + throwIfError(p1->DefinePostfixOprt(_T("{m}"), Milli)); + throwIfError(p1->DefinePostfixOprt(_T("{M}"), Mega)); + throwIfError(p1->DefinePostfixOprt(_T("m"), Milli)); + throwIfError(p1->DefinePostfixOprt(_T("meg"), Mega)); + throwIfError(p1->DefinePostfixOprt(_T("#"), times3)); + throwIfError(p1->DefinePostfixOprt(_T("'"), sqr)); + throwIfError(p1->SetExpr(a_str)); // Test bytecode integrity // String parsing and bytecode parsing must yield the same result @@ -1201,13 +1203,13 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa try { value_type fVal[2] = {-99, -999}; // results: initially should be different ParserInt p; - p.DefineConst(_T("const1"), 1); - p.DefineConst(_T("const2"), 2); - p.DefineVar(_T("a"), &vVarVal[0]); - p.DefineVar(_T("b"), &vVarVal[1]); - p.DefineVar(_T("c"), &vVarVal[2]); + throwIfError(p.DefineConst(_T("const1"), 1)); + throwIfError(p.DefineConst(_T("const2"), 2)); + throwIfError(p.DefineVar(_T("a"), &vVarVal[0])); + throwIfError(p.DefineVar(_T("b"), &vVarVal[1])); + throwIfError(p.DefineVar(_T("c"), &vVarVal[2])); - p.SetExpr(a_str); + throwIfError((p.SetExpr(a_str))); fVal[0] = getOrThrow(p.Eval()); // result from stringparsing fVal[1] = getOrThrow(p.Eval()); // result from bytecode From 6f14d556125d05a4ec8bb014472e4dae69d0bbe0 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 16 Dec 2017 14:10:45 -0800 Subject: [PATCH 34/62] [muparser] Convert more exception handling into explicit errors --- muparser-2.2.5/include/muParserTest.h | 9 +++------ muparser-2.2.5/include/muParserToken.h | 4 ++-- muparser-2.2.5/src/muParserBase.cpp | 13 ++++--------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/muparser-2.2.5/include/muParserTest.h b/muparser-2.2.5/include/muParserTest.h index 71607d44c..6ad628839 100644 --- a/muparser-2.2.5/include/muParserTest.h +++ b/muparser-2.2.5/include/muParserTest.h @@ -95,21 +95,18 @@ class ParserTester // final static ValueOrError land(value_type v1, value_type v2) { return (int)v1 & (int)v2; } static ValueOrError FirstArg(const value_type* a_afArg, int a_iArgc) { - if (!a_iArgc) - throw mu::Parser::exception_type(_T("too few arguments for function FirstArg.")); - + if (!a_iArgc) return ParserError(_T("too few arguments for function FirstArg.")); return a_afArg[0]; } static ValueOrError LastArg(const value_type* a_afArg, int a_iArgc) { - if (!a_iArgc) - throw mu::Parser::exception_type(_T("too few arguments for function LastArg.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function LastArg.")); return a_afArg[a_iArgc - 1]; } static ValueOrError Sum(const value_type* a_afArg, int a_iArgc) { - if (!a_iArgc) throw mu::Parser::exception_type(_T("too few arguments for function sum.")); + if (!a_iArgc) return ParserError(_T("too few arguments for function sum.")); value_type fRes = 0; for (int i = 0; i < a_iArgc; ++i) fRes += a_afArg[i]; diff --git a/muparser-2.2.5/include/muParserToken.h b/muparser-2.2.5/include/muParserToken.h index aeb5397ed..acfa0ff71 100644 --- a/muparser-2.2.5/include/muParserToken.h +++ b/muparser-2.2.5/include/muParserToken.h @@ -288,7 +288,7 @@ class ParserToken { } //------------------------------------------------------------------------------ - /** \biref Get value of the token. + /** \brifef Get value of the token. Only applicable to variable and value tokens. */ @@ -299,7 +299,7 @@ class ParserToken { case cmVAR: return *((TBase *)m_pTok); default: - throw ParserError(ecVAL_EXPECTED); + return ParserError(ecVAL_EXPECTED); } } diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index a10e49f8c..6cf060679 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1250,15 +1250,10 @@ OptionalError ParserBase::CreateRPN() const { uses bytecode instead of string parsing. */ ValueOrError ParserBase::ParseString() const { - try { - OptionalError oerr = CreateRPN(); - if (oerr.has_error()) return oerr.error(); - m_pParseFormula = &ParserBase::ParseCmdCode; - return (this->*m_pParseFormula)(); - } catch (ParserError &exc) { - exc.SetFormula(m_pTokenReader->GetExpr()); - throw; - } + OptionalError oerr = CreateRPN(); + if (oerr.has_error()) return oerr.error(); + m_pParseFormula = &ParserBase::ParseCmdCode; + return (this->*m_pParseFormula)(); } //--------------------------------------------------------------------------- From 11d729d09c1f852a5318fd5545613d5c81f3e111 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 14:26:55 -0800 Subject: [PATCH 35/62] [muparser] DefineFun() to return an error instead of throwing --- muparser-2.2.5/include/muParserBase.h | 7 ++- muparser-2.2.5/src/muParser.cpp | 68 +++++++++++++-------------- muparser-2.2.5/src/muParserInt.cpp | 22 ++++----- muparser-2.2.5/src/muParserTest.cpp | 64 ++++++++++++------------- 4 files changed, 80 insertions(+), 81 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 6e57ad57f..5440808ea 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -122,10 +122,9 @@ class ParserBase { \param a_bAllowOpt A flag indicating this function may be optimized */ template - void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) { - auto oerr = - AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars()); - if (oerr.has_error()) throw oerr.error(); + OptionalError DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) { + return AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, + ValidNameChars()); } OptionalError DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 9b6271b94..6a8a93219 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -226,6 +226,14 @@ void Parser::InitCharSets() { DefineInfixOprtChars(_T("/+-*^?<>=#!$%&|~'_")); } +/// assert that the given optional error \p oerr is not an error. +/// This is used only during initialization, when it ought to be impossible +/// to generate an error. +static void assertNoError(OptionalError oerr) { + assert(!oerr.has_error() && "Unexpected error during initialization"); + (void)oerr; +} + //--------------------------------------------------------------------------- /** \brief Initialize the default functions. */ void Parser::InitFun() { @@ -237,49 +245,41 @@ void Parser::InitFun() { // ... } else { // trigonometric functions - DefineFun(_T("sin"), Sin); - DefineFun(_T("cos"), Cos); - DefineFun(_T("tan"), Tan); + assertNoError(DefineFun(_T("sin"), Sin)); + assertNoError(DefineFun(_T("cos"), Cos)); + assertNoError(DefineFun(_T("tan"), Tan)); // arcus functions - DefineFun(_T("asin"), ASin); - DefineFun(_T("acos"), ACos); - DefineFun(_T("atan"), ATan); - DefineFun(_T("atan2"), ATan2); + assertNoError(DefineFun(_T("asin"), ASin)); + assertNoError(DefineFun(_T("acos"), ACos)); + assertNoError(DefineFun(_T("atan"), ATan)); + assertNoError(DefineFun(_T("atan2"), ATan2)); // hyperbolic functions - DefineFun(_T("sinh"), Sinh); - DefineFun(_T("cosh"), Cosh); - DefineFun(_T("tanh"), Tanh); + assertNoError(DefineFun(_T("sinh"), Sinh)); + assertNoError(DefineFun(_T("cosh"), Cosh)); + assertNoError(DefineFun(_T("tanh"), Tanh)); // arcus hyperbolic functions - DefineFun(_T("asinh"), ASinh); - DefineFun(_T("acosh"), ACosh); - DefineFun(_T("atanh"), ATanh); + assertNoError(DefineFun(_T("asinh"), ASinh)); + assertNoError(DefineFun(_T("acosh"), ACosh)); + assertNoError(DefineFun(_T("atanh"), ATanh)); // Logarithm functions - DefineFun(_T("log2"), Log2); - DefineFun(_T("log10"), Log10); - DefineFun(_T("log"), Ln); - DefineFun(_T("ln"), Ln); + assertNoError(DefineFun(_T("log2"), Log2)); + assertNoError(DefineFun(_T("log10"), Log10)); + assertNoError(DefineFun(_T("log"), Ln)); + assertNoError(DefineFun(_T("ln"), Ln)); // misc - DefineFun(_T("exp"), Exp); - DefineFun(_T("sqrt"), Sqrt); - DefineFun(_T("sign"), Sign); - DefineFun(_T("rint"), Rint); - DefineFun(_T("abs"), Abs); + assertNoError(DefineFun(_T("exp"), Exp)); + assertNoError(DefineFun(_T("sqrt"), Sqrt)); + assertNoError(DefineFun(_T("sign"), Sign)); + assertNoError(DefineFun(_T("rint"), Rint)); + assertNoError(DefineFun(_T("abs"), Abs)); // Functions with variable number of arguments - DefineFun(_T("sum"), Sum); - DefineFun(_T("avg"), Avg); - DefineFun(_T("min"), Min); - DefineFun(_T("max"), Max); + assertNoError(DefineFun(_T("sum"), Sum)); + assertNoError(DefineFun(_T("avg"), Avg)); + assertNoError(DefineFun(_T("min"), Min)); + assertNoError(DefineFun(_T("max"), Max)); } } -/// assert that the given optional error \p oerr is not an error. -/// This is used only during initialization, when it ought to be impossible -/// to generate an error. -static void assertNoError(OptionalError oerr) { - assert(!oerr.has_error() && "Unexpected error during initialization"); - (void)oerr; -} - //--------------------------------------------------------------------------- /** \brief Initialize constants. diff --git a/muparser-2.2.5/src/muParserInt.cpp b/muparser-2.2.5/src/muParserInt.cpp index d5c47380e..2de24800d 100644 --- a/muparser-2.2.5/src/muParserInt.cpp +++ b/muparser-2.2.5/src/muParserInt.cpp @@ -196,17 +196,6 @@ void ParserInt::InitCharSets() { DefineInfixOprtChars(_T("/+-*^?<>=!%&|~'_")); } -//--------------------------------------------------------------------------- -/** \brief Initialize the default functions. */ -void ParserInt::InitFun() { - DefineFun(_T("sign"), Sign); - DefineFun(_T("abs"), Abs); - DefineFun(_T("if"), Ite); - DefineFun(_T("sum"), Sum); - DefineFun(_T("min"), Min); - DefineFun(_T("max"), Max); -} - /// assert that the given optional error \p oerr is not an error. /// This is used only during initialization, when it ought to be impossible /// to generate an error. @@ -215,6 +204,17 @@ static void assertNoError(OptionalError oerr) { (void)oerr; } +//--------------------------------------------------------------------------- +/** \brief Initialize the default functions. */ +void ParserInt::InitFun() { + assertNoError(DefineFun(_T("sign"), Sign)); + assertNoError(DefineFun(_T("abs"), Abs)); + assertNoError(DefineFun(_T("if"), Ite)); + assertNoError(DefineFun(_T("sum"), Sum)); + assertNoError(DefineFun(_T("min"), Min)); + assertNoError(DefineFun(_T("max"), Max)); +} + //--------------------------------------------------------------------------- /** \brief Initialize operators. */ void ParserInt::InitOprt() { diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 188759657..de1544ce7 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -977,11 +977,11 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) throwIfError(p.DefineVar(_T("c"), &fVal[2])); throwIfError(p.DefinePostfixOprt(_T("{m}"), Milli)); throwIfError(p.DefinePostfixOprt(_T("m"), Milli)); - p.DefineFun(_T("ping"), Ping); - p.DefineFun(_T("valueof"), ValueOf); - p.DefineFun(_T("strfun1"), StrFun1); - p.DefineFun(_T("strfun2"), StrFun2); - p.DefineFun(_T("strfun3"), StrFun3); + throwIfError(p.DefineFun(_T("ping"), Ping)); + throwIfError(p.DefineFun(_T("valueof"), ValueOf)); + throwIfError(p.DefineFun(_T("strfun1"), StrFun1)); + throwIfError(p.DefineFun(_T("strfun2"), StrFun2)); + throwIfError(p.DefineFun(_T("strfun3"), StrFun3)); throwIfError(p.SetExpr(a_str)); getOrThrow(p.Eval()); } catch (ParserError &e) { @@ -1091,22 +1091,22 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) p1->AddValIdent(&ParserTester::IsHexVal); // functions - p1->DefineFun(_T("ping"), Ping); - p1->DefineFun(_T("f1of1"), f1of1); // one parameter - p1->DefineFun(_T("f1of2"), f1of2); // two parameter - p1->DefineFun(_T("f2of2"), f2of2); - p1->DefineFun(_T("f1of3"), f1of3); // three parameter - p1->DefineFun(_T("f2of3"), f2of3); - p1->DefineFun(_T("f3of3"), f3of3); - p1->DefineFun(_T("f1of4"), f1of4); // four parameter - p1->DefineFun(_T("f2of4"), f2of4); - p1->DefineFun(_T("f3of4"), f3of4); - p1->DefineFun(_T("f4of4"), f4of4); - p1->DefineFun(_T("f1of5"), f1of5); // five parameter - p1->DefineFun(_T("f2of5"), f2of5); - p1->DefineFun(_T("f3of5"), f3of5); - p1->DefineFun(_T("f4of5"), f4of5); - p1->DefineFun(_T("f5of5"), f5of5); + throwIfError(p1->DefineFun(_T("ping"), Ping)); + throwIfError(p1->DefineFun(_T("f1of1"), f1of1)); // one parameter + throwIfError(p1->DefineFun(_T("f1of2"), f1of2)); // two parameter + throwIfError(p1->DefineFun(_T("f2of2"), f2of2)); + throwIfError(p1->DefineFun(_T("f1of3"), f1of3)); // three parameter + throwIfError(p1->DefineFun(_T("f2of3"), f2of3)); + throwIfError(p1->DefineFun(_T("f3of3"), f3of3)); + throwIfError(p1->DefineFun(_T("f1of4"), f1of4)); // four parameter + throwIfError(p1->DefineFun(_T("f2of4"), f2of4)); + throwIfError(p1->DefineFun(_T("f3of4"), f3of4)); + throwIfError(p1->DefineFun(_T("f4of4"), f4of4)); + throwIfError(p1->DefineFun(_T("f1of5"), f1of5)); // five parameter + throwIfError(p1->DefineFun(_T("f2of5"), f2of5)); + throwIfError(p1->DefineFun(_T("f3of5"), f3of5)); + throwIfError(p1->DefineFun(_T("f4of5"), f4of5)); + throwIfError(p1->DefineFun(_T("f5of5"), f5of5)); // binary operators throwIfError(p1->DefineOprt(_T("add"), add, 0)); @@ -1114,17 +1114,17 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) throwIfError(p1->DefineOprt(_T("&"), land, prLAND)); // sample functions - p1->DefineFun(_T("min"), Min); - p1->DefineFun(_T("max"), Max); - p1->DefineFun(_T("sum"), Sum); - p1->DefineFun(_T("valueof"), ValueOf); - p1->DefineFun(_T("atof"), StrToFloat); - p1->DefineFun(_T("strfun1"), StrFun1); - p1->DefineFun(_T("strfun2"), StrFun2); - p1->DefineFun(_T("strfun3"), StrFun3); - p1->DefineFun(_T("lastArg"), LastArg); - p1->DefineFun(_T("firstArg"), FirstArg); - p1->DefineFun(_T("order"), FirstArg); + throwIfError(p1->DefineFun(_T("min"), Min)); + throwIfError(p1->DefineFun(_T("max"), Max)); + throwIfError(p1->DefineFun(_T("sum"), Sum)); + throwIfError(p1->DefineFun(_T("valueof"), ValueOf)); + throwIfError(p1->DefineFun(_T("atof"), StrToFloat)); + throwIfError(p1->DefineFun(_T("strfun1"), StrFun1)); + throwIfError(p1->DefineFun(_T("strfun2"), StrFun2)); + throwIfError(p1->DefineFun(_T("strfun3"), StrFun3)); + throwIfError(p1->DefineFun(_T("lastArg"), LastArg)); + throwIfError(p1->DefineFun(_T("firstArg"), FirstArg)); + throwIfError(p1->DefineFun(_T("order"), FirstArg)); // infix / postfix operator // Note: Identifiers used here do not have any meaning From 2f2f4b42870459555174736c811286e176981e48 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 14:31:39 -0800 Subject: [PATCH 36/62] [muparser] ParserBase::Eval to return an error instead of throwing --- muparser-2.2.5/src/muParserBase.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 6cf060679..80c1abc9c 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1470,7 +1470,10 @@ void ParserBase::StackDump(const ParserStack &a_stVal, */ void ParserBase::Eval(std::vector *outResult) const { ValueOrError v = (this->*m_pParseFormula)(); - if (v.has_error()) throw v.error(); + if (v.has_error()) { + outResult->push_back(std::move(v)); + return; + } int stackSize = m_nFinalResultIdx; // (for historic reasons the stack starts at position 1) From 5d2cf3f6664af22f7b414094055bf34ee4525a80 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 17:17:08 -0800 Subject: [PATCH 37/62] [muparser] Remove getOrThrow() This is no longer used or needed --- muparser-2.2.5/include/muParserDef.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index e309af55d..6327b545f 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -389,12 +389,6 @@ class ValueOrError { return value_; } - /// \return the value or throw the error - value_type getOrThrow() const { - if (has_error()) throw error(); - return value(); - } - /// \return whether this has a value. explicit operator bool() const { return has_value(); } From 11e6cfeb82225253fb041565f5404564db881a4c Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 14:41:55 -0800 Subject: [PATCH 38/62] [math] Remove exception handling in builtin_math This handles errors explicitly instead of catching them. --- src/builtin_math.cpp | 54 ++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/builtin_math.cpp b/src/builtin_math.cpp index ba61af8fb..e86e6039a 100644 --- a/src/builtin_math.cpp +++ b/src/builtin_math.cpp @@ -119,36 +119,40 @@ static const wchar_t *math_get_arg(int *argidx, wchar_t **argv, wcstring *storag static mu::ValueOrError moduloOperator(double v, double w) { return (int)v % std::max(1, (int)w); }; /// Evaluate math expressions. -static int evaluate_expression(wchar_t *cmd, parser_t &parser, io_streams_t &streams, +static int evaluate_expression(const wchar_t *cmd, parser_t &parser, io_streams_t &streams, math_cmd_opts_t &opts, wcstring &expression) { UNUSED(parser); - try { - mu::Parser p; - // MuParser doesn't implement the modulo operator so we add it ourselves since there are - // likely users of our old math wrapper around bc that expect it to be available. - p.DefineOprtChars(L"%"); - p.DefineOprt(L"%", moduloOperator, mu::prINFIX); - - mu::OptionalError oerr = p.SetExpr(expression); - if (oerr.has_error()) throw oerr.error(); - std::vector vs; - p.Eval(&vs); - for (const mu::ValueOrError &v : vs) { - if (v.has_error()) throw v.error(); - } - for (const mu::ValueOrError &v : vs) { - if (opts.scale == 0) { - streams.out.append_format(L"%ld\n", static_cast(*v)); - } else { - streams.out.append_format(L"%.*lf\n", opts.scale, *v); - } - } - return STATUS_CMD_OK; - } catch (mu::Parser::exception_type &e) { - streams.err.append_format(_(L"%ls: Invalid expression: %ls\n"), cmd, e.GetMsg().c_str()); + // Helper to print an error and return an error code. + auto printError = [&streams, cmd](const mu::ParserError &err) { + streams.err.append_format(_(L"%ls: Invalid expression: %ls\n"), cmd, err.GetMsg().c_str()); return STATUS_CMD_ERROR; + }; + + mu::Parser p; + // MuParser doesn't implement the modulo operator so we add it ourselves since there are + // likely users of our old math wrapper around bc that expect it to be available. + p.DefineOprtChars(L"%"); + mu::OptionalError oerr = p.DefineOprt(L"%", moduloOperator, mu::prINFIX); + assert(!oerr.has_error() && "Unexpected error defining modulo operator"); + (void)oerr; + + oerr = p.SetExpr(expression); + if (oerr.has_error()) return printError(oerr.error()); + + std::vector vs; + p.Eval(&vs); + for (const mu::ValueOrError &v : vs) { + if (v.has_error()) return printError(v.error()); } + for (const mu::ValueOrError &v : vs) { + if (opts.scale == 0) { + streams.out.append_format(L"%ld\n", static_cast(*v)); + } else { + streams.out.append_format(L"%.*lf\n", opts.scale, *v); + } + } + return STATUS_CMD_OK; } /// The math builtin evaluates math expressions. From 8b16fccebf54afff70e1c353d1026909da9ea024 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 14:43:53 -0800 Subject: [PATCH 39/62] Disable exception handling in Xcode build Now that muparser no longer relies on exceptions, we can disable them again. --- fish.xcodeproj/project.pbxproj | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index f50483453..1e783337c 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -379,7 +379,6 @@ D068222E1F5149B500040321 /* muParserDLL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822251F51498700040321 /* muParserDLL.cpp */; }; D068222F1F5149B500040321 /* muParserError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822261F51498700040321 /* muParserError.cpp */; }; D06822301F5149B500040321 /* muParserInt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822271F51498700040321 /* muParserInt.cpp */; }; - D06822311F5149B500040321 /* muParserTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822281F51498700040321 /* muParserTest.cpp */; }; D06822321F5149B500040321 /* muParserTokenReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822291F51498700040321 /* muParserTokenReader.cpp */; }; D07B247315BCC15700D4ADB4 /* add-shell in Resources */ = {isa = PBXBuildFile; fileRef = D07B247215BCC15700D4ADB4 /* add-shell */; }; D07B247615BCC4BE00D4ADB4 /* install.sh in Resources */ = {isa = PBXBuildFile; fileRef = D07B247515BCC4BE00D4ADB4 /* install.sh */; }; @@ -822,7 +821,6 @@ D06822251F51498700040321 /* muParserDLL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserDLL.cpp; sourceTree = ""; }; D06822261F51498700040321 /* muParserError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserError.cpp; sourceTree = ""; }; D06822271F51498700040321 /* muParserInt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserInt.cpp; sourceTree = ""; }; - D06822281F51498700040321 /* muParserTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserTest.cpp; sourceTree = ""; }; D06822291F51498700040321 /* muParserTokenReader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserTokenReader.cpp; sourceTree = ""; }; D07B247215BCC15700D4ADB4 /* add-shell */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "add-shell"; path = "build_tools/osx_package_scripts/add-shell"; sourceTree = ""; }; D07B247515BCC4BE00D4ADB4 /* install.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = install.sh; path = osx/install.sh; sourceTree = ""; }; @@ -1082,7 +1080,6 @@ D06822251F51498700040321 /* muParserDLL.cpp */, D06822261F51498700040321 /* muParserError.cpp */, D06822271F51498700040321 /* muParserInt.cpp */, - D06822281F51498700040321 /* muParserTest.cpp */, D06822291F51498700040321 /* muParserTokenReader.cpp */, ); path = src; @@ -1930,7 +1927,6 @@ D068222E1F5149B500040321 /* muParserDLL.cpp in Sources */, D068222F1F5149B500040321 /* muParserError.cpp in Sources */, D06822301F5149B500040321 /* muParserInt.cpp in Sources */, - D06822311F5149B500040321 /* muParserTest.cpp in Sources */, D06822321F5149B500040321 /* muParserTokenReader.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2432,6 +2428,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = YES; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; GCC_NO_COMMON_BLOCKS = YES; @@ -2485,6 +2482,7 @@ DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = YES; GCC_INLINES_ARE_PRIVATE_EXTERN = YES; GCC_NO_COMMON_BLOCKS = YES; From 3099d46736f1a89f184fcf00ad33ffb06e76e820 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 14:45:29 -0800 Subject: [PATCH 40/62] Disable exception handling in CMake build Now that muparser no longer relies on exceptions, we can disable them again. --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab522b63e..a9999939d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,9 @@ PROJECT(fish-shell CXX) # We are C++11. SET(CMAKE_CXX_STANDARD 11) +# Disable exception handling. +ADD_COMPILE_OPTIONS(-fno-exceptions) + # Hide the CMake Rules directories in Xcode projects. SOURCE_GROUP("CMake Rules" REGULAR_EXPRESSION "^$") From 452211ebf549ac36d1cd0f1e6774a8b42e73ebe8 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 14:53:23 -0800 Subject: [PATCH 41/62] Disable exception handling in autotools build Now that muparser no longer relies on exceptions, we can disable them again. --- configure.ac | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 9fa0b5954..c33107b53 100644 --- a/configure.ac +++ b/configure.ac @@ -212,11 +212,8 @@ AS_IF([test "$use_doxygen" != "no"], AC_SYS_LARGEFILE -# Fish does not use exceptions itself. However the MuParser library does so we -# need to enable support for them and pay the cost of larger code. Note: -# Enabling exceptions increases the compiled code size but to avoid that we -# would have to maintain our own patches to the MuParser code. -#CXXFLAGS="$CXXFLAGS -fno-exceptions" +# Fish does not use exceptions. +CXXFLAGS="$CXXFLAGS -fno-exceptions" # # Set some warning flags From 554382a28661201fe86deddc4e05e07163e551e2 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 17 Dec 2017 18:04:52 -0800 Subject: [PATCH 42/62] [muparser] Remove 'AllowOpt' parameters This parameter was used as a hint to optimize functions invoked with constants, but is no longer used. --- muparser-2.2.5/include/muParserBase.h | 17 ++--- muparser-2.2.5/include/muParserCallback.h | 34 +++++----- muparser-2.2.5/src/muParserBase.cpp | 23 +++---- muparser-2.2.5/src/muParserCallback.cpp | 81 +++++++++-------------- muparser-2.2.5/src/muParserDLL.cpp | 81 +++++++++-------------- 5 files changed, 97 insertions(+), 139 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 5440808ea..93637fca6 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -114,29 +114,24 @@ class ParserBase { bool HasBuiltInOprt() const; void AddValIdent(identfun_type a_pCallback); - /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool - a_bAllowOpt = true) + /** \fn void mu::ParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun) \brief Define a parser function without arguments. \param a_strName Name of the function \param a_pFun Pointer to the callback function - \param a_bAllowOpt A flag indicating this function may be optimized */ template - OptionalError DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true) { - return AddCallback(a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, - ValidNameChars()); + OptionalError DefineFun(const string_type &a_strName, T a_pFun) { + return AddCallback(a_strName, ParserCallback(a_pFun), m_FunDef, ValidNameChars()); } OptionalError DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri = 0, - EOprtAssociativity a_eAssociativity = oaLEFT, - bool a_bAllowOpt = false); + EOprtAssociativity a_eAssociativity = oaLEFT); OptionalError DefineConst(const string_type &a_sName, value_type a_fVal); OptionalError DefineStrConst(const string_type &a_sName, const string_type &a_strVal); OptionalError DefineVar(const string_type &a_sName, value_type *a_fVar); - OptionalError DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, - bool a_bAllowOpt = true); + OptionalError DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt); OptionalError DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, - int a_iPrec = prINFIX, bool a_bAllowOpt = true); + int a_iPrec = prINFIX); // Clear user defined variables, constants or functions void ClearVar(); diff --git a/muparser-2.2.5/include/muParserCallback.h b/muparser-2.2.5/include/muParserCallback.h index 83417f27b..08d7a7cba 100644 --- a/muparser-2.2.5/include/muParserCallback.h +++ b/muparser-2.2.5/include/muParserCallback.h @@ -48,25 +48,23 @@ namespace mu { */ class ParserCallback final { public: - ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, - ECmdCode a_iCode = cmFUNC); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, - EOprtAssociativity a_eAssociativity); - ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti); - ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti); + explicit ParserCallback(fun_type0 a_pFun); + ParserCallback(fun_type1 a_pFun, int a_iPrec = -1, ECmdCode a_iCode = cmFUNC); + ParserCallback(fun_type2 a_pFun, int a_iPrec, EOprtAssociativity a_eAssociativity); + explicit ParserCallback(fun_type2 a_pFun); + explicit ParserCallback(fun_type3 a_pFun); + explicit ParserCallback(fun_type4 a_pFun); + explicit ParserCallback(fun_type5 a_pFun); + explicit ParserCallback(fun_type6 a_pFun); + explicit ParserCallback(fun_type7 a_pFun); + explicit ParserCallback(fun_type8 a_pFun); + explicit ParserCallback(fun_type9 a_pFun); + explicit ParserCallback(fun_type10 a_pFun); - ParserCallback(multfun_type a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti); - ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti); + explicit ParserCallback(multfun_type a_pFun); + explicit ParserCallback(strfun_type1 a_pFun); + explicit ParserCallback(strfun_type2 a_pFun); + explicit ParserCallback(strfun_type3 a_pFun); ParserCallback(); ParserCallback(const ParserCallback& a_Fun); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 80c1abc9c..1643c944c 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -365,10 +365,9 @@ const char_type *ParserBase::ValidInfixOprtChars() const { /** \brief Add a user defined operator. \post Will reset the Parser to string parsing mode. */ -OptionalError ParserBase::DefinePostfixOprt(const string_type &a_sName, fun_type1 a_pFun, - bool a_bAllowOpt) { - return AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX), - m_PostOprtDef, ValidOprtChars()); +OptionalError ParserBase::DefinePostfixOprt(const string_type &a_sName, fun_type1 a_pFun) { + return AddCallback(a_sName, ParserCallback(a_pFun, prPOSTFIX, cmOPRT_POSTFIX), m_PostOprtDef, + ValidOprtChars()); } //--------------------------------------------------------------------------- @@ -389,13 +388,12 @@ void ParserBase::Init() { \param [in] a_sName operator Identifier \param [in] a_pFun Operator callback function \param [in] a_iPrec Operator Precedence (default=prSIGN) - \param [in] a_bAllowOpt True if operator is volatile (default=false) \sa EPrec */ -OptionalError ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, int a_iPrec, - bool a_bAllowOpt) { - return AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX), - m_InfixOprtDef, ValidInfixOprtChars()); +OptionalError ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 a_pFun, + int a_iPrec) { + return AddCallback(a_sName, ParserCallback(a_pFun, a_iPrec, cmOPRT_INFIX), m_InfixOprtDef, + ValidInfixOprtChars()); } //--------------------------------------------------------------------------- @@ -404,18 +402,17 @@ OptionalError ParserBase::DefineInfixOprt(const string_type &a_sName, fun_type1 \param [in] a_pFun Pointer to the callback function. \param [in] a_iPrec Precedence of the operator. \param [in] a_eAssociativity The associativity of the operator. - \param [in] a_bAllowOpt If this is true the operator may be optimized away. Adds a new Binary operator the the parser instance. */ OptionalError ParserBase::DefineOprt(const string_type &a_sName, fun_type2 a_pFun, unsigned a_iPrec, - EOprtAssociativity a_eAssociativity, bool a_bAllowOpt) { + EOprtAssociativity a_eAssociativity) { // Check for conflicts with built in operator names for (int i = 0; m_bBuiltInOp && i < cmENDIF; ++i) if (a_sName == string_type(c_DefaultOprt[i])) return Error(ecBUILTIN_OVERLOAD, -1, a_sName); - return AddCallback(a_sName, ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity), - m_OprtDef, ValidOprtChars()); + return AddCallback(a_sName, ParserCallback(a_pFun, a_iPrec, a_eAssociativity), m_OprtDef, + ValidOprtChars()); } //--------------------------------------------------------------------------- diff --git a/muparser-2.2.5/src/muParserCallback.cpp b/muparser-2.2.5/src/muParserCallback.cpp index abb2c594f..9feae7b9a 100644 --- a/muparser-2.2.5/src/muParserCallback.cpp +++ b/muparser-2.2.5/src/muParserCallback.cpp @@ -31,36 +31,33 @@ namespace mu { //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type0 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type0 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(0), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode) +ParserCallback::ParserCallback(fun_type1 a_pFun, int a_iPrec, ECmdCode a_iCode) : m_pFun((void*)a_pFun), m_iArgc(1), m_iPri(a_iPrec), m_eOprtAsct(oaNONE), m_iCode(a_iCode), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- /** \brief Constructor for constructing function callbacks taking two arguments. */ -ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type2 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(2), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- /** \brief Constructor for constructing binary operator callbacks. @@ -69,135 +66,121 @@ ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti) \param a_iPrec The operator precedence \param a_eOprtAsct The operators associativity */ -ParserCallback::ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, - EOprtAssociativity a_eOprtAsct) +ParserCallback::ParserCallback(fun_type2 a_pFun, int a_iPrec, EOprtAssociativity a_eOprtAsct) : m_pFun((void*)a_pFun), m_iArgc(2), m_iPri(a_iPrec), m_eOprtAsct(a_eOprtAsct), m_iCode(cmOPRT_BIN), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type3 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(3), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type4 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(4), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type5 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(5), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type6 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type6 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(6), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type7 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type7 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(7), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type8 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type8 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(8), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type9 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type9 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(9), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type10 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(fun_type10 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(10), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(multfun_type a_pFun) : m_pFun((void*)a_pFun), m_iArgc(-1), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC), - m_iType(tpDBL), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpDBL) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(strfun_type1 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(0), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC_STR), - m_iType(tpSTR), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpSTR) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(strfun_type2 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(1), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC_STR), - m_iType(tpSTR), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpSTR) {} //--------------------------------------------------------------------------- -ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti) +ParserCallback::ParserCallback(strfun_type3 a_pFun) : m_pFun((void*)a_pFun), m_iArgc(2), m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmFUNC_STR), - m_iType(tpSTR), - m_bAllowOpti(a_bAllowOpti) {} + m_iType(tpSTR) {} //--------------------------------------------------------------------------- /** \brief Default constructor. diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 59d8e286a..9942b46a8 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -264,111 +264,100 @@ API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) { //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun0_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun0_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } @@ -377,7 +366,7 @@ API_EXPORT(void) mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); + p->DefineFun(a_szName, a_pFun); MU_CATCH } @@ -386,7 +375,7 @@ API_EXPORT(void) mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); + p->DefineFun(a_szName, a_pFun); MU_CATCH } @@ -395,28 +384,26 @@ API_EXPORT(void) mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, false); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun, - muBool_t a_bAllowOpt) { +mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun, a_bAllowOpt != 0); + p->DefineFun(a_szName, a_pFun); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, - muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) { + muInt_t a_nPrec, muInt_t a_nOprtAsct) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, - a_bAllowOpt != 0)); + throwIfError(p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct)); MU_CATCH } @@ -478,21 +465,19 @@ API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) { //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, - muBool_t a_bAllowOpt) { +mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); + p->DefinePostfixOprt(a_szName, a_pOprt); MU_CATCH } //--------------------------------------------------------------------------- API_EXPORT(void) -mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt, - muBool_t a_bAllowOpt) { +mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt != 0); + p->DefineInfixOprt(a_szName, a_pOprt); MU_CATCH } From 128aacaf877e1aecb1bdfc049480aeafbec44665 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 01:54:14 -0800 Subject: [PATCH 43/62] [muparser] Disable muparser shared lib build fish does not use its shared library, only the static one --- muparser-2.2.5/Makefile.in | 3 +-- muparser-2.2.5/configure | 11 ++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index 0619f08a0..87a060603 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -190,8 +190,7 @@ COND_USE_SOTWOSYMLINKS_1___muParser_dll___so_symlinks_uninst_cmd = rm -f \ @COND_USE_SOVERSOLARIS_1@ $(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) @COND_PLATFORM_MACOSX_1@__muParser_dll___macver = \ @COND_PLATFORM_MACOSX_1@ -compatibility_version 1 -current_version 1 -@COND_SAMPLES_1@__example1___depname = \ -@COND_SAMPLES_1@ $(top_builddir)/samples/example1/example1$(EXEEXT) +__example1___depname = $(top_builddir)/samples/example1/example1$(EXEEXT) @COND_PLATFORM_MAC_0@__example1___mac_setfilecmd = @true @COND_PLATFORM_MAC_1@__example1___mac_setfilecmd = \ @COND_PLATFORM_MAC_1@ $(SETFILE) -t APPL \ diff --git a/muparser-2.2.5/configure b/muparser-2.2.5/configure index 1a16abdc2..84543fc12 100755 --- a/muparser-2.2.5/configure +++ b/muparser-2.2.5/configure @@ -3569,11 +3569,12 @@ $as_echo "no" >&6; } fi # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; -else - enableval="$default" -fi + # fish: disabled +# if test "${enable_shared+set}" = set; then : +# enableval=$enable_shared; +# else +# enableval="$default" +# fi From bb9e15675e8c7da32381a33fb188f3b40a22214f Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 01:57:32 -0800 Subject: [PATCH 44/62] [muparser] Remove muParserDLL.h and muParserDLL.cpp This is a C interface (?) which fish does not use and is not needed. --- fish.xcodeproj/project.pbxproj | 4 - muparser-2.2.5/CMakeLists.txt | 1 - muparser-2.2.5/Makefile.in | 81 +--- muparser-2.2.5/include/muParserDLL.h | 228 ---------- muparser-2.2.5/src/muParserDLL.cpp | 630 --------------------------- 5 files changed, 3 insertions(+), 941 deletions(-) delete mode 100644 muparser-2.2.5/include/muParserDLL.h delete mode 100644 muparser-2.2.5/src/muParserDLL.cpp diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index 1e783337c..6837f768a 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -376,7 +376,6 @@ D068222B1F5149B500040321 /* muParserBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822221F51498700040321 /* muParserBase.cpp */; }; D068222C1F5149B500040321 /* muParserBytecode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822231F51498700040321 /* muParserBytecode.cpp */; }; D068222D1F5149B500040321 /* muParserCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822241F51498700040321 /* muParserCallback.cpp */; }; - D068222E1F5149B500040321 /* muParserDLL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822251F51498700040321 /* muParserDLL.cpp */; }; D068222F1F5149B500040321 /* muParserError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822261F51498700040321 /* muParserError.cpp */; }; D06822301F5149B500040321 /* muParserInt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822271F51498700040321 /* muParserInt.cpp */; }; D06822321F5149B500040321 /* muParserTokenReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D06822291F51498700040321 /* muParserTokenReader.cpp */; }; @@ -818,7 +817,6 @@ D06822221F51498700040321 /* muParserBase.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserBase.cpp; sourceTree = ""; }; D06822231F51498700040321 /* muParserBytecode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserBytecode.cpp; sourceTree = ""; }; D06822241F51498700040321 /* muParserCallback.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserCallback.cpp; sourceTree = ""; }; - D06822251F51498700040321 /* muParserDLL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserDLL.cpp; sourceTree = ""; }; D06822261F51498700040321 /* muParserError.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserError.cpp; sourceTree = ""; }; D06822271F51498700040321 /* muParserInt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserInt.cpp; sourceTree = ""; }; D06822291F51498700040321 /* muParserTokenReader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = muParserTokenReader.cpp; sourceTree = ""; }; @@ -1077,7 +1075,6 @@ D06822221F51498700040321 /* muParserBase.cpp */, D06822231F51498700040321 /* muParserBytecode.cpp */, D06822241F51498700040321 /* muParserCallback.cpp */, - D06822251F51498700040321 /* muParserDLL.cpp */, D06822261F51498700040321 /* muParserError.cpp */, D06822271F51498700040321 /* muParserInt.cpp */, D06822291F51498700040321 /* muParserTokenReader.cpp */, @@ -1924,7 +1921,6 @@ D068222B1F5149B500040321 /* muParserBase.cpp in Sources */, D068222C1F5149B500040321 /* muParserBytecode.cpp in Sources */, D068222D1F5149B500040321 /* muParserCallback.cpp in Sources */, - D068222E1F5149B500040321 /* muParserDLL.cpp in Sources */, D068222F1F5149B500040321 /* muParserError.cpp in Sources */, D06822301F5149B500040321 /* muParserInt.cpp in Sources */, D06822321F5149B500040321 /* muParserTokenReader.cpp in Sources */, diff --git a/muparser-2.2.5/CMakeLists.txt b/muparser-2.2.5/CMakeLists.txt index d7e5caa74..64b49fe84 100644 --- a/muparser-2.2.5/CMakeLists.txt +++ b/muparser-2.2.5/CMakeLists.txt @@ -3,7 +3,6 @@ SET(MUPARSER_SRCS ${CMAKE_CURRENT_LIST_DIR}/src/muParserBase.cpp ${CMAKE_CURRENT_LIST_DIR}/src/muParserBytecode.cpp ${CMAKE_CURRENT_LIST_DIR}/src/muParserCallback.cpp - ${CMAKE_CURRENT_LIST_DIR}/src/muParserDLL.cpp ${CMAKE_CURRENT_LIST_DIR}/src/muParserError.cpp ${CMAKE_CURRENT_LIST_DIR}/src/muParserInt.cpp ${CMAKE_CURRENT_LIST_DIR}/src/muParserTokenReader.cpp) diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index 87a060603..a5aaf692c 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -49,7 +49,6 @@ MUPARSER_LIB_OBJECTS = \ muParser_lib_muParserBase.o \ muParser_lib_muParserBytecode.o \ muParser_lib_muParserCallback.o \ - muParser_lib_muParserDLL.o \ muParser_lib_muParserError.o \ muParser_lib_muParserInt.o \ muParser_lib_muParserTest.o \ @@ -59,32 +58,6 @@ MUPARSER_LIB_HEADERS = \ include/muParserBase.h \ include/muParserBytecode.h \ include/muParserCallback.h \ - include/muParserDLL.h \ - include/muParserDef.h \ - include/muParserFixes.h \ - include/muParserInt.h \ - include/muParserTemplateMagic.h \ - include/muParserTest.h \ - include/muParserToken.h \ - include/muParserTokenReader.h -MUPARSER_DLL_CXXFLAGS = $(____DEBUG) $(____SHARED) $(____SHARED_0) \ - -I$(srcdir)/include $(PIC_FLAG) $(CPPFLAGS) $(CXXFLAGS) -std=c++11 -MUPARSER_DLL_OBJECTS = \ - muParser_dll_muParser.o \ - muParser_dll_muParserBase.o \ - muParser_dll_muParserBytecode.o \ - muParser_dll_muParserCallback.o \ - muParser_dll_muParserDLL.o \ - muParser_dll_muParserError.o \ - muParser_dll_muParserInt.o \ - muParser_dll_muParserTest.o \ - muParser_dll_muParserTokenReader.o -MUPARSER_DLL_HEADERS = \ - include/muParser.h \ - include/muParserBase.h \ - include/muParserBytecode.h \ - include/muParserCallback.h \ - include/muParserDLL.h \ include/muParserDef.h \ include/muParserFixes.h \ include/muParserInt.h \ @@ -102,17 +75,13 @@ EXAMPLE1_OBJECTS = \ @COND_DEPS_TRACKING_1@CXXC = $(BK_DEPS) $(CXX) @COND_DEBUG_0@DEBUG_BUILD_POSTFIX = @COND_DEBUG_1@DEBUG_BUILD_POSTFIX = d -@COND_SHARED_0@__muParser_lib___depname = \ -@COND_SHARED_0@ $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) +__muParser_lib___depname = $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(LIBEXT) @COND_SHARED_0@__install_muParser_lib___depname = install_muParser_lib @COND_SHARED_0@__uninstall_muParser_lib___depname = uninstall_muParser_lib @COND_SHARED_0@__install_muParser_lib_headers___depname = \ @COND_SHARED_0@ install_muParser_lib_headers @COND_SHARED_0@__uninstall_muParser_lib_headers___depname = \ @COND_SHARED_0@ uninstall_muParser_lib_headers -COND_SHARED_1___muParser_dll___depname = \ - $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) -@COND_SHARED_1@__muParser_dll___depname = $(COND_SHARED_1___muParser_dll___depname) @COND_SHARED_1@__install_muParser_dll___depname = install_muParser_dll @COND_SHARED_1@__uninstall_muParser_dll___depname = uninstall_muParser_dll COND_PLATFORM_MACOSX_1___muParser_dll___macinstnamecmd = -install_name \ @@ -204,7 +173,7 @@ __example1___depname = $(top_builddir)/samples/example1/example1$(EXEEXT) ### Targets: ### -all: $(__muParser_lib___depname) $(__muParser_dll___depname) $(__example1___depname) +all: $(__muParser_lib___depname) $(__example1___depname) install: $(__install_muParser_lib___depname) $(__install_muParser_lib_headers___depname) $(__install_muParser_dll___depname) $(__install_muParser_dll_headers___depname) $(INSTALL_DIR) $(DESTDIR)$(libdir)/pkgconfig @@ -254,12 +223,9 @@ distclean: clean @COND_SHARED_0@ rm -f $(DESTDIR)$(prefix)/$$f; \ @COND_SHARED_0@ done -@COND_SHARED_1@$(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3): $(MUPARSER_DLL_OBJECTS) -@COND_SHARED_1@ $(SHARED_LD_CXX) $@ $(MUPARSER_DLL_OBJECTS) $(__muParser_dll___macinstnamecmd) $(__muParser_dll___importlib) $(__muParser_dll___soname_flags) $(__muParser_dll___macver) $(LDFLAGS) $(LIBS) @COND_SHARED_1@ @COND_SHARED_1@ $(__muParser_dll___so_symlinks_cmd) -@COND_SHARED_1@install_muParser_dll: $(__muParser_dll___depname) @COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(libdir) @COND_SHARED_1@ $(INSTALL_DATA) $(top_builddir)/lib/$(LIBPREFIX)muparser$(DEBUG_BUILD_POSTFIX).$(DLLIMP_SUFFIX) $(DESTDIR)$(libdir) @COND_SHARED_1@ $(INSTALL_PROGRAM) $(top_builddir)/lib/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) $(DESTDIR)$(libdir) @@ -270,26 +236,12 @@ distclean: clean @COND_SHARED_1@ rm -f $(DESTDIR)$(libdir)/$(DLLPREFIX)muparser$(DEBUG_BUILD_POSTFIX)$(__muParser_dll___targetsuf3) @COND_SHARED_1@ (cd $(DESTDIR)$(libdir) ; $(__muParser_dll___so_symlinks_uninst_cmd)) -@COND_SHARED_1@install_muParser_dll_headers: -@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(prefix) -@COND_SHARED_1@ for f in $(MUPARSER_DLL_HEADERS); do \ -@COND_SHARED_1@ if test ! -d $(DESTDIR)$(prefix)/`dirname $$f` ; then \ -@COND_SHARED_1@ $(INSTALL_DIR) $(DESTDIR)$(prefix)/`dirname $$f`; \ -@COND_SHARED_1@ fi; \ -@COND_SHARED_1@ $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(prefix)/$$f; \ -@COND_SHARED_1@ done - -@COND_SHARED_1@uninstall_muParser_dll_headers: -@COND_SHARED_1@ for f in $(MUPARSER_DLL_HEADERS); do \ -@COND_SHARED_1@ rm -f $(DESTDIR)$(prefix)/$$f; \ -@COND_SHARED_1@ done - @COND_SAMPLES_1@$(top_builddir)/samples/example1/example1$(EXEEXT): $(EXAMPLE1_OBJECTS) $(__muParser_lib___depname) @COND_SAMPLES_1@ $(CXX) -o $@ $(EXAMPLE1_OBJECTS) -L$(top_builddir)/lib -L$(srcdir)/lib $(LDFLAGS) -lmuparser$(DEBUG_BUILD_POSTFIX) $(LIBS) @COND_SAMPLES_1@ @COND_SAMPLES_1@ $(__example1___mac_setfilecmd) -lib: $(__muParser_lib___depname) $(__muParser_dll___depname) +lib: $(__muParser_lib___depname) samples: $(__example1___depname) @@ -323,33 +275,6 @@ muParser_lib_muParserTest.o: $(srcdir)/src/muParserTest.cpp muParser_lib_muParserTokenReader.o: $(srcdir)/src/muParserTokenReader.cpp $(CXXC) -c -o $@ $(MUPARSER_LIB_CXXFLAGS) $(srcdir)/src/muParserTokenReader.cpp -muParser_dll_muParser.o: $(srcdir)/src/muParser.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParser.cpp - -muParser_dll_muParserBase.o: $(srcdir)/src/muParserBase.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserBase.cpp - -muParser_dll_muParserBytecode.o: $(srcdir)/src/muParserBytecode.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserBytecode.cpp - -muParser_dll_muParserCallback.o: $(srcdir)/src/muParserCallback.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserCallback.cpp - -muParser_dll_muParserDLL.o: $(srcdir)/src/muParserDLL.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserDLL.cpp - -muParser_dll_muParserError.o: $(srcdir)/src/muParserError.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserError.cpp - -muParser_dll_muParserInt.o: $(srcdir)/src/muParserInt.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserInt.cpp - -muParser_dll_muParserTest.o: $(srcdir)/src/muParserTest.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserTest.cpp - -muParser_dll_muParserTokenReader.o: $(srcdir)/src/muParserTokenReader.cpp - $(CXXC) -c -o $@ $(MUPARSER_DLL_CXXFLAGS) $(srcdir)/src/muParserTokenReader.cpp - example1_example1.o: $(srcdir)/samples/example1/example1.cpp $(CXXC) -c -o $@ $(EXAMPLE1_CXXFLAGS) $(srcdir)/samples/example1/example1.cpp diff --git a/muparser-2.2.5/include/muParserDLL.h b/muparser-2.2.5/include/muParserDLL.h deleted file mode 100644 index 396f63ccf..000000000 --- a/muparser-2.2.5/include/muParserDLL.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#ifndef MU_PARSER_DLL_H -#define MU_PARSER_DLL_H - -#if defined(WIN32) || defined(_WIN32) -#ifdef MUPARSERLIB_EXPORTS -#define API_EXPORT(TYPE) __declspec(dllexport) TYPE __cdecl -#else -#define API_EXPORT(TYPE) __declspec(dllimport) TYPE __cdecl -#endif -#else -#define API_EXPORT(TYPE) TYPE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file - \brief This file contains the DLL interface of muparser. -*/ - -// Basic types -typedef void *muParserHandle_t; // parser handle - -#ifndef _UNICODE -typedef char muChar_t; // character type -#else -typedef wchar_t muChar_t; // character type -#endif - -typedef int muBool_t; // boolean type -typedef int muInt_t; // integer type -typedef double muFloat_t; // floating point type -using mu::ValueOrError; - -// function types for calculation -typedef ValueOrError (*muFun0_t)(); -typedef ValueOrError (*muFun1_t)(muFloat_t); -typedef ValueOrError (*muFun2_t)(muFloat_t, muFloat_t); -typedef ValueOrError (*muFun3_t)(muFloat_t, muFloat_t, muFloat_t); -typedef ValueOrError (*muFun4_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef ValueOrError (*muFun5_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef ValueOrError (*muFun6_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t); -typedef ValueOrError (*muFun7_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t); -typedef ValueOrError (*muFun8_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t); -typedef ValueOrError (*muFun9_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t); -typedef ValueOrError (*muFun10_t)(muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, muFloat_t, - muFloat_t, muFloat_t, muFloat_t, muFloat_t); - -typedef ValueOrError (*muMultFun_t)(const muFloat_t *, muInt_t); -typedef ValueOrError (*muStrFun1_t)(const muChar_t *); -typedef ValueOrError (*muStrFun2_t)(const muChar_t *, muFloat_t); -typedef ValueOrError (*muStrFun3_t)(const muChar_t *, muFloat_t, muFloat_t); - -// Functions for parser management -typedef void (*muErrorHandler_t)( - muParserHandle_t a_hParser); // [optional] callback to an error handler -typedef muFloat_t *(*muFacFun_t)(const muChar_t *, - void *); // [optional] callback for creating new variables -typedef muInt_t (*muIdentFun_t)(const muChar_t *, muInt_t *, - muFloat_t *); // [optional] value identification callbacks - -//----------------------------------------------------------------------------------------------------- -// Constants -static const int muOPRT_ASCT_LEFT = 0; -static const int muOPRT_ASCT_RIGHT = 1; - -static const int muBASETYPE_FLOAT = 0; -static const int muBASETYPE_INT = 1; - -//----------------------------------------------------------------------------------------------------- -// -// -// muParser C compatible bindings -// -// -//----------------------------------------------------------------------------------------------------- - -// Basic operations / initialization -API_EXPORT(muParserHandle_t) mupCreate(int nBaseType); -API_EXPORT(void) mupRelease(muParserHandle_t a_hParser); -API_EXPORT(const muChar_t *) mupGetExpr(muParserHandle_t a_hParser); -API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t *a_szExpr); -API_EXPORT(void) -mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void *pUserData); -API_EXPORT(const muChar_t *) mupGetVersion(muParserHandle_t a_hParser); -API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser); - -// Defining callbacks / variables / constants -API_EXPORT(void) -mupDefineFun0(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun0_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun3_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun4(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun4_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun5(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun5_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun6(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun6_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun7(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun7_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun8(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun8_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun9(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun9_t a_pFun, - muBool_t a_bOptimize); -API_EXPORT(void) -mupDefineFun10(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun10_t a_pFun, - muBool_t a_bOptimize); - -// string functions -API_EXPORT(void) -mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun1_t a_pFun); -API_EXPORT(void) -mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun2_t a_pFun); -API_EXPORT(void) -mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t *a_szName, muStrFun3_t a_pFun); - -API_EXPORT(void) -mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t *a_szName, muMultFun_t a_pFun, - muBool_t a_bOptimize); - -API_EXPORT(void) -mupDefineOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun2_t a_pFun, - muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bOptimize); - -API_EXPORT(void) -mupDefineConst(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t a_fVal); - -API_EXPORT(void) -mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t *a_szName, const muChar_t *a_sVal); - -API_EXPORT(void) -mupDefineVar(muParserHandle_t a_hParser, const muChar_t *a_szName, muFloat_t *a_fVar); - -API_EXPORT(void) -mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pOprt, - muBool_t a_bOptimize); - -API_EXPORT(void) -mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t *a_szName, muFun1_t a_pOprt, - muBool_t a_bOptimize); - -// Define character sets for identifiers -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t *a_szCharset); -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t *a_szCharset); -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t *a_szCharset); - -// Remove all / single variables -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t *a_szName); -API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser); -API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser); -API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser); -API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser); - -// Querying variables / expression variables / constants -API_EXPORT(int) mupGetExprVarNum(muParserHandle_t a_hParser); -API_EXPORT(void) -mupGetExprVar(muParserHandle_t a_hParser, unsigned a_iVar, const muChar_t **a_pszName, - muFloat_t **a_pVar); -API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep); -API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cArgSep); -API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cArgSep); -API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser); - -// Add value recognition callbacks -API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t); - -// Error handling -API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser); -API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser); -API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pErrHandler); -API_EXPORT(const muChar_t *) mupGetErrorMsg(muParserHandle_t a_hParser); -API_EXPORT(muInt_t) mupGetErrorCode(muParserHandle_t a_hParser); -API_EXPORT(muInt_t) mupGetErrorPos(muParserHandle_t a_hParser); -API_EXPORT(const muChar_t *) mupGetErrorToken(muParserHandle_t a_hParser); -// API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser); - -// This is used for .NET only. It creates a new variable allowing the dll to -// manage the variable rather than the .NET garbage collector. -API_EXPORT(muFloat_t *) mupCreateVar(); -API_EXPORT(void) mupReleaseVar(muFloat_t *); - -#ifdef __cplusplus -} -#endif - -#endif // include guard diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp deleted file mode 100644 index 9942b46a8..000000000 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ /dev/null @@ -1,630 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2004-2011 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of - this - software and associated documentation files (the "Software"), to deal in the - Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be included in all - copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ -#if defined(MUPARSER_DLL) - -#if defined(_WIN32) -#define WIN32_LEAN_AND_MEAN -#include -#endif - -#include "muParser.h" -#include "muParserDLL.h" -#include "muParserInt.h" - -static void throwIfError(mu::OptionalError oerr) { - if (oerr.has_error()) throw oerr.error(); -} - -#define MU_TRY try { -#define MU_CATCH \ - } \ - catch (muError_t & e) { \ - ParserTag* pTag = static_cast(a_hParser); \ - pTag->exc = e; \ - pTag->bError = true; \ - if (pTag->errHandler) (pTag->errHandler)(a_hParser); \ - } \ - catch (...) { \ - ParserTag* pTag = static_cast(a_hParser); \ - pTag->bError = true; \ - if (pTag->errHandler) (pTag->errHandler)(a_hParser); \ - } - -/** \file - \brief This file contains the implementation of the DLL interface of muparser. - */ - -//--------------------------------------------------------------------------- -// private types -typedef mu::ParserBase::exception_type muError_t; -typedef mu::ParserBase muParser_t; - -int g_nBulkSize; - -//--------------------------------------------------------------------------- -class ParserTag { - public: - ParserTag(int nType) - : pParser((nType == muBASETYPE_FLOAT) - ? (mu::ParserBase*)new mu::Parser() - : (nType == muBASETYPE_INT) ? (mu::ParserBase*)new mu::ParserInt() : NULL), - exc(), - errHandler(NULL), - bError(false), - m_nParserType(nType) {} - - ~ParserTag() { delete pParser; } - - mu::ParserBase* pParser; - mu::ParserBase::exception_type exc; - muErrorHandler_t errHandler; - bool bError; - - private: - ParserTag(const ParserTag& ref); - ParserTag& operator=(const ParserTag& ref); - - int m_nParserType; -}; - -static muChar_t s_tmpOutBuf[2048]; - -//--------------------------------------------------------------------------- -// -// -// unexported functions -// -// -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -muParser_t* AsParser(muParserHandle_t a_hParser) { - return static_cast(a_hParser)->pParser; -} - -//--------------------------------------------------------------------------- -ParserTag* AsParserTag(muParserHandle_t a_hParser) { return static_cast(a_hParser); } - -//--------------------------------------------------------------------------- -#if defined(_WIN32) -#define _CRT_SECURE_NO_DEPRECATE - -BOOL APIENTRY DllMain(HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) { - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - - return TRUE; -} - -#endif - -//--------------------------------------------------------------------------- -// -// -// exported functions -// -// -//--------------------------------------------------------------------------- - -API_EXPORT(void) -mupSetVarFactory(muParserHandle_t a_hParser, muFacFun_t a_pFactory, void* pUserData) { - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->SetVarFactory(a_pFactory, pUserData); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Create a new Parser instance and return its handle. -*/ -API_EXPORT(muParserHandle_t) mupCreate(int nBaseType) { - switch (nBaseType) { - case muBASETYPE_FLOAT: - return (void*)(new ParserTag(muBASETYPE_FLOAT)); - case muBASETYPE_INT: - return (void*)(new ParserTag(muBASETYPE_INT)); - default: - return NULL; - } -} - -//--------------------------------------------------------------------------- -/** \brief Release the parser instance related with a parser handle. -*/ -API_EXPORT(void) mupRelease(muParserHandle_t a_hParser) { - MU_TRY - ParserTag* p = static_cast(a_hParser); - delete p; - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(const muChar_t*) mupGetVersion(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str()); -#else - wsprintf(s_tmpOutBuf, _T("%s"), p->GetVersion().c_str()); -#endif - - return s_tmpOutBuf; - MU_CATCH - - return _T(""); -} - -//--------------------------------------------------------------------------- -/** \brief Evaluate the expression. -*/ -API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - return *p->Eval(); - MU_CATCH - - return 0; -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->SetExpr(a_szExpr)); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupRemoveVar(muParserHandle_t a_hParser, const muChar_t* a_szName) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->RemoveVar(a_szName); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Release all parser variables. - \param a_hParser Handle to the parser instance. - */ -API_EXPORT(void) mupClearVar(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearVar(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Release all parser variables. - \param a_hParser Handle to the parser instance. - */ -API_EXPORT(void) mupClearConst(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearConst(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Clear all user defined operators. - \param a_hParser Handle to the parser instance. - */ -API_EXPORT(void) mupClearOprt(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearOprt(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupClearFun(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ClearFun(); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun0(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun0_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun3_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun4(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun4_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun5(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun5_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun6(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun6_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun7(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun7_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun8(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun8_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun9(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun9_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineFun10(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun10_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineStrFun1(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun1_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineStrFun2(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun2_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineStrFun3(muParserHandle_t a_hParser, const muChar_t* a_szName, muStrFun3_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineMultFun(muParserHandle_t a_hParser, const muChar_t* a_szName, muMultFun_t a_pFun) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineFun(a_szName, a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_pFun, - muInt_t a_nPrec, muInt_t a_nOprtAsct) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct)); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->DefineVar(a_szName, a_pVar)); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->DefineVar(a_szName, a_pVar)); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->DefineConst(a_szName, a_fVal)); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - throwIfError(p->DefineStrConst(a_szName, a_szVal)); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(const muChar_t*) mupGetExpr(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - -// C# explodes when pMsg is returned directly. For some reason it can't access -// the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str()); -#else - wsprintf(s_tmpOutBuf, _T("%s"), p->GetExpr().c_str()); -#endif - - return s_tmpOutBuf; - - MU_CATCH - - return _T(""); -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefinePostfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefinePostfixOprt(a_szName, a_pOprt); - MU_CATCH -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) -mupDefineInfixOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun1_t a_pOprt) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprt(a_szName, a_pOprt); - MU_CATCH -} - -// Define character sets for identifiers -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineNameChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) { - muParser_t* const p(AsParser(a_hParser)); - p->DefineNameChars(a_szCharset); -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) { - muParser_t* const p(AsParser(a_hParser)); - p->DefineOprtChars(a_szCharset); -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupDefineInfixOprtChars(muParserHandle_t a_hParser, const muChar_t* a_szCharset) { - muParser_t* const p(AsParser(a_hParser)); - p->DefineInfixOprtChars(a_szCharset); -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetArgSep(muParserHandle_t a_hParser, const muChar_t cArgSep) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetArgSep(cArgSep); - MU_CATCH -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupResetLocale(muParserHandle_t a_hParser) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->ResetLocale(); - MU_CATCH -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetDecSep(muParserHandle_t a_hParser, const muChar_t cDecSep) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetDecSep(cDecSep); - MU_CATCH -} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupSetThousandsSep(muParserHandle_t a_hParser, const muChar_t cThousandsSep) { - MU_TRY - muParser_t* const p(AsParser(a_hParser)); - p->SetThousandsSep(cThousandsSep); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Add a custom value recognition function. -*/ -API_EXPORT(void) mupAddValIdent(muParserHandle_t a_hParser, muIdentFun_t a_pFun) { - MU_TRY - muParser_t* p(AsParser(a_hParser)); - p->AddValIdent(a_pFun); - MU_CATCH -} - -//--------------------------------------------------------------------------- -/** \brief Query if an error occurred. - - After querying the internal error bit will be reset. So a consecutive call - will return false. - */ -API_EXPORT(muBool_t) mupError(muParserHandle_t a_hParser) { - bool bError(AsParserTag(a_hParser)->bError); - AsParserTag(a_hParser)->bError = false; - return bError; -} - -//--------------------------------------------------------------------------- -/** \brief Reset the internal error flag. -*/ -API_EXPORT(void) mupErrorReset(muParserHandle_t a_hParser) { - AsParserTag(a_hParser)->bError = false; -} - -//--------------------------------------------------------------------------- -API_EXPORT(void) mupSetErrorHandler(muParserHandle_t a_hParser, muErrorHandler_t a_pHandler) { - AsParserTag(a_hParser)->errHandler = a_pHandler; -} - -//--------------------------------------------------------------------------- -/** \brief Return the message associated with the last error. -*/ -API_EXPORT(const muChar_t*) mupGetErrorMsg(muParserHandle_t a_hParser) { - ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t* pMsg = p->exc.GetMsg().c_str(); - -// C# explodes when pMsg is returned directly. For some reason it can't access -// the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", pMsg); -#else - wsprintf(s_tmpOutBuf, _T("%s"), pMsg); -#endif - - return s_tmpOutBuf; -} - -//--------------------------------------------------------------------------- -/** \brief Return the message associated with the last error. -*/ -API_EXPORT(const muChar_t*) mupGetErrorToken(muParserHandle_t a_hParser) { - ParserTag* const p(AsParserTag(a_hParser)); - const muChar_t* pToken = p->exc.GetToken().c_str(); - -// C# explodes when pMsg is returned directly. For some reason it can't access -// the memory where the message lies directly. -#ifndef _UNICODE - sprintf(s_tmpOutBuf, "%s", pToken); -#else - wsprintf(s_tmpOutBuf, _T("%s"), pToken); -#endif - - return s_tmpOutBuf; -} - -//--------------------------------------------------------------------------- -/** \brief Return the code associated with the last error. -*/ -API_EXPORT(int) mupGetErrorCode(muParserHandle_t a_hParser) { - return AsParserTag(a_hParser)->exc.GetCode(); -} - -//--------------------------------------------------------------------------- -/** \brief Return the position associated with the last error. */ -API_EXPORT(int) mupGetErrorPos(muParserHandle_t a_hParser) { - return (int)AsParserTag(a_hParser)->exc.GetPos(); -} - -////----------------------------------------------------------------------------------------------------- -// API_EXPORT(const muChar_t*) mupGetErrorExpr(muParserHandle_t a_hParser) -//{ -// return AsParserTag(a_hParser)->exc.GetExpr().c_str(); -//} - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(muFloat_t*) mupCreateVar() { return new muFloat_t(0); } - -//----------------------------------------------------------------------------------------------------- -API_EXPORT(void) mupReleaseVar(muFloat_t* ptr) { delete ptr; } - -#endif // MUPARSER_DLL From fdefabdb1dde8cdd153d0fda024a1c9f82a3069e Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 02:00:16 -0800 Subject: [PATCH 45/62] [muparser] Remove fun_type overloads that have four or more parameters Supporting these is rather excessive. --- muparser-2.2.5/include/muParserCallback.h | 7 --- muparser-2.2.5/include/muParserDef.h | 26 ---------- muparser-2.2.5/include/muParserTest.h | 21 -------- muparser-2.2.5/src/muParserBase.cpp | 17 ------ muparser-2.2.5/src/muParserCallback.cpp | 63 ----------------------- muparser-2.2.5/src/muParserTest.cpp | 21 -------- 6 files changed, 155 deletions(-) diff --git a/muparser-2.2.5/include/muParserCallback.h b/muparser-2.2.5/include/muParserCallback.h index 08d7a7cba..5621c6d66 100644 --- a/muparser-2.2.5/include/muParserCallback.h +++ b/muparser-2.2.5/include/muParserCallback.h @@ -53,13 +53,6 @@ class ParserCallback final { ParserCallback(fun_type2 a_pFun, int a_iPrec, EOprtAssociativity a_eAssociativity); explicit ParserCallback(fun_type2 a_pFun); explicit ParserCallback(fun_type3 a_pFun); - explicit ParserCallback(fun_type4 a_pFun); - explicit ParserCallback(fun_type5 a_pFun); - explicit ParserCallback(fun_type6 a_pFun); - explicit ParserCallback(fun_type7 a_pFun); - explicit ParserCallback(fun_type8 a_pFun); - explicit ParserCallback(fun_type9 a_pFun); - explicit ParserCallback(fun_type10 a_pFun); explicit ParserCallback(multfun_type a_pFun); explicit ParserCallback(strfun_type1 a_pFun); diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 6327b545f..6f2a7efc6 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -416,32 +416,6 @@ typedef ValueOrError (*fun_type2)(value_type, value_type); /** \brief Callback type used for functions with three arguments. */ typedef ValueOrError (*fun_type3)(value_type, value_type, value_type); -/** \brief Callback type used for functions with four arguments. */ -typedef ValueOrError (*fun_type4)(value_type, value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef ValueOrError (*fun_type5)(value_type, value_type, value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef ValueOrError (*fun_type6)(value_type, value_type, value_type, value_type, value_type, - value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef ValueOrError (*fun_type7)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef ValueOrError (*fun_type8)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef ValueOrError (*fun_type9)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type); - -/** \brief Callback type used for functions with five arguments. */ -typedef ValueOrError (*fun_type10)(value_type, value_type, value_type, value_type, value_type, - value_type, value_type, value_type, value_type, value_type); - /** \brief Callback type used for functions with a variable argument list. */ typedef ValueOrError (*multfun_type)(const value_type *, int); diff --git a/muparser-2.2.5/include/muParserTest.h b/muparser-2.2.5/include/muParserTest.h index 6ad628839..d5bb7d3d9 100644 --- a/muparser-2.2.5/include/muParserTest.h +++ b/muparser-2.2.5/include/muParserTest.h @@ -59,27 +59,6 @@ class ParserTester // final static ValueOrError f2of3(value_type, value_type v, value_type) { return v; }; static ValueOrError f3of3(value_type, value_type, value_type v) { return v; }; - static ValueOrError f1of4(value_type v, value_type, value_type, value_type) { return v; } - static ValueOrError f2of4(value_type, value_type v, value_type, value_type) { return v; } - static ValueOrError f3of4(value_type, value_type, value_type v, value_type) { return v; } - static ValueOrError f4of4(value_type, value_type, value_type, value_type v) { return v; } - - static ValueOrError f1of5(value_type v, value_type, value_type, value_type, value_type) { - return v; - } - static ValueOrError f2of5(value_type, value_type v, value_type, value_type, value_type) { - return v; - } - static ValueOrError f3of5(value_type, value_type, value_type v, value_type, value_type) { - return v; - } - static ValueOrError f4of5(value_type, value_type, value_type, value_type v, value_type) { - return v; - } - static ValueOrError f5of5(value_type, value_type, value_type, value_type, value_type v) { - return v; - } - static ValueOrError Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1 < a_fVal2) ? a_fVal1 : a_fVal2; } diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 1643c944c..1587a3cd8 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -810,23 +810,6 @@ ValueOrError ParserBase::InvokeFunction(generic_fun_type func, const value_type return ((fun_type2)func)(args[0], args[1]); case 3: return ((fun_type3)func)(args[0], args[1], args[2]); - case 4: - return ((fun_type4)func)(args[0], args[1], args[2], args[3]); - case 5: - return ((fun_type5)func)(args[0], args[1], args[2], args[3], args[4]); - case 6: - return ((fun_type6)func)(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: - return ((fun_type7)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - case 8: - return ((fun_type8)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], - args[7]); - case 9: - return ((fun_type9)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], - args[7], args[8]); - case 10: - return ((fun_type10)func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], - args[7], args[8], args[9]); default: // Unreachable. assert(0 && "Internal error"); diff --git a/muparser-2.2.5/src/muParserCallback.cpp b/muparser-2.2.5/src/muParserCallback.cpp index 9feae7b9a..2867f0658 100644 --- a/muparser-2.2.5/src/muParserCallback.cpp +++ b/muparser-2.2.5/src/muParserCallback.cpp @@ -83,69 +83,6 @@ ParserCallback::ParserCallback(fun_type3 a_pFun) m_iCode(cmFUNC), m_iType(tpDBL) {} -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type4 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(4), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type5 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(5), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type6 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(6), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type7 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(7), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type8 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(8), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type9 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(9), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - -//--------------------------------------------------------------------------- -ParserCallback::ParserCallback(fun_type10 a_pFun) - : m_pFun((void*)a_pFun), - m_iArgc(10), - m_iPri(-1), - m_eOprtAsct(oaNONE), - m_iCode(cmFUNC), - m_iType(tpDBL) {} - //--------------------------------------------------------------------------- ParserCallback::ParserCallback(multfun_type a_pFun) : m_pFun((void*)a_pFun), diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index de1544ce7..6a05f5981 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -455,15 +455,6 @@ int ParserTester::TestMultiArg() { iStat += EqnTest(_T("f1of3(1, 2, 3)"), 1, true); iStat += EqnTest(_T("f2of3(1, 2, 3)"), 2, true); iStat += EqnTest(_T("f3of3(1, 2, 3)"), 3, true); - iStat += EqnTest(_T("f1of4(1, 2, 3, 4)"), 1, true); - iStat += EqnTest(_T("f2of4(1, 2, 3, 4)"), 2, true); - iStat += EqnTest(_T("f3of4(1, 2, 3, 4)"), 3, true); - iStat += EqnTest(_T("f4of4(1, 2, 3, 4)"), 4, true); - iStat += EqnTest(_T("f1of5(1, 2, 3, 4, 5)"), 1, true); - iStat += EqnTest(_T("f2of5(1, 2, 3, 4, 5)"), 2, true); - iStat += EqnTest(_T("f3of5(1, 2, 3, 4, 5)"), 3, true); - iStat += EqnTest(_T("f4of5(1, 2, 3, 4, 5)"), 4, true); - iStat += EqnTest(_T("f5of5(1, 2, 3, 4, 5)"), 5, true); // Too few arguments / Too many arguments iStat += EqnTest(_T("1+ping()"), 11, true); iStat += EqnTest(_T("ping()+1"), 11, true); @@ -477,8 +468,6 @@ int ParserTester::TestMultiArg() { iStat += EqnTest(_T("f1of2(1)"), 0, false); iStat += EqnTest(_T("f1of3(1, 2, 3, 4)"), 0, false); iStat += EqnTest(_T("f1of3(1)"), 0, false); - iStat += EqnTest(_T("f1of4(1, 2, 3, 4, 5)"), 0, false); - iStat += EqnTest(_T("f1of4(1)"), 0, false); iStat += EqnTest(_T("(1,2,3)"), 0, false); iStat += EqnTest(_T("1,2,3"), 0, false); iStat += EqnTest(_T("(1*a,2,3)"), 0, false); @@ -613,7 +602,6 @@ int ParserTester::TestPostFix() { iStat += EqnTest(_T("f1of1(1000){m}"), 1, true); iStat += EqnTest(_T("-f1of1(1000){m}"), -1, true); iStat += EqnTest(_T("-f1of1(-1000){m}"), 1, true); - iStat += EqnTest(_T("f4of4(0,0,0,1000){m}"), 1, true); iStat += EqnTest(_T("2+(a*1000){m}"), 3, true); // can postfix operators "m" und "meg" be told apart properly? @@ -1098,15 +1086,6 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) throwIfError(p1->DefineFun(_T("f1of3"), f1of3)); // three parameter throwIfError(p1->DefineFun(_T("f2of3"), f2of3)); throwIfError(p1->DefineFun(_T("f3of3"), f3of3)); - throwIfError(p1->DefineFun(_T("f1of4"), f1of4)); // four parameter - throwIfError(p1->DefineFun(_T("f2of4"), f2of4)); - throwIfError(p1->DefineFun(_T("f3of4"), f3of4)); - throwIfError(p1->DefineFun(_T("f4of4"), f4of4)); - throwIfError(p1->DefineFun(_T("f1of5"), f1of5)); // five parameter - throwIfError(p1->DefineFun(_T("f2of5"), f2of5)); - throwIfError(p1->DefineFun(_T("f3of5"), f3of5)); - throwIfError(p1->DefineFun(_T("f4of5"), f4of5)); - throwIfError(p1->DefineFun(_T("f5of5"), f5of5)); // binary operators throwIfError(p1->DefineOprt(_T("add"), add, 0)); From 3ed9c851a3a41f28d6ed85251f93a1f015f8a788 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 09:17:47 -0800 Subject: [PATCH 46/62] [muparser] Remove some OpenMP / "bulk mode" detritus --- muparser-2.2.5/include/muParserBase.h | 4 ---- muparser-2.2.5/src/muParserBase.cpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 93637fca6..2a38a255e 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -79,9 +79,6 @@ class ParserBase { /** \brief Type used for parser tokens. */ typedef ParserToken token_type; - /** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */ - static const int s_MaxNumOpenMPThreads = 16; - public: /** \brief Type of the error class. @@ -235,7 +232,6 @@ class ParserBase { ValueOrError ParseString() const; ValueOrError ParseCmdCode() const; - ValueOrError ParseCmdCodeBulk(int nOffset, int nThreadID) const; ValueOrError InvokeFunction(generic_fun_type func, const value_type *args, int argCount) const; OptionalError CheckName(const string_type &a_strName, const string_type &a_CharSet) const; diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 1587a3cd8..f16a8bd36 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1216,7 +1216,7 @@ OptionalError ParserBase::CreateRPN() const { if (stVal.top().GetType() != tpDBL) return Error(ecSTR_RESULT); - m_vStackBuffer.resize(m_vRPN.GetMaxStackSize() * s_MaxNumOpenMPThreads); + m_vStackBuffer.resize(m_vRPN.GetMaxStackSize()); return {}; } From 4452d9ce18b1c78fa05e52297012d46c97426f7e Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 09:30:18 -0800 Subject: [PATCH 47/62] [muparser] Remove m_pParseFormula function pointer This is a very strange design that determines whether initialization needs to be performed by reassigning a function pointer. A misguided optimization? Just check explicitly. --- muparser-2.2.5/include/muParserBase.h | 8 +++--- muparser-2.2.5/include/muParserBytecode.h | 1 + muparser-2.2.5/src/muParserBase.cpp | 31 ++++++++--------------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 2a38a255e..c8eae0d79 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -230,10 +230,13 @@ class ParserBase { OptionalError CreateRPN() const; - ValueOrError ParseString() const; - ValueOrError ParseCmdCode() const; + ValueOrError ExecuteRPN() const; ValueOrError InvokeFunction(generic_fun_type func, const value_type *args, int argCount) const; + /// Build the RPN if necessary, and then execute it. + /// \return the result, or an error. + ValueOrError BuildAndExecuteRPN() const; + OptionalError CheckName(const string_type &a_strName, const string_type &a_CharSet) const; OptionalError CheckOprt(const string_type &a_sName, const ParserCallback &a_Callback, const string_type &a_szCharSet) const; @@ -245,7 +248,6 @@ class ParserBase { Eval() calls the function whose address is stored there. */ - mutable ParseFunction m_pParseFormula; mutable ParserByteCode m_vRPN; ///< The Bytecode class. mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index ac70842af..9d4ffc2c3 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -112,6 +112,7 @@ class ParserByteCode { void clear(); std::size_t GetMaxStackSize() const; std::size_t GetSize() const; + bool empty() const { return GetSize() == 0; } const SToken *GetBase() const; void AsciiDump(); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index f16a8bd36..495fc6e43 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -65,8 +65,7 @@ const char_type *ParserBase::c_DefaultOprt[] = { \throw ParserException if a_szFormula is null. */ ParserBase::ParserBase() - : m_pParseFormula(&ParserBase::ParseString), - m_vRPN(), + : m_vRPN(), m_vStringBuf(), m_pTokenReader(), m_FunDef(), @@ -142,7 +141,6 @@ void ParserBase::InitTokenReader() { m_pTokenReader.reset(new token_reader_type( Clear bytecode, reset the token reader. */ void ParserBase::ReInit() const { - m_pParseFormula = &ParserBase::ParseString; m_vStringBuf.clear(); m_vRPN.clear(); m_pTokenReader->ReInit(); @@ -818,14 +816,14 @@ ValueOrError ParserBase::InvokeFunction(generic_fun_type func, const value_type } //--------------------------------------------------------------------------- -/** \brief Parse the command code. - \sa ParseString(...) +/** \brief Execute the RPN. Command code contains precalculated stack positions of the values and the associated operators. The Stack is filled beginning from index one the value at index zero is not used at all. */ -ValueOrError ParserBase::ParseCmdCode() const { +ValueOrError ParserBase::ExecuteRPN() const { + assert(! m_vRPN.empty() && "Missing RPN"); value_type *Stack = &m_vStackBuffer[0]; value_type buf; int sidx(0); @@ -1220,20 +1218,13 @@ OptionalError ParserBase::CreateRPN() const { return {}; } -//--------------------------------------------------------------------------- -/** \brief One of the two main parse functions. - \sa ParseCmdCode(...) - - Parse expression from input string. Perform syntax checking and create - bytecode. After parsing the string and creating the bytecode the function - pointer #m_pParseFormula will be changed to the second parse routine the - uses bytecode instead of string parsing. -*/ -ValueOrError ParserBase::ParseString() const { +ValueOrError ParserBase::BuildAndExecuteRPN() const { + if (m_vRPN.empty()) { OptionalError oerr = CreateRPN(); if (oerr.has_error()) return oerr.error(); - m_pParseFormula = &ParserBase::ParseCmdCode; - return (this->*m_pParseFormula)(); + assert(! m_vRPN.empty() && "RPN should no longer be empty"); + } + return ExecuteRPN(); } //--------------------------------------------------------------------------- @@ -1449,7 +1440,7 @@ void ParserBase::StackDump(const ParserStack &a_stVal, made up of multiple comma separated subexpressions (i.e. "x+y,sin(x),cos(y)") */ void ParserBase::Eval(std::vector *outResult) const { - ValueOrError v = (this->*m_pParseFormula)(); + ValueOrError v = BuildAndExecuteRPN(); if (v.has_error()) { outResult->push_back(std::move(v)); return; @@ -1484,6 +1475,6 @@ int ParserBase::GetNumResults() const { return m_nFinalResultIdx; } \return The evaluation result \throw ParseException if no Formula is set or in case of any other error related to the formula. */ -ValueOrError ParserBase::Eval() const { return (this->*m_pParseFormula)(); } +ValueOrError ParserBase::Eval() const { return BuildAndExecuteRPN(); } } // namespace mu From ab95f940485e5725bb91c37e4a1c32910e500161 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 09:34:53 -0800 Subject: [PATCH 48/62] [muparser] Remove m_nIfElseCounter instance variable No idea why this isn't just a local. --- muparser-2.2.5/include/muParserBase.h | 3 --- muparser-2.2.5/src/muParserBase.cpp | 11 +++++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index c8eae0d79..cbc3d0546 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -270,9 +270,6 @@ class ParserBase { string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens string_type m_sInfixOprtChars; ///< Charset for infix operator tokens - mutable int - m_nIfElseCounter; ///< Internal counter for keeping track of nested if-then-else clauses - // items merely used for caching state information mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 495fc6e43..e0dc8ff0d 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -79,7 +79,6 @@ ParserBase::ParserBase() m_sNameChars(), m_sOprtChars(), m_sInfixOprtChars(), - m_nIfElseCounter(0), m_vStackBuffer(), m_nFinalResultIdx(0) { InitTokenReader(); @@ -144,7 +143,6 @@ void ParserBase::ReInit() const { m_vStringBuf.clear(); m_vRPN.clear(); m_pTokenReader->ReInit(); - m_nIfElseCounter = 0; } //--------------------------------------------------------------------------- @@ -1003,6 +1001,7 @@ ValueOrError ParserBase::ExecuteRPN() const { //--------------------------------------------------------------------------- OptionalError ParserBase::CreateRPN() const { if (!m_pTokenReader->GetExpr().length()) return ParserError(ecUNEXPECTED_EOF, 0); + int ifElseCounter = 0; ParserStack stOpt, stVal; ParserStack stArgCount; @@ -1044,8 +1043,8 @@ OptionalError ParserBase::CreateRPN() const { } case cmELSE: - m_nIfElseCounter--; - if (m_nIfElseCounter < 0) return Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); + ifElseCounter--; + if (ifElseCounter < 0) return Error(ecMISPLACED_COLON, m_pTokenReader->GetPos()); oerr = ApplyRemainingOprt(stOpt, stVal); if (oerr.has_error()) return oerr.error(); @@ -1111,7 +1110,7 @@ OptionalError ParserBase::CreateRPN() const { // case cmOR: // case cmXOR: case cmIF: - m_nIfElseCounter++; + ifElseCounter++; // fallthrough intentional (no break!) case cmLAND: @@ -1203,7 +1202,7 @@ OptionalError ParserBase::CreateRPN() const { if (ParserBase::g_DbgDumpCmdCode) m_vRPN.AsciiDump(); - if (m_nIfElseCounter > 0) return Error(ecMISSING_ELSE_CLAUSE); + if (ifElseCounter > 0) return Error(ecMISSING_ELSE_CLAUSE); // get the last value (= final result) from the stack assert(stArgCount.size() == 1 && "Expected arg count of 1"); From 3f21fb64de872fba5841c4d1bca4ce6a87717ca1 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 09:43:07 -0800 Subject: [PATCH 49/62] [muparser] Remove additional unused functions --- muparser-2.2.5/include/muParserBase.h | 8 +- muparser-2.2.5/include/muParserDef.h | 3 - muparser-2.2.5/samples/example1/example1.cpp | 1 - muparser-2.2.5/src/muParserBase.cpp | 94 -------------------- 4 files changed, 1 insertion(+), 105 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index cbc3d0546..6aaa1863f 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -130,19 +130,13 @@ class ParserBase { OptionalError DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec = prINFIX); - // Clear user defined variables, constants or functions - void ClearVar(); - void ClearFun(); + // Clear user defined constants or operators. void ClearConst(); - void ClearInfixOprt(); void ClearPostfixOprt(); - void ClearOprt(); void RemoveVar(const string_type &a_strVarName); const varmap_type &GetVar() const; const string_type &GetExpr() const; - const funmap_type &GetFunDef() const; - string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; const char_type **GetOprtDef() const; void DefineNameChars(const char_type *a_szCharset); diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 6f2a7efc6..58cf6c5f9 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -172,9 +172,6 @@ enum ETypeCode { tpVOID = 2 ///< Undefined type. }; -//------------------------------------------------------------------------------ -enum EParserVersionInfo { pviBRIEF, pviFULL }; - //------------------------------------------------------------------------------ /** \brief Parser operator precedence values. */ enum EOprtAssociativity { oaLEFT = 0, oaRIGHT = 1, oaNONE = 2 }; diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index fac5e253c..c4733d1dc 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -149,7 +149,6 @@ void Splash() { << _T(" | Y Y \\| | /| | / __ \\_| | \\/\\___ \\ \\ ___/ | | \\/ \n"); mu::console() << _T(" |__|_| /|____/ |____| (____ /|__| /____ > \\___ >|__| \n"); mu::console() << _T(" \\/ \\/ \\/ \\/ \n"); - mu::console() << _T(" Version ") << Parser().GetVersion(pviFULL) << _T("\n"); mu::console() << _T(" (C) 2015 Ingo Berg\n"); } diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index e0dc8ff0d..c167f2f9f 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -148,51 +148,6 @@ void ParserBase::ReInit() const { //--------------------------------------------------------------------------- void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) {} -//--------------------------------------------------------------------------- -/** \brief Returns the version of muparser. - \param eInfo A flag indicating whether the full version info should be - returned or not. - - Format is as follows: "MAJOR.MINOR (COMPILER_FLAGS)" The COMPILER_FLAGS - are returned only if eInfo==pviFULL. -*/ -string_type ParserBase::GetVersion(EParserVersionInfo eInfo) const { - stringstream_type ss; - - ss << MUP_VERSION; - - if (eInfo == pviFULL) { - ss << _T(" (") << MUP_VERSION_DATE; - ss << std::dec << _T("; ") << sizeof(void *) * 8 << _T("BIT"); - -#ifdef _DEBUG - ss << _T("; DEBUG"); -#else - ss << _T("; RELEASE"); -#endif - -#ifdef _UNICODE - ss << _T("; UNICODE"); -#else -#ifdef _MBCS - ss << _T("; MBCS"); -#else - ss << _T("; ASCII"); -#endif -#endif - -#if defined(MUP_MATH_EXCEPTIONS) - ss << _T("; MATHEXC"); -//#else -// ss << _T("; NO_MATHEXC"); -#endif - - ss << _T(")"); - } - - return ss.str(); -} - //--------------------------------------------------------------------------- /** \brief Add a value parsing function. @@ -542,18 +497,6 @@ EOprtAssociativity ParserBase::GetOprtAssociativity(const token_type &a_Tok) con } } -//--------------------------------------------------------------------------- -/** \brief Return prototypes of all parser functions. - \return #m_FunDef - \sa FunProt - - The return type is a map of the public type #funmap_type containing the prototype - definitions for all numerical parser functions. String functions are not part of - this map. The Prototype definition is encapsulated in objects of the class FunProt - one per parser function each associated with function names via a map construct. -*/ -const funmap_type &ParserBase::GetFunDef() const { return m_FunDef; } - //--------------------------------------------------------------------------- /** \brief Retrieve the formula. */ const string_type &ParserBase::GetExpr() const { return m_pTokenReader->GetExpr(); } @@ -1240,16 +1183,6 @@ ParserError ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type return ParserError(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); } -//------------------------------------------------------------------------------ -/** \brief Clear all user defined variables. - - Resets the parser to string parsing mode by calling #ReInit. -*/ -void ParserBase::ClearVar() { - m_VarDef.clear(); - ReInit(); -} - //------------------------------------------------------------------------------ /** \brief Remove a variable from internal storage. @@ -1263,15 +1196,6 @@ void ParserBase::RemoveVar(const string_type &a_strVarName) { } } -//------------------------------------------------------------------------------ -/** \brief Clear all functions. - \post Resets the parser to string parsing mode. -*/ -void ParserBase::ClearFun() { - m_FunDef.clear(); - ReInit(); -} - //------------------------------------------------------------------------------ /** \brief Clear all user defined constants. @@ -1293,24 +1217,6 @@ void ParserBase::ClearPostfixOprt() { ReInit(); } -//------------------------------------------------------------------------------ -/** \brief Clear all user defined binary operators. - \post Resets the parser to string parsing mode. -*/ -void ParserBase::ClearOprt() { - m_OprtDef.clear(); - ReInit(); -} - -//------------------------------------------------------------------------------ -/** \brief Clear the user defined Prefix operators. - \post Resets the parser to string parser mode. -*/ -void ParserBase::ClearInfixOprt() { - m_InfixOprtDef.clear(); - ReInit(); -} - //--------------------------------------------------------------------------- /** \brief Enable the dumping of bytecode and stack content on the console. \param bDumpCmd Flag to enable dumping of the current bytecode to the console. From e675a66504538079cec95a94fa1220cee5a4161c Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 09:45:36 -0800 Subject: [PATCH 50/62] [muparser] Remove some unused "optimized" opcodes --- muparser-2.2.5/include/muParserDef.h | 7 ------- muparser-2.2.5/src/muParserBase.cpp | 19 ------------------- muparser-2.2.5/src/muParserBytecode.cpp | 22 ---------------------- 3 files changed, 48 deletions(-) diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 58cf6c5f9..d4938fcd7 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -145,13 +145,6 @@ enum ECmdCode { cmVAR = 20, ///< variable item cmVAL = 21, ///< value item - // For optimization purposes - cmVARPOW2, - cmVARPOW3, - cmVARPOW4, - cmVARMUL, - cmPOW2, - // operators and functions cmFUNC, ///< Code for a generic function item cmFUNC_STR, ///< Code for a function with a string parameter diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index c167f2f9f..32f909bf3 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -868,25 +868,6 @@ ValueOrError ParserBase::ExecuteRPN() const { Stack[++sidx] = pTok->Val.data2; continue; - case cmVARPOW2: - buf = *(pTok->Val.ptr); - Stack[++sidx] = buf * buf; - continue; - - case cmVARPOW3: - buf = *(pTok->Val.ptr); - Stack[++sidx] = buf * buf * buf; - continue; - - case cmVARPOW4: - buf = *(pTok->Val.ptr); - Stack[++sidx] = buf * buf * buf * buf; - continue; - - case cmVARMUL: - Stack[++sidx] = *(pTok->Val.ptr) * pTok->Val.data + pTok->Val.data2; - continue; - // Next is treatment of numeric functions case cmFUNC: { int iArgCount = pTok->Fun.argc; diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index f2dd8c0c5..e0f3bd896 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -255,28 +255,6 @@ void ParserByteCode::AsciiDump() { mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); break; - case cmVARPOW2: - mu::console() << _T("VARPOW2 \t"); - mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); - break; - - case cmVARPOW3: - mu::console() << _T("VARPOW3 \t"); - mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); - break; - - case cmVARPOW4: - mu::console() << _T("VARPOW4 \t"); - mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]\n"); - break; - - case cmVARMUL: - mu::console() << _T("VARMUL \t"); - mu::console() << _T("[ADDR: 0x") << std::hex << m_vRPN[i].Val.ptr << _T("]"); - mu::console() << _T(" * [") << m_vRPN[i].Val.data << _T("]"); - mu::console() << _T(" + [") << m_vRPN[i].Val.data2 << _T("]\n"); - break; - case cmFUNC: mu::console() << _T("CALL\t"); mu::console() << _T("[ARG:") << std::dec << m_vRPN[i].Fun.argc << _T("]"); From 732b32c8b4eb745f585b5df53b02fce2586d8972 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 10:33:59 -0800 Subject: [PATCH 51/62] [muparser] Clean up constructors and other miscellaneous --- muparser-2.2.5/include/muParserBase.h | 19 +++++--------- muparser-2.2.5/include/muParserBytecode.h | 5 +--- muparser-2.2.5/src/muParserBase.cpp | 32 +---------------------- muparser-2.2.5/src/muParserBytecode.cpp | 17 +++++++----- 4 files changed, 18 insertions(+), 55 deletions(-) diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index 6aaa1863f..b65d92a83 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -67,15 +67,9 @@ class ParserBase { */ typedef ValueOrError (ParserBase::*ParseFunction)() const; - /** \brief Type used for storing an array of values. */ - typedef std::vector valbuf_type; - /** \brief Type for a vector of strings. */ typedef std::vector stringbuf_type; - /** \brief Typedef for the token reader. */ - typedef ParserTokenReader token_reader_type; - /** \brief Type used for parser tokens. */ typedef ParserToken token_type; @@ -199,7 +193,6 @@ class ParserBase { }; private: - void InitTokenReader(); void ReInit() const; OptionalError AddCallback(const string_type &a_strName, const ParserCallback &a_Callback, @@ -247,8 +240,7 @@ class ParserBase { m_vStringBuf; ///< String buffer, used for storing string function arguments stringbuf_type m_vStringVarBuf; - std::auto_ptr - m_pTokenReader; ///< Managed pointer to the token reader object. + std::unique_ptr m_pTokenReader; funmap_type m_FunDef; ///< Map of function names and pointers. funmap_type m_PostOprtDef; ///< Postfix operator callbacks @@ -258,16 +250,17 @@ class ParserBase { strmap_type m_StrVarDef; ///< user defined string constants varmap_type m_VarDef; ///< user defind variables. - bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off + bool m_bBuiltInOp = + true; ///< Flag that can be used for switching built in operators on and off string_type m_sNameChars; ///< Charset for names string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens string_type m_sInfixOprtChars; ///< Charset for infix operator tokens // items merely used for caching state information - mutable valbuf_type - m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine - mutable int m_nFinalResultIdx; + /// This is merely a buffer used for the stack in the cmd parsing routine + mutable std::vector m_vStackBuffer; + mutable int m_nFinalResultIdx = 0; }; } // namespace mu diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index 9d4ffc2c3..951282646 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -83,9 +83,6 @@ class ParserByteCode { /** \brief Token type for internal use only. */ typedef ParserToken token_type; - /** \brief Token vector for storing the RPN. */ - typedef std::vector rpn_type; - /** \brief Position in the Calculation array. */ unsigned m_iStackPos; @@ -93,7 +90,7 @@ class ParserByteCode { std::size_t m_iMaxStackSize; /** \brief The actual rpn storage. */ - rpn_type m_vRPN; + std::vector m_vRPN; public: ParserByteCode(); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 32f909bf3..dbdbc8963 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -64,25 +64,7 @@ const char_type *ParserBase::c_DefaultOprt[] = { \param a_szFormula the formula to interpret. \throw ParserException if a_szFormula is null. */ -ParserBase::ParserBase() - : m_vRPN(), - m_vStringBuf(), - m_pTokenReader(), - m_FunDef(), - m_PostOprtDef(), - m_InfixOprtDef(), - m_OprtDef(), - m_ConstDef(), - m_StrVarDef(), - m_VarDef(), - m_bBuiltInOp(true), - m_sNameChars(), - m_sOprtChars(), - m_sInfixOprtChars(), - m_vStackBuffer(), - m_nFinalResultIdx(0) { - InitTokenReader(); -} +ParserBase::ParserBase() : m_pTokenReader(new ParserTokenReader(this)) {} //--------------------------------------------------------------------------- ParserBase::~ParserBase() = default; @@ -124,16 +106,6 @@ void ParserBase::ResetLocale() { SetArgSep(','); } -//--------------------------------------------------------------------------- -/** \brief Initialize the token reader. - - Create new token reader object and submit pointers to function, operator, - constant and variable definitions. - - \post m_pTokenReader.get()!=0 -*/ -void ParserBase::InitTokenReader() { m_pTokenReader.reset(new token_reader_type(this)); } - //--------------------------------------------------------------------------- /** \brief Reset parser to string parsing mode and clear internal buffers. @@ -539,7 +511,6 @@ OptionalError ParserBase::ApplyStrFunc(const token_type &a_FunTok, return Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString()); } - // string functions won't be optimized m_vRPN.AddStrFun(pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx()); return {}; } @@ -766,7 +737,6 @@ ValueOrError ParserBase::InvokeFunction(generic_fun_type func, const value_type ValueOrError ParserBase::ExecuteRPN() const { assert(! m_vRPN.empty() && "Missing RPN"); value_type *Stack = &m_vStackBuffer[0]; - value_type buf; int sidx(0); for (const SToken *pTok = m_vRPN.GetBase(); pTok->Cmd != cmEND; ++pTok) { switch (pTok->Cmd) { diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index e0f3bd896..48883469f 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -179,27 +179,30 @@ void ParserByteCode::Finalize() { SToken tok; tok.Cmd = cmEND; m_vRPN.push_back(tok); - rpn_type(m_vRPN).swap(m_vRPN); // shrink bytecode vector to fit + m_vRPN.shrink_to_fit(); // Determine the if-then-else jump offsets ParserStack stIf, stElse; - int idx; for (int i = 0; i < (int)m_vRPN.size(); ++i) { switch (m_vRPN[i].Cmd) { case cmIF: stIf.push_back(i); break; - case cmELSE: + case cmELSE: { + int idx = stIf.back(); + stIf.pop_back(); + m_vRPN[idx].Oprt.offset = i - idx; stElse.push_back(i); - idx = stIf.pop(); - m_vRPN[idx].Oprt.offset = i - idx; break; + } - case cmENDIF: - idx = stElse.pop(); + case cmENDIF: { + int idx = stElse.back(); + stElse.pop_back(); m_vRPN[idx].Oprt.offset = i - idx; break; + } default: break; From fd60a7cff7c7a27b19184eb1d4ecfd9739643aba Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 10:49:29 -0800 Subject: [PATCH 52/62] [muparser] Remove unused fields from SToken --- muparser-2.2.5/include/muParserBytecode.h | 2 -- muparser-2.2.5/src/muParserBase.cpp | 2 +- muparser-2.2.5/src/muParserBytecode.cpp | 9 +++------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index 951282646..b0639fc21 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -40,14 +40,12 @@ namespace mu { struct SToken { ECmdCode Cmd; - int StackPos; union { struct // SValData { value_type *ptr; value_type data; - value_type data2; } Val; struct // SFunData diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index dbdbc8963..e49ce3bae 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -835,7 +835,7 @@ ValueOrError ParserBase::ExecuteRPN() const { Stack[++sidx] = *(pTok->Val.ptr); continue; case cmVAL: - Stack[++sidx] = pTok->Val.data2; + Stack[++sidx] = pTok->Val.data; continue; // Next is treatment of numeric functions diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index 48883469f..06efd6add 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -51,12 +51,10 @@ void ParserByteCode::AddVar(value_type *a_pVar) { ++m_iStackPos; m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); - // optimization does not apply SToken tok; tok.Cmd = cmVAR; tok.Val.ptr = a_pVar; - tok.Val.data = 1; - tok.Val.data2 = 0; + tok.Val.data = 0; m_vRPN.push_back(tok); } @@ -80,8 +78,7 @@ void ParserByteCode::AddVal(value_type a_fVal) { SToken tok; tok.Cmd = cmVAL; tok.Val.ptr = NULL; - tok.Val.data = 0; - tok.Val.data2 = a_fVal; + tok.Val.data = a_fVal; m_vRPN.push_back(tok); } @@ -250,7 +247,7 @@ void ParserByteCode::AsciiDump() { switch (m_vRPN[i].Cmd) { case cmVAL: mu::console() << _T("VAL \t"); - mu::console() << _T("[") << m_vRPN[i].Val.data2 << _T("]\n"); + mu::console() << _T("[") << m_vRPN[i].Val.data << _T("]\n"); break; case cmVAR: From 364f58fcfaaca793ba4fc957e231660b893a2163 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 10:51:24 -0800 Subject: [PATCH 53/62] Remove some deleted muparser headers from Xcode build --- fish.xcodeproj/project.pbxproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index 6837f768a..8957dab79 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -804,11 +804,8 @@ D06821FD1F51498700040321 /* muParserBytecode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserBytecode.h; sourceTree = ""; }; D06821FE1F51498700040321 /* muParserCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserCallback.h; sourceTree = ""; }; D06821FF1F51498700040321 /* muParserDef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserDef.h; sourceTree = ""; }; - D06822001F51498700040321 /* muParserDLL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserDLL.h; sourceTree = ""; }; - D06822011F51498700040321 /* muParserError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserError.h; sourceTree = ""; }; D06822021F51498700040321 /* muParserFixes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserFixes.h; sourceTree = ""; }; D06822031F51498700040321 /* muParserInt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserInt.h; sourceTree = ""; }; - D06822041F51498700040321 /* muParserStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserStack.h; sourceTree = ""; }; D06822051F51498700040321 /* muParserTemplateMagic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserTemplateMagic.h; sourceTree = ""; }; D06822061F51498700040321 /* muParserTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserTest.h; sourceTree = ""; }; D06822071F51498700040321 /* muParserToken.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserToken.h; sourceTree = ""; }; @@ -1055,11 +1052,8 @@ D06821FD1F51498700040321 /* muParserBytecode.h */, D06821FE1F51498700040321 /* muParserCallback.h */, D06821FF1F51498700040321 /* muParserDef.h */, - D06822001F51498700040321 /* muParserDLL.h */, - D06822011F51498700040321 /* muParserError.h */, D06822021F51498700040321 /* muParserFixes.h */, D06822031F51498700040321 /* muParserInt.h */, - D06822041F51498700040321 /* muParserStack.h */, D06822051F51498700040321 /* muParserTemplateMagic.h */, D06822061F51498700040321 /* muParserTest.h */, D06822071F51498700040321 /* muParserToken.h */, From f0de6e0852d2d7d87d79f4382922670e17cac755 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 10:56:07 -0800 Subject: [PATCH 54/62] [muparser] Remove struct TypeInfo The STL's facilities are totally sufficient here. --- .../include/muParserTemplateMagic.h | 53 ------------------- muparser-2.2.5/samples/example1/example1.cpp | 2 +- muparser-2.2.5/src/muParser.cpp | 3 +- 3 files changed, 3 insertions(+), 55 deletions(-) diff --git a/muparser-2.2.5/include/muParserTemplateMagic.h b/muparser-2.2.5/include/muParserTemplateMagic.h index 69a54c8d2..f87290f2a 100644 --- a/muparser-2.2.5/include/muParserTemplateMagic.h +++ b/muparser-2.2.5/include/muParserTemplateMagic.h @@ -4,59 +4,6 @@ #include namespace mu { -//----------------------------------------------------------------------------------------------- -// -// Compile time type detection -// -//----------------------------------------------------------------------------------------------- - -/** \brief A class singling out integer types at compile time using - template meta programming. -*/ -template -struct TypeInfo { - static bool IsInteger() { return false; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; - -template <> -struct TypeInfo { - static bool IsInteger() { return true; } -}; //----------------------------------------------------------------------------------------------- // diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index c4733d1dc..398b7f980 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -158,7 +158,7 @@ ValueOrError SelfTest() { mu::console() << _T( "Running test suite:\n\n"); // Skip the self test if the value type is set to an integer type. - if (mu::TypeInfo::IsInteger()) { + if (std::numeric_limits::is_integer) { mu::console() << _T( " Test skipped: integer data type are not compatible with the unit test!\n\n"); } else { diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 6a8a93219..35f909412 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -29,6 +29,7 @@ //--- Standard includes ------------------------------------------------------------------------ #include #include +#include #include /** \brief Pi (what else?). */ @@ -237,7 +238,7 @@ static void assertNoError(OptionalError oerr) { //--------------------------------------------------------------------------- /** \brief Initialize the default functions. */ void Parser::InitFun() { - if (mu::TypeInfo::IsInteger()) { + if (std::numeric_limits::is_integer) { // When setting MUP_BASETYPE to an integer type // Place functions for dealing with integer values here // ... From 1f456c71f703baf7b1b0c30f7b2062ff42ccc662 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:11:04 -0800 Subject: [PATCH 55/62] [muparser] Remove MathImpl This layer of indirection is silly. --- .../include/muParserTemplateMagic.h | 40 ---------------- muparser-2.2.5/src/muParser.cpp | 47 ++++++++++--------- muparser-2.2.5/src/muParserBase.cpp | 2 +- 3 files changed, 25 insertions(+), 64 deletions(-) diff --git a/muparser-2.2.5/include/muParserTemplateMagic.h b/muparser-2.2.5/include/muParserTemplateMagic.h index f87290f2a..3cd7e3a63 100644 --- a/muparser-2.2.5/include/muParserTemplateMagic.h +++ b/muparser-2.2.5/include/muParserTemplateMagic.h @@ -3,44 +3,4 @@ #include -namespace mu { - -//----------------------------------------------------------------------------------------------- -// -// Standard math functions with dummy overload for integer types -// -//----------------------------------------------------------------------------------------------- - -/** \brief A template class for providing wrappers for essential math functions. - - This template is spezialized for several types in order to provide a unified interface - for parser internal math function calls regardless of the data type. -*/ -template -struct MathImpl { - static T Sin(T v) { return sin(v); } - static T Cos(T v) { return cos(v); } - static T Tan(T v) { return tan(v); } - static T ASin(T v) { return asin(v); } - static T ACos(T v) { return acos(v); } - static T ATan(T v) { return atan(v); } - static T ATan2(T v1, T v2) { return atan2(v1, v2); } - static T Sinh(T v) { return sinh(v); } - static T Cosh(T v) { return cosh(v); } - static T Tanh(T v) { return tanh(v); } - static T ASinh(T v) { return log(v + sqrt(v * v + 1)); } - static T ACosh(T v) { return log(v + sqrt(v * v - 1)); } - static T ATanh(T v) { return ((T)0.5 * log((1 + v) / (1 - v))); } - static T Log(T v) { return log(v); } - static T Log2(T v) { return log(v) / log((T)2); } // Logarithm base 2 - static T Log10(T v) { return log10(v); } // Logarithm base 10 - static T Exp(T v) { return exp(v); } - static T Abs(T v) { return (v >= 0) ? v : -v; } - static T Sqrt(T v) { return sqrt(v); } - static T Rint(T v) { return floor(v + (T)0.5); } - static T Sign(T v) { return (T)((v < 0) ? -1 : (v > 0) ? 1 : 0); } - static T Pow(T v1, T v2) { return std::pow(v1, v2); } -}; -} - #endif diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 35f909412..356f48414 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -49,21 +49,19 @@ namespace mu { //--------------------------------------------------------------------------- // Trigonometric function -ValueOrError Parser::Sin(value_type v) { return MathImpl::Sin(v); } -ValueOrError Parser::Cos(value_type v) { return MathImpl::Cos(v); } -ValueOrError Parser::Tan(value_type v) { return MathImpl::Tan(v); } -ValueOrError Parser::ASin(value_type v) { return MathImpl::ASin(v); } -ValueOrError Parser::ACos(value_type v) { return MathImpl::ACos(v); } -ValueOrError Parser::ATan(value_type v) { return MathImpl::ATan(v); } -ValueOrError Parser::ATan2(value_type v1, value_type v2) { - return MathImpl::ATan2(v1, v2); -} -ValueOrError Parser::Sinh(value_type v) { return MathImpl::Sinh(v); } -ValueOrError Parser::Cosh(value_type v) { return MathImpl::Cosh(v); } -ValueOrError Parser::Tanh(value_type v) { return MathImpl::Tanh(v); } -ValueOrError Parser::ASinh(value_type v) { return MathImpl::ASinh(v); } -ValueOrError Parser::ACosh(value_type v) { return MathImpl::ACosh(v); } -ValueOrError Parser::ATanh(value_type v) { return MathImpl::ATanh(v); } +ValueOrError Parser::Sin(value_type v) { return std::sin(v); } +ValueOrError Parser::Cos(value_type v) { return std::cos(v); } +ValueOrError Parser::Tan(value_type v) { return std::tan(v); } +ValueOrError Parser::ASin(value_type v) { return std::asin(v); } +ValueOrError Parser::ACos(value_type v) { return std::acos(v); } +ValueOrError Parser::ATan(value_type v) { return std::atan(v); } +ValueOrError Parser::ATan2(value_type v1, value_type v2) { return std::atan2(v1, v2); } +ValueOrError Parser::Sinh(value_type v) { return std::sinh(v); } +ValueOrError Parser::Cosh(value_type v) { return std::cosh(v); } +ValueOrError Parser::Tanh(value_type v) { return std::tanh(v); } +ValueOrError Parser::ASinh(value_type v) { return std::asinh(v); } +ValueOrError Parser::ACosh(value_type v) { return std::acosh(v); } +ValueOrError Parser::ATanh(value_type v) { return std::atanh(v); } //--------------------------------------------------------------------------- // Logarithm functions @@ -74,7 +72,7 @@ ValueOrError Parser::Log2(value_type v) { if (v <= 0) return ParserError(ecDOMAIN_ERROR, _T("Log2")); #endif - return MathImpl::Log2(v); + return std::log2(v); } // Logarithm base 10 @@ -83,7 +81,7 @@ ValueOrError Parser::Log10(value_type v) { if (v <= 0) return ParserError(ecDOMAIN_ERROR, _T("Log10")); #endif - return MathImpl::Log10(v); + return std::log10(v); } // Logarithm base e (natural logarithm) @@ -92,22 +90,25 @@ ValueOrError Parser::Ln(value_type v) { if (v <= 0) return ParserError(ecDOMAIN_ERROR, _T("Ln")); #endif - return MathImpl::Log(v); + return std::log(v); } //--------------------------------------------------------------------------- // misc -ValueOrError Parser::Exp(value_type v) { return MathImpl::Exp(v); } -ValueOrError Parser::Abs(value_type v) { return MathImpl::Abs(v); } +ValueOrError Parser::Exp(value_type v) { return std::exp(v); } +ValueOrError Parser::Abs(value_type v) { return std::abs(v); } ValueOrError Parser::Sqrt(value_type v) { #ifdef MUP_MATH_EXCEPTIONS if (v < 0) return ParserError(ecDOMAIN_ERROR, _T("sqrt")); #endif - return MathImpl::Sqrt(v); + return std::sqrt(v); +} +ValueOrError Parser::Rint(value_type v) { return std::floor(v + 0.5); } +ValueOrError Parser::Sign(value_type v) { + // return 1, 0, -1 according to whether v is positive, zero, negative. + return (v > 0) - (v < 0); } -ValueOrError Parser::Rint(value_type v) { return MathImpl::Rint(v); } -ValueOrError Parser::Sign(value_type v) { return MathImpl::Sign(v); } //--------------------------------------------------------------------------- /** \brief Callback for the unary minus operator. diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index e49ce3bae..0d40c722a 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -788,7 +788,7 @@ ValueOrError ParserBase::ExecuteRPN() const { case cmPOW: --sidx; - Stack[sidx] = MathImpl::Pow(Stack[sidx], Stack[1 + sidx]); + Stack[sidx] = std::pow(Stack[sidx], Stack[1 + sidx]); continue; case cmLAND: From 8b0d2ff64170bdb8534b39f4995b71b11d4cb2bd Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:14:46 -0800 Subject: [PATCH 56/62] [muparser] Remove muParserTemplateMagic.h This header is now empty --- fish.xcodeproj/project.pbxproj | 2 -- muparser-2.2.5/Makefile.in | 1 - muparser-2.2.5/include/muParser.h | 1 - muparser-2.2.5/include/muParserTemplateMagic.h | 6 ------ muparser-2.2.5/src/muParser.cpp | 1 - muparser-2.2.5/src/muParserBase.cpp | 1 - muparser-2.2.5/src/muParserBytecode.cpp | 1 - 7 files changed, 13 deletions(-) delete mode 100644 muparser-2.2.5/include/muParserTemplateMagic.h diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index 8957dab79..14ed2a76e 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -806,7 +806,6 @@ D06821FF1F51498700040321 /* muParserDef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserDef.h; sourceTree = ""; }; D06822021F51498700040321 /* muParserFixes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserFixes.h; sourceTree = ""; }; D06822031F51498700040321 /* muParserInt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserInt.h; sourceTree = ""; }; - D06822051F51498700040321 /* muParserTemplateMagic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserTemplateMagic.h; sourceTree = ""; }; D06822061F51498700040321 /* muParserTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserTest.h; sourceTree = ""; }; D06822071F51498700040321 /* muParserToken.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserToken.h; sourceTree = ""; }; D06822081F51498700040321 /* muParserTokenReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserTokenReader.h; sourceTree = ""; }; @@ -1054,7 +1053,6 @@ D06821FF1F51498700040321 /* muParserDef.h */, D06822021F51498700040321 /* muParserFixes.h */, D06822031F51498700040321 /* muParserInt.h */, - D06822051F51498700040321 /* muParserTemplateMagic.h */, D06822061F51498700040321 /* muParserTest.h */, D06822071F51498700040321 /* muParserToken.h */, D06822081F51498700040321 /* muParserTokenReader.h */, diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index a5aaf692c..3cda158f4 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -61,7 +61,6 @@ MUPARSER_LIB_HEADERS = \ include/muParserDef.h \ include/muParserFixes.h \ include/muParserInt.h \ - include/muParserTemplateMagic.h \ include/muParserTest.h \ include/muParserToken.h \ include/muParserTokenReader.h diff --git a/muparser-2.2.5/include/muParser.h b/muparser-2.2.5/include/muParser.h index 3b8ad7120..af2ce2ca9 100644 --- a/muparser-2.2.5/include/muParser.h +++ b/muparser-2.2.5/include/muParser.h @@ -30,7 +30,6 @@ //--- Parser includes -------------------------------------------------------------------------- #include "muParserBase.h" -#include "muParserTemplateMagic.h" /** \file \brief Definition of the standard floating point parser. diff --git a/muparser-2.2.5/include/muParserTemplateMagic.h b/muparser-2.2.5/include/muParserTemplateMagic.h deleted file mode 100644 index 3cd7e3a63..000000000 --- a/muparser-2.2.5/include/muParserTemplateMagic.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MU_PARSER_TEMPLATE_MAGIC_H -#define MU_PARSER_TEMPLATE_MAGIC_H - -#include - -#endif diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 356f48414..3f74324f7 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -24,7 +24,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "muParser.h" -#include "muParserTemplateMagic.h" //--- Standard includes ------------------------------------------------------------------------ #include diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 0d40c722a..8ce9ffe46 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -24,7 +24,6 @@ */ #include "muParserBase.h" -#include "muParserTemplateMagic.h" //--- Standard includes ------------------------------------------------------------------------ #include diff --git a/muparser-2.2.5/src/muParserBytecode.cpp b/muparser-2.2.5/src/muParserBytecode.cpp index 06efd6add..92669acb1 100644 --- a/muparser-2.2.5/src/muParserBytecode.cpp +++ b/muparser-2.2.5/src/muParserBytecode.cpp @@ -33,7 +33,6 @@ #include #include "muParserDef.h" -#include "muParserTemplateMagic.h" #include "muParserToken.h" namespace mu { From e9c106b881b97a5b332692fcc7d6d32fb4effb49 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:18:20 -0800 Subject: [PATCH 57/62] [muparser] Delete ParserByteCode copy and assignment ctors These are not used. --- muparser-2.2.5/include/muParserBytecode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/muparser-2.2.5/include/muParserBytecode.h b/muparser-2.2.5/include/muParserBytecode.h index b0639fc21..1f432e0a9 100644 --- a/muparser-2.2.5/include/muParserBytecode.h +++ b/muparser-2.2.5/include/muParserBytecode.h @@ -92,8 +92,8 @@ class ParserByteCode { public: ParserByteCode(); - ParserByteCode(const ParserByteCode &a_ByteCode) = default; - ParserByteCode &operator=(const ParserByteCode &a_ByteCode) = default; + ParserByteCode(const ParserByteCode &a_ByteCode) = delete; + ParserByteCode &operator=(const ParserByteCode &a_ByteCode) = delete; void AddVar(value_type *a_pVar); void AddVal(value_type a_fVal); From 409173e0f0d19c595ea4dd63cef23681d47daaef Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:28:20 -0800 Subject: [PATCH 58/62] [muparser] Default ParserError's constructors No need to define these explicitly when the defaults will do. --- muparser-2.2.5/include/muParserDef.h | 10 ++++++---- muparser-2.2.5/src/muParserError.cpp | 28 ++-------------------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index d4938fcd7..0c7e023aa 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -312,8 +312,10 @@ class ParserError { const string_type &sFormula = string_type(), int a_iPos = -1); ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type &sTok); ParserError(const char_type *a_szMsg, int a_iPos = -1, const string_type &sTok = string_type()); - ParserError(const ParserError &a_Obj); - ParserError &operator=(const ParserError &a_Obj); + ParserError(ParserError &&) = default; + ParserError &operator=(ParserError &&) = default; + ParserError(const ParserError &a_Obj) = default; + ParserError &operator=(const ParserError &a_Obj) = default; ~ParserError(); void SetFormula(const string_type &a_strFormula); @@ -327,8 +329,8 @@ class ParserError { string_type m_strMsg; ///< The message string string_type m_strFormula; ///< Formula string string_type m_strTok; ///< Token related with the error - int m_iPos; ///< Formula position related to the error - EErrorCodes m_iErrc; ///< Error code + int m_iPos = -1; ///< Formula position related to the error + EErrorCodes m_iErrc = ecUNDEFINED; ///< Error code } MUPARSER_ATTR_WARN_UNUSED_RESULT; // OptionalError is used to optionally encapsulate an error. diff --git a/muparser-2.2.5/src/muParserError.cpp b/muparser-2.2.5/src/muParserError.cpp index 2ccad2399..099ebe825 100644 --- a/muparser-2.2.5/src/muParserError.cpp +++ b/muparser-2.2.5/src/muParserError.cpp @@ -116,16 +116,14 @@ string_type parser_error_for_code(EErrorCodes code) { //--------------------------------------------------------------------------- /** \brief Default constructor. */ -ParserError::ParserError() - : m_strMsg(), m_strFormula(), m_strTok(), m_iPos(-1), m_iErrc(ecUNDEFINED) {} +ParserError::ParserError() {} //------------------------------------------------------------------------------ /** \brief This Constructor is used for internal exceptions only. It does not contain any information but the error code. */ -ParserError::ParserError(EErrorCodes a_iErrc) - : m_strMsg(), m_strFormula(), m_strTok(), m_iPos(-1), m_iErrc(a_iErrc) { +ParserError::ParserError(EErrorCodes a_iErrc) : m_iErrc(a_iErrc) { m_strMsg = parser_error_for_code(m_iErrc); stringstream_type stream; stream << (int)m_iPos; @@ -186,28 +184,6 @@ ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sT ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok); } -//------------------------------------------------------------------------------ -/** \brief Copy constructor. */ -ParserError::ParserError(const ParserError &a_Obj) - : m_strMsg(a_Obj.m_strMsg), - m_strFormula(a_Obj.m_strFormula), - m_strTok(a_Obj.m_strTok), - m_iPos(a_Obj.m_iPos), - m_iErrc(a_Obj.m_iErrc) {} - -//------------------------------------------------------------------------------ -/** \brief Assignment operator. */ -ParserError &ParserError::operator=(const ParserError &a_Obj) { - if (this == &a_Obj) return *this; - - m_strMsg = a_Obj.m_strMsg; - m_strFormula = a_Obj.m_strFormula; - m_strTok = a_Obj.m_strTok; - m_iPos = a_Obj.m_iPos; - m_iErrc = a_Obj.m_iErrc; - return *this; -} - //------------------------------------------------------------------------------ ParserError::~ParserError() {} From e728bf45de04adb1c52c6b925dee743041fc28f6 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:38:55 -0800 Subject: [PATCH 59/62] [muparser] Remove m_strFormula from the ParserError --- muparser-2.2.5/include/muParserDef.h | 4 +- muparser-2.2.5/samples/example1/example1.cpp | 56 -------------------- muparser-2.2.5/src/muParserBase.cpp | 2 +- muparser-2.2.5/src/muParserError.cpp | 19 ++----- muparser-2.2.5/src/muParserTest.cpp | 2 +- 5 files changed, 7 insertions(+), 76 deletions(-) diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 0c7e023aa..126616dc2 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -308,8 +308,7 @@ class ParserError { ParserError(); explicit ParserError(EErrorCodes a_iErrc); explicit ParserError(const string_type &sMsg); - ParserError(EErrorCodes a_iErrc, const string_type &sTok, - const string_type &sFormula = string_type(), int a_iPos = -1); + ParserError(EErrorCodes a_iErrc, const string_type &sTok, int a_iPos = -1); ParserError(EErrorCodes a_iErrc, int a_iPos, const string_type &sTok); ParserError(const char_type *a_szMsg, int a_iPos = -1, const string_type &sTok = string_type()); ParserError(ParserError &&) = default; @@ -327,7 +326,6 @@ class ParserError { private: string_type m_strMsg; ///< The message string - string_type m_strFormula; ///< Formula string string_type m_strTok; ///< Token related with the error int m_iPos = -1; ///< Formula position related to the error EErrorCodes m_iErrc = ecUNDEFINED; ///< Error code diff --git a/muparser-2.2.5/samples/example1/example1.cpp b/muparser-2.2.5/samples/example1/example1.cpp index 398b7f980..3d9332d7a 100644 --- a/muparser-2.2.5/samples/example1/example1.cpp +++ b/muparser-2.2.5/samples/example1/example1.cpp @@ -187,61 +187,6 @@ ValueOrError Help() { return 0; } -//--------------------------------------------------------------------------- -/* -void CheckLocale() -{ - // Local names: - // "C" - the classic C locale - // "de_DE" - not for Windows? - // "en_US" - not for Windows? - // "German_germany" - For MSVC8 - try - { - std::locale loc("German_germany"); - console() << _T("Locale settings:\n"); - console() << _T(" Decimal point: '") << std::use_facet ->(loc).decimal_point() << _T("'\n"); - console() << _T(" Thousands sep: '") << std::use_facet ->(loc).thousands_sep() << _T("'\n"); - console() << _T(" Grouping: '") << std::use_facet >(loc).grouping() -<< _T("'\n"); - console() << _T(" True is named: '") << std::use_facet >(loc).truename() -<< _T("'\n"); - console() << _T(" False is named: '") << std::use_facet >(loc).falsename() -<< _T("'\n"); - console() << _T("-----------------------------------------------------------\n"); - } - catch(...) - { - console() << _T("Locale settings:\n"); - console() << _T(" invalid locale name\n"); - console() << _T("-----------------------------------------------------------\n"); - } -} - -//--------------------------------------------------------------------------- -void CheckDiff() -{ - mu::Parser parser; - value_type x = 1, - v1, - v2, - v3, - eps(pow(std::numeric_limits::epsilon(), 0.2)); - parser.DefineVar(_T("x"), &x); - parser.SetExpr(_T("_e^-x*sin(x)")); - - v1 = parser.Diff(&x, 1), - v2 = parser.Diff(&x, 1, eps); - v3 = cos((value_type)1.0)/exp((value_type)1) - sin((value_type)1.0)/exp((value_type)1); -//-0.110793765307; - mu::console() << parser.GetExpr() << _T("\n"); - mu::console() << _T("v1 = ") << v1 << _T("; v1-v3 = ") << v1-v3 << _T("\n"); - mu::console() << _T("v2 = ") << v2 << _T("; v2-v3 = ") << v2-v3 << _T("\n"); -} -*/ - //--------------------------------------------------------------------------- /** \brief Check for external keywords. */ @@ -371,7 +316,6 @@ void Calc() { mu::console() << _T("\nError:\n"); mu::console() << _T("------\n"); mu::console() << _T("Message: ") << e.GetMsg() << _T("\n"); - mu::console() << _T("Expression: \"") << e.GetExpr() << _T("\"\n"); mu::console() << _T("Token: \"") << e.GetToken() << _T("\"\n"); mu::console() << _T("Position: ") << (int)e.GetPos() << _T("\n"); mu::console() << _T("Errc: ") << std::dec << e.GetCode() << _T("\n"); diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 8ce9ffe46..6d02c6f3c 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1130,7 +1130,7 @@ ValueOrError ParserBase::BuildAndExecuteRPN() const { \param a_strTok [in] The token string representation associated with the error. */ ParserError ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const { - return ParserError(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos); + return ParserError(a_iErrc, a_sTok, a_iPos); } //------------------------------------------------------------------------------ diff --git a/muparser-2.2.5/src/muParserError.cpp b/muparser-2.2.5/src/muParserError.cpp index 099ebe825..f02be129d 100644 --- a/muparser-2.2.5/src/muParserError.cpp +++ b/muparser-2.2.5/src/muParserError.cpp @@ -142,12 +142,10 @@ ParserError::ParserError(const string_type &sMsg) { /** \brief Construct an error object. \param [in] a_iErrc the error code. \param [in] sTok The token string related to this error. - \param [in] sExpr The expression related to the error. \param [in] a_iPos the position in the expression where the error occurred. */ -ParserError::ParserError(EErrorCodes iErrc, const string_type &sTok, const string_type &sExpr, - int iPos) - : m_strMsg(), m_strFormula(sExpr), m_strTok(sTok), m_iPos(iPos), m_iErrc(iErrc) { +ParserError::ParserError(EErrorCodes iErrc, const string_type &sTok, int iPos) + : m_strTok(sTok), m_iPos(iPos), m_iErrc(iErrc) { m_strMsg = parser_error_for_code(m_iErrc); stringstream_type stream; stream << (int)m_iPos; @@ -162,7 +160,7 @@ ParserError::ParserError(EErrorCodes iErrc, const string_type &sTok, const strin \param [in] sTok The token string related to this error. */ ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) - : m_strMsg(), m_strFormula(), m_strTok(sTok), m_iPos(iPos), m_iErrc(iErrc) { + : m_strMsg(), m_strTok(sTok), m_iPos(iPos), m_iErrc(iErrc) { m_strMsg = parser_error_for_code(m_iErrc); stringstream_type stream; stream << (int)m_iPos; @@ -177,7 +175,7 @@ ParserError::ParserError(EErrorCodes iErrc, int iPos, const string_type &sTok) \param [in] sTok The token string related to this error. */ ParserError::ParserError(const char_type *szMsg, int iPos, const string_type &sTok) - : m_strMsg(szMsg), m_strFormula(), m_strTok(sTok), m_iPos(iPos), m_iErrc(ecGENERIC) { + : m_strMsg(szMsg), m_strTok(sTok), m_iPos(iPos), m_iErrc(ecGENERIC) { stringstream_type stream; stream << (int)m_iPos; ReplaceSubString(m_strMsg, _T("$POS$"), stream.str()); @@ -214,20 +212,11 @@ void ParserError::ReplaceSubString(string_type &strSource, const string_type &st /** \brief Reset the erro object. */ void ParserError::Reset() { m_strMsg = _T(""); - m_strFormula = _T(""); m_strTok = _T(""); m_iPos = -1; m_iErrc = ecUNDEFINED; } -//------------------------------------------------------------------------------ -/** \brief Set the expression related to this error. */ -void ParserError::SetFormula(const string_type &a_strFormula) { m_strFormula = a_strFormula; } - -//------------------------------------------------------------------------------ -/** \brief gets the expression related tp this error.*/ -const string_type &ParserError::GetExpr() const { return m_strFormula; } - //------------------------------------------------------------------------------ /** \brief Returns the message string for this error. */ const string_type &ParserError::GetMsg() const { return m_strMsg; } diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 6a05f5981..b1e66577b 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -1202,7 +1202,7 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa } } catch (Parser::exception_type &e) { if (a_fPass) { - mu::console() << _T("\n fail: ") << e.GetExpr() << _T(" : ") << e.GetMsg(); + mu::console() << _T("\n fail: ") << e.GetMsg(); iRet = 1; } } catch (...) { From 886341fdeacc3758584882b9bb43b29b350ef9c5 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:46:29 -0800 Subject: [PATCH 60/62] [muparser] Remove ParserCallback m_bAllowOpti flag muParser can no longer optimize, so this is unused. --- muparser-2.2.5/include/muParserCallback.h | 2 -- muparser-2.2.5/src/muParserCallback.cpp | 10 +--------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/muparser-2.2.5/include/muParserCallback.h b/muparser-2.2.5/include/muParserCallback.h index 5621c6d66..a2cb4039c 100644 --- a/muparser-2.2.5/include/muParserCallback.h +++ b/muparser-2.2.5/include/muParserCallback.h @@ -61,7 +61,6 @@ class ParserCallback final { ParserCallback(); ParserCallback(const ParserCallback& a_Fun); - bool IsOptimizable() const; void* GetAddr() const; ECmdCode GetCode() const; ETypeCode GetType() const; @@ -82,7 +81,6 @@ class ParserCallback final { EOprtAssociativity m_eOprtAsct; ///< Operator associativity; Valid only for binary operators ECmdCode m_iCode; ETypeCode m_iType; - bool m_bAllowOpti; ///< Flag indication optimizeability }; //------------------------------------------------------------------------------ diff --git a/muparser-2.2.5/src/muParserCallback.cpp b/muparser-2.2.5/src/muParserCallback.cpp index 2867f0658..ab06b4c17 100644 --- a/muparser-2.2.5/src/muParserCallback.cpp +++ b/muparser-2.2.5/src/muParserCallback.cpp @@ -128,21 +128,13 @@ ParserCallback::ParserCallback() m_iPri(-1), m_eOprtAsct(oaNONE), m_iCode(cmUNKNOWN), - m_iType(tpVOID), - m_bAllowOpti(0) {} + m_iType(tpVOID) {} //--------------------------------------------------------------------------- /** \brief Copy constructor. */ ParserCallback::ParserCallback(const ParserCallback& ref) = default; -//--------------------------------------------------------------------------- -/** \brief Return tru if the function is conservative. - - Conservative functions return always the same result for the same argument. -*/ -bool ParserCallback::IsOptimizable() const { return m_bAllowOpti; } - //--------------------------------------------------------------------------- /** \brief Get the callback address for the parser function. From 2c317a2585c9c1e03068a26f5a15e61ead6dfd4d Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 11:51:28 -0800 Subject: [PATCH 61/62] [muparser] Remove muParserFixes.h This appears to be random pragmas for ICC only. --- fish.xcodeproj/project.pbxproj | 2 - muparser-2.2.5/Makefile.in | 1 - muparser-2.2.5/include/muParserDef.h | 2 - muparser-2.2.5/include/muParserFixes.h | 60 -------------------------- 4 files changed, 65 deletions(-) delete mode 100644 muparser-2.2.5/include/muParserFixes.h diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj index 14ed2a76e..eb812e451 100644 --- a/fish.xcodeproj/project.pbxproj +++ b/fish.xcodeproj/project.pbxproj @@ -804,7 +804,6 @@ D06821FD1F51498700040321 /* muParserBytecode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserBytecode.h; sourceTree = ""; }; D06821FE1F51498700040321 /* muParserCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserCallback.h; sourceTree = ""; }; D06821FF1F51498700040321 /* muParserDef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserDef.h; sourceTree = ""; }; - D06822021F51498700040321 /* muParserFixes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserFixes.h; sourceTree = ""; }; D06822031F51498700040321 /* muParserInt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserInt.h; sourceTree = ""; }; D06822061F51498700040321 /* muParserTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserTest.h; sourceTree = ""; }; D06822071F51498700040321 /* muParserToken.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = muParserToken.h; sourceTree = ""; }; @@ -1051,7 +1050,6 @@ D06821FD1F51498700040321 /* muParserBytecode.h */, D06821FE1F51498700040321 /* muParserCallback.h */, D06821FF1F51498700040321 /* muParserDef.h */, - D06822021F51498700040321 /* muParserFixes.h */, D06822031F51498700040321 /* muParserInt.h */, D06822061F51498700040321 /* muParserTest.h */, D06822071F51498700040321 /* muParserToken.h */, diff --git a/muparser-2.2.5/Makefile.in b/muparser-2.2.5/Makefile.in index 3cda158f4..712999ac9 100644 --- a/muparser-2.2.5/Makefile.in +++ b/muparser-2.2.5/Makefile.in @@ -59,7 +59,6 @@ MUPARSER_LIB_HEADERS = \ include/muParserBytecode.h \ include/muParserCallback.h \ include/muParserDef.h \ - include/muParserFixes.h \ include/muParserInt.h \ include/muParserTest.h \ include/muParserToken.h \ diff --git a/muparser-2.2.5/include/muParserDef.h b/muparser-2.2.5/include/muParserDef.h index 126616dc2..750c519b1 100644 --- a/muparser-2.2.5/include/muParserDef.h +++ b/muparser-2.2.5/include/muParserDef.h @@ -33,8 +33,6 @@ #include #include -#include "muParserFixes.h" - /** \file \brief This file contains standard definitions used by the parser. */ diff --git a/muparser-2.2.5/include/muParserFixes.h b/muparser-2.2.5/include/muParserFixes.h deleted file mode 100644 index 35bcdd80d..000000000 --- a/muparser-2.2.5/include/muParserFixes.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - __________ - _____ __ __\______ \_____ _______ ______ ____ _______ - / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \ - | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/ - |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__| - \/ \/ \/ \/ - Copyright (C) 2013 Ingo Berg - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, - merge, publish, distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef MU_PARSER_FIXES_H -#define MU_PARSER_FIXES_H - -/** \file - \brief This file contains compatibility fixes for some platforms. -*/ - -// -// Compatibility fixes -// - -//--------------------------------------------------------------------------- -// -// Intel Compiler -// -//--------------------------------------------------------------------------- - -#ifdef __INTEL_COMPILER - -// remark #981: operands are evaluated in unspecified order -// disabled -> completely pointless if the functions do not have side effects -// -#pragma warning(disable : 981) - -// remark #383: value copied to temporary, reference to temporary used -#pragma warning(disable : 383) - -// remark #1572: floating-point equality and inequality comparisons are unreliable -// disabled -> everyone knows it, the parser passes this problem -// deliberately to the user -#pragma warning(disable : 1572) - -#endif - -#endif // include guard From 873ea0f0df31e7b3a1a4839af448e8195048cf12 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 18 Dec 2017 12:02:47 -0800 Subject: [PATCH 62/62] [muparser] Remove OnDetectVar and Diff These are unused and useless. --- muparser-2.2.5/include/muParser.h | 3 -- muparser-2.2.5/include/muParserBase.h | 2 - muparser-2.2.5/src/muParser.cpp | 61 ---------------------- muparser-2.2.5/src/muParserBase.cpp | 3 -- muparser-2.2.5/src/muParserTokenReader.cpp | 2 - 5 files changed, 71 deletions(-) diff --git a/muparser-2.2.5/include/muParser.h b/muparser-2.2.5/include/muParser.h index af2ce2ca9..a4a6135f7 100644 --- a/muparser-2.2.5/include/muParser.h +++ b/muparser-2.2.5/include/muParser.h @@ -54,9 +54,6 @@ namespace mu { virtual void InitFun(); virtual void InitConst(); virtual void InitOprt(); - virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - - ValueOrError Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon = 0) const; protected: // Trigonometric functions diff --git a/muparser-2.2.5/include/muParserBase.h b/muparser-2.2.5/include/muParserBase.h index b65d92a83..31cde1abc 100644 --- a/muparser-2.2.5/include/muParserBase.h +++ b/muparser-2.2.5/include/muParserBase.h @@ -155,8 +155,6 @@ class ParserBase { virtual void InitConst() = 0; virtual void InitOprt() = 0; - virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); - static const char_type *c_DefaultOprt[]; static std::locale s_locale; ///< The locale used by the parser static bool g_DbgDumpCmdCode; diff --git a/muparser-2.2.5/src/muParser.cpp b/muparser-2.2.5/src/muParser.cpp index 3f74324f7..b0b845e3f 100644 --- a/muparser-2.2.5/src/muParser.cpp +++ b/muparser-2.2.5/src/muParser.cpp @@ -302,65 +302,4 @@ void Parser::InitOprt() { assertNoError(DefineInfixOprt(_T("+"), UnaryPlus)); } -//--------------------------------------------------------------------------- -void Parser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) { - // this is just sample code to illustrate modifying variable names on the fly. - // I'm not sure anyone really needs such a feature... - /* - - - string sVar(pExpr->begin()+nStart, pExpr->begin()+nEnd); - string sRepl = std::string("_") + sVar + "_"; - - int nOrigVarEnd = nEnd; - cout << "variable detected!\n"; - cout << " Expr: " << *pExpr << "\n"; - cout << " Start: " << nStart << "\n"; - cout << " End: " << nEnd << "\n"; - cout << " Var: \"" << sVar << "\"\n"; - cout << " Repl: \"" << sRepl << "\"\n"; - nEnd = nStart + sRepl.length(); - cout << " End: " << nEnd << "\n"; - pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl); - cout << " New expr: " << *pExpr << "\n"; - */ -} - -//--------------------------------------------------------------------------- -/** \brief Numerically differentiate with regard to a variable. - \param [in] a_Var Pointer to the differentiation variable. - \param [in] a_fPos Position at which the differentiation should take place. - \param [in] a_fEpsilon Epsilon used for the numerical differentiation. - - Numerical differentiation uses a 5 point operator yielding a 4th order - formula. The default value for epsilon is 0.00074 which is - numeric_limits::epsilon() ^ (1/5) as suggested in the muparser - forum: - - http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 -*/ -ValueOrError Parser::Diff(value_type *a_Var, value_type a_fPos, value_type a_fEpsilon) const { - value_type fRes(0), fBuf(*a_Var), fEpsilon(a_fEpsilon); - ValueOrError f[4] = {0, 0, 0, 0}; - - // Backwards compatible calculation of epsilon in case the user doesn't provide - // his own epsilon - if (fEpsilon == 0) fEpsilon = (a_fPos == 0) ? (value_type)1e-10 : (value_type)1e-7 * a_fPos; - - *a_Var = a_fPos + 2 * fEpsilon; - f[0] = Eval(); - *a_Var = a_fPos + 1 * fEpsilon; - f[1] = Eval(); - *a_Var = a_fPos - 1 * fEpsilon; - f[2] = Eval(); - *a_Var = a_fPos - 2 * fEpsilon; - f[3] = Eval(); - *a_Var = fBuf; // restore variable - - for (ValueOrError &v : f) { - if (!v) return std::move(v); - } - fRes = (-*f[0] + 8 * *f[1] - 8 * *f[2] + *f[3]) / (12 * fEpsilon); - return fRes; -} } // namespace mu diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index 6d02c6f3c..69857e9d9 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -116,9 +116,6 @@ void ParserBase::ReInit() const { m_pTokenReader->ReInit(); } -//--------------------------------------------------------------------------- -void ParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) {} - //--------------------------------------------------------------------------- /** \brief Add a value parsing function. diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 2dff4aed2..13090e5fc 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -615,8 +615,6 @@ bool ParserTokenReader::IsVarTok(token_type &a_Tok) { if (m_iSynFlags & noVAR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok); - m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); - m_iPos = iEnd; a_Tok.SetVar(item->second, strTok); m_UsedVar[item->first] = item->second; // Add variable to used-var-list