Tests passed.

--HG--
branch : feature
This commit is contained in:
dismine 2014-05-06 12:45:21 +03:00
parent 60ba211f2a
commit d65368bafb
15 changed files with 243 additions and 336 deletions

View file

@ -102,7 +102,7 @@ CONFIG(debug, debug|release){
-Wmissing-include-dirs -Wpacked -Wredundant-decls -Winline \
-Wswitch-default -Wswitch-enum -Wuninitialized -Wvariadic-macros \
-Wlogical-op -Wnoexcept -Wmissing-noreturn -Wpointer-arith\
-Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -gdwarf-3
-Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -gdwarf-3 \
-ftrapv
}
} else {

View file

@ -42,26 +42,26 @@ class VException : public QException
{
Q_DECLARE_TR_FUNCTIONS(VException)
public:
/**
* @brief VException constructor exception
* @param what string with error
*/
VException(const QString &what);
/**
* @brief VException copy constructor
* @param e exception
*/
VException(const VException &e);
virtual ~VException() noexcept (true){}
/**
* @brief VException constructor exception
* @param what string with error
*/
VException(const QString &what);
/**
* @brief VException copy constructor
* @param e exception
*/
VException(const VException &e);
virtual ~VException() noexcept (true){}
/**
* @brief raise method raise for exception
*/
void raise() const;
virtual void raise() const;
/**
* @brief clone clone exception
* @return new exception
*/
VException *clone() const;
virtual VException *clone() const;
/**
* @brief ErrorMessage return main error message
* @return error message

View file

@ -74,8 +74,9 @@ void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &context, c
switch (type)
{
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line,
context.function);
fprintf(stderr, "Debug: %s\n", localMsg.constData());
// fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line,
// context.function);
return;
case QtWarningMsg:
messageBox.setIcon(QMessageBox::Warning);

View file

@ -131,7 +131,7 @@ qreal QmuParser::Sum(const qreal *a_afArg, int a_iArgc)
{
if (a_iArgc == false)
{
throw exception_type("too few arguments for function sum.");
throw QmuParserError("too few arguments for function sum.");
}
qreal fRes=0;
for (int i=0; i<a_iArgc; ++i)
@ -151,7 +151,7 @@ qreal QmuParser::Avg(const qreal *a_afArg, int a_iArgc)
{
if (a_iArgc == false)
{
throw exception_type("too few arguments for function sum.");
throw QmuParserError("too few arguments for function sum.");
}
qreal fRes=0;
for (int i=0; i<a_iArgc; ++i)
@ -171,7 +171,7 @@ qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
{
if (a_iArgc == false)
{
throw exception_type("too few arguments for function min.");
throw QmuParserError("too few arguments for function min.");
}
qreal fRes=a_afArg[0];
for (int i=0; i<a_iArgc; ++i)
@ -191,7 +191,7 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
{
if (a_iArgc == false)
{
throw exception_type("too few arguments for function min.");
throw QmuParserError("too few arguments for function min.");
}
qreal fRes=a_afArg[0];
for (int i=0; i<a_iArgc; ++i)

View file

@ -53,7 +53,7 @@ HEADERS += \
qmuparsertest.h \
stable.h
VERSION = 2.2.3
VERSION = 2.2.4
unix {
target.path = /usr/lib
@ -83,7 +83,7 @@ CONFIG(debug, debug|release){
-Wmissing-include-dirs -Wpacked -Wredundant-decls -Winline \
-Wswitch-default -Wswitch-enum -Wuninitialized -Wvariadic-macros \
-Wlogical-op -Wnoexcept -Wmissing-noreturn -Wpointer-arith\
-Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -gdwarf-3
-Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -gdwarf-3 \
-ftrapv
}
} else {

View file

@ -27,6 +27,9 @@
#include <omp.h>
#endif
#include "qmuparsererror.h"
#include "qmuparsertokenreader.h"
using namespace std;
/**
@ -438,19 +441,19 @@ void QmuParserBase::CheckOprt(const QString &a_sName, const QmuParserCallback &a
Q_UNREACHABLE();
break;
case cmVARPOW2:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmVARPOW3:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmVARPOW4:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmVARMUL:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmPOW2:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmFUNC:
Q_UNREACHABLE();
@ -937,7 +940,7 @@ const varmap_type& QmuParserBase::GetUsedVar() const
m_pParseFormula = &QmuParserBase::ParseString;
m_pTokenReader->IgnoreUndefVar(false);
}
catch (const exception_type &e)
catch (const QmuParserError &e)
{
// Make sure to stay in string parse mode, dont call ReInit()
// because it deletes the array with the used variables
@ -995,7 +998,7 @@ const QString& QmuParserBase::GetExpr() const
/**
* @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
* @throw QmuParserError If the function token is not a string function
*/
QmuParserBase::token_type QmuParserBase::ApplyStrFunc(const token_type &a_FunTok,
const QVector<token_type> &a_vArg) const
@ -1052,7 +1055,7 @@ QmuParserBase::token_type QmuParserBase::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 mach function requirements.
* @throw QmuParserError if Argument count does not mach function requirements.
*/
void QmuParserBase::ApplyFunc( QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal, int a_iArgCount) const
{
@ -2051,7 +2054,7 @@ qreal QmuParserBase::ParseString() const
m_pParseFormula = &QmuParserBase::ParseCmdCode;
return (this->*m_pParseFormula)();
}
catch (QmuParserError &exc)
catch (qmu::QmuParserError &exc)
{
exc.SetFormula(m_pTokenReader->GetExpr());
throw;
@ -2071,7 +2074,7 @@ qreal QmuParserBase::ParseString() const
*/
void Q_NORETURN QmuParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const QString &a_sTok) const
{
throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
throw qmu::QmuParserError (a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
}
//---------------------------------------------------------------------------------------------------------------------

View file

@ -23,6 +23,7 @@
#ifndef QMUQPARSERBASE_H
#define QMUQPARSERBASE_H
#include "qmuparser_global.h"
#include <QStack>
#include <QString>
#include <QStringList>
@ -51,17 +52,10 @@ namespace qmu
* Complementary to a set of internally implemented functions the parser is able to handle
* user defined functions and variables.
*/
class QmuParserBase
class QMUPARSERSHARED_EXPORT QmuParserBase
{
friend class QmuParserTokenReader;
public:
/**
* @brief Type of the error class.
*
* Included for backwards compatibility.
*/
typedef QmuParserError exception_type;
QmuParserBase();
QmuParserBase(const QmuParserBase &a_Parser);
QmuParserBase& operator=(const QmuParserBase &a_Parser) Q_DECL_NOEXCEPT;
@ -112,7 +106,7 @@ public:
const QString& ValidInfixOprtChars() const;
void SetArgSep(char_type cArgSep);
QChar GetArgSep() const;
void Error(EErrorCodes a_iErrc, int a_iPos = -1, const QString &a_strTok = QString() ) const;
void Q_NORETURN Error(EErrorCodes a_iErrc, int a_iPos = -1, const QString &a_strTok = QString() ) const;
/**
* @fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun,
* bool a_bAllowOpt = true)

View file

@ -430,10 +430,8 @@ void QmuParserByteCode::AddOp(ECmdCode a_Oprt)
}
break;
case cmLE:
Q_UNREACHABLE();
break;
case cmGE:
Q_UNREACHABLE();
break;
case cmNEQ:
Q_UNREACHABLE();
@ -442,13 +440,10 @@ void QmuParserByteCode::AddOp(ECmdCode a_Oprt)
Q_UNREACHABLE();
break;
case cmLT:
Q_UNREACHABLE();
break;
case cmGT:
Q_UNREACHABLE();
break;
case cmLAND:
Q_UNREACHABLE();
break;
case cmLOR:
Q_UNREACHABLE();
@ -670,10 +665,8 @@ void QmuParserByteCode::Finalize() Q_DECL_NOEXCEPT
m_vRPN[idx].Oprt.offset = i - idx;
break;
case cmLE:
Q_UNREACHABLE();
break;
case cmGE:
Q_UNREACHABLE();
break;
case cmNEQ:
Q_UNREACHABLE();
@ -682,34 +675,25 @@ void QmuParserByteCode::Finalize() Q_DECL_NOEXCEPT
Q_UNREACHABLE();
break;
case cmLT:
Q_UNREACHABLE();
break;
case cmGT:
Q_UNREACHABLE();
break;
case cmADD:
Q_UNREACHABLE();
break;
case cmSUB:
Q_UNREACHABLE();
break;
case cmMUL:
Q_UNREACHABLE();
break;
case cmDIV:
Q_UNREACHABLE();
break;
case cmPOW:
Q_UNREACHABLE();
break;
case cmLAND:
Q_UNREACHABLE();
break;
case cmLOR:
Q_UNREACHABLE();
break;
case cmASSIGN:
Q_UNREACHABLE();
break;
case cmBO:
Q_UNREACHABLE();
@ -721,31 +705,27 @@ void QmuParserByteCode::Finalize() Q_DECL_NOEXCEPT
Q_UNREACHABLE();
break;
case cmVAR:
Q_UNREACHABLE();
break;
case cmVAL:
Q_UNREACHABLE();
break;
case cmVARPOW2:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmVARPOW3:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmVARPOW4:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmVARMUL:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmPOW2:
Q_UNREACHABLE();
// For optimization purposes
break;
case cmFUNC:
Q_UNREACHABLE();
break;
case cmFUNC_STR:
Q_UNREACHABLE();
break;
case cmFUNC_BULK:
Q_UNREACHABLE();
@ -763,7 +743,6 @@ void QmuParserByteCode::Finalize() Q_DECL_NOEXCEPT
Q_UNREACHABLE();
break;
case cmEND:
Q_UNREACHABLE();
break;
case cmUNKNOWN:
Q_UNREACHABLE();

View file

@ -109,7 +109,7 @@ QmuParserErrorMsg::QmuParserErrorMsg()
* @brief Default constructor.
*/
QmuParserError::QmuParserError()
: m_sMsg(), m_sExpr(), m_sTok(), m_iPos ( -1 ), m_iErrc ( ecUNDEFINED ),
: QException(), m_sMsg(), m_sExpr(), m_sTok(), m_iPos ( -1 ), m_iErrc ( ecUNDEFINED ),
m_ErrMsg ( QmuParserErrorMsg::Instance() )
{}
@ -120,7 +120,7 @@ QmuParserError::QmuParserError()
* It does not contain any information but the error code.
*/
QmuParserError::QmuParserError ( EErrorCodes a_iErrc )
: m_sMsg(), m_sExpr(), m_sTok(), m_iPos ( -1 ), m_iErrc ( a_iErrc ),
: QException(), m_sMsg(), m_sExpr(), m_sTok(), m_iPos ( -1 ), m_iErrc ( a_iErrc ),
m_ErrMsg ( QmuParserErrorMsg::Instance() )
{
m_sMsg = m_ErrMsg[m_iErrc];
@ -133,7 +133,7 @@ QmuParserError::QmuParserError ( EErrorCodes a_iErrc )
* @brief Construct an error from a message text.
*/
QmuParserError::QmuParserError ( const QString &sMsg )
: m_sMsg(sMsg), m_sExpr(), m_sTok(), m_iPos ( -1 ), m_iErrc ( ecUNDEFINED ),
: QException(), m_sMsg(sMsg), m_sExpr(), m_sTok(), m_iPos ( -1 ), m_iErrc ( ecUNDEFINED ),
m_ErrMsg ( QmuParserErrorMsg::Instance() )
{}
@ -146,7 +146,7 @@ QmuParserError::QmuParserError ( const QString &sMsg )
* @param [in] a_iPos the position in the expression where the error occured.
*/
QmuParserError::QmuParserError ( EErrorCodes iErrc, const QString &sTok, const QString &sExpr, int iPos )
: m_sMsg(), m_sExpr ( sExpr ), m_sTok ( sTok ), m_iPos ( iPos ), m_iErrc ( iErrc ),
: QException(), m_sMsg(), m_sExpr ( sExpr ), m_sTok ( sTok ), m_iPos ( iPos ), m_iErrc ( iErrc ),
m_ErrMsg ( QmuParserErrorMsg::Instance() )
{
m_sMsg = m_ErrMsg[m_iErrc];
@ -162,7 +162,7 @@ QmuParserError::QmuParserError ( EErrorCodes iErrc, const QString &sTok, const Q
* @param [in] sTok The token string related to this error.
*/
QmuParserError::QmuParserError ( EErrorCodes a_iErrc, int a_iPos, const QString &sTok )
: m_sMsg(), m_sExpr(), m_sTok ( sTok ), m_iPos ( a_iPos ), m_iErrc ( a_iErrc ),
: QException(), m_sMsg(), m_sExpr(), m_sTok ( sTok ), m_iPos ( a_iPos ), m_iErrc ( a_iErrc ),
m_ErrMsg ( QmuParserErrorMsg::Instance() )
{
m_sMsg = m_ErrMsg[m_iErrc];
@ -177,7 +177,7 @@ QmuParserError::QmuParserError ( EErrorCodes a_iErrc, int a_iPos, const QString
* @param [in] sTok The token string related to this error.
*/
QmuParserError::QmuParserError ( const QString &szMsg, int iPos, const QString &sTok )
: m_sMsg ( szMsg ), m_sExpr(), m_sTok ( sTok ), m_iPos ( iPos ), m_iErrc ( ecGENERIC ),
: QException(), m_sMsg ( szMsg ), m_sExpr(), m_sTok ( sTok ), m_iPos ( iPos ), m_iErrc ( ecGENERIC ),
m_ErrMsg ( QmuParserErrorMsg::Instance() )
{
ReplaceSubString ( m_sMsg, "$POS$", QString().setNum ( m_iPos ) );
@ -187,7 +187,7 @@ QmuParserError::QmuParserError ( const QString &szMsg, int iPos, const QString &
//---------------------------------------------------------------------------------------------------------------------
/** @brief Copy constructor. */
QmuParserError::QmuParserError ( const QmuParserError &a_Obj )
: m_sMsg ( a_Obj.m_sMsg ), m_sExpr ( a_Obj.m_sExpr ), m_sTok ( a_Obj.m_sTok ),
: QException(), m_sMsg ( a_Obj.m_sMsg ), m_sExpr ( a_Obj.m_sExpr ), m_sTok ( a_Obj.m_sTok ),
m_iPos ( a_Obj.m_iPos ), m_iErrc ( a_Obj.m_iErrc ), m_ErrMsg ( QmuParserErrorMsg::Instance() )
{}
@ -208,10 +208,6 @@ QmuParserError& QmuParserError::operator= ( const QmuParserError &a_Obj )
return *this;
}
//---------------------------------------------------------------------------------------------------------------------
QmuParserError::~QmuParserError()
{}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Replace all ocuurences of a substring with another string.
@ -309,4 +305,5 @@ EErrorCodes QmuParserError::GetCode() const
{
return m_iErrc;
}
} // namespace qmu

View file

@ -23,11 +23,9 @@
#ifndef QMUPARSERERROR_H
#define QMUPARSERERROR_H
#include <cassert>
#include <stdexcept>
#include <string>
#include "qmuparser_global.h"
#include <sstream>
#include <memory>
#include <QException>
#include "qmuparserdef.h"
@ -117,10 +115,9 @@ private:
Part of the math parser package.
*/
class QmuParserError
class QMUPARSERSHARED_EXPORT QmuParserError : public QException
{
public:
QmuParserError();
explicit QmuParserError ( EErrorCodes a_iErrc );
explicit QmuParserError ( const QString &sMsg );
@ -129,7 +126,7 @@ public:
QmuParserError ( const QString &a_szMsg, int a_iPos, const QString &sTok = QString() );
QmuParserError ( const QmuParserError &a_Obj );
QmuParserError& operator= ( const QmuParserError &a_Obj );
~QmuParserError();
virtual ~QmuParserError() noexcept (true){}
void SetFormula ( const QString &a_strFormula );
const QString& GetExpr() const;
@ -138,6 +135,15 @@ public:
const QString& GetToken() const;
EErrorCodes GetCode() const;
/**
* @brief raise method raise for exception
*/
virtual void raise() const;
/**
* @brief clone clone exception
* @return new exception
*/
virtual QmuParserError *clone() const;
private:
QString m_sMsg; ///< The message string
QString m_sExpr; ///< Formula string
@ -152,6 +158,16 @@ private:
void Reset();
};
inline void QmuParserError::raise() const
{
throw *this;
}
inline QmuParserError *QmuParserError::clone() const
{
return new QmuParserError(*this);
}
} // namespace qmu
#endif

View file

@ -23,10 +23,8 @@
#include "qmuparsertest.h"
#include <QtMath>
#include <QString>
#include <cstdio>
#include <iostream>
#include <limits>
#include <QDebug>
#include "qmuparsererror.h"
using namespace std;
@ -64,32 +62,33 @@ QmuParserTester::QmuParserTester()
//---------------------------------------------------------------------------------------------------------------------
int QmuParserTester::IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal )
{
if ( a_szExpr[1] == 0 || ( a_szExpr[0] != '0' || a_szExpr[1] != 'x' ) )
if ( a_szExpr.data()[1] == 0 || ( a_szExpr.data()[0] != '0' || a_szExpr.data()[1] != 'x' ) )
{
return 0;
}
unsigned iVal ( 0 );
bool ok = false;
iVal = a_szExpr.toUInt ( &ok, 16 );
if ( ok )
#if defined(_UNICODE)
std::wstring a_szExprStd = a_szExpr.mid(2).toStdWString();
#else
std::string a_szExprStd = a_szExpr.mid(2).toStdString();
#endif
// New code based on streams for UNICODE compliance:
stringstream_type::pos_type nPos(0);
stringstream_type ss(a_szExprStd);
ss >> std::hex >> iVal;
nPos = ss.tellg();
if (nPos==static_cast<stringstream_type::pos_type>(0))
{
int nPos = a_szExpr.indexOf ( QString().setNum ( iVal, 16 ) );
if ( nPos == 0 )
{
return 1;
}
*a_iPos += 2 + nPos;
*a_fVal = static_cast<qreal>(iVal);
return 1;
}
else
{
return 0;
}
*a_iPos += static_cast<int>(2 + nPos);
*a_fVal = static_cast<qreal>(iVal);
return 1;
}
//---------------------------------------------------------------------------------------------------------------------
@ -128,11 +127,11 @@ int QmuParserTester::TestInterface()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestInterface passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestInterface failed with " << iStat << " errors";
}
return iStat;
@ -157,11 +156,11 @@ int QmuParserTester::TestStrArg()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestStrArg passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestStrArg failed with " << iStat << " errors";
}
return iStat;
@ -232,11 +231,11 @@ int QmuParserTester::TestBinOprt()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestBinOprt passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestBinOprt failed with " << iStat << " errors";
}
return iStat;
@ -260,7 +259,7 @@ int QmuParserTester::TestNames()
{ \
p.Define##DOMAIN(EXPR, ARG); \
} \
catch (QmuParser::exception_type&) \
catch (QmuParserError &) \
{ \
iErr = (FAIL==false) ? 0 : 1; \
} \
@ -345,11 +344,11 @@ int QmuParserTester::TestNames()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestNames passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestNames failed with " << iStat << " errors";
}
return iStat;
@ -398,11 +397,11 @@ int QmuParserTester::TestSyntax()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestSyntax passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestSyntax failed with " << iStat << " errors";
}
return iStat;
@ -531,11 +530,11 @@ int QmuParserTester::TestVarConst()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestVarConst passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestVarConst failed with " << iStat << " errors";
}
return iStat;
@ -629,11 +628,11 @@ int QmuParserTester::TestMultiArg()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestMultiArg passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestMultiArg failed with " << iStat << " errors";
}
return iStat;
@ -698,11 +697,11 @@ int QmuParserTester::TestInfixOprt()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestInfixOprt passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestInfixOprt failed with " << iStat << " errors";
}
return iStat;
@ -754,11 +753,11 @@ int QmuParserTester::TestPostFix()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestPostFix passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestPostFix failed with " << iStat << " errors";
}
return iStat;
@ -792,6 +791,8 @@ int QmuParserTester::TestExpression()
iStat += EqnTest ( "(2*b+1)*4", ( 2 * b + 1 ) * 4, true );
iStat += EqnTest ( "4*(2*b+1)", ( 2 * b + 1 ) * 4, true );
// 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2
iStat += EqnTest ( "1+2+3", 6, true );
// operator precedencs
iStat += EqnTest ( "1+2-3*4/5^6", 2.99923, true );
@ -839,11 +840,11 @@ int QmuParserTester::TestExpression()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestExpression passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestExpression failed with " << iStat << " errors";
}
return iStat;
@ -949,11 +950,11 @@ int QmuParserTester::TestIfThenElse()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestIfThenElse passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestIfThenElse failed with " << iStat << " errors";
}
return iStat;
@ -1047,11 +1048,11 @@ int QmuParserTester::TestException()
if ( iStat == 0 )
{
qDebug() << "passed";
qDebug() << "TestException passed";
}
else
{
qDebug() << "\n failed with " << iStat << " errors";
qDebug() << "\n TestException failed with " << iStat << " errors";
}
return iStat;
@ -1076,7 +1077,7 @@ void QmuParserTester::Run()
iStat += ( this->*m_vTestFun[i] ) ();
}
}
catch ( QmuParser::exception_type &e )
catch ( QmuParserError &e )
{
qDebug() << "\n" << e.GetMsg();
qDebug() << e.GetToken();
@ -1130,14 +1131,12 @@ int QmuParserTester::ThrowTest ( const QString &a_str, int a_iErrc, bool a_bFail
p.SetExpr ( a_str );
p.Eval();
}
catch ( QmuParserError &e )
catch ( const qmu::QmuParserError &e )
{
// output the formula in case of an failed test
if ( a_bFail == false || ( a_bFail == true && a_iErrc != e.GetCode() ) )
{
qDebug() << "\n "
<< "Expression: " << a_str
<< " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
qDebug() << "\n " << "Expression: " << a_str << " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
<< " Expected:" << a_iErrc;
}
@ -1194,7 +1193,7 @@ int QmuParserTester::EqnTestWithVarChange ( const QString &a_str, double a_fVar1
throw std::runtime_error ( "incorrect result (second pass)" );
}
}
catch ( QmuParser::exception_type &e )
catch ( QmuParserError &e )
{
qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")";
return 1;
@ -1308,7 +1307,7 @@ int QmuParserTester::EqnTest ( const QString &a_str, double a_fRes, bool a_fPass
fVal[1] = p1->Eval(); // result from bytecode
if ( qFuzzyCompare( fVal[0], fVal[1] ) == false )
{
throw QmuParser::exception_type ( "Bytecode / string parsing mismatch." );
throw QmuParserError ( "Bytecode / string parsing mismatch." );
}
// Test copy and assignement operators
@ -1379,7 +1378,7 @@ int QmuParserTester::EqnTest ( const QString &a_str, double a_fRes, bool a_fPass
<< fVal[4] << ").";
}
}
catch ( QmuParser::exception_type &e )
catch ( QmuParserError &e )
{
if ( a_fPass )
{

View file

@ -23,9 +23,7 @@
#ifndef QMUPARSERTEST_H
#define QMUPARSERTEST_H
#include <string>
#include <cstdlib>
#include <numeric> // for accumulate
#include "qmuparser_global.h"
#include "qmuparser.h"
#include <QString>
@ -47,7 +45,7 @@ namespace Test
*
* (C) 2004-2011 Ingo Berg
*/
class QmuParserTester // final
class QMUPARSERSHARED_EXPORT QmuParserTester // final
{
public:
typedef int ( QmuParserTester::*testfun_type ) ();
@ -186,7 +184,7 @@ private:
{
if ( a_iArgc == false)
{
throw qmu::QmuParser::exception_type ( "too few arguments for function FirstArg." );
throw QmuParserError ( "too few arguments for function FirstArg." );
}
return a_afArg[0];
@ -196,7 +194,7 @@ private:
{
if ( a_iArgc == false)
{
throw qmu::QmuParser::exception_type ( "too few arguments for function LastArg." );
throw QmuParserError ( "too few arguments for function LastArg." );
}
return a_afArg[a_iArgc - 1];
@ -206,7 +204,7 @@ private:
{
if ( a_iArgc == false)
{
throw qmu::QmuParser::exception_type ( "too few arguments for function sum." );
throw QmuParserError ( "too few arguments for function sum." );
}
qreal fRes = 0;

View file

@ -232,7 +232,7 @@ public:
*
* 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
* @throw QmuParserError if #a_iIdx<0 or #m_iType!=cmSTRING
*/
void SetIdx ( int a_iIdx )
{
@ -250,7 +250,7 @@ public:
*
* 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
* @throw QmuParserError 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
@ -327,7 +327,7 @@ public:
* @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:
* @throw QmuParserError if token type is non of:
* <ul>
* <li>cmFUNC</li>
* <li>cmSTRFUNC</li>
@ -348,7 +348,7 @@ public:
* @brief Get value of the token.
*
* Only applicable to variable and value tokens.
* @throw exception_type if token is no value/variable token.
* @throw QmuParserError if token is no value/variable token.
*/
TBase GetVal() const
{
@ -359,107 +359,39 @@ public:
case cmVAR:
return * ( reinterpret_cast<TBase*>(m_pTok) );
case cmLE:
Q_UNREACHABLE();
break;
case cmGE:
Q_UNREACHABLE();
break;
case cmNEQ:
Q_UNREACHABLE();
break;
case cmEQ:
Q_UNREACHABLE();
break;
case cmLT:
Q_UNREACHABLE();
break;
case cmGT:
Q_UNREACHABLE();
break;
case cmADD:
Q_UNREACHABLE();
break;
case cmSUB:
Q_UNREACHABLE();
break;
case cmMUL:
Q_UNREACHABLE();
break;
case cmDIV:
Q_UNREACHABLE();
break;
case cmPOW:
Q_UNREACHABLE();
break;
case cmLAND:
Q_UNREACHABLE();
break;
case cmLOR:
Q_UNREACHABLE();
break;
case cmASSIGN:
Q_UNREACHABLE();
break;
case cmBO:
Q_UNREACHABLE();
break;
case cmBC:
Q_UNREACHABLE();
break;
case cmIF:
Q_UNREACHABLE();
break;
case cmELSE:
Q_UNREACHABLE();
break;
case cmENDIF:
Q_UNREACHABLE();
break;
case cmARG_SEP:
Q_UNREACHABLE();
break;
case cmVARPOW2:
Q_UNREACHABLE();
break;
case cmVARPOW3:
Q_UNREACHABLE();
break;
case cmVARPOW4:
Q_UNREACHABLE();
break;
case cmVARMUL:
Q_UNREACHABLE();
break;
case cmPOW2:
Q_UNREACHABLE();
break;
case cmFUNC:
Q_UNREACHABLE();
break;
case cmFUNC_STR:
Q_UNREACHABLE();
break;
case cmFUNC_BULK:
Q_UNREACHABLE();
break;
case cmSTRING:
Q_UNREACHABLE();
break;
case cmOPRT_BIN:
Q_UNREACHABLE();
break;
case cmOPRT_POSTFIX:
Q_UNREACHABLE();
break;
case cmOPRT_INFIX:
Q_UNREACHABLE();
break;
case cmEND:
Q_UNREACHABLE();
break;
case cmUNKNOWN:
Q_UNREACHABLE();
break;
case cmSTRING:
default:
throw QmuParserError ( ecVAL_EXPECTED );
}
@ -470,7 +402,7 @@ public:
* @brief Get address of a variable token.
*
* Valid only if m_iType==CmdVar.
* @throw exception_type if token is no variable token.
* @throw QmuParserError if token is no variable token.
*/
TBase* GetVar() const
{

View file

@ -254,15 +254,10 @@ QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken()
{
assert ( m_pParser );
#if defined(_UNICODE)
const char_type *szFormula = m_strFormula.toStdWString().c_str();
#else
const char_type *szFormula = m_strFormula.toStdString().c_str();
#endif
token_type tok;
// Ignore all non printable characters when reading the expression
while ( szFormula[m_iPos] > 0 && szFormula[m_iPos] <= 0x20 )
while ( m_strFormula.data()[m_iPos] > 0 && m_strFormula.data()[m_iPos] <= 0x20 )
{
++m_iPos;
}
@ -452,7 +447,7 @@ bool QmuParserTokenReader::IsBuiltIn ( token_type &a_Tok )
for ( int i = 0; i < pOprtDef.size(); ++i )
{
int len = pOprtDef.at ( i ).length();
if ( pOprtDef.at ( i ) == m_strFormula.mid ( m_iPos, m_iPos + len ) )
if ( pOprtDef.at ( i ) == m_strFormula.mid ( m_iPos, len ) )
{
switch ( i )
{
@ -596,23 +591,31 @@ bool QmuParserTokenReader::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 QmuParserTokenReader::IsEOF ( token_type &a_Tok ) Q_DECL_NOEXCEPT
bool QmuParserTokenReader::IsEOF ( token_type &a_Tok )
{
#if defined(_UNICODE)
const char_type* szFormula = m_strFormula.toStdWString().c_str();
#else
const char_type* szFormula = m_strFormula.toStdString().c_str();
#endif
//#if defined(_UNICODE)
// const char_type* szFormula = m_strFormula.toStdWString().c_str();
//#else
// const char_type* szFormula = m_strFormula.toStdString().c_str();
//#endif
// check for EOF
if ( szFormula[m_iPos] == false /*|| szFormula[m_iPos] == '\n'*/ )
if ( m_strFormula.data()[m_iPos] == false /*|| szFormula[m_iPos] == '\n'*/ )
{
if ( m_iSynFlags & noEND )
{
Error ( ecUNEXPECTED_EOF, m_iPos );
try
{
Error ( ecUNEXPECTED_EOF, m_iPos );
}
catch (qmu::QmuParserError &e)
{
qDebug() << "\n "
<< " Code:" << e.GetCode() << "(" << e.GetMsg() << ")";
throw e;
}
}
if ( m_iBrackets > 0 )
@ -756,7 +759,7 @@ bool QmuParserTokenReader::IsOprt ( token_type &a_Tok )
for ( ; it != m_pOprtDef->rend(); ++it )
{
const QString &sID = it->first;
if ( sID == m_strFormula.mid ( m_iPos, m_iPos + sID.length() ) )
if ( sID == m_strFormula.mid ( m_iPos, sID.length() ) )
{
a_Tok.Set ( it->second, strTok );
@ -891,7 +894,8 @@ bool QmuParserTokenReader::IsValTok ( token_type &a_Tok )
if ( ( *item ) ( m_strFormula.mid ( m_iPos ), &m_iPos, &fVal ) == 1 )
{
// 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2
strTok = m_strFormula.mid ( iStart, m_iPos-iStart );
//strTok = m_strFormula.mid ( iStart, m_iPos-iStart );
strTok = m_strFormula.mid ( iStart, m_iPos );
if ( m_iSynFlags & noVAL )
{
Error ( ecUNEXPECTED_VAL, m_iPos - strTok.length(), strTok );
@ -1050,16 +1054,15 @@ bool QmuParserTokenReader::IsUndefVarTok ( token_type &a_Tok ) Q_DECL_NOEXCEPT
* @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 QmuParserTokenReader::IsString ( token_type &a_Tok ) Q_DECL_NOEXCEPT
bool QmuParserTokenReader::IsString ( token_type &a_Tok )
{
if ( m_strFormula[m_iPos] != '"' )
{
return false;
}
QString strBuf ( m_strFormula[m_iPos + 1] );
QString strBuf (m_strFormula.mid(m_iPos + 1));
int iEnd ( 0 ), iSkip ( 0 );
// parser over escaped '\"' end replace them with '"'
@ -1105,7 +1108,7 @@ bool QmuParserTokenReader::IsString ( token_type &a_Tok ) Q_DECL_NOEXCEPT
* @param a_strTok [in] The token string representation associated with the error.
* @throw ParserException always throws thats the only purpose of this function.
*/
void QmuParserTokenReader::Error ( EErrorCodes a_iErrc, int a_iPos, const QString &a_sTok ) const
void Q_NORETURN QmuParserTokenReader::Error ( EErrorCodes a_iErrc, int a_iPos, const QString &a_sTok ) const
{
m_pParser->Error ( a_iErrc, a_iPos, a_sTok );
}

View file

@ -23,66 +23,53 @@
#ifndef QMUPARSERTOKENREADER_H
#define QMUPARSERTOKENREADER_H
#include <cassert>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <memory>
#include <stack>
#include <string>
#include "qmuparserdef.h"
#include "qmuparsertoken.h"
/** @file
@brief This file contains the parser token reader definition.
*/
/**
* @file
* @brief This file contains the parser token reader definition.
*/
namespace qmu
{
// Forward declaration
class QmuParserBase;
// Forward declaration
class QmuParserBase;
/** @brief Token reader for the ParserBase class.
/**
* @brief Token reader for the ParserBase class.
*
*/
class QmuParserTokenReader
{
private:
typedef QmuParserToken<qreal, QString> token_type;
public:
QmuParserTokenReader(QmuParserBase *a_pParent);
QmuParserTokenReader* Clone(QmuParserBase *a_pParent) const Q_DECL_NOEXCEPT;
*/
class QmuParserTokenReader
{
private:
void AddValIdent(identfun_type a_pCallback);
void SetVarCreator(facfun_type a_pFactory, void *pUserData);
void SetFormula(const QString &a_strFormula);
void SetArgSep(char_type cArgSep);
int GetPos() const Q_DECL_NOEXCEPT;
const QString& GetExpr() const Q_DECL_NOEXCEPT;
varmap_type& GetUsedVar();
QChar GetArgSep() const;
void IgnoreUndefVar(bool bIgnore);
void ReInit() Q_DECL_NOEXCEPT;
token_type ReadNextToken();
private:
typedef QmuParserToken<qreal, QString> token_type;
public:
QmuParserTokenReader(QmuParserBase *a_pParent);
QmuParserTokenReader* Clone(QmuParserBase *a_pParent) const Q_DECL_NOEXCEPT;
void AddValIdent(identfun_type a_pCallback);
void SetVarCreator(facfun_type a_pFactory, void *pUserData);
void SetFormula(const QString &a_strFormula);
void SetArgSep(char_type cArgSep);
int GetPos() const Q_DECL_NOEXCEPT;
const QString &GetExpr() const Q_DECL_NOEXCEPT;
varmap_type& GetUsedVar();
QChar GetArgSep() const;
void IgnoreUndefVar(bool bIgnore);
void ReInit() Q_DECL_NOEXCEPT;
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
{
/**
* @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"
@ -99,56 +86,54 @@ namespace qmu
noELSE = 1 << 13,
sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,
noANY = ~0 ///< All of he above flags set
};
};
QmuParserTokenReader(const QmuParserTokenReader &a_Reader);
QmuParserTokenReader& operator=(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT;
void Assign(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT;
QmuParserTokenReader(const QmuParserTokenReader &a_Reader);
QmuParserTokenReader& operator=(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT;
void Assign(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT;
void SetParent(QmuParserBase *a_pParent);
int ExtractToken(const QString &a_szCharSet, QString &a_strTok, int a_iPos) const Q_DECL_NOEXCEPT;
int ExtractOperatorToken(QString &a_sTok, int a_iPos) const;
void SetParent(QmuParserBase *a_pParent);
int ExtractToken(const QString &a_szCharSet, QString &a_strTok, int a_iPos) const Q_DECL_NOEXCEPT;
int ExtractOperatorToken(QString &a_sTok, int a_iPos) const;
bool IsBuiltIn(token_type &a_Tok);
bool IsArgSep(token_type &a_Tok);
bool IsEOF(token_type &a_Tok) Q_DECL_NOEXCEPT;
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) Q_DECL_NOEXCEPT;
bool IsString(token_type &a_Tok) Q_DECL_NOEXCEPT;
void Error(EErrorCodes a_iErrc,
int a_iPos = -1,
const QString &a_sTok = QString() ) 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) Q_DECL_NOEXCEPT;
bool IsString(token_type &a_Tok);
void Q_NORETURN Error(EErrorCodes a_iErrc, int a_iPos = -1, const QString &a_sTok = QString() ) const;
token_type& SaveBeforeReturn(const token_type &tok);
token_type& SaveBeforeReturn(const token_type &tok);
QmuParserBase *m_pParser;
QString m_strFormula;
int m_iPos;
int m_iSynFlags;
bool m_bIgnoreUndefVar;
QmuParserBase *m_pParser;
QString 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<identfun_type> m_vIdentFun; ///< Value token identification function
varmap_type m_UsedVar;
qreal m_fZero; ///< Dummy value of zero, referenced by undefined variables
int m_iBrackets;
token_type m_lastTok;
QChar m_cArgSep; ///< The character used for separating function arguments
};
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<identfun_type> m_vIdentFun; ///< Value token identification function
varmap_type m_UsedVar;
qreal m_fZero; ///< Dummy value of zero, referenced by undefined variables
int m_iBrackets; ///< Keep count open brackets
token_type m_lastTok;
QChar m_cArgSep; ///< The character used for separating function arguments
};
} // namespace qmu
#endif