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 \ -Wmissing-include-dirs -Wpacked -Wredundant-decls -Winline \
-Wswitch-default -Wswitch-enum -Wuninitialized -Wvariadic-macros \ -Wswitch-default -Wswitch-enum -Wuninitialized -Wvariadic-macros \
-Wlogical-op -Wnoexcept -Wmissing-noreturn -Wpointer-arith\ -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 -ftrapv
} }
} else { } else {

View File

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

View File

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

View File

@ -131,7 +131,7 @@ qreal QmuParser::Sum(const qreal *a_afArg, int a_iArgc)
{ {
if (a_iArgc == false) if (a_iArgc == false)
{ {
throw exception_type("too few arguments for function sum."); throw QmuParserError("too few arguments for function sum.");
} }
qreal fRes=0; qreal fRes=0;
for (int i=0; i<a_iArgc; ++i) 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) if (a_iArgc == false)
{ {
throw exception_type("too few arguments for function sum."); throw QmuParserError("too few arguments for function sum.");
} }
qreal fRes=0; qreal fRes=0;
for (int i=0; i<a_iArgc; ++i) 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) 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]; qreal fRes=a_afArg[0];
for (int i=0; i<a_iArgc; ++i) 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) 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]; qreal fRes=a_afArg[0];
for (int i=0; i<a_iArgc; ++i) for (int i=0; i<a_iArgc; ++i)

View File

@ -53,7 +53,7 @@ HEADERS += \
qmuparsertest.h \ qmuparsertest.h \
stable.h stable.h
VERSION = 2.2.3 VERSION = 2.2.4
unix { unix {
target.path = /usr/lib target.path = /usr/lib
@ -83,7 +83,7 @@ CONFIG(debug, debug|release){
-Wmissing-include-dirs -Wpacked -Wredundant-decls -Winline \ -Wmissing-include-dirs -Wpacked -Wredundant-decls -Winline \
-Wswitch-default -Wswitch-enum -Wuninitialized -Wvariadic-macros \ -Wswitch-default -Wswitch-enum -Wuninitialized -Wvariadic-macros \
-Wlogical-op -Wnoexcept -Wmissing-noreturn -Wpointer-arith\ -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 -ftrapv
} }
} else { } else {

View File

@ -27,6 +27,9 @@
#include <omp.h> #include <omp.h>
#endif #endif
#include "qmuparsererror.h"
#include "qmuparsertokenreader.h"
using namespace std; using namespace std;
/** /**
@ -438,19 +441,19 @@ void QmuParserBase::CheckOprt(const QString &a_sName, const QmuParserCallback &a
Q_UNREACHABLE(); Q_UNREACHABLE();
break; break;
case cmVARPOW2: case cmVARPOW2:
Q_UNREACHABLE(); // For optimization purposes
break; break;
case cmVARPOW3: case cmVARPOW3:
Q_UNREACHABLE(); // For optimization purposes
break; break;
case cmVARPOW4: case cmVARPOW4:
Q_UNREACHABLE(); // For optimization purposes
break; break;
case cmVARMUL: case cmVARMUL:
Q_UNREACHABLE(); // For optimization purposes
break; break;
case cmPOW2: case cmPOW2:
Q_UNREACHABLE(); // For optimization purposes
break; break;
case cmFUNC: case cmFUNC:
Q_UNREACHABLE(); Q_UNREACHABLE();
@ -937,7 +940,7 @@ const varmap_type& QmuParserBase::GetUsedVar() const
m_pParseFormula = &QmuParserBase::ParseString; m_pParseFormula = &QmuParserBase::ParseString;
m_pTokenReader->IgnoreUndefVar(false); m_pTokenReader->IgnoreUndefVar(false);
} }
catch (const exception_type &e) catch (const QmuParserError &e)
{ {
// Make sure to stay in string parse mode, dont call ReInit() // Make sure to stay in string parse mode, dont call ReInit()
// because it deletes the array with the used variables // 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. * @brief Execute a function that takes a single string argument.
* @param a_FunTok Function token. * @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, QmuParserBase::token_type QmuParserBase::ApplyStrFunc(const token_type &a_FunTok,
const QVector<token_type> &a_vArg) const 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. * @param iArgCount Number of Arguments actually gathered used only for multiarg functions.
* @post The result is pushed to the value stack * @post The result is pushed to the value stack
* @post The function token is removed from the 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 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; m_pParseFormula = &QmuParserBase::ParseCmdCode;
return (this->*m_pParseFormula)(); return (this->*m_pParseFormula)();
} }
catch (QmuParserError &exc) catch (qmu::QmuParserError &exc)
{ {
exc.SetFormula(m_pTokenReader->GetExpr()); exc.SetFormula(m_pTokenReader->GetExpr());
throw; 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 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 #ifndef QMUQPARSERBASE_H
#define QMUQPARSERBASE_H #define QMUQPARSERBASE_H
#include "qmuparser_global.h"
#include <QStack> #include <QStack>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
@ -51,17 +52,10 @@ namespace qmu
* Complementary to a set of internally implemented functions the parser is able to handle * Complementary to a set of internally implemented functions the parser is able to handle
* user defined functions and variables. * user defined functions and variables.
*/ */
class QmuParserBase class QMUPARSERSHARED_EXPORT QmuParserBase
{ {
friend class QmuParserTokenReader; friend class QmuParserTokenReader;
public: public:
/**
* @brief Type of the error class.
*
* Included for backwards compatibility.
*/
typedef QmuParserError exception_type;
QmuParserBase(); QmuParserBase();
QmuParserBase(const QmuParserBase &a_Parser); QmuParserBase(const QmuParserBase &a_Parser);
QmuParserBase& operator=(const QmuParserBase &a_Parser) Q_DECL_NOEXCEPT; QmuParserBase& operator=(const QmuParserBase &a_Parser) Q_DECL_NOEXCEPT;
@ -112,7 +106,7 @@ public:
const QString& ValidInfixOprtChars() const; const QString& ValidInfixOprtChars() const;
void SetArgSep(char_type cArgSep); void SetArgSep(char_type cArgSep);
QChar GetArgSep() const; 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, * @fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun,
* bool a_bAllowOpt = true) * bool a_bAllowOpt = true)

View File

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

View File

@ -109,7 +109,7 @@ QmuParserErrorMsg::QmuParserErrorMsg()
* @brief Default constructor. * @brief Default constructor.
*/ */
QmuParserError::QmuParserError() 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() ) m_ErrMsg ( QmuParserErrorMsg::Instance() )
{} {}
@ -120,7 +120,7 @@ QmuParserError::QmuParserError()
* It does not contain any information but the error code. * It does not contain any information but the error code.
*/ */
QmuParserError::QmuParserError ( EErrorCodes a_iErrc ) 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_ErrMsg ( QmuParserErrorMsg::Instance() )
{ {
m_sMsg = m_ErrMsg[m_iErrc]; m_sMsg = m_ErrMsg[m_iErrc];
@ -133,7 +133,7 @@ QmuParserError::QmuParserError ( EErrorCodes a_iErrc )
* @brief Construct an error from a message text. * @brief Construct an error from a message text.
*/ */
QmuParserError::QmuParserError ( const QString &sMsg ) 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() ) 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. * @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 ) 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_ErrMsg ( QmuParserErrorMsg::Instance() )
{ {
m_sMsg = m_ErrMsg[m_iErrc]; 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. * @param [in] sTok The token string related to this error.
*/ */
QmuParserError::QmuParserError ( EErrorCodes a_iErrc, int a_iPos, const QString &sTok ) 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_ErrMsg ( QmuParserErrorMsg::Instance() )
{ {
m_sMsg = m_ErrMsg[m_iErrc]; 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. * @param [in] sTok The token string related to this error.
*/ */
QmuParserError::QmuParserError ( const QString &szMsg, int iPos, const QString &sTok ) 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() ) m_ErrMsg ( QmuParserErrorMsg::Instance() )
{ {
ReplaceSubString ( m_sMsg, "$POS$", QString().setNum ( m_iPos ) ); ReplaceSubString ( m_sMsg, "$POS$", QString().setNum ( m_iPos ) );
@ -187,7 +187,7 @@ QmuParserError::QmuParserError ( const QString &szMsg, int iPos, const QString &
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** @brief Copy constructor. */ /** @brief Copy constructor. */
QmuParserError::QmuParserError ( const QmuParserError &a_Obj ) 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() ) 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; return *this;
} }
//---------------------------------------------------------------------------------------------------------------------
QmuParserError::~QmuParserError()
{}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief Replace all ocuurences of a substring with another string. * @brief Replace all ocuurences of a substring with another string.
@ -309,4 +305,5 @@ EErrorCodes QmuParserError::GetCode() const
{ {
return m_iErrc; return m_iErrc;
} }
} // namespace qmu } // namespace qmu

View File

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

View File

@ -23,10 +23,8 @@
#include "qmuparsertest.h" #include "qmuparsertest.h"
#include <QtMath> #include <QtMath>
#include <QString> #include <QString>
#include <QDebug>
#include <cstdio> #include "qmuparsererror.h"
#include <iostream>
#include <limits>
using namespace std; using namespace std;
@ -64,32 +62,33 @@ QmuParserTester::QmuParserTester()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
int QmuParserTester::IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal ) 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; return 0;
} }
unsigned iVal ( 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; 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 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestInterface passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestInterface failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -157,11 +156,11 @@ int QmuParserTester::TestStrArg()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestStrArg passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestStrArg failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -232,11 +231,11 @@ int QmuParserTester::TestBinOprt()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestBinOprt passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestBinOprt failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -260,7 +259,7 @@ int QmuParserTester::TestNames()
{ \ { \
p.Define##DOMAIN(EXPR, ARG); \ p.Define##DOMAIN(EXPR, ARG); \
} \ } \
catch (QmuParser::exception_type&) \ catch (QmuParserError &) \
{ \ { \
iErr = (FAIL==false) ? 0 : 1; \ iErr = (FAIL==false) ? 0 : 1; \
} \ } \
@ -345,11 +344,11 @@ int QmuParserTester::TestNames()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestNames passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestNames failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -398,11 +397,11 @@ int QmuParserTester::TestSyntax()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestSyntax passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestSyntax failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -531,11 +530,11 @@ int QmuParserTester::TestVarConst()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestVarConst passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestVarConst failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -629,11 +628,11 @@ int QmuParserTester::TestMultiArg()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestMultiArg passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestMultiArg failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -698,11 +697,11 @@ int QmuParserTester::TestInfixOprt()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestInfixOprt passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestInfixOprt failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -754,11 +753,11 @@ int QmuParserTester::TestPostFix()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestPostFix passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestPostFix failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -792,6 +791,8 @@ int QmuParserTester::TestExpression()
iStat += EqnTest ( "(2*b+1)*4", ( 2 * b + 1 ) * 4, true ); iStat += EqnTest ( "(2*b+1)*4", ( 2 * b + 1 ) * 4, true );
iStat += EqnTest ( "4*(2*b+1)", ( 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 // operator precedencs
iStat += EqnTest ( "1+2-3*4/5^6", 2.99923, true ); iStat += EqnTest ( "1+2-3*4/5^6", 2.99923, true );
@ -839,11 +840,11 @@ int QmuParserTester::TestExpression()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestExpression passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestExpression failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -949,11 +950,11 @@ int QmuParserTester::TestIfThenElse()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestIfThenElse passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestIfThenElse failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -1047,11 +1048,11 @@ int QmuParserTester::TestException()
if ( iStat == 0 ) if ( iStat == 0 )
{ {
qDebug() << "passed"; qDebug() << "TestException passed";
} }
else else
{ {
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n TestException failed with " << iStat << " errors";
} }
return iStat; return iStat;
@ -1076,7 +1077,7 @@ void QmuParserTester::Run()
iStat += ( this->*m_vTestFun[i] ) (); iStat += ( this->*m_vTestFun[i] ) ();
} }
} }
catch ( QmuParser::exception_type &e ) catch ( QmuParserError &e )
{ {
qDebug() << "\n" << e.GetMsg(); qDebug() << "\n" << e.GetMsg();
qDebug() << e.GetToken(); 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.SetExpr ( a_str );
p.Eval(); p.Eval();
} }
catch ( QmuParserError &e ) catch ( const qmu::QmuParserError &e )
{ {
// 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() ) )
{ {
qDebug() << "\n " qDebug() << "\n " << "Expression: " << a_str << " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
<< "Expression: " << a_str
<< " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
<< " Expected:" << a_iErrc; << " 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)" ); throw std::runtime_error ( "incorrect result (second pass)" );
} }
} }
catch ( QmuParser::exception_type &e ) catch ( QmuParserError &e )
{ {
qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")"; qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")";
return 1; 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 fVal[1] = p1->Eval(); // result from bytecode
if ( qFuzzyCompare( fVal[0], fVal[1] ) == false ) 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 // Test copy and assignement operators
@ -1379,7 +1378,7 @@ int QmuParserTester::EqnTest ( const QString &a_str, double a_fRes, bool a_fPass
<< fVal[4] << ")."; << fVal[4] << ").";
} }
} }
catch ( QmuParser::exception_type &e ) catch ( QmuParserError &e )
{ {
if ( a_fPass ) if ( a_fPass )
{ {

View File

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

View File

@ -232,7 +232,7 @@ public:
* *
* In cmSTRFUNC - This is the index to a string table in the main parser. * 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. * @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 ) void SetIdx ( int a_iIdx )
{ {
@ -250,7 +250,7 @@ public:
* *
* In cmSTRFUNC - This is the index to a string table in the main parser. * 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). * @return The index the result will take in the Bytecode calculatin array (#m_iIdx).
*/ */
int GetIdx() const int GetIdx() const
@ -327,7 +327,7 @@ public:
* @brief Return the address of the callback function assoziated with function and operator tokens. * @brief Return the address of the callback function assoziated with function and operator tokens.
* *
* @return The pointer stored in #m_pTok. * @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> * <ul>
* <li>cmFUNC</li> * <li>cmFUNC</li>
* <li>cmSTRFUNC</li> * <li>cmSTRFUNC</li>
@ -348,7 +348,7 @@ public:
* @brief Get value of the token. * @brief Get value of the token.
* *
* Only applicable to variable and value tokens. * 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 TBase GetVal() const
{ {
@ -359,107 +359,39 @@ public:
case cmVAR: case cmVAR:
return * ( reinterpret_cast<TBase*>(m_pTok) ); return * ( reinterpret_cast<TBase*>(m_pTok) );
case cmLE: case cmLE:
Q_UNREACHABLE();
break;
case cmGE: case cmGE:
Q_UNREACHABLE();
break;
case cmNEQ: case cmNEQ:
Q_UNREACHABLE();
break;
case cmEQ: case cmEQ:
Q_UNREACHABLE();
break;
case cmLT: case cmLT:
Q_UNREACHABLE();
break;
case cmGT: case cmGT:
Q_UNREACHABLE();
break;
case cmADD: case cmADD:
Q_UNREACHABLE();
break;
case cmSUB: case cmSUB:
Q_UNREACHABLE();
break;
case cmMUL: case cmMUL:
Q_UNREACHABLE();
break;
case cmDIV: case cmDIV:
Q_UNREACHABLE();
break;
case cmPOW: case cmPOW:
Q_UNREACHABLE();
break;
case cmLAND: case cmLAND:
Q_UNREACHABLE();
break;
case cmLOR: case cmLOR:
Q_UNREACHABLE();
break;
case cmASSIGN: case cmASSIGN:
Q_UNREACHABLE();
break;
case cmBO: case cmBO:
Q_UNREACHABLE();
break;
case cmBC: case cmBC:
Q_UNREACHABLE();
break;
case cmIF: case cmIF:
Q_UNREACHABLE();
break;
case cmELSE: case cmELSE:
Q_UNREACHABLE();
break;
case cmENDIF: case cmENDIF:
Q_UNREACHABLE();
break;
case cmARG_SEP: case cmARG_SEP:
Q_UNREACHABLE();
break;
case cmVARPOW2: case cmVARPOW2:
Q_UNREACHABLE();
break;
case cmVARPOW3: case cmVARPOW3:
Q_UNREACHABLE();
break;
case cmVARPOW4: case cmVARPOW4:
Q_UNREACHABLE();
break;
case cmVARMUL: case cmVARMUL:
Q_UNREACHABLE();
break;
case cmPOW2: case cmPOW2:
Q_UNREACHABLE();
break;
case cmFUNC: case cmFUNC:
Q_UNREACHABLE();
break;
case cmFUNC_STR: case cmFUNC_STR:
Q_UNREACHABLE();
break;
case cmFUNC_BULK: case cmFUNC_BULK:
Q_UNREACHABLE();
break;
case cmSTRING:
Q_UNREACHABLE();
break;
case cmOPRT_BIN: case cmOPRT_BIN:
Q_UNREACHABLE();
break;
case cmOPRT_POSTFIX: case cmOPRT_POSTFIX:
Q_UNREACHABLE();
break;
case cmOPRT_INFIX: case cmOPRT_INFIX:
Q_UNREACHABLE();
break;
case cmEND: case cmEND:
Q_UNREACHABLE();
break;
case cmUNKNOWN: case cmUNKNOWN:
Q_UNREACHABLE(); case cmSTRING:
break;
default: default:
throw QmuParserError ( ecVAL_EXPECTED ); throw QmuParserError ( ecVAL_EXPECTED );
} }
@ -470,7 +402,7 @@ public:
* @brief Get address of a variable token. * @brief Get address of a variable token.
* *
* Valid only if m_iType==CmdVar. * 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 TBase* GetVar() const
{ {

View File

@ -254,15 +254,10 @@ QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken()
{ {
assert ( m_pParser ); 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; token_type tok;
// Ignore all non printable characters when reading the expression // 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; ++m_iPos;
} }
@ -452,7 +447,7 @@ bool QmuParserTokenReader::IsBuiltIn ( token_type &a_Tok )
for ( int i = 0; i < pOprtDef.size(); ++i ) for ( int i = 0; i < pOprtDef.size(); ++i )
{ {
int len = pOprtDef.at ( i ).length(); 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 ) switch ( i )
{ {
@ -596,23 +591,31 @@ bool QmuParserTokenReader::IsArgSep ( token_type &a_Tok )
* *
* @return true if an end of formula is found false otherwise. * @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. * @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 * @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) //#if defined(_UNICODE)
const char_type* szFormula = m_strFormula.toStdWString().c_str(); // const char_type* szFormula = m_strFormula.toStdWString().c_str();
#else //#else
const char_type* szFormula = m_strFormula.toStdString().c_str(); // const char_type* szFormula = m_strFormula.toStdString().c_str();
#endif //#endif
// check for EOF // 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 ) 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 ) if ( m_iBrackets > 0 )
@ -756,7 +759,7 @@ bool QmuParserTokenReader::IsOprt ( token_type &a_Tok )
for ( ; it != m_pOprtDef->rend(); ++it ) for ( ; it != m_pOprtDef->rend(); ++it )
{ {
const QString &sID = it->first; 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 ); 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 ) 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 // 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 ) if ( m_iSynFlags & noVAL )
{ {
Error ( ecUNEXPECTED_VAL, m_iPos - strTok.length(), strTok ); 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. * @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. * @return true if a string token has been found.
* @sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok * @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] != '"' ) if ( m_strFormula[m_iPos] != '"' )
{ {
return false; return false;
} }
QString strBuf ( m_strFormula[m_iPos + 1] ); QString strBuf (m_strFormula.mid(m_iPos + 1));
int iEnd ( 0 ), iSkip ( 0 ); int iEnd ( 0 ), iSkip ( 0 );
// parser over escaped '\"' end replace them with '"' // 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. * @param a_strTok [in] The token string representation associated with the error.
* @throw ParserException always throws thats the only purpose of this function. * @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 ); m_pParser->Error ( a_iErrc, a_iPos, a_sTok );
} }

View File

@ -23,66 +23,53 @@
#ifndef QMUPARSERTOKENREADER_H #ifndef QMUPARSERTOKENREADER_H
#define 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 "qmuparserdef.h"
#include "qmuparsertoken.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 namespace qmu
{ {
// Forward declaration // Forward declaration
class QmuParserBase; 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;
*/ void AddValIdent(identfun_type a_pCallback);
class QmuParserTokenReader void SetVarCreator(facfun_type a_pFactory, void *pUserData);
{ void SetFormula(const QString &a_strFormula);
private: 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; /**
* @brief Syntax codes.
public: *
* The syntax codes control the syntax check done during the first time parsing of
QmuParserTokenReader(QmuParserBase *a_pParent); * the expression string. They are flags that indicate which tokens are allowed next
QmuParserTokenReader* Clone(QmuParserBase *a_pParent) const Q_DECL_NOEXCEPT; * if certain tokens are identified.
*/
void AddValIdent(identfun_type a_pCallback); enum ESynCodes
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
{
noBO = 1 << 0, ///< to avoid i.e. "cos(7)(" noBO = 1 << 0, ///< to avoid i.e. "cos(7)("
noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()" noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"
noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14" noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
@ -99,56 +86,54 @@ namespace qmu
noELSE = 1 << 13, noELSE = 1 << 13,
sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP, sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,
noANY = ~0 ///< All of he above flags set noANY = ~0 ///< All of he above flags set
}; };
QmuParserTokenReader(const QmuParserTokenReader &a_Reader); QmuParserTokenReader(const QmuParserTokenReader &a_Reader);
QmuParserTokenReader& operator=(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT; QmuParserTokenReader& operator=(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT;
void Assign(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT; void Assign(const QmuParserTokenReader &a_Reader) Q_DECL_NOEXCEPT;
void SetParent(QmuParserBase *a_pParent); void SetParent(QmuParserBase *a_pParent);
int ExtractToken(const QString &a_szCharSet, QString &a_strTok, int a_iPos) const Q_DECL_NOEXCEPT; 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; int ExtractOperatorToken(QString &a_sTok, int a_iPos) const;
bool IsBuiltIn(token_type &a_Tok); bool IsBuiltIn(token_type &a_Tok);
bool IsArgSep(token_type &a_Tok); bool IsArgSep(token_type &a_Tok);
bool IsEOF(token_type &a_Tok) Q_DECL_NOEXCEPT; bool IsEOF(token_type &a_Tok);
bool IsInfixOpTok(token_type &a_Tok); bool IsInfixOpTok(token_type &a_Tok);
bool IsFunTok(token_type &a_Tok); bool IsFunTok(token_type &a_Tok);
bool IsPostOpTok(token_type &a_Tok); bool IsPostOpTok(token_type &a_Tok);
bool IsOprt(token_type &a_Tok); bool IsOprt(token_type &a_Tok);
bool IsValTok(token_type &a_Tok); bool IsValTok(token_type &a_Tok);
bool IsVarTok(token_type &a_Tok); bool IsVarTok(token_type &a_Tok);
bool IsStrVarTok(token_type &a_Tok); bool IsStrVarTok(token_type &a_Tok);
bool IsUndefVarTok(token_type &a_Tok) Q_DECL_NOEXCEPT; bool IsUndefVarTok(token_type &a_Tok) Q_DECL_NOEXCEPT;
bool IsString(token_type &a_Tok) Q_DECL_NOEXCEPT; bool IsString(token_type &a_Tok);
void Error(EErrorCodes a_iErrc, void Q_NORETURN Error(EErrorCodes a_iErrc, int a_iPos = -1, const QString &a_sTok = QString() ) const;
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; QmuParserBase *m_pParser;
QString m_strFormula; QString m_strFormula;
int m_iPos; int m_iPos;
int m_iSynFlags; int m_iSynFlags;
bool m_bIgnoreUndefVar; bool m_bIgnoreUndefVar;
const funmap_type *m_pFunDef; const funmap_type *m_pFunDef;
const funmap_type *m_pPostOprtDef; const funmap_type *m_pPostOprtDef;
const funmap_type *m_pInfixOprtDef; const funmap_type *m_pInfixOprtDef;
const funmap_type *m_pOprtDef; const funmap_type *m_pOprtDef;
const valmap_type *m_pConstDef; const valmap_type *m_pConstDef;
const strmap_type *m_pStrVarDef; const strmap_type *m_pStrVarDef;
varmap_type *m_pVarDef; ///< The only non const pointer to parser internals varmap_type *m_pVarDef; ///< The only non const pointer to parser internals
facfun_type m_pFactory; facfun_type m_pFactory;
void *m_pFactoryData; void *m_pFactoryData;
std::list<identfun_type> m_vIdentFun; ///< Value token identification function std::list<identfun_type> m_vIdentFun; ///< Value token identification function
varmap_type m_UsedVar; varmap_type m_UsedVar;
qreal m_fZero; ///< Dummy value of zero, referenced by undefined variables qreal m_fZero; ///< Dummy value of zero, referenced by undefined variables
int m_iBrackets; int m_iBrackets; ///< Keep count open brackets
token_type m_lastTok; token_type m_lastTok;
QChar m_cArgSep; ///< The character used for separating function arguments QChar m_cArgSep; ///< The character used for separating function arguments
}; };
} // namespace qmu } // namespace qmu
#endif #endif