Use Qt math function.
--HG-- branch : feature
This commit is contained in:
parent
59c7405b88
commit
21c38b446d
|
@ -21,7 +21,8 @@
|
||||||
******************************************************************************************************/
|
******************************************************************************************************/
|
||||||
|
|
||||||
#include "qmuparser.h"
|
#include "qmuparser.h"
|
||||||
#include "qmuparsertemplatemagic.h"
|
#include <QtMath>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
//--- Standard includes ------------------------------------------------------------------------
|
//--- Standard includes ------------------------------------------------------------------------
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -40,28 +41,17 @@ using namespace std;
|
||||||
\brief Implementation of the standard floating point QmuParser.
|
\brief Implementation of the standard floating point QmuParser.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Namespace for mathematical applications. */
|
/** \brief Namespace for mathematical applications. */
|
||||||
namespace qmu
|
namespace qmu
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Trigonometric function
|
// Trigonometric function
|
||||||
qreal QmuParser::Sin(qreal v) { return MathImpl<qreal>::Sin(v); }
|
qreal QmuParser::Sinh(qreal v) { return sinh(v); }
|
||||||
qreal QmuParser::Cos(qreal v) { return MathImpl<qreal>::Cos(v); }
|
qreal QmuParser::Cosh(qreal v) { return cosh(v); }
|
||||||
qreal QmuParser::Tan(qreal v) { return MathImpl<qreal>::Tan(v); }
|
qreal QmuParser::Tanh(qreal v) { return tanh(v); }
|
||||||
qreal QmuParser::ASin(qreal v) { return MathImpl<qreal>::ASin(v); }
|
qreal QmuParser::ASinh(qreal v) { return log(v + qSqrt(v * v + 1)); }
|
||||||
qreal QmuParser::ACos(qreal v) { return MathImpl<qreal>::ACos(v); }
|
qreal QmuParser::ACosh(qreal v) { return log(v + qSqrt(v * v - 1)); }
|
||||||
qreal QmuParser::ATan(qreal v) { return MathImpl<qreal>::ATan(v); }
|
qreal QmuParser::ATanh(qreal v) { return ((qreal)0.5 * log((1 + v) / (1 - v))); }
|
||||||
qreal QmuParser::ATan2(qreal v1, qreal v2) { return MathImpl<qreal>::ATan2(v1, v2); }
|
|
||||||
qreal QmuParser::Sinh(qreal v) { return MathImpl<qreal>::Sinh(v); }
|
|
||||||
qreal QmuParser::Cosh(qreal v) { return MathImpl<qreal>::Cosh(v); }
|
|
||||||
qreal QmuParser::Tanh(qreal v) { return MathImpl<qreal>::Tanh(v); }
|
|
||||||
qreal QmuParser::ASinh(qreal v) { return MathImpl<qreal>::ASinh(v); }
|
|
||||||
qreal QmuParser::ACosh(qreal v) { return MathImpl<qreal>::ACosh(v); }
|
|
||||||
qreal QmuParser::ATanh(qreal v) { return MathImpl<qreal>::ATanh(v); }
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Logarithm functions
|
// Logarithm functions
|
||||||
|
@ -74,7 +64,7 @@ namespace qmu
|
||||||
throw QmuParserError(ecDOMAIN_ERROR, "Log2");
|
throw QmuParserError(ecDOMAIN_ERROR, "Log2");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return MathImpl<qreal>::Log2(v);
|
return log(v)/log((qreal)2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logarithm base 10
|
// Logarithm base 10
|
||||||
|
@ -85,35 +75,14 @@ namespace qmu
|
||||||
throw QmuParserError(ecDOMAIN_ERROR, "Log10");
|
throw QmuParserError(ecDOMAIN_ERROR, "Log10");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return MathImpl<qreal>::Log10(v);
|
return log10(v);
|
||||||
}
|
|
||||||
|
|
||||||
// Logarithm base e (natural logarithm)
|
|
||||||
qreal QmuParser::Ln(qreal v)
|
|
||||||
{
|
|
||||||
#ifdef MUP_MATH_EXCEPTIONS
|
|
||||||
if (v<=0)
|
|
||||||
throw QmuParserError(ecDOMAIN_ERROR, "Ln");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return MathImpl<qreal>::Log(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// misc
|
// misc
|
||||||
qreal QmuParser::Exp(qreal v) { return MathImpl<qreal>::Exp(v); }
|
qreal QmuParser::Abs(qreal v) { return (v>=0) ? v : -v; }
|
||||||
qreal QmuParser::Abs(qreal v) { return MathImpl<qreal>::Abs(v); }
|
qreal QmuParser::Rint(qreal v) { return qFloor(v + (qreal)0.5); }
|
||||||
qreal QmuParser::Sqrt(qreal v)
|
qreal QmuParser::Sign(qreal v) { return (qreal)((v<0) ? -1 : (v>0) ? 1 : 0); }
|
||||||
{
|
|
||||||
#ifdef MUP_MATH_EXCEPTIONS
|
|
||||||
if (v<0)
|
|
||||||
throw QmuParserError(ecDOMAIN_ERROR, "sqrt");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return MathImpl<qreal>::Sqrt(v);
|
|
||||||
}
|
|
||||||
qreal QmuParser::Rint(qreal v) { return MathImpl<qreal>::Rint(v); }
|
|
||||||
qreal QmuParser::Sign(qreal v) { return MathImpl<qreal>::Sign(v); }
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
/** \brief Callback for the unary minus operator.
|
/** \brief Callback for the unary minus operator.
|
||||||
|
@ -156,39 +125,45 @@ namespace qmu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
/** \brief Callback for determining the minimum value out of a vector.
|
/** \brief Callback for determining the minimum value out of a vector.
|
||||||
\param [in] a_afArg Vector with the function arguments
|
\param [in] a_afArg Vector with the function arguments
|
||||||
\param [in] a_iArgc The size of a_afArg
|
\param [in] a_iArgc The size of a_afArg
|
||||||
*/
|
*/
|
||||||
qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
|
qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
|
||||||
{
|
{
|
||||||
if (!a_iArgc)
|
if (!a_iArgc)
|
||||||
|
{
|
||||||
throw exception_type("too few arguments for function min.");
|
throw exception_type("too few arguments for function min.");
|
||||||
|
}
|
||||||
|
|
||||||
qreal fRes=a_afArg[0];
|
qreal fRes=a_afArg[0];
|
||||||
for (int i=0; i<a_iArgc; ++i)
|
for (int i=0; i<a_iArgc; ++i)
|
||||||
fRes = std::min(fRes, a_afArg[i]);
|
{
|
||||||
|
fRes = qMin(fRes, a_afArg[i]);
|
||||||
return fRes;
|
|
||||||
}
|
}
|
||||||
|
return fRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
//---------------------------------------------------------------------------
|
/** \brief Callback for determining the maximum value out of a vector.
|
||||||
/** \brief Callback for determining the maximum value out of a vector.
|
|
||||||
\param [in] a_afArg Vector with the function arguments
|
\param [in] a_afArg Vector with the function arguments
|
||||||
\param [in] a_iArgc The size of a_afArg
|
\param [in] a_iArgc The size of a_afArg
|
||||||
*/
|
*/
|
||||||
qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
|
qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
|
||||||
{
|
{
|
||||||
if (!a_iArgc)
|
if (!a_iArgc)
|
||||||
|
{
|
||||||
throw exception_type("too few arguments for function min.");
|
throw exception_type("too few arguments for function min.");
|
||||||
|
}
|
||||||
|
|
||||||
qreal fRes=a_afArg[0];
|
qreal fRes=a_afArg[0];
|
||||||
for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);
|
for (int i=0; i<a_iArgc; ++i)
|
||||||
|
{
|
||||||
return fRes;
|
fRes = qMax(fRes, a_afArg[i]);
|
||||||
}
|
}
|
||||||
|
return fRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -247,29 +222,19 @@ namespace qmu
|
||||||
DefineInfixOprtChars( "/+-*^?<>=#!$%&|~'_" );
|
DefineInfixOprtChars( "/+-*^?<>=#!$%&|~'_" );
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
/** \brief Initialize the default functions. */
|
/** \brief Initialize the default functions. */
|
||||||
void QmuParser::InitFun()
|
void QmuParser::InitFun()
|
||||||
{
|
{
|
||||||
if (qmu::TypeInfo<qreal>::IsInteger())
|
|
||||||
{
|
|
||||||
// When setting MUP_BASETYPE to an integer type
|
|
||||||
// Place functions for dealing with integer values here
|
|
||||||
// ...
|
|
||||||
// ...
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// trigonometric functions
|
// trigonometric functions
|
||||||
DefineFun("sin", Sin);
|
DefineFun("sin", qSin);
|
||||||
DefineFun("cos", Cos);
|
DefineFun("cos", qCos);
|
||||||
DefineFun("tan", Tan);
|
DefineFun("tan", qTan);
|
||||||
// arcus functions
|
// arcus functions
|
||||||
DefineFun("asin", ASin);
|
DefineFun("asin", qAsin);
|
||||||
DefineFun("acos", ACos);
|
DefineFun("acos", qAcos);
|
||||||
DefineFun("atan", ATan);
|
DefineFun("atan", qAtan);
|
||||||
DefineFun("atan2", ATan2);
|
DefineFun("atan2", qAtan2);
|
||||||
// hyperbolic functions
|
// hyperbolic functions
|
||||||
DefineFun("sinh", Sinh);
|
DefineFun("sinh", Sinh);
|
||||||
DefineFun("cosh", Cosh);
|
DefineFun("cosh", Cosh);
|
||||||
|
@ -282,10 +247,10 @@ namespace qmu
|
||||||
DefineFun("log2", Log2);
|
DefineFun("log2", Log2);
|
||||||
DefineFun("log10", Log10);
|
DefineFun("log10", Log10);
|
||||||
DefineFun("log", Log10);
|
DefineFun("log", Log10);
|
||||||
DefineFun("ln", Ln);
|
DefineFun("ln", qLn);
|
||||||
// misc
|
// misc
|
||||||
DefineFun("exp", Exp);
|
DefineFun("exp", qExp);
|
||||||
DefineFun("sqrt", Sqrt);
|
DefineFun("sqrt", qSqrt);
|
||||||
DefineFun("sign", Sign);
|
DefineFun("sign", Sign);
|
||||||
DefineFun("rint", Rint);
|
DefineFun("rint", Rint);
|
||||||
DefineFun("abs", Abs);
|
DefineFun("abs", Abs);
|
||||||
|
@ -294,8 +259,7 @@ namespace qmu
|
||||||
DefineFun("avg", Avg);
|
DefineFun("avg", Avg);
|
||||||
DefineFun("min", Min);
|
DefineFun("min", Min);
|
||||||
DefineFun("max", Max);
|
DefineFun("max", Max);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
/** \brief Initialize constants.
|
/** \brief Initialize constants.
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
//--- Parser includes --------------------------------------------------------------------------
|
//--- Parser includes --------------------------------------------------------------------------
|
||||||
#include "qmuparserbase.h"
|
#include "qmuparserbase.h"
|
||||||
#include "qmuparsertemplatemagic.h"
|
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
\brief Definition of the standard floating point parser.
|
\brief Definition of the standard floating point parser.
|
||||||
|
@ -61,18 +60,8 @@ public:
|
||||||
|
|
||||||
qreal Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon = 0) const;
|
qreal Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon = 0) const;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Trigonometric functions
|
// Trigonometric functions
|
||||||
static qreal Sin(qreal);
|
|
||||||
static qreal Cos(qreal);
|
|
||||||
static qreal Tan(qreal);
|
|
||||||
static qreal Tan2(qreal, qreal);
|
static qreal Tan2(qreal, qreal);
|
||||||
// arcus functions
|
|
||||||
static qreal ASin(qreal);
|
|
||||||
static qreal ACos(qreal);
|
|
||||||
static qreal ATan(qreal);
|
|
||||||
static qreal ATan2(qreal, qreal);
|
|
||||||
|
|
||||||
// hyperbolic functions
|
// hyperbolic functions
|
||||||
static qreal Sinh(qreal);
|
static qreal Sinh(qreal);
|
||||||
static qreal Cosh(qreal);
|
static qreal Cosh(qreal);
|
||||||
|
@ -84,18 +73,13 @@ protected:
|
||||||
// Logarithm functions
|
// Logarithm functions
|
||||||
static qreal Log2(qreal); // Logarithm Base 2
|
static qreal Log2(qreal); // Logarithm Base 2
|
||||||
static qreal Log10(qreal); // Logarithm Base 10
|
static qreal Log10(qreal); // Logarithm Base 10
|
||||||
static qreal Ln(qreal); // Logarithm Base e (natural logarithm)
|
|
||||||
// misc
|
// misc
|
||||||
static qreal Exp(qreal);
|
|
||||||
static qreal Abs(qreal);
|
static qreal Abs(qreal);
|
||||||
static qreal Sqrt(qreal);
|
|
||||||
static qreal Rint(qreal);
|
static qreal Rint(qreal);
|
||||||
static qreal Sign(qreal);
|
static qreal Sign(qreal);
|
||||||
|
|
||||||
// Prefix operators
|
// Prefix operators
|
||||||
// !!! Unary Minus is a MUST if you want to use negative signs !!!
|
// !!! Unary Minus is a MUST if you want to use negative signs !!!
|
||||||
static qreal UnaryMinus(qreal);
|
static qreal UnaryMinus(qreal);
|
||||||
|
|
||||||
// Functions with variable number of arguments
|
// Functions with variable number of arguments
|
||||||
static qreal Sum(const qreal*, int); // sum
|
static qreal Sum(const qreal*, int); // sum
|
||||||
static qreal Avg(const qreal*, int); // mean value
|
static qreal Avg(const qreal*, int); // mean value
|
||||||
|
|
|
@ -52,7 +52,6 @@ HEADERS += \
|
||||||
qmuparserbytecode.h \
|
qmuparserbytecode.h \
|
||||||
qmuparserbase.h \
|
qmuparserbase.h \
|
||||||
qmuparsertest.h \
|
qmuparsertest.h \
|
||||||
qmuparsertemplatemagic.h \
|
|
||||||
qmuparserint.h \
|
qmuparserint.h \
|
||||||
stable.h
|
stable.h
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
******************************************************************************************************/
|
******************************************************************************************************/
|
||||||
|
|
||||||
#include "qmuparserbase.h"
|
#include "qmuparserbase.h"
|
||||||
#include "qmuparsertemplatemagic.h"
|
|
||||||
|
|
||||||
//--- Standard includes ------------------------------------------------------------------------
|
//--- Standard includes ------------------------------------------------------------------------
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -266,11 +265,11 @@ namespace qmu
|
||||||
|
|
||||||
stringstream_type ss;
|
stringstream_type ss;
|
||||||
|
|
||||||
ss << MUP_VERSION;
|
ss << QMUP_VERSION;
|
||||||
|
|
||||||
if (eInfo==pviFULL)
|
if (eInfo==pviFULL)
|
||||||
{
|
{
|
||||||
ss << " (" << MUP_VERSION_DATE;
|
ss << " (" << QMUP_VERSION_DATE;
|
||||||
ss << std::dec << "; " << sizeof(void*)*8 << "BIT";
|
ss << std::dec << "; " << sizeof(void*)*8 << "BIT";
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
@ -1030,7 +1029,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case cmPOW:
|
case cmPOW:
|
||||||
--sidx; Stack[sidx] = MathImpl<qreal>::Pow(Stack[sidx], Stack[1+sidx]);
|
--sidx; Stack[sidx] = std::pow(Stack[sidx], Stack[1+sidx]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue;
|
case cmLAND: --sidx; Stack[sidx] = Stack[sidx] && Stack[sidx+1]; continue;
|
||||||
|
@ -1607,22 +1606,22 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
|
||||||
QStack<token_type> stOprt(a_stOprt),
|
QStack<token_type> stOprt(a_stOprt),
|
||||||
stVal(a_stVal);
|
stVal(a_stVal);
|
||||||
|
|
||||||
mu::console() << "\nValue stack:\n";
|
qmu::console() << "\nValue stack:\n";
|
||||||
while ( !stVal.empty() )
|
while ( !stVal.empty() )
|
||||||
{
|
{
|
||||||
token_type val = stVal.pop();
|
token_type val = stVal.pop();
|
||||||
if (val.GetType()==tpSTR)
|
if (val.GetType()==tpSTR)
|
||||||
mu::console() << " \"" << val.GetAsString() << "\" ";
|
qmu::console() << " \"" << val.GetAsString() << "\" ";
|
||||||
else
|
else
|
||||||
mu::console() << " " << val.GetVal() << " ";
|
qmu::console() << " " << val.GetVal() << " ";
|
||||||
}
|
}
|
||||||
mu::console() << "\nOperator stack:\n";
|
qmu::console() << "\nOperator stack:\n";
|
||||||
|
|
||||||
while ( !stOprt.empty() )
|
while ( !stOprt.empty() )
|
||||||
{
|
{
|
||||||
if (stOprt.top().GetCode()<=cmASSIGN)
|
if (stOprt.top().GetCode()<=cmASSIGN)
|
||||||
{
|
{
|
||||||
mu::console() << "OPRT_INTRNL \""
|
qmu::console() << "OPRT_INTRNL \""
|
||||||
<< QmuParserBase::c_DefaultOprt[stOprt.top().GetCode()]
|
<< QmuParserBase::c_DefaultOprt[stOprt.top().GetCode()]
|
||||||
<< "\" \n";
|
<< "\" \n";
|
||||||
}
|
}
|
||||||
|
@ -1630,35 +1629,35 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
|
||||||
{
|
{
|
||||||
switch(stOprt.top().GetCode())
|
switch(stOprt.top().GetCode())
|
||||||
{
|
{
|
||||||
case cmVAR: mu::console() << "VAR\n"; break;
|
case cmVAR: qmu::console() << "VAR\n"; break;
|
||||||
case cmVAL: mu::console() << "VAL\n"; break;
|
case cmVAL: qmu::console() << "VAL\n"; break;
|
||||||
case cmFUNC: mu::console() << "FUNC \""
|
case cmFUNC: qmu::console() << "FUNC \""
|
||||||
<< stOprt.top().GetAsString()
|
<< stOprt.top().GetAsString()
|
||||||
<< "\"\n"; break;
|
<< "\"\n"; break;
|
||||||
case cmFUNC_BULK: mu::console() << "FUNC_BULK \""
|
case cmFUNC_BULK: qmu::console() << "FUNC_BULK \""
|
||||||
<< stOprt.top().GetAsString()
|
<< stOprt.top().GetAsString()
|
||||||
<< "\"\n"; break;
|
<< "\"\n"; break;
|
||||||
case cmOPRT_INFIX: mu::console() << "OPRT_INFIX \""
|
case cmOPRT_INFIX: qmu::console() << "OPRT_INFIX \""
|
||||||
<< stOprt.top().GetAsString()
|
<< stOprt.top().GetAsString()
|
||||||
<< "\"\n"; break;
|
<< "\"\n"; break;
|
||||||
case cmOPRT_BIN: mu::console() << "OPRT_BIN \""
|
case cmOPRT_BIN: qmu::console() << "OPRT_BIN \""
|
||||||
<< stOprt.top().GetAsString()
|
<< stOprt.top().GetAsString()
|
||||||
<< "\"\n"; break;
|
<< "\"\n"; break;
|
||||||
case cmFUNC_STR: mu::console() << "FUNC_STR\n"; break;
|
case cmFUNC_STR: qmu::console() << "FUNC_STR\n"; break;
|
||||||
case cmEND: mu::console() << "END\n"; break;
|
case cmEND: qmu::console() << "END\n"; break;
|
||||||
case cmUNKNOWN: mu::console() << "UNKNOWN\n"; break;
|
case cmUNKNOWN: qmu::console() << "UNKNOWN\n"; break;
|
||||||
case cmBO: mu::console() << "BRACKET \"(\"\n"; break;
|
case cmBO: qmu::console() << "BRACKET \"(\"\n"; break;
|
||||||
case cmBC: mu::console() << "BRACKET \")\"\n"; break;
|
case cmBC: qmu::console() << "BRACKET \")\"\n"; break;
|
||||||
case cmIF: mu::console() << "IF\n"; break;
|
case cmIF: qmu::console() << "IF\n"; break;
|
||||||
case cmELSE: mu::console() << "ELSE\n"; break;
|
case cmELSE: qmu::console() << "ELSE\n"; break;
|
||||||
case cmENDIF: mu::console() << "ENDIF\n"; break;
|
case cmENDIF: qmu::console() << "ENDIF\n"; break;
|
||||||
default: mu::console() << stOprt.top().GetCode() << " "; break;
|
default: qmu::console() << stOprt.top().GetCode() << " "; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stOprt.pop();
|
stOprt.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mu::console() << dec << endl;
|
qmu::console() << dec << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
//--- Parser includes --------------------------------------------------------------------------
|
//--- Parser includes --------------------------------------------------------------------------
|
||||||
#include "qmuparserdef.h"
|
#include "qmuparserdef.h"
|
||||||
#include "qmuparserstack.h"
|
|
||||||
#include "qmuparsertokenreader.h"
|
#include "qmuparsertokenreader.h"
|
||||||
#include "qmuparserbytecode.h"
|
#include "qmuparserbytecode.h"
|
||||||
#include "qmuparsererror.h"
|
#include "qmuparsererror.h"
|
||||||
|
@ -121,7 +120,7 @@ private:
|
||||||
bool HasBuiltInOprt() const;
|
bool HasBuiltInOprt() const;
|
||||||
void AddValIdent(identfun_type a_pCallback);
|
void AddValIdent(identfun_type a_pCallback);
|
||||||
|
|
||||||
/** \fn void mu::QParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
|
/** \fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
|
||||||
\brief Define a parser function without arguments.
|
\brief Define a parser function without arguments.
|
||||||
\param a_strName Name of the function
|
\param a_strName Name of the function
|
||||||
\param a_pFun Pointer to the callback function
|
\param a_pFun Pointer to the callback function
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
#include "qmuparserdef.h"
|
#include "qmuparserdef.h"
|
||||||
#include "qmuparsererror.h"
|
#include "qmuparsererror.h"
|
||||||
#include "qmuparsertoken.h"
|
#include "qmuparsertoken.h"
|
||||||
#include "qmuparserstack.h"
|
|
||||||
#include "qmuparsertemplatemagic.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace qmu
|
namespace qmu
|
||||||
|
@ -166,7 +164,7 @@ namespace qmu
|
||||||
m_vRPN.pop_back();
|
m_vRPN.pop_back();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmPOW: x = MathImpl<qreal>::Pow(x, y);
|
case cmPOW: x = std::pow(x, y);
|
||||||
m_vRPN.pop_back();
|
m_vRPN.pop_back();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -495,89 +493,89 @@ namespace qmu
|
||||||
{
|
{
|
||||||
if (!m_vRPN.size())
|
if (!m_vRPN.size())
|
||||||
{
|
{
|
||||||
mu::console() << "No bytecode available\n";
|
qmu::console() << "No bytecode available\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mu::console() << "Number of RPN tokens:" << (int)m_vRPN.size() << "\n";
|
qmu::console() << "Number of RPN tokens:" << (int)m_vRPN.size() << "\n";
|
||||||
for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)
|
for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)
|
||||||
{
|
{
|
||||||
mu::console() << std::dec << i << " : \t";
|
qmu::console() << std::dec << i << " : \t";
|
||||||
switch (m_vRPN[i].Cmd)
|
switch (m_vRPN[i].Cmd)
|
||||||
{
|
{
|
||||||
case cmVAL: mu::console() << "VAL \t";
|
case cmVAL: qmu::console() << "VAL \t";
|
||||||
mu::console() << "[" << m_vRPN[i].Val.data2 << "]\n";
|
qmu::console() << "[" << m_vRPN[i].Val.data2 << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmVAR: mu::console() << "VAR \t";
|
case cmVAR: qmu::console() << "VAR \t";
|
||||||
mu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmVARPOW2: mu::console() << "VARPOW2 \t";
|
case cmVARPOW2: qmu::console() << "VARPOW2 \t";
|
||||||
mu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmVARPOW3: mu::console() << "VARPOW3 \t";
|
case cmVARPOW3: qmu::console() << "VARPOW3 \t";
|
||||||
mu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmVARPOW4: mu::console() << "VARPOW4 \t";
|
case cmVARPOW4: qmu::console() << "VARPOW4 \t";
|
||||||
mu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmVARMUL: mu::console() << "VARMUL \t";
|
case cmVARMUL: qmu::console() << "VARMUL \t";
|
||||||
mu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]";
|
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]";
|
||||||
mu::console() << " * [" << m_vRPN[i].Val.data << "]";
|
qmu::console() << " * [" << m_vRPN[i].Val.data << "]";
|
||||||
mu::console() << " + [" << m_vRPN[i].Val.data2 << "]\n";
|
qmu::console() << " + [" << m_vRPN[i].Val.data2 << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmFUNC: mu::console() << "CALL\t";
|
case cmFUNC: qmu::console() << "CALL\t";
|
||||||
mu::console() << "[ARG:" << std::dec << m_vRPN[i].Fun.argc << "]";
|
qmu::console() << "[ARG:" << std::dec << m_vRPN[i].Fun.argc << "]";
|
||||||
mu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Fun.ptr << "]";
|
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Fun.ptr << "]";
|
||||||
mu::console() << "\n";
|
qmu::console() << "\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmFUNC_STR:
|
case cmFUNC_STR:
|
||||||
mu::console() << "CALL STRFUNC\t";
|
qmu::console() << "CALL STRFUNC\t";
|
||||||
mu::console() << "[ARG:" << std::dec << m_vRPN[i].Fun.argc << "]";
|
qmu::console() << "[ARG:" << std::dec << m_vRPN[i].Fun.argc << "]";
|
||||||
mu::console() << "[IDX:" << std::dec << m_vRPN[i].Fun.idx << "]";
|
qmu::console() << "[IDX:" << std::dec << m_vRPN[i].Fun.idx << "]";
|
||||||
mu::console() << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]\n";
|
qmu::console() << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmLT: mu::console() << "LT\n"; break;
|
case cmLT: qmu::console() << "LT\n"; break;
|
||||||
case cmGT: mu::console() << "GT\n"; break;
|
case cmGT: qmu::console() << "GT\n"; break;
|
||||||
case cmLE: mu::console() << "LE\n"; break;
|
case cmLE: qmu::console() << "LE\n"; break;
|
||||||
case cmGE: mu::console() << "GE\n"; break;
|
case cmGE: qmu::console() << "GE\n"; break;
|
||||||
case cmEQ: mu::console() << "EQ\n"; break;
|
case cmEQ: qmu::console() << "EQ\n"; break;
|
||||||
case cmNEQ: mu::console() << "NEQ\n"; break;
|
case cmNEQ: qmu::console() << "NEQ\n"; break;
|
||||||
case cmADD: mu::console() << "ADD\n"; break;
|
case cmADD: qmu::console() << "ADD\n"; break;
|
||||||
case cmLAND: mu::console() << "&&\n"; break;
|
case cmLAND: qmu::console() << "&&\n"; break;
|
||||||
case cmLOR: mu::console() << "||\n"; break;
|
case cmLOR: qmu::console() << "||\n"; break;
|
||||||
case cmSUB: mu::console() << "SUB\n"; break;
|
case cmSUB: qmu::console() << "SUB\n"; break;
|
||||||
case cmMUL: mu::console() << "MUL\n"; break;
|
case cmMUL: qmu::console() << "MUL\n"; break;
|
||||||
case cmDIV: mu::console() << "DIV\n"; break;
|
case cmDIV: qmu::console() << "DIV\n"; break;
|
||||||
case cmPOW: mu::console() << "POW\n"; break;
|
case cmPOW: qmu::console() << "POW\n"; break;
|
||||||
|
|
||||||
case cmIF: mu::console() << "IF\t";
|
case cmIF: qmu::console() << "IF\t";
|
||||||
mu::console() << "[OFFSET:" << std::dec << m_vRPN[i].Oprt.offset << "]\n";
|
qmu::console() << "[OFFSET:" << std::dec << m_vRPN[i].Oprt.offset << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmELSE: mu::console() << "ELSE\t";
|
case cmELSE: qmu::console() << "ELSE\t";
|
||||||
mu::console() << "[OFFSET:" << std::dec << m_vRPN[i].Oprt.offset << "]\n";
|
qmu::console() << "[OFFSET:" << std::dec << m_vRPN[i].Oprt.offset << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cmENDIF: mu::console() << "ENDIF\n"; break;
|
case cmENDIF: qmu::console() << "ENDIF\n"; break;
|
||||||
|
|
||||||
case cmASSIGN:
|
case cmASSIGN:
|
||||||
mu::console() << "ASSIGN\t";
|
qmu::console() << "ASSIGN\t";
|
||||||
mu::console() << "[ADDR: 0x" << m_vRPN[i].Oprt.ptr << "]\n";
|
qmu::console() << "[ADDR: 0x" << m_vRPN[i].Oprt.ptr << "]\n";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: mu::console() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
|
default: qmu::console() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
|
||||||
break;
|
break;
|
||||||
} // switch cmdCode
|
} // switch cmdCode
|
||||||
} // while bytecode
|
} // while bytecode
|
||||||
|
|
||||||
mu::console() << "END" << std::endl;
|
qmu::console() << "END" << std::endl;
|
||||||
}
|
}
|
||||||
} // namespace qmu
|
} // namespace qmu
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
#ifndef QMUPARSERTEMPLATEMAGIC_H
|
|
||||||
#define QMUPARSERTEMPLATEMAGIC_H
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include "muParserError.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace qmu
|
|
||||||
{
|
|
||||||
//-----------------------------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Compile time type detection
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** \brief A class singling out integer types at compile time using
|
|
||||||
template meta programming.
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
struct TypeInfo
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<char>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<short>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<int>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<long>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<unsigned char>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<unsigned short>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<unsigned int>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct TypeInfo<unsigned long>
|
|
||||||
{
|
|
||||||
static bool IsInteger() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// 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<typename T>
|
|
||||||
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); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create (mostly) dummy math function definitions for integer types. They are mostly
|
|
||||||
// empty since they are not applicable for integer values.
|
|
||||||
#define MAKE_MATH_DUMMY(TYPE) \
|
|
||||||
template<> \
|
|
||||||
struct MathImpl<TYPE> \
|
|
||||||
{ \
|
|
||||||
static TYPE Sin(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Cos(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Tan(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ASin(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ACos(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ATan(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ATan2(TYPE, TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Sinh(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Cosh(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Tanh(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ASinh(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ACosh(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE ATanh(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Log(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Log2(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Log10(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Exp(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Abs(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Sqrt(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Rint(TYPE) { throw QmuParserError("unimplemented function."); } \
|
|
||||||
static TYPE Sign(TYPE v) { return (TYPE)((v<0) ? -1 : (v>0) ? 1 : 0); } \
|
|
||||||
static TYPE Pow(TYPE v1, TYPE v2) { return (TYPE)std::pow((double)v1, (double)v2); } \
|
|
||||||
};
|
|
||||||
|
|
||||||
MAKE_MATH_DUMMY(char)
|
|
||||||
MAKE_MATH_DUMMY(short)
|
|
||||||
MAKE_MATH_DUMMY(int)
|
|
||||||
MAKE_MATH_DUMMY(long)
|
|
||||||
|
|
||||||
#undef MAKE_MATH_DUMMY
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -88,7 +88,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestInterface()
|
int QmuParserTester::TestInterface()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing member functions...";
|
qmu::console() << "testing member functions...";
|
||||||
|
|
||||||
// Test RemoveVar
|
// Test RemoveVar
|
||||||
qreal afVal[3] = {1,2,3};
|
qreal afVal[3] = {1,2,3};
|
||||||
|
@ -119,9 +119,9 @@ namespace qmu
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestStrArg()
|
int QmuParserTester::TestStrArg()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing string arguments...";
|
qmu::console() << "testing string arguments...";
|
||||||
|
|
||||||
iStat += EqnTest("valueof(\"\")", 123, true); // empty string arguments caused a crash
|
iStat += EqnTest("valueof(\"\")", 123, true); // empty string arguments caused a crash
|
||||||
iStat += EqnTest("valueof(\"aaa\")+valueof(\"bbb\") ", 246, true);
|
iStat += EqnTest("valueof(\"aaa\")+valueof(\"bbb\") ", 246, true);
|
||||||
|
@ -144,9 +144,9 @@ namespace qmu
|
||||||
iStat += EqnTest("strfun3(\"99\",1,2)", 102, true);
|
iStat += EqnTest("strfun3(\"99\",1,2)", 102, true);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestBinOprt()
|
int QmuParserTester::TestBinOprt()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing binary operators...";
|
qmu::console() << "testing binary operators...";
|
||||||
|
|
||||||
// built in operators
|
// built in operators
|
||||||
// xor operator
|
// xor operator
|
||||||
|
@ -288,9 +288,9 @@ namespace qmu
|
||||||
|
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +302,7 @@ namespace qmu
|
||||||
int iStat= 0,
|
int iStat= 0,
|
||||||
iErr = 0;
|
iErr = 0;
|
||||||
|
|
||||||
mu::console() << "testing name restriction enforcement...";
|
qmu::console() << "testing name restriction enforcement...";
|
||||||
|
|
||||||
QmuParser p;
|
QmuParser p;
|
||||||
|
|
||||||
|
@ -397,9 +397,9 @@ namespace qmu
|
||||||
#undef PARSER_THROWCHECK
|
#undef PARSER_THROWCHECK
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestSyntax()
|
int QmuParserTester::TestSyntax()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing syntax engine...";
|
qmu::console() << "testing syntax engine...";
|
||||||
|
|
||||||
iStat += ThrowTest("1,", ecUNEXPECTED_EOF); // incomplete hex definition
|
iStat += ThrowTest("1,", ecUNEXPECTED_EOF); // incomplete hex definition
|
||||||
iStat += ThrowTest("a,", ecUNEXPECTED_EOF); // incomplete hex definition
|
iStat += ThrowTest("a,", ecUNEXPECTED_EOF); // incomplete hex definition
|
||||||
|
@ -446,9 +446,9 @@ namespace qmu
|
||||||
iStat += EqnTest("sin()", 0, false); // unexpected closing bracket
|
iStat += EqnTest("sin()", 0, false); // unexpected closing bracket
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -457,7 +457,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestVarConst()
|
int QmuParserTester::TestVarConst()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing variable/constant detection...";
|
qmu::console() << "testing variable/constant detection...";
|
||||||
|
|
||||||
// Test if the result changes when a variable changes
|
// Test if the result changes when a variable changes
|
||||||
iStat += EqnTestWithVarChange( "a", 1, 1, 2, 2 );
|
iStat += EqnTestWithVarChange( "a", 1, 1, 2, 2 );
|
||||||
|
@ -504,7 +504,7 @@ namespace qmu
|
||||||
// Test lookup of defined variables
|
// Test lookup of defined variables
|
||||||
// 4 used variables
|
// 4 used variables
|
||||||
p.SetExpr( "a+b+c+d" );
|
p.SetExpr( "a+b+c+d" );
|
||||||
mu::varmap_type UsedVar = p.GetUsedVar();
|
qmu::varmap_type UsedVar = p.GetUsedVar();
|
||||||
int iCount = (int)UsedVar.size();
|
int iCount = (int)UsedVar.size();
|
||||||
if (iCount!=4)
|
if (iCount!=4)
|
||||||
throw false;
|
throw false;
|
||||||
|
@ -514,7 +514,7 @@ namespace qmu
|
||||||
if (p.GetVar().size()!=5)
|
if (p.GetVar().size()!=5)
|
||||||
throw false;
|
throw false;
|
||||||
|
|
||||||
mu::varmap_type::const_iterator item = UsedVar.begin();
|
qmu::varmap_type::const_iterator item = UsedVar.begin();
|
||||||
for (idx=0; item!=UsedVar.end(); ++item)
|
for (idx=0; item!=UsedVar.end(); ++item)
|
||||||
{
|
{
|
||||||
if (&vVarVal[idx++]!=item->second)
|
if (&vVarVal[idx++]!=item->second)
|
||||||
|
@ -555,9 +555,9 @@ namespace qmu
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestMultiArg()
|
int QmuParserTester::TestMultiArg()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing multiarg functions...";
|
qmu::console() << "testing multiarg functions...";
|
||||||
|
|
||||||
// Compound expressions
|
// Compound expressions
|
||||||
iStat += EqnTest( "1,2,3", 3, true);
|
iStat += EqnTest( "1,2,3", 3, true);
|
||||||
|
@ -649,9 +649,9 @@ namespace qmu
|
||||||
iStat += EqnTest( "sum(,1,2)", 0, false);
|
iStat += EqnTest( "sum(,1,2)", 0, false);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -661,7 +661,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestInfixOprt()
|
int QmuParserTester::TestInfixOprt()
|
||||||
{
|
{
|
||||||
int iStat(0);
|
int iStat(0);
|
||||||
mu::console() << "testing infix operators...";
|
qmu::console() << "testing infix operators...";
|
||||||
|
|
||||||
iStat += EqnTest( "-1", -1, true);
|
iStat += EqnTest( "-1", -1, true);
|
||||||
iStat += EqnTest( "-(-1)", 1, true);
|
iStat += EqnTest( "-(-1)", 1, true);
|
||||||
|
@ -714,9 +714,9 @@ namespace qmu
|
||||||
iStat += EqnTest( "~~ 123", 123+2, true);
|
iStat += EqnTest( "~~ 123", 123+2, true);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -726,7 +726,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestPostFix()
|
int QmuParserTester::TestPostFix()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing postfix operators...";
|
qmu::console() << "testing postfix operators...";
|
||||||
|
|
||||||
// application
|
// application
|
||||||
iStat += EqnTest( "3{m}+5", 5.003, true);
|
iStat += EqnTest( "3{m}+5", 5.003, true);
|
||||||
|
@ -766,9 +766,9 @@ namespace qmu
|
||||||
iStat += ThrowTest( "multi*1.0", ecUNASSIGNABLE_TOKEN);
|
iStat += ThrowTest( "multi*1.0", ecUNASSIGNABLE_TOKEN);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -777,7 +777,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestExpression()
|
int QmuParserTester::TestExpression()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing expression samples...";
|
qmu::console() << "testing expression samples...";
|
||||||
|
|
||||||
qreal b = 2;
|
qreal b = 2;
|
||||||
|
|
||||||
|
@ -846,9 +846,9 @@ namespace qmu
|
||||||
iStat += EqnTest( "1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12", -7995810.09926, true);
|
iStat += EqnTest( "1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12", -7995810.09926, true);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -859,7 +859,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestIfThenElse()
|
int QmuParserTester::TestIfThenElse()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing if-then-else operator...";
|
qmu::console() << "testing if-then-else operator...";
|
||||||
|
|
||||||
// Test error detection
|
// Test error detection
|
||||||
iStat += ThrowTest(":3", ecUNEXPECTED_CONDITIONAL);
|
iStat += ThrowTest(":3", ecUNEXPECTED_CONDITIONAL);
|
||||||
|
@ -954,9 +954,9 @@ namespace qmu
|
||||||
iStat += EqnTest("a=0?5:b=1?3:4, b", 3, true);
|
iStat += EqnTest("a=0?5:b=1?3:4, b", 3, true);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -965,7 +965,7 @@ namespace qmu
|
||||||
int QmuParserTester::TestException()
|
int QmuParserTester::TestException()
|
||||||
{
|
{
|
||||||
int iStat = 0;
|
int iStat = 0;
|
||||||
mu::console() << "testing error codes...";
|
qmu::console() << "testing error codes...";
|
||||||
|
|
||||||
iStat += ThrowTest("3+", ecUNEXPECTED_EOF);
|
iStat += ThrowTest("3+", ecUNEXPECTED_EOF);
|
||||||
iStat += ThrowTest("3+)", ecUNEXPECTED_PARENS);
|
iStat += ThrowTest("3+)", ecUNEXPECTED_PARENS);
|
||||||
|
@ -1048,9 +1048,9 @@ namespace qmu
|
||||||
iStat += ThrowTest( "a=\"tttt\"", ecOPRT_TYPE_CONFLICT);
|
iStat += ThrowTest( "a=\"tttt\"", ecOPRT_TYPE_CONFLICT);
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
mu::console() << "passed" << endl;
|
qmu::console() << "passed" << endl;
|
||||||
else
|
else
|
||||||
mu::console() << "\n failed with " << iStat << " errors" << endl;
|
qmu::console() << "\n failed with " << iStat << " errors" << endl;
|
||||||
|
|
||||||
return iStat;
|
return iStat;
|
||||||
}
|
}
|
||||||
|
@ -1073,28 +1073,28 @@ namespace qmu
|
||||||
}
|
}
|
||||||
catch(QmuParser::exception_type &e)
|
catch(QmuParser::exception_type &e)
|
||||||
{
|
{
|
||||||
mu::console() << "\n" << e.GetMsg() << endl;
|
qmu::console() << "\n" << e.GetMsg() << endl;
|
||||||
mu::console() << e.GetToken() << endl;
|
qmu::console() << e.GetToken() << endl;
|
||||||
Abort();
|
Abort();
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
mu::console() << e.what() << endl;
|
qmu::console() << e.what() << endl;
|
||||||
Abort();
|
Abort();
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mu::console() << "Internal error";
|
qmu::console() << "Internal error";
|
||||||
Abort();
|
Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iStat==0)
|
if (iStat==0)
|
||||||
{
|
{
|
||||||
mu::console() << "Test passed (" << QmuParserTester::c_iCount << " expressions)" << endl;
|
qmu::console() << "Test passed (" << QmuParserTester::c_iCount << " expressions)" << endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mu::console() << "Test failed with " << iStat
|
qmu::console() << "Test failed with " << iStat
|
||||||
<< " errors (" << QmuParserTester::c_iCount
|
<< " errors (" << QmuParserTester::c_iCount
|
||||||
<< " expressions)" << endl;
|
<< " expressions)" << endl;
|
||||||
}
|
}
|
||||||
|
@ -1130,7 +1130,7 @@ namespace qmu
|
||||||
// output the formula in case of an failed test
|
// output the formula in case of an failed test
|
||||||
if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )
|
if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )
|
||||||
{
|
{
|
||||||
mu::console() << "\n "
|
qmu::console() << "\n "
|
||||||
<< "Expression: " << a_str
|
<< "Expression: " << a_str
|
||||||
<< " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
|
<< " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
|
||||||
<< " Expected:" << a_iErrc;
|
<< " Expected:" << a_iErrc;
|
||||||
|
@ -1143,7 +1143,7 @@ namespace qmu
|
||||||
bool bRet((a_bFail==false) ? 0 : 1);
|
bool bRet((a_bFail==false) ? 0 : 1);
|
||||||
if (bRet==1)
|
if (bRet==1)
|
||||||
{
|
{
|
||||||
mu::console() << "\n "
|
qmu::console() << "\n "
|
||||||
<< "Expression: " << a_str
|
<< "Expression: " << a_str
|
||||||
<< " did evaluate; Expected error:" << a_iErrc;
|
<< " did evaluate; Expected error:" << a_iErrc;
|
||||||
}
|
}
|
||||||
|
@ -1188,17 +1188,17 @@ namespace qmu
|
||||||
}
|
}
|
||||||
catch(QmuParser::exception_type &e)
|
catch(QmuParser::exception_type &e)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (" << e.GetMsg() << ")";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.GetMsg() << ")";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (" << e.what() << ")";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.what() << ")";
|
||||||
return 1; // always return a failure since this exception is not expected
|
return 1; // always return a failure since this exception is not expected
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
|
||||||
return 1; // exceptions other than ParserException are not allowed
|
return 1; // exceptions other than ParserException are not allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1329,7 +1329,7 @@ namespace qmu
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
mu::console() << "\n " << e.what() << "\n";
|
qmu::console() << "\n " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// limited floating point accuracy requires the following test
|
// limited floating point accuracy requires the following test
|
||||||
|
@ -1350,7 +1350,7 @@ namespace qmu
|
||||||
|
|
||||||
if (iRet==1)
|
if (iRet==1)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str()
|
qmu::console() << "\n fail: " << a_str.c_str()
|
||||||
<< " (incorrect result; expected: " << a_fRes
|
<< " (incorrect result; expected: " << a_fRes
|
||||||
<< " ;calculated: " << fVal[0] << ","
|
<< " ;calculated: " << fVal[0] << ","
|
||||||
<< fVal[1] << ","
|
<< fVal[1] << ","
|
||||||
|
@ -1364,20 +1364,20 @@ namespace qmu
|
||||||
if (a_fPass)
|
if (a_fPass)
|
||||||
{
|
{
|
||||||
if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)
|
if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (copy construction)";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (copy construction)";
|
||||||
else
|
else
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (" << e.GetMsg() << ")";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.GetMsg() << ")";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (" << e.what() << ")";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.what() << ")";
|
||||||
return 1; // always return a failure since this exception is not expected
|
return 1; // always return a failure since this exception is not expected
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
|
||||||
return 1; // exceptions other than ParserException are not allowed
|
return 1; // exceptions other than ParserException are not allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1413,7 +1413,7 @@ namespace qmu
|
||||||
(a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;
|
(a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;
|
||||||
if (iRet==1)
|
if (iRet==1)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str()
|
qmu::console() << "\n fail: " << a_str.c_str()
|
||||||
<< " (incorrect result; expected: " << a_fRes
|
<< " (incorrect result; expected: " << a_fRes
|
||||||
<< " ;calculated: " << fVal[0]<< ").";
|
<< " ;calculated: " << fVal[0]<< ").";
|
||||||
}
|
}
|
||||||
|
@ -1422,13 +1422,13 @@ namespace qmu
|
||||||
{
|
{
|
||||||
if (a_fPass)
|
if (a_fPass)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << e.GetExpr() << " : " << e.GetMsg();
|
qmu::console() << "\n fail: " << e.GetExpr() << " : " << e.GetMsg();
|
||||||
iRet = 1;
|
iRet = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
mu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
|
qmu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
|
||||||
iRet = 1; // exceptions other than ParserException are not allowed
|
iRet = 1; // exceptions other than ParserException are not allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1439,7 +1439,7 @@ namespace qmu
|
||||||
/** \brief Internal error in test class Test is going to be aborted. */
|
/** \brief Internal error in test class Test is going to be aborted. */
|
||||||
void QmuParserTester::Abort() const
|
void QmuParserTester::Abort() const
|
||||||
{
|
{
|
||||||
mu::console() << "Test failed (internal error in test class)" << endl;
|
qmu::console() << "Test failed (internal error in test class)" << endl;
|
||||||
while (!getchar());
|
while (!getchar());
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include "qmuparsererror.h"
|
#include "qmuparsererror.h"
|
||||||
#include "qmuparsercallback.h"
|
#include "qmuparsercallback.h"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user