We don't need parser for integer value.
--HG-- branch : feature
This commit is contained in:
parent
d8f0cc2824
commit
148d2fb3f7
|
@ -37,7 +37,6 @@ SOURCES += \
|
|||
qmuparserbytecode.cpp \
|
||||
qmuparserbase.cpp \
|
||||
qmuparsertest.cpp \
|
||||
qmuparserint.cpp \
|
||||
stable.cpp
|
||||
|
||||
HEADERS += \
|
||||
|
@ -52,7 +51,6 @@ HEADERS += \
|
|||
qmuparserbytecode.h \
|
||||
qmuparserbase.h \
|
||||
qmuparsertest.h \
|
||||
qmuparserint.h \
|
||||
stable.h
|
||||
|
||||
VERSION = 2.2.3
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
/***************************************************************************************************
|
||||
**
|
||||
** Original work Copyright (C) 2013 Ingo Berg
|
||||
** Modified work Copyright 2014 Roman Telezhinsky <dismine@gmail.com>
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
******************************************************************************************************/
|
||||
|
||||
#include "qmuparserint.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** \file
|
||||
\brief Implementation of a parser using integer value.
|
||||
*/
|
||||
|
||||
/** \brief Namespace for mathematical applications. */
|
||||
namespace qmu
|
||||
{
|
||||
qreal QmuParserInt::Abs(qreal v) { return (qreal)Round(fabs((double)v)); }
|
||||
qreal QmuParserInt::Sign(qreal v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }
|
||||
qreal QmuParserInt::Ite(qreal v1,
|
||||
qreal v2,
|
||||
qreal v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }
|
||||
qreal QmuParserInt::Add(qreal v1, qreal v2) { return Round(v1) + Round(v2); }
|
||||
qreal QmuParserInt::Sub(qreal v1, qreal v2) { return Round(v1) - Round(v2); }
|
||||
qreal QmuParserInt::Mul(qreal v1, qreal v2) { return Round(v1) * Round(v2); }
|
||||
qreal QmuParserInt::Div(qreal v1, qreal v2) { return Round(v1) / Round(v2); }
|
||||
qreal QmuParserInt::Mod(qreal v1, qreal v2) { return Round(v1) % Round(v2); }
|
||||
qreal QmuParserInt::Shr(qreal v1, qreal v2) { return Round(v1) >> Round(v2); }
|
||||
qreal QmuParserInt::Shl(qreal v1, qreal v2) { return Round(v1) << Round(v2); }
|
||||
qreal QmuParserInt::LogAnd(qreal v1, qreal v2) { return Round(v1) & Round(v2); }
|
||||
qreal QmuParserInt::LogOr(qreal v1, qreal v2) { return Round(v1) | Round(v2); }
|
||||
qreal QmuParserInt::And(qreal v1, qreal v2) { return Round(v1) && Round(v2); }
|
||||
qreal QmuParserInt::Or(qreal v1, qreal v2) { return Round(v1) || Round(v2); }
|
||||
qreal QmuParserInt::Less(qreal v1, qreal v2) { return Round(v1) < Round(v2); }
|
||||
qreal QmuParserInt::Greater(qreal v1, qreal v2) { return Round(v1) > Round(v2); }
|
||||
qreal QmuParserInt::LessEq(qreal v1, qreal v2) { return Round(v1) <= Round(v2); }
|
||||
qreal QmuParserInt::GreaterEq(qreal v1, qreal v2) { return Round(v1) >= Round(v2); }
|
||||
qreal QmuParserInt::Equal(qreal v1, qreal v2) { return Round(v1) == Round(v2); }
|
||||
qreal QmuParserInt::NotEqual(qreal v1, qreal v2) { return Round(v1) != Round(v2); }
|
||||
qreal QmuParserInt::Not(qreal v) { return !Round(v); }
|
||||
|
||||
qreal QmuParserInt::Pow(qreal v1, qreal v2)
|
||||
{
|
||||
return std::pow((double)Round(v1), (double)Round(v2));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Unary operator Callbacks: Infix operators
|
||||
qreal QmuParserInt::UnaryMinus(qreal v)
|
||||
{
|
||||
return -Round(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
qreal QmuParserInt::Sum(const qreal* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw QmuParserError("too few arguments for function sum.");
|
||||
|
||||
qreal fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes += a_afArg[i];
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
qreal QmuParserInt::Min(const qreal* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw QmuParserError( "too few arguments for function min." );
|
||||
|
||||
qreal fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes = std::min(fRes, a_afArg[i]);
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
qreal QmuParserInt::Max(const qreal* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw QmuParserError("too few arguments for function min.");
|
||||
|
||||
qreal fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
fRes = std::max(fRes, a_afArg[i]);
|
||||
|
||||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Default value recognition callback
|
||||
int QmuParserInt::IsVal(const char_type *a_szExpr, int *a_iPos, qreal *a_fVal)
|
||||
{
|
||||
string_type buf(a_szExpr);
|
||||
std::size_t pos = buf.find_first_not_of("0123456789");
|
||||
|
||||
if (pos==std::string::npos)
|
||||
return 0;
|
||||
|
||||
stringstream_type stream( buf.substr(0, pos ) );
|
||||
int iVal(0);
|
||||
|
||||
stream >> iVal;
|
||||
if (stream.fail())
|
||||
return 0;
|
||||
|
||||
stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
|
||||
if (stream.fail())
|
||||
iEnd = stream.str().length();
|
||||
|
||||
if (iEnd==(stringstream_type::pos_type)-1)
|
||||
return 0;
|
||||
|
||||
*a_iPos += (int)iEnd;
|
||||
*a_fVal = (qreal)iVal;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \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 interger 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 QmuParserInt::IsHexVal(const char_type *a_szExpr, int *a_iPos, qreal *a_fVal)
|
||||
{
|
||||
if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') )
|
||||
return 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();
|
||||
|
||||
if (nPos==(stringstream_type::pos_type)0)
|
||||
return 1;
|
||||
|
||||
*a_iPos += (int)(2 + nPos);
|
||||
*a_fVal = (qreal)iVal;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int QmuParserInt::IsBinVal(const char_type *a_szExpr, int *a_iPos, qreal *a_fVal)
|
||||
{
|
||||
if (a_szExpr[0]!='#')
|
||||
return 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)
|
||||
iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);
|
||||
|
||||
if (i==0)
|
||||
return 0;
|
||||
|
||||
if (i==iBits)
|
||||
throw exception_type("Binary to integer conversion error (overflow).");
|
||||
|
||||
*a_fVal = (unsigned)(iVal >> (iBits-i) );
|
||||
*a_iPos += i+1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor.
|
||||
|
||||
Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
|
||||
*/
|
||||
QmuParserInt::QmuParserInt()
|
||||
:QmuParserBase()
|
||||
{
|
||||
AddValIdent(IsVal); // lowest priority
|
||||
AddValIdent(IsBinVal);
|
||||
AddValIdent(IsHexVal); // highest priority
|
||||
|
||||
InitCharSets();
|
||||
InitFun();
|
||||
InitOprt();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void QmuParserInt::InitConst()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void QmuParserInt::InitCharSets()
|
||||
{
|
||||
DefineNameChars( "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" );
|
||||
DefineOprtChars( "+-*^/?<>=!%&|~'_" );
|
||||
DefineInfixOprtChars( "/+-*^?<>=!%&|~'_" );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize the default functions. */
|
||||
void QmuParserInt::InitFun()
|
||||
{
|
||||
DefineFun( "sign", Sign);
|
||||
DefineFun( "abs", Abs);
|
||||
DefineFun( "if", Ite);
|
||||
DefineFun( "sum", Sum);
|
||||
DefineFun( "min", Min);
|
||||
DefineFun( "max", Max);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize operators. */
|
||||
void QmuParserInt::InitOprt()
|
||||
{
|
||||
// disable all built in operators, not all of them usefull 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( "-", UnaryMinus);
|
||||
DefineInfixOprt( "!", Not);
|
||||
|
||||
DefineOprt( "&", LogAnd, prLOGIC);
|
||||
DefineOprt( "|", LogOr, prLOGIC);
|
||||
DefineOprt( "&&", And, prLOGIC);
|
||||
DefineOprt( "||", Or, prLOGIC);
|
||||
|
||||
DefineOprt( "<", Less, prCMP);
|
||||
DefineOprt( ">", Greater, prCMP);
|
||||
DefineOprt( "<=", LessEq, prCMP);
|
||||
DefineOprt( ">=", GreaterEq, prCMP);
|
||||
DefineOprt( "==", Equal, prCMP);
|
||||
DefineOprt( "!=", NotEqual, prCMP);
|
||||
|
||||
DefineOprt( "+", Add, prADD_SUB);
|
||||
DefineOprt( "-", Sub, prADD_SUB);
|
||||
|
||||
DefineOprt( "*", Mul, prMUL_DIV);
|
||||
DefineOprt( "/", Div, prMUL_DIV);
|
||||
DefineOprt( "%", Mod, prMUL_DIV);
|
||||
|
||||
DefineOprt( "^", Pow, prPOW, oaRIGHT);
|
||||
DefineOprt( ">>", Shr, prMUL_DIV+1);
|
||||
DefineOprt( "<<", Shl, prMUL_DIV+1);
|
||||
}
|
||||
|
||||
} // namespace qmu
|
|
@ -1,132 +0,0 @@
|
|||
/***************************************************************************************************
|
||||
**
|
||||
** Original work Copyright (C) 2013 Ingo Berg
|
||||
** Modified work Copyright 2014 Roman Telezhinsky <dismine@gmail.com>
|
||||
**
|
||||
** 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 QMUPARSERINT_H
|
||||
#define QMUPARSERINT_H
|
||||
|
||||
#include "qmuparserbase.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
/** \file
|
||||
\brief Definition of a parser using integer value.
|
||||
*/
|
||||
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
|
||||
/** \brief Mathematical expressions parser.
|
||||
|
||||
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 QmuParserInt : public QmuParserBase
|
||||
{
|
||||
private:
|
||||
static int Round(qreal v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };
|
||||
|
||||
static qreal Abs(qreal);
|
||||
static qreal Sign(qreal);
|
||||
static qreal Ite(qreal, qreal, qreal);
|
||||
// !! The unary Minus is a MUST, otherwise you cant use negative signs !!
|
||||
static qreal UnaryMinus(qreal);
|
||||
// Functions with variable number of arguments
|
||||
static qreal Sum(const qreal* a_afArg, int a_iArgc); // sum
|
||||
static qreal Min(const qreal* a_afArg, int a_iArgc); // minimum
|
||||
static qreal Max(const qreal* a_afArg, int a_iArgc); // maximum
|
||||
// binary operator callbacks
|
||||
static qreal Add(qreal v1, qreal v2);
|
||||
static qreal Sub(qreal v1, qreal v2);
|
||||
static qreal Mul(qreal v1, qreal v2);
|
||||
static qreal Div(qreal v1, qreal v2);
|
||||
static qreal Mod(qreal v1, qreal v2);
|
||||
static qreal Pow(qreal v1, qreal v2);
|
||||
static qreal Shr(qreal v1, qreal v2);
|
||||
static qreal Shl(qreal v1, qreal v2);
|
||||
static qreal LogAnd(qreal v1, qreal v2);
|
||||
static qreal LogOr(qreal v1, qreal v2);
|
||||
static qreal And(qreal v1, qreal v2);
|
||||
static qreal Or(qreal v1, qreal v2);
|
||||
static qreal Xor(qreal v1, qreal v2);
|
||||
static qreal Less(qreal v1, qreal v2);
|
||||
static qreal Greater(qreal v1, qreal v2);
|
||||
static qreal LessEq(qreal v1, qreal v2);
|
||||
static qreal GreaterEq(qreal v1, qreal v2);
|
||||
static qreal Equal(qreal v1, qreal v2);
|
||||
static qreal NotEqual(qreal v1, qreal v2);
|
||||
static qreal Not(qreal v1);
|
||||
|
||||
static int IsHexVal(const char_type* a_szExpr, int *a_iPos, qreal *a_iVal);
|
||||
static int IsBinVal(const char_type* a_szExpr, int *a_iPos, qreal *a_iVal);
|
||||
static int IsVal (const char_type* a_szExpr, int *a_iPos, qreal *a_iVal);
|
||||
|
||||
/** \brief A facet class used to change decimal and thousands separator. */
|
||||
template<class TChar>
|
||||
class change_dec_sep : public std::numpunct<TChar>
|
||||
{
|
||||
public:
|
||||
|
||||
explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
|
||||
:std::numpunct<TChar>()
|
||||
,m_cDecPoint(cDecSep)
|
||||
,m_cThousandsSep(cThousandsSep)
|
||||
,m_nGroup(nGroup)
|
||||
{}
|
||||
|
||||
protected:
|
||||
|
||||
virtual char_type do_decimal_point() const
|
||||
{
|
||||
return m_cDecPoint;
|
||||
}
|
||||
|
||||
virtual char_type do_thousands_sep() const
|
||||
{
|
||||
return m_cThousandsSep;
|
||||
}
|
||||
|
||||
virtual std::string do_grouping() const
|
||||
{
|
||||
return std::string(1, m_nGroup);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_nGroup;
|
||||
char_type m_cDecPoint;
|
||||
char_type m_cThousandsSep;
|
||||
};
|
||||
|
||||
public:
|
||||
QmuParserInt();
|
||||
|
||||
virtual void InitFun();
|
||||
virtual void InitOprt();
|
||||
virtual void InitConst();
|
||||
virtual void InitCharSets();
|
||||
};
|
||||
|
||||
} // namespace qmu
|
||||
|
||||
#endif
|
||||
|
|
@ -214,79 +214,6 @@ namespace qmu
|
|||
// reference: http://www.wolframalpha.com/input/?i=3%2B4*2%2F%281-5%29^2^3
|
||||
iStat += EqnTest("3+4*2/(1-5)^2^3", 3.0001220703125, true);
|
||||
|
||||
// Test user defined binary operators
|
||||
iStat += EqnTestInt("1 | 2", 3, true);
|
||||
iStat += EqnTestInt("1 || 2", 1, true);
|
||||
iStat += EqnTestInt("123 & 456", 72, true);
|
||||
iStat += EqnTestInt("(123 & 456) % 10", 2, true);
|
||||
iStat += EqnTestInt("1 && 0", 0, true);
|
||||
iStat += EqnTestInt("123 && 456", 1, true);
|
||||
iStat += EqnTestInt("1 << 3", 8, true);
|
||||
iStat += EqnTestInt("8 >> 3", 1, true);
|
||||
iStat += EqnTestInt("9 / 4", 2, true);
|
||||
iStat += EqnTestInt("9 % 4", 1, true);
|
||||
iStat += EqnTestInt("if(5%2,1,0)", 1, true);
|
||||
iStat += EqnTestInt("if(4%2,1,0)", 0, true);
|
||||
iStat += EqnTestInt("-10+1", -9, true);
|
||||
iStat += EqnTestInt("1+2*3", 7, true);
|
||||
iStat += EqnTestInt("const1 != const2", 1, true);
|
||||
iStat += EqnTestInt("const1 != const2", 0, false);
|
||||
iStat += EqnTestInt("const1 == const2", 0, true);
|
||||
iStat += EqnTestInt("const1 == 1", 1, true);
|
||||
iStat += EqnTestInt("10*(const1 == 1)", 10, true);
|
||||
iStat += EqnTestInt("2*(const1 | const2)", 6, true);
|
||||
iStat += EqnTestInt("2*(const1 | const2)", 7, false);
|
||||
iStat += EqnTestInt("const1 < const2", 1, true);
|
||||
iStat += EqnTestInt("const2 > const1", 1, true);
|
||||
iStat += EqnTestInt("const1 <= 1", 1, true);
|
||||
iStat += EqnTestInt("const2 >= 2", 1, true);
|
||||
iStat += EqnTestInt("2*(const1 + const2)", 6, true);
|
||||
iStat += EqnTestInt("2*(const1 - const2)", -2, true);
|
||||
iStat += EqnTestInt("a != b", 1, true);
|
||||
iStat += EqnTestInt("a != b", 0, false);
|
||||
iStat += EqnTestInt("a == b", 0, true);
|
||||
iStat += EqnTestInt("a == 1", 1, true);
|
||||
iStat += EqnTestInt("10*(a == 1)", 10, true);
|
||||
iStat += EqnTestInt("2*(a | b)", 6, true);
|
||||
iStat += EqnTestInt("2*(a | b)", 7, false);
|
||||
iStat += EqnTestInt("a < b", 1, true);
|
||||
iStat += EqnTestInt("b > a", 1, true);
|
||||
iStat += EqnTestInt("a <= 1", 1, true);
|
||||
iStat += EqnTestInt("b >= 2", 1, true);
|
||||
iStat += EqnTestInt("2*(a + b)", 6, true);
|
||||
iStat += EqnTestInt("2*(a - b)", -2, true);
|
||||
iStat += EqnTestInt("a + (a << b)", 5, true);
|
||||
iStat += EqnTestInt("-2^2", -4, true);
|
||||
iStat += EqnTestInt("3--a", 4, true);
|
||||
iStat += EqnTestInt("3+-3^2", -6, true);
|
||||
|
||||
// Test reading of hex values:
|
||||
iStat += EqnTestInt("0xff", 255, true);
|
||||
iStat += EqnTestInt("10+0xff", 265, true);
|
||||
iStat += EqnTestInt("0xff+10", 265, true);
|
||||
iStat += EqnTestInt("10*0xff", 2550, true);
|
||||
iStat += EqnTestInt("0xff*10", 2550, true);
|
||||
iStat += EqnTestInt("10+0xff+1", 266, true);
|
||||
iStat += EqnTestInt("1+0xff+10", 266, true);
|
||||
|
||||
// incorrect: '^' is your 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("a + b * c", 7, true);
|
||||
iStat += EqnTestInt("a * b + c", 5, true);
|
||||
iStat += EqnTestInt("a<b && b>10", 0, true);
|
||||
iStat += EqnTestInt("a<b && b<10", 1, true);
|
||||
|
||||
iStat += EqnTestInt("a + b << c", 17, true);
|
||||
iStat += EqnTestInt("a << b + c", 7, true);
|
||||
iStat += EqnTestInt("c * b < a", 0, true);
|
||||
iStat += EqnTestInt("c * b == 6 * a", 1, true);
|
||||
iStat += EqnTestInt("2^2^3", 256, true);
|
||||
|
||||
|
||||
if (iStat==0)
|
||||
qmu::console() << "passed" << endl;
|
||||
else
|
||||
|
@ -1384,57 +1311,6 @@ namespace qmu
|
|||
return iRet;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int QmuParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass)
|
||||
{
|
||||
QmuParserTester::c_iCount++;
|
||||
|
||||
qreal vVarVal[] = {1, 2, 3}; // variable values
|
||||
qreal fVal[2] = {-99, -999}; // results: initially should be different
|
||||
int iRet(0);
|
||||
|
||||
try
|
||||
{
|
||||
QmuParserInt p;
|
||||
p.DefineConst( "const1", 1);
|
||||
p.DefineConst( "const2", 2);
|
||||
p.DefineVar( "a", &vVarVal[0]);
|
||||
p.DefineVar( "b", &vVarVal[1]);
|
||||
p.DefineVar( "c", &vVarVal[2]);
|
||||
|
||||
p.SetExpr(a_str);
|
||||
fVal[0] = p.Eval(); // result from stringparsing
|
||||
fVal[1] = p.Eval(); // result from bytecode
|
||||
|
||||
if (fVal[0]!=fVal[1])
|
||||
throw QmuParser::exception_type( "Bytecode corrupt." );
|
||||
|
||||
iRet = ( (a_fRes==fVal[0] && a_fPass) ||
|
||||
(a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;
|
||||
if (iRet==1)
|
||||
{
|
||||
qmu::console() << "\n fail: " << a_str.c_str()
|
||||
<< " (incorrect result; expected: " << a_fRes
|
||||
<< " ;calculated: " << fVal[0]<< ").";
|
||||
}
|
||||
}
|
||||
catch(QmuParser::exception_type &e)
|
||||
{
|
||||
if (a_fPass)
|
||||
{
|
||||
qmu::console() << "\n fail: " << e.GetExpr() << " : " << e.GetMsg();
|
||||
iRet = 1;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
qmu::console() << "\n fail: " << a_str.c_str() << " (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 QmuParserTester::Abort() const
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <cstdlib>
|
||||
#include <numeric> // for accumulate
|
||||
#include "qmuparser.h"
|
||||
#include "qmuparserint.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser test class.
|
||||
|
@ -195,9 +194,6 @@ namespace qmu
|
|||
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);
|
||||
};
|
||||
} // namespace Test
|
||||
} // namespace qmu
|
||||
|
|
Loading…
Reference in New Issue
Block a user