Apply project code style.

--HG--
branch : feature
This commit is contained in:
dismine 2014-04-30 08:32:29 +03:00
parent 0b49785255
commit 2c77a73343
17 changed files with 7033 additions and 6698 deletions

View file

@ -24,29 +24,49 @@
#include <QtMath> #include <QtMath>
#include <QtGlobal> #include <QtGlobal>
//--- Standard includes ------------------------------------------------------------------------
#include <algorithm>
#include <numeric>
using namespace std; using namespace std;
/** \file /**
\brief Implementation of the standard floating point QmuParser. * @file
* @brief Implementation of the standard floating point QmuParser.
*/ */
/** \brief Namespace for mathematical applications. */ /**
* @brief Namespace for mathematical applications.
*/
namespace qmu namespace qmu
{ {
//---------------------------------------------------------------------------
// Trigonometric function // Trigonometric function
qreal QmuParser::Sinh(qreal v) { return sinh(v); } qreal QmuParser::Sinh(qreal v)
qreal QmuParser::Cosh(qreal v) { return cosh(v); } {
qreal QmuParser::Tanh(qreal v) { return tanh(v); } return sinh(v);
qreal QmuParser::ASinh(qreal v) { return log(v + qSqrt(v * v + 1)); } }
qreal QmuParser::ACosh(qreal v) { return log(v + qSqrt(v * v - 1)); }
qreal QmuParser::ATanh(qreal v) { return ((qreal)0.5 * log((1 + v) / (1 - v))); }
//--------------------------------------------------------------------------- qreal QmuParser::Cosh(qreal v)
{
return cosh(v);
}
qreal QmuParser::Tanh(qreal v)
{
return tanh(v);
}
qreal QmuParser::ASinh(qreal v)
{
return log(v + qSqrt(v * v + 1));
}
qreal QmuParser::ACosh(qreal v)
{
return log(v + qSqrt(v * v - 1));
}
qreal QmuParser::ATanh(qreal v)
{
return ((qreal)0.5 * log((1 + v) / (1 - v)));
}
//----------------------------------------------------------------------------------------------------------------------
// Logarithm functions // Logarithm functions
// Logarithm base 2 // Logarithm base 2
@ -54,9 +74,10 @@ namespace qmu
{ {
#ifdef MUP_MATH_EXCEPTIONS #ifdef MUP_MATH_EXCEPTIONS
if (v<=0) if (v<=0)
{
throw QmuParserError(ecDOMAIN_ERROR, "Log2"); throw QmuParserError(ecDOMAIN_ERROR, "Log2");
}
#endif #endif
return log(v)/log((qreal)2); return log(v)/log((qreal)2);
} }
@ -65,63 +86,80 @@ namespace qmu
{ {
#ifdef MUP_MATH_EXCEPTIONS #ifdef MUP_MATH_EXCEPTIONS
if (v<=0) if (v<=0)
{
throw QmuParserError(ecDOMAIN_ERROR, "Log10"); throw QmuParserError(ecDOMAIN_ERROR, "Log10");
}
#endif #endif
return log10(v); return log10(v);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// misc // misc
qreal QmuParser::Abs(qreal v) { return qAbs(v); } qreal QmuParser::Abs(qreal v)
qreal QmuParser::Rint(qreal v) { return qFloor(v + (qreal)0.5); } {
qreal QmuParser::Sign(qreal v) { return (qreal)((v<0) ? -1 : (v>0) ? 1 : 0); } return qAbs(v);
}
//--------------------------------------------------------------------------- qreal QmuParser::Rint(qreal v)
/** \brief Callback for the unary minus operator. {
\param v The value to negate return qFloor(v + (qreal)0.5);
\return -v }
qreal QmuParser::Sign(qreal v)
{
return (qreal)((v<0) ? -1 : (v>0) ? 1 : 0);
}
//----------------------------------------------------------------------------------------------------------------------
/**
* @brief Callback for the unary minus operator.
* @param v The value to negate
* @return -v
*/ */
qreal QmuParser::UnaryMinus(qreal v) qreal QmuParser::UnaryMinus(qreal v)
{ {
return -v; return -v;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Callback for adding multiple values. /**
\param [in] a_afArg Vector with the function arguments * @brief Callback for adding multiple values.
\param [in] a_iArgc The size of a_afArg * @param [in] a_afArg Vector with the function arguments
* @param [in] a_iArgc The size of a_afArg
*/ */
qreal QmuParser::Sum(const qreal *a_afArg, int a_iArgc) qreal QmuParser::Sum(const qreal *a_afArg, int a_iArgc)
{ {
if (!a_iArgc) if (!a_iArgc)
{
throw exception_type("too few arguments for function sum."); throw exception_type("too few arguments for function sum.");
}
qreal fRes=0; qreal fRes=0;
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i]; for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
return fRes; return fRes;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Callback for averaging multiple values. /**
\param [in] a_afArg Vector with the function arguments * @brief Callback for averaging multiple values.
\param [in] a_iArgc The size of a_afArg * @param [in] a_afArg Vector with the function arguments
* @param [in] a_iArgc The size of a_afArg
*/ */
qreal QmuParser::Avg(const qreal *a_afArg, int a_iArgc) qreal QmuParser::Avg(const qreal *a_afArg, int a_iArgc)
{ {
if (!a_iArgc) if (!a_iArgc)
{
throw exception_type("too few arguments for function sum."); throw exception_type("too few arguments for function sum.");
}
qreal fRes=0; qreal fRes=0;
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i]; for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
return fRes/(qreal)a_iArgc; return fRes/(qreal)a_iArgc;
} }
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Callback for determining the minimum value out of a vector. * @brief Callback for determining the minimum value out of a vector.
\param [in] a_afArg Vector with the function arguments * @param [in] a_afArg Vector with the function arguments
\param [in] a_iArgc The size of a_afArg * @param [in] a_iArgc The size of a_afArg
*/ */
qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc) qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
{ {
@ -129,7 +167,6 @@ qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
{ {
throw exception_type("too few arguments for function min."); throw exception_type("too few arguments for function min.");
} }
qreal fRes=a_afArg[0]; qreal fRes=a_afArg[0];
for (int i=0; i<a_iArgc; ++i) for (int i=0; i<a_iArgc; ++i)
{ {
@ -138,10 +175,11 @@ qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
return fRes; return fRes;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Callback for determining the maximum value out of a vector. /**
\param [in] a_afArg Vector with the function arguments * @brief Callback for determining the maximum value out of a vector.
\param [in] a_iArgc The size of a_afArg * @param [in] a_afArg Vector with the function arguments
* @param [in] a_iArgc The size of a_afArg
*/ */
qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc) qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
{ {
@ -149,7 +187,6 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
{ {
throw exception_type("too few arguments for function min."); throw exception_type("too few arguments for function min.");
} }
qreal fRes=a_afArg[0]; qreal fRes=a_afArg[0];
for (int i=0; i<a_iArgc; ++i) for (int i=0; i<a_iArgc; ++i)
{ {
@ -158,13 +195,13 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
return fRes; return fRes;
} }
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Default value recognition callback. * @brief Default value recognition callback.
\param [in] a_szExpr Pointer to the expression * @param [in] a_szExpr Pointer to the expression
\param [in, out] a_iPos Pointer to an index storing the current position within the expression * @param [in, out] a_iPos Pointer to an index storing the current position within the expression
\param [out] a_fVal Pointer where the value should be stored in case one is found. * @param [out] a_fVal Pointer where the value should be stored in case one is found.
\return 1 if a value was found 0 otherwise. * @return 1 if a value was found 0 otherwise.
*/ */
int QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal) int QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal)
{ {
@ -182,21 +219,22 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
if (iEnd==(stringstream_type::pos_type)-1) if (iEnd==(stringstream_type::pos_type)-1)
{
return 0; return 0;
}
*a_iPos += (int)iEnd; *a_iPos += (int)iEnd;
*a_fVal = fVal; *a_fVal = fVal;
return 1; return 1;
} }
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Constructor. * @brief Constructor.
*
Call QmuParserBase class constructor and trigger Function, Operator and Constant initialization. * Call QmuParserBase class constructor and trigger Function, Operator and Constant initialization.
*/ */
QmuParser::QmuParser() QmuParser::QmuParser():QmuParserBase()
:QmuParserBase()
{ {
AddValIdent(IsVal); AddValIdent(IsVal);
@ -206,12 +244,13 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
InitOprt(); InitOprt();
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Define the character sets. /**
\sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars * @brief Define the character sets.
* @sa DefineNameChars, DefineOprtChars, DefineInfixOprtChars
This function is used for initializing the default character sets that define *
the characters to be useable in function and variable names and operators. * This function is used for initializing the default character sets that define
* the characters to be useable in function and variable names and operators.
*/ */
void QmuParser::InitCharSets() void QmuParser::InitCharSets()
{ {
@ -220,8 +259,10 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
DefineInfixOprtChars( "/+-*^?<>=#!$%&|~'_" ); DefineInfixOprtChars( "/+-*^?<>=#!$%&|~'_" );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Initialize the default functions. */ /**
* @brief Initialize the default functions.
*/
void QmuParser::InitFun() void QmuParser::InitFun()
{ {
// trigonometric functions // trigonometric functions
@ -259,11 +300,12 @@ void QmuParser::InitFun()
DefineFun("max", Max); DefineFun("max", Max);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Initialize constants. /**
* @brief Initialize constants.
By default the QmuParser recognizes two constants. Pi ("pi") and the eulerian *
number ("_e"). * By default the QmuParser recognizes two constants. Pi ("pi") and the eulerian
* number ("_e").
*/ */
void QmuParser::InitConst() void QmuParser::InitConst()
{ {
@ -271,17 +313,18 @@ void QmuParser::InitFun()
DefineConst("_e", (qreal)M_E); DefineConst("_e", (qreal)M_E);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Initialize operators. /**
* @brief Initialize operators.
By default only the unary minus operator is added. *
* By default only the unary minus operator is added.
*/ */
void QmuParser::InitOprt() void QmuParser::InitOprt()
{ {
DefineInfixOprt("-", UnaryMinus); DefineInfixOprt("-", UnaryMinus);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/) void QmuParser::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
{ {
// this is just sample code to illustrate modifying variable names on the fly. // this is just sample code to illustrate modifying variable names on the fly.
@ -306,22 +349,21 @@ void QmuParser::InitFun()
*/ */
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Numerically differentiate with regard to a variable. /**
\param [in] a_Var Pointer to the differentiation variable. * @brief Numerically differentiate with regard to a variable.
\param [in] a_fPos Position at which the differentiation should take place. * @param [in] a_Var Pointer to the differentiation variable.
\param [in] a_fEpsilon Epsilon used for the numerical differentiation. * @param [in] a_fPos Position at which the differentiation should take place.
* @param [in] a_fEpsilon Epsilon used for the numerical differentiation.
Numerical differentiation uses a 5 point operator yielding a 4th order *
formula. The default value for epsilon is 0.00074 which is * Numerical differentiation uses a 5 point operator yielding a 4th order
numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muQmuParser * formula. The default value for epsilon is 0.00074 which is
forum: * numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muQmuParser
* forum:
http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843 *
* http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843
*/ */
qreal QmuParser::Diff(qreal *a_Var, qreal QmuParser::Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon) const
qreal a_fPos,
qreal a_fEpsilon) const
{ {
qreal fRes(0), qreal fRes(0),
fBuf(*a_Var), fBuf(*a_Var),
@ -331,7 +373,9 @@ void QmuParser::InitFun()
// Backwards compatible calculation of epsilon inc case the user doesnt provide // Backwards compatible calculation of epsilon inc case the user doesnt provide
// his own epsilon // his own epsilon
if (fEpsilon==0) if (fEpsilon==0)
{
fEpsilon = (a_fPos==0) ? (qreal)1e-10 : (qreal)1e-7 * a_fPos; fEpsilon = (a_fPos==0) ? (qreal)1e-10 : (qreal)1e-7 * a_fPos;
}
*a_Var = a_fPos+2 * fEpsilon; f[0] = Eval(); *a_Var = a_fPos+2 * fEpsilon; f[0] = Eval();
*a_Var = a_fPos+1 * fEpsilon; f[1] = Eval(); *a_Var = a_fPos+1 * fEpsilon; f[1] = Eval();

View file

@ -24,29 +24,27 @@
#define QMUPARSER_H #define QMUPARSER_H
#include "qmuparser_global.h" #include "qmuparser_global.h"
//--- Parser includes --------------------------------------------------------------------------
#include "qmuparserbase.h" #include "qmuparserbase.h"
/** \file /**
\brief Definition of the standard floating point parser. * @file
* @brief Definition of the standard floating point parser.
*/ */
namespace qmu namespace qmu
{ {
/** \brief Mathematical expressions parser. /** @brief Mathematical expressions parser.
*
Standard implementation of the mathematical expressions parser. * Standard implementation of the mathematical expressions parser.
Can be used as a reference implementation for subclassing the parser. * Can be used as a reference implementation for subclassing the parser.
*
<small> * <small>
(C) 2011 Ingo Berg<br> * (C) 2011 Ingo Berg<br>
muparser(at)gmx.de * muparser(at)gmx.de
</small> * </small>
*/ */
/* final */ class QMUPARSERSHARED_EXPORT QmuParser : public QmuParserBase /* final */ class QMUPARSERSHARED_EXPORT QmuParser : public QmuParserBase
{ {
public: public:
QmuParser(); QmuParser();
virtual void InitCharSets(); virtual void InitCharSets();
@ -54,9 +52,9 @@ public:
virtual void InitConst(); virtual void InitConst();
virtual void InitOprt(); virtual void InitOprt();
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd); virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
qreal Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon = 0) const; qreal Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon = 0) const;
protected: protected:
static int IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal);
// Trigonometric functions // Trigonometric functions
static qreal Tan2(qreal, qreal); static qreal Tan2(qreal, qreal);
// hyperbolic functions // hyperbolic functions
@ -82,8 +80,6 @@ protected:
static qreal Avg(const qreal*, int); // mean value static qreal Avg(const qreal*, int); // mean value
static qreal Min(const qreal*, int); // minimum static qreal Min(const qreal*, int); // minimum
static qreal Max(const qreal*, int); // maximum static qreal Max(const qreal*, int); // maximum
static int IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal);
}; };
} // namespace qmu } // namespace qmu

File diff suppressed because it is too large Load diff

View file

@ -23,18 +23,10 @@
#ifndef QMUQPARSERBASE_H #ifndef QMUQPARSERBASE_H
#define QMUQPARSERBASE_H #define QMUQPARSERBASE_H
//--- Standard includes ------------------------------------------------------------------------
#include <cmath>
#include <string>
#include <iostream>
#include <map>
#include <memory>
#include <locale>
#include <QStack> #include <QStack>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
//--- Parser includes --------------------------------------------------------------------------
#include "qmuparserdef.h" #include "qmuparserdef.h"
#include "qmuparsertokenreader.h" #include "qmuparsertokenreader.h"
#include "qmuparserbytecode.h" #include "qmuparserbytecode.h"
@ -43,108 +35,60 @@
namespace qmu namespace qmu
{ {
/** \file /**
\brief This file contains the class definition of the qmuparser engine. * @file
* @brief This file contains the class definition of the qmuparser engine.
*/ */
//-------------------------------------------------------------------------------------------------- /**
/** \brief Mathematical expressions parser (base parser engine). * @brief Mathematical expressions parser (base parser engine).
\author (C) 2013 Ingo Berg * @author (C) 2013 Ingo Berg
*
This is the implementation of a bytecode based mathematical expressions parser. * This is the implementation of a bytecode based mathematical expressions parser.
The formula will be parsed from string and converted into a bytecode. * The formula will be parsed from string and converted into a bytecode.
Future calculations will be done with the bytecode instead the formula string * Future calculations will be done with the bytecode instead the formula string
resulting in a significant performance increase. * resulting in a significant performance increase.
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 QmuParserBase
{ {
friend class QmuParserTokenReader; friend class QmuParserTokenReader;
private:
/** \brief Typedef for the parse functions.
The parse function do the actual work. The parser exchanges
the function pointer to the parser function depending on
which state it is in. (i.e. bytecode parser vs. string parser)
*/
typedef qreal (QmuParserBase::*ParseFunction)() const;
/** \brief Type used for storing an array of values. */
typedef QVector<qreal> valbuf_type;
/** \brief Type for a vector of strings. */
typedef QVector<QString> stringbuf_type;
/** \brief Typedef for the token reader. */
typedef QmuParserTokenReader token_reader_type;
/** \brief Type used for parser tokens. */
typedef QmuParserToken<qreal, QString> token_type;
/** \brief Maximum number of threads spawned by OpenMP when using the bulk mode. */
static const int s_MaxNumOpenMPThreads = 4;
public: public:
/**
/** \brief Type of the error class. * @brief Type of the error class.
*
Included for backwards compatibility. * Included for backwards compatibility.
*/ */
typedef QmuParserError exception_type; typedef QmuParserError exception_type;
static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
QmuParserBase(); QmuParserBase();
QmuParserBase(const QmuParserBase &a_Parser); QmuParserBase(const QmuParserBase &a_Parser);
QmuParserBase& operator=(const QmuParserBase &a_Parser); QmuParserBase& operator=(const QmuParserBase &a_Parser);
virtual ~QmuParserBase(); virtual ~QmuParserBase();
static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
qreal Eval() const; qreal Eval() const;
qreal* Eval(int &nStackSize) const; qreal* Eval(int &nStackSize) const;
void Eval(qreal *results, int nBulkSize); void Eval(qreal *results, int nBulkSize);
int GetNumResults() const; int GetNumResults() const;
void SetExpr(const QString &a_sExpr); void SetExpr(const QString &a_sExpr);
void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL); void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
void SetDecSep(char_type cDecSep); void SetDecSep(char_type cDecSep);
void SetThousandsSep(char_type cThousandsSep = 0); void SetThousandsSep(char_type cThousandsSep = 0);
void ResetLocale(); void ResetLocale();
void EnableOptimizer(bool a_bIsOn=true); void EnableOptimizer(bool a_bIsOn=true);
void EnableBuiltInOprt(bool a_bIsOn=true); void EnableBuiltInOprt(bool a_bIsOn=true);
bool HasBuiltInOprt() const; bool HasBuiltInOprt() const;
void AddValIdent(identfun_type a_pCallback); void AddValIdent(identfun_type a_pCallback);
void DefineOprt(const QString &a_strName, fun_type2 a_pFun, unsigned a_iPri=0,
/** \fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true) EOprtAssociativity a_eAssociativity = oaLEFT, bool a_bAllowOpt = false);
\brief Define a parser function without arguments.
\param a_strName Name of the function
\param a_pFun Pointer to the callback function
\param a_bAllowOpt A flag indicating this function may be optimized
*/
template<typename T>
void DefineFun(const QString &a_strName, T a_pFun, bool a_bAllowOpt = true)
{
AddCallback( a_strName, QmuParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );
}
void DefineOprt(const QString &a_strName,
fun_type2 a_pFun,
unsigned a_iPri=0,
EOprtAssociativity a_eAssociativity = oaLEFT,
bool a_bAllowOpt = false);
void DefineConst(const QString &a_sName, qreal a_fVal); void DefineConst(const QString &a_sName, qreal a_fVal);
void DefineStrConst(const QString &a_sName, const QString &a_strVal); void DefineStrConst(const QString &a_sName, const QString &a_strVal);
void DefineVar(const QString &a_sName, qreal *a_fVar); void DefineVar(const QString &a_sName, qreal *a_fVar);
void DefinePostfixOprt(const QString &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true); void DefinePostfixOprt(const QString &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);
void DefineInfixOprt(const QString &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true); void DefineInfixOprt(const QString &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX,
bool a_bAllowOpt=true);
// Clear user defined variables, constants or functions // Clear user defined variables, constants or functions
void ClearVar(); void ClearVar();
void ClearFun(); void ClearFun();
@ -152,62 +96,58 @@ private:
void ClearInfixOprt(); void ClearInfixOprt();
void ClearPostfixOprt(); void ClearPostfixOprt();
void ClearOprt(); void ClearOprt();
void RemoveVar(const QString &a_strVarName); void RemoveVar(const QString &a_strVarName);
const varmap_type& GetUsedVar() const; const varmap_type& GetUsedVar() const;
const varmap_type& GetVar() const; const varmap_type& GetVar() const;
const valmap_type& GetConst() const; const valmap_type& GetConst() const;
const QString& GetExpr() const; const QString& GetExpr() const;
const funmap_type& GetFunDef() const; const funmap_type& GetFunDef() const;
string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const; QString GetVersion(EParserVersionInfo eInfo = pviFULL) const;
const QStringList& GetOprtDef() const; const QStringList& GetOprtDef() const;
void DefineNameChars(const QString &a_szCharset); void DefineNameChars(const QString &a_szCharset);
void DefineOprtChars(const QString &a_szCharset); void DefineOprtChars(const QString &a_szCharset);
void DefineInfixOprtChars(const QString &a_szCharset); void DefineInfixOprtChars(const QString &a_szCharset);
const QString& ValidNameChars() const; const QString& ValidNameChars() const;
const QString& ValidOprtChars() const; const QString& ValidOprtChars() const;
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 Error(EErrorCodes a_iErrc, /**
int a_iPos = -1, * @fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun,
const QString &a_strTok = QString() ) const; * bool a_bAllowOpt = true)
* @brief Define a parser function without arguments.
* @param a_strName Name of the function
* @param a_pFun Pointer to the callback function
* @param a_bAllowOpt A flag indicating this function may be optimized
*/
template<typename T>
void DefineFun(const QString &a_strName, T a_pFun, bool a_bAllowOpt = true)
{
AddCallback( a_strName, QmuParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );
}
protected: protected:
void Init();
virtual void InitCharSets() = 0;
virtual void InitFun() = 0;
virtual void InitConst() = 0;
virtual void InitOprt() = 0;
virtual void OnDetectVar(QString *pExpr, int &nStart, int &nEnd);
static const QStringList c_DefaultOprt; static const QStringList c_DefaultOprt;
static std::locale s_locale; ///< The locale used by the parser static std::locale s_locale; ///< The locale used by the parser
static bool g_DbgDumpCmdCode; static bool g_DbgDumpCmdCode;
static bool g_DbgDumpStack; static bool g_DbgDumpStack;
void Init();
/** \brief A facet class used to change decimal and thousands separator. */ virtual void InitCharSets() = 0;
virtual void InitFun() = 0;
virtual void InitConst() = 0;
virtual void InitOprt() = 0;
virtual void OnDetectVar(QString *pExpr, int &nStart, int &nEnd);
/**
* @brief A facet class used to change decimal and thousands separator.
*/
template<class TChar> template<class TChar>
class change_dec_sep : public std::numpunct<TChar> class change_dec_sep : public std::numpunct<TChar>
{ {
public: public:
explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3) explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
:std::numpunct<TChar>() :std::numpunct<TChar>(), m_nGroup(nGroup), m_cDecPoint(cDecSep), m_cThousandsSep(cThousandsSep)
,m_nGroup(nGroup)
,m_cDecPoint(cDecSep)
,m_cThousandsSep(cThousandsSep)
{} {}
protected: protected:
virtual char_type do_decimal_point() const virtual char_type do_decimal_point() const
{ {
return m_cDecPoint; return m_cDecPoint;
@ -222,53 +162,50 @@ private:
{ {
return std::string(1, m_nGroup); return std::string(1, m_nGroup);
} }
private: private:
int m_nGroup; int m_nGroup;
char_type m_cDecPoint; char_type m_cDecPoint;
char_type m_cThousandsSep; char_type m_cThousandsSep;
}; };
private: private:
/**
* @brief Typedef for the parse functions.
*
* The parse function do the actual work. The parser exchanges
* the function pointer to the parser function depending on
* which state it is in. (i.e. bytecode parser vs. string parser)
*/
typedef qreal (QmuParserBase::*ParseFunction)() const;
void Assign(const QmuParserBase &a_Parser); /**
void InitTokenReader(); * @brief Type used for storing an array of values.
void ReInit() const; */
typedef QVector<qreal> valbuf_type;
void AddCallback(const QString &a_strName, /**
const QmuParserCallback &a_Callback, * @brief Type for a vector of strings.
funmap_type &a_Storage, */
const QString &a_szCharSet ); typedef QVector<QString> stringbuf_type;
void ApplyRemainingOprt(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal) const; /**
void ApplyBinOprt(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal) const; * @brief Typedef for the token reader.
void ApplyIfElse(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal) const; */
void ApplyFunc(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal, int iArgCount) const; typedef QmuParserTokenReader token_reader_type;
token_type ApplyStrFunc(const token_type &a_FunTok, /**
const QVector<token_type> &a_vArg) const; * @brief Type used for parser tokens.
*/
typedef QmuParserToken<qreal, QString> token_type;
int GetOprtPrecedence(const token_type &a_Tok) const; /**
EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const; * @brief Maximum number of threads spawned by OpenMP when using the bulk mode.
*/
static const int s_MaxNumOpenMPThreads = 4;
void CreateRPN() const; /**
* @brief Pointer to the parser function.
qreal ParseString() const; *
qreal ParseCmdCode() const; * Eval() calls the function whose address is stored there.
qreal ParseCmdCodeBulk(int nOffset, int nThreadID) const;
void CheckName(const QString &a_strName, const QString &a_CharSet) const;
void CheckOprt(const QString &a_sName,
const QmuParserCallback &a_Callback,
const QString &a_szCharSet) const;
void StackDump(const QStack<token_type > &a_stVal,
const QStack<token_type > &a_stOprt) const;
/** \brief Pointer to the parser function.
Eval() calls the function whose address is stored there.
*/ */
mutable ParseFunction m_pParseFormula; mutable ParseFunction m_pParseFormula;
mutable QmuParserByteCode m_vRPN; ///< The Bytecode class. mutable QmuParserByteCode m_vRPN; ///< The Bytecode class.
@ -296,6 +233,27 @@ private:
// items merely used for caching state information // items merely used for caching state information
mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine mutable valbuf_type m_vStackBuffer; ///< This is merely a buffer used for the stack in the cmd parsing routine
mutable int m_nFinalResultIdx; mutable int m_nFinalResultIdx;
void Assign(const QmuParserBase &a_Parser);
void InitTokenReader();
void ReInit() const;
void AddCallback(const QString &a_strName, const QmuParserCallback &a_Callback,
funmap_type &a_Storage, const QString &a_szCharSet );
void ApplyRemainingOprt(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal) const;
void ApplyBinOprt(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal) const;
void ApplyIfElse(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal) const;
void ApplyFunc(QStack<token_type> &a_stOpt, QStack<token_type> &a_stVal, int iArgCount) const;
token_type ApplyStrFunc(const token_type &a_FunTok, const QVector<token_type> &a_vArg) const;
int GetOprtPrecedence(const token_type &a_Tok) const;
EOprtAssociativity GetOprtAssociativity(const token_type &a_Tok) const;
void CreateRPN() const;
qreal ParseString() const;
qreal ParseCmdCode() const;
qreal ParseCmdCodeBulk(int nOffset, int nThreadID) const;
void CheckName(const QString &a_strName, const QString &a_CharSet) const;
void CheckOprt(const QString &a_sName, const QmuParserCallback &a_Callback,
const QString &a_szCharSet) const;
void StackDump(const QStack<token_type > &a_stVal, const QStack<token_type > &a_stOprt) const;
}; };
} // namespace qmu } // namespace qmu

View file

@ -35,31 +35,32 @@
namespace qmu namespace qmu
{ {
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Bytecode default constructor. */ /**
* @brief Bytecode default constructor.
*/
QmuParserByteCode::QmuParserByteCode() QmuParserByteCode::QmuParserByteCode()
:m_iStackPos(0) :m_iStackPos(0), m_iMaxStackSize(0), m_vRPN(), m_bEnableOptimizer(true)
,m_iMaxStackSize(0)
,m_vRPN()
,m_bEnableOptimizer(true)
{ {
m_vRPN.reserve(50); m_vRPN.reserve(50);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Copy constructor. /**
* @brief Copy constructor.
Implemented in Terms of Assign(const QParserByteCode &a_ByteCode) *
* Implemented in Terms of Assign(const QParserByteCode &a_ByteCode)
*/ */
QmuParserByteCode::QmuParserByteCode(const QmuParserByteCode &a_ByteCode) QmuParserByteCode::QmuParserByteCode(const QmuParserByteCode &a_ByteCode)
{ {
Assign(a_ByteCode); Assign(a_ByteCode);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Assignment operator. /**
* @brief Assignment operator.
Implemented in Terms of Assign(const QParserByteCode &a_ByteCode) *
* Implemented in Terms of Assign(const QParserByteCode &a_ByteCode)
*/ */
QmuParserByteCode& QmuParserByteCode::operator=(const QmuParserByteCode &a_ByteCode) QmuParserByteCode& QmuParserByteCode::operator=(const QmuParserByteCode &a_ByteCode)
{ {
@ -67,31 +68,35 @@ namespace qmu
return *this; return *this;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserByteCode::EnableOptimizer(bool bStat) void QmuParserByteCode::EnableOptimizer(bool bStat)
{ {
m_bEnableOptimizer = bStat; m_bEnableOptimizer = bStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Copy state of another object to this. /**
* @brief Copy state of another object to this.
\throw nowthrow *
* @throw nowthrow
*/ */
void QmuParserByteCode::Assign(const QmuParserByteCode &a_ByteCode) void QmuParserByteCode::Assign(const QmuParserByteCode &a_ByteCode)
{ {
if (this==&a_ByteCode) if (this==&a_ByteCode)
{
return; return;
}
m_iStackPos = a_ByteCode.m_iStackPos; m_iStackPos = a_ByteCode.m_iStackPos;
m_vRPN = a_ByteCode.m_vRPN; m_vRPN = a_ByteCode.m_vRPN;
m_iMaxStackSize = a_ByteCode.m_iMaxStackSize; m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add a Variable pointer to bytecode. /**
\param a_pVar Pointer to be added. * @brief Add a Variable pointer to bytecode.
\throw nothrow * @param a_pVar Pointer to be added.
* @throw nothrow
*/ */
void QmuParserByteCode::AddVar(qreal *a_pVar) void QmuParserByteCode::AddVar(qreal *a_pVar)
{ {
@ -107,18 +112,19 @@ namespace qmu
m_vRPN.push_back(tok); m_vRPN.push_back(tok);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add a Variable pointer to bytecode. /**
* @brief Add a Variable pointer to bytecode.
Value entries in byte code consist of: *
<ul> * Value entries in byte code consist of:
<li>value array position of the value</li> * <ul>
<li>the operator code according to ParserToken::cmVAL</li> * <li>value array position of the value</li>
<li>the value stored in #mc_iSizeVal number of bytecode entries.</li> * <li>the operator code according to ParserToken::cmVAL</li>
</ul> * <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
* </ul>
\param a_pVal Value to be added. *
\throw nothrow * @param a_pVal Value to be added.
* @throw nothrow
*/ */
void QmuParserByteCode::AddVal(qreal a_fVal) void QmuParserByteCode::AddVal(qreal a_fVal)
{ {
@ -134,7 +140,7 @@ namespace qmu
m_vRPN.push_back(tok); m_vRPN.push_back(tok);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserByteCode::ConstantFolding(ECmdCode a_Oprt) void QmuParserByteCode::ConstantFolding(ECmdCode a_Oprt)
{ {
std::size_t sz = m_vRPN.size(); std::size_t sz = m_vRPN.size();
@ -142,47 +148,80 @@ namespace qmu
&y = m_vRPN[sz-1].Val.data2; &y = m_vRPN[sz-1].Val.data2;
switch (a_Oprt) switch (a_Oprt)
{ {
case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break; case cmLAND:
case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break; x = (int)x && (int)y;
case cmLT: x = x < y; m_vRPN.pop_back(); break; m_vRPN.pop_back();
case cmGT: x = x > y; m_vRPN.pop_back(); break; break;
case cmLE: x = x <= y; m_vRPN.pop_back(); break; case cmLOR:
case cmGE: x = x >= y; m_vRPN.pop_back(); break; x = (int)x || (int)y;
case cmNEQ: x = x != y; m_vRPN.pop_back(); break; m_vRPN.pop_back();
case cmEQ: x = x == y; m_vRPN.pop_back(); break; break;
case cmADD: x = x + y; m_vRPN.pop_back(); break; case cmLT:
case cmSUB: x = x - y; m_vRPN.pop_back(); break; x = x < y;
case cmMUL: x = x * y; m_vRPN.pop_back(); break; m_vRPN.pop_back();
break;
case cmGT:
x = x > y;
m_vRPN.pop_back();
break;
case cmLE:
x = x <= y;
m_vRPN.pop_back();
break;
case cmGE:
x = x >= y;
m_vRPN.pop_back();
break;
case cmNEQ:
x = x != y;
m_vRPN.pop_back();
break;
case cmEQ:
x = x == y;
m_vRPN.pop_back();
break;
case cmADD:
x = x + y;
m_vRPN.pop_back();
break;
case cmSUB:
x = x - y;
m_vRPN.pop_back();
break;
case cmMUL:
x = x * y;
m_vRPN.pop_back();
break;
case cmDIV: case cmDIV:
#if defined(MUP_MATH_EXCEPTIONS) #if defined(MUP_MATH_EXCEPTIONS)
if (y==0) if (y==0)
{
throw ParserError(ecDIV_BY_ZERO, "0"); throw ParserError(ecDIV_BY_ZERO, "0");
}
#endif #endif
x = x / y; x = x / y;
m_vRPN.pop_back(); m_vRPN.pop_back();
break; break;
case cmPOW:
case cmPOW: x = std::pow(x, y); x = qPow(x, y);
m_vRPN.pop_back(); m_vRPN.pop_back();
break; break;
default: default:
break; break;
} // switch opcode } // switch opcode
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add an operator identifier to bytecode. /**
* @brief Add an operator identifier to bytecode.
Operator entries in byte code consist of: *
<ul> * Operator entries in byte code consist of:
<li>value array position of the result</li> * <ul>
<li>the operator code according to ParserToken::ECmdCode</li> * <li>value array position of the result</li>
</ul> * <li>the operator code according to ParserToken::ECmdCode</li>
* </ul>
\sa ParserToken::ECmdCode *
* @sa ParserToken::ECmdCode
*/ */
void QmuParserByteCode::AddOp(ECmdCode a_Oprt) void QmuParserByteCode::AddOp(ECmdCode a_Oprt)
{ {
@ -210,14 +249,21 @@ namespace qmu
if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL) if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)
{ {
if (m_vRPN[sz-1].Val.data2==2) if (m_vRPN[sz-1].Val.data2==2)
{
m_vRPN[sz-2].Cmd = cmVARPOW2; m_vRPN[sz-2].Cmd = cmVARPOW2;
}
else if (m_vRPN[sz-1].Val.data2==3) else if (m_vRPN[sz-1].Val.data2==3)
{
m_vRPN[sz-2].Cmd = cmVARPOW3; m_vRPN[sz-2].Cmd = cmVARPOW3;
}
else if (m_vRPN[sz-1].Val.data2==4) else if (m_vRPN[sz-1].Val.data2==4)
{
m_vRPN[sz-2].Cmd = cmVARPOW4; m_vRPN[sz-2].Cmd = cmVARPOW4;
}
else else
{
break; break;
}
m_vRPN.pop_back(); m_vRPN.pop_back();
bOptimized = true; bOptimized = true;
} }
@ -231,30 +277,35 @@ namespace qmu
(m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) || (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ||
(m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) || (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL) ||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) || (m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAL) ||
(m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAR &&
(m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) || (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVARMUL
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ) && m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVAR &&
m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ||
(m_vRPN[sz-1].Cmd == cmVARMUL && m_vRPN[sz-2].Cmd == cmVARMUL &&
m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) )
{ {
assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) || assert( (m_vRPN[sz-2].Val.ptr==NULL && m_vRPN[sz-1].Val.ptr!=NULL) ||
(m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) || (m_vRPN[sz-2].Val.ptr!=NULL && m_vRPN[sz-1].Val.ptr==NULL) ||
(m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) ); (m_vRPN[sz-2].Val.ptr == m_vRPN[sz-1].Val.ptr) );
m_vRPN[sz-2].Cmd = cmVARMUL; m_vRPN[sz-2].Cmd = cmVARMUL;
m_vRPN[sz-2].Val.ptr = (qreal*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); // variable m_vRPN[sz-2].Val.ptr = (qreal*)((long long)(m_vRPN[sz-2].Val.ptr) |
(long long)(m_vRPN[sz-1].Val.ptr)); // variable
m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset m_vRPN[sz-2].Val.data2 += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data2; // offset
m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplikatior m_vRPN[sz-2].Val.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplikatior
m_vRPN.pop_back(); m_vRPN.pop_back();
bOptimized = true; bOptimized = true;
} }
break; break;
case cmMUL: case cmMUL:
if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) || if ( (m_vRPN[sz-1].Cmd == cmVAR && m_vRPN[sz-2].Cmd == cmVAL) ||
(m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) ) (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVAR) )
{ {
m_vRPN[sz-2].Cmd = cmVARMUL; m_vRPN[sz-2].Cmd = cmVARMUL;
m_vRPN[sz-2].Val.ptr = (qreal*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); m_vRPN[sz-2].Val.ptr = (qreal*)((long long)(m_vRPN[sz-2].Val.ptr) |
(long long)(m_vRPN[sz-1].Val.ptr));
m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2; m_vRPN[sz-2].Val.data = m_vRPN[sz-2].Val.data2 + m_vRPN[sz-1].Val.data2;
m_vRPN[sz-2].Val.data2 = 0; m_vRPN[sz-2].Val.data2 = 0;
m_vRPN.pop_back(); m_vRPN.pop_back();
@ -265,7 +316,8 @@ namespace qmu
{ {
// Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2 // Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
m_vRPN[sz-2].Cmd = cmVARMUL; m_vRPN[sz-2].Cmd = cmVARMUL;
m_vRPN[sz-2].Val.ptr = (qreal*)((long long)(m_vRPN[sz-2].Val.ptr) | (long long)(m_vRPN[sz-1].Val.ptr)); m_vRPN[sz-2].Val.ptr = (qreal*)((long long)(m_vRPN[sz-2].Val.ptr) |
(long long)(m_vRPN[sz-1].Val.ptr));
if (m_vRPN[sz-1].Cmd == cmVAL) if (m_vRPN[sz-1].Cmd == cmVAL)
{ {
m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2; m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2;
@ -288,7 +340,6 @@ namespace qmu
bOptimized = true; bOptimized = true;
} }
break; break;
case cmDIV: case cmDIV:
if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0) if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
{ {
@ -314,7 +365,7 @@ namespace qmu
} }
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserByteCode::AddIfElse(ECmdCode a_Oprt) void QmuParserByteCode::AddIfElse(ECmdCode a_Oprt)
{ {
SToken tok; SToken tok;
@ -322,16 +373,17 @@ namespace qmu
m_vRPN.push_back(tok); m_vRPN.push_back(tok);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add an assignement operator /**
* @brief Add an assignement operator
Operator entries in byte code consist of: *
<ul> * Operator entries in byte code consist of:
<li>cmASSIGN code</li> * <ul>
<li>the pointer of the destination variable</li> * <li>cmASSIGN code</li>
</ul> * <li>the pointer of the destination variable</li>
* </ul>
\sa ParserToken::ECmdCode *
* @sa ParserToken::ECmdCode
*/ */
void QmuParserByteCode::AddAssignOp(qreal *a_pVar) void QmuParserByteCode::AddAssignOp(qreal *a_pVar)
{ {
@ -343,11 +395,12 @@ namespace qmu
m_vRPN.push_back(tok); m_vRPN.push_back(tok);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add function to bytecode. /**
* @brief Add function to bytecode.
\param a_iArgc Number of arguments, negative numbers indicate multiarg functions. *
\param a_pFun Pointer to function callback. * @param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
* @param a_pFun Pointer to function callback.
*/ */
void QmuParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc) void QmuParserByteCode::AddFun(generic_fun_type a_pFun, int a_iArgc)
{ {
@ -369,11 +422,12 @@ namespace qmu
m_vRPN.push_back(tok); m_vRPN.push_back(tok);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add a bulk function to bytecode. /**
* @brief Add a bulk function to bytecode.
\param a_iArgc Number of arguments, negative numbers indicate multiarg functions. *
\param a_pFun Pointer to function callback. * @param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
* @param a_pFun Pointer to function callback.
*/ */
void QmuParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc) void QmuParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
{ {
@ -387,13 +441,13 @@ namespace qmu
m_vRPN.push_back(tok); m_vRPN.push_back(tok);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add Strung function entry to the parser bytecode. /**
\throw nothrow * @brief Add Strung function entry to the parser bytecode.
* @throw nothrow
A string function entry consists of the stack position of the return value, *
followed by a cmSTRFUNC code, the function pointer and an index into the * A string function entry consists of the stack position of the return value, followed by a cmSTRFUNC code, the
string buffer maintained by the parser. * function pointer and an index into the string buffer maintained by the parser.
*/ */
void QmuParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx) void QmuParserByteCode::AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx)
{ {
@ -409,10 +463,11 @@ namespace qmu
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos); m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Add end marker to bytecode. /**
* @brief Add end marker to bytecode.
\throw nothrow *
* @throw nothrow
*/ */
void QmuParserByteCode::Finalize() void QmuParserByteCode::Finalize()
{ {
@ -431,54 +486,57 @@ namespace qmu
case cmIF: case cmIF:
stIf.push(i); stIf.push(i);
break; break;
case cmELSE: case cmELSE:
stElse.push(i); stElse.push(i);
idx = stIf.pop(); idx = stIf.pop();
m_vRPN[idx].Oprt.offset = i - idx; m_vRPN[idx].Oprt.offset = i - idx;
break; break;
case cmENDIF: case cmENDIF:
idx = stElse.pop(); idx = stElse.pop();
m_vRPN[idx].Oprt.offset = i - idx; m_vRPN[idx].Oprt.offset = i - idx;
break; break;
default: default:
break; break;
} }
} }
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
const SToken* QmuParserByteCode::GetBase() const const SToken* QmuParserByteCode::GetBase() const
{ {
if (m_vRPN.size()==0) if (m_vRPN.size()==0)
{
throw QmuParserError(ecINTERNAL_ERROR); throw QmuParserError(ecINTERNAL_ERROR);
}
else else
{
return &m_vRPN[0]; return &m_vRPN[0];
} }
}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
std::size_t QmuParserByteCode::GetMaxStackSize() const std::size_t QmuParserByteCode::GetMaxStackSize() const
{ {
return m_iMaxStackSize+1; return m_iMaxStackSize+1;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Returns the number of entries in the bytecode. */ /**
* @brief Returns the number of entries in the bytecode.
*/
std::size_t QmuParserByteCode::GetSize() const std::size_t QmuParserByteCode::GetSize() const
{ {
return m_vRPN.size(); return m_vRPN.size();
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Delete the bytecode. /**
* @brief Delete the bytecode.
\throw nothrow *
* @throw nothrow
The name of this function is a violation of my own coding guidelines *
but this way it's more in line with the STL functions thus more * The name of this function is a violation of my own coding guidelines but this way it's more in line with the STL
intuitive. * functions thus more intuitive.
*/ */
void QmuParserByteCode::clear() void QmuParserByteCode::clear()
{ {
@ -487,8 +545,10 @@ namespace qmu
m_iMaxStackSize = 0; m_iMaxStackSize = 0;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Dump bytecode (for debugging only!). */ /**
* @brief Dump bytecode (for debugging only!).
*/
void QmuParserByteCode::AsciiDump() void QmuParserByteCode::AsciiDump()
{ {
if (!m_vRPN.size()) if (!m_vRPN.size())
@ -503,62 +563,85 @@ namespace qmu
qDebug() << i << " : \t"; qDebug() << i << " : \t";
switch (m_vRPN[i].Cmd) switch (m_vRPN[i].Cmd)
{ {
case cmVAL: qDebug() << "VAL \t" << "[" << m_vRPN[i].Val.data2 << "]\n"; case cmVAL:
qDebug() << "VAL \t" << "[" << m_vRPN[i].Val.data2 << "]\n";
break; break;
case cmVAR:
case cmVAR: qDebug() << "VAR \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n"; qDebug() << "VAR \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break; break;
case cmVARPOW2:
case cmVARPOW2: qDebug() << "VARPOW2 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n"; qDebug() << "VARPOW2 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break; break;
case cmVARPOW3:
case cmVARPOW3: qDebug() << "VARPOW3 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n"; qDebug() << "VARPOW3 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break; break;
case cmVARPOW4:
case cmVARPOW4: qDebug() << "VARPOW4 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n"; qDebug() << "VARPOW4 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break; break;
case cmVARMUL:
case cmVARMUL: qDebug() << "VARMUL \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]" qDebug() << "VARMUL \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]" << " * ["
<< " * [" << m_vRPN[i].Val.data << "]" << " + [" << m_vRPN[i].Val.data2 << "]\n"; << m_vRPN[i].Val.data << "]" << " + [" << m_vRPN[i].Val.data2 << "]\n";
break; break;
case cmFUNC:
case cmFUNC: qDebug() << "CALL\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[ADDR: 0x" qDebug() << "CALL\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]"
<< m_vRPN[i].Fun.ptr << "]" << "\n"; << "\n";
break; break;
case cmFUNC_STR: case cmFUNC_STR:
qDebug() << "CALL STRFUNC\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[IDX:" qDebug() << "CALL STRFUNC\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[IDX:" << m_vRPN[i].Fun.idx
<< m_vRPN[i].Fun.idx << "]" << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]" << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]\n";
<< "]\n";
break; break;
case cmLT:
case cmLT: qDebug() << "LT\n"; break; qDebug() << "LT\n";
case cmGT: qDebug() << "GT\n"; break;
case cmLE: qDebug() << "LE\n"; break;
case cmGE: qDebug() << "GE\n"; break;
case cmEQ: qDebug() << "EQ\n"; break;
case cmNEQ: qDebug() << "NEQ\n"; break;
case cmADD: qDebug() << "ADD\n"; break;
case cmLAND: qDebug() << "&&\n"; break;
case cmLOR: qDebug() << "||\n"; break;
case cmSUB: qDebug() << "SUB\n"; break;
case cmMUL: qDebug() << "MUL\n"; break;
case cmDIV: qDebug() << "DIV\n"; break;
case cmPOW: qDebug() << "POW\n"; break;
case cmIF: qDebug() << "IF\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
break; break;
case cmGT:
case cmELSE: qDebug() << "ELSE\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n"; qDebug() << "GT\n";
break; break;
case cmLE:
case cmENDIF: qDebug() << "ENDIF\n"; break; qDebug() << "LE\n";
break;
case cmGE:
qDebug() << "GE\n";
break;
case cmEQ:
qDebug() << "EQ\n";
break;
case cmNEQ:
qDebug() << "NEQ\n";
break;
case cmADD:
qDebug() << "ADD\n";
break;
case cmLAND:
qDebug() << "&&\n";
break;
case cmLOR:
qDebug() << "||\n";
break;
case cmSUB:
qDebug() << "SUB\n";
break;
case cmMUL:
qDebug() << "MUL\n";
break;
case cmDIV:
qDebug() << "DIV\n";
break;
case cmPOW:
qDebug() << "POW\n";
break;
case cmIF:
qDebug() << "IF\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
break;
case cmELSE:
qDebug() << "ELSE\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
break;
case cmENDIF:
qDebug() << "ENDIF\n"; break;
case cmASSIGN: case cmASSIGN:
qDebug() << "ASSIGN\t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Oprt.ptr, 'f', 16) << "]\n"; qDebug() << "ASSIGN\t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Oprt.ptr, 'f', 16) << "]\n";
break; break;
default:
default: qDebug() << "(unknown code: " << m_vRPN[i].Cmd << ")\n"; qDebug() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
break; break;
} // switch cmdCode } // switch cmdCode
} // while bytecode } // while bytecode

View file

@ -23,19 +23,15 @@
#ifndef QMUPARSERBYTECODE_H #ifndef QMUPARSERBYTECODE_H
#define QMUPARSERBYTECODE_H #define QMUPARSERBYTECODE_H
#include <cassert>
#include <string>
#include <stack>
#include "qmuparserdef.h" #include "qmuparserdef.h"
#include "qmuparsererror.h" #include "qmuparsererror.h"
#include "qmuparsertoken.h" #include "qmuparsertoken.h"
/** \file /**
\brief Definition of the parser bytecode class. * @file
* @brief Definition of the parser bytecode class.
*/ */
namespace qmu namespace qmu
{ {
struct SToken struct SToken
@ -72,45 +68,42 @@ namespace qmu
}; };
/** \brief Bytecode implementation of the Math Parser. /**
* @brief Bytecode implementation of the Math Parser.
The bytecode contains the formula converted to revers polish notation stored in a continious *
memory area. Associated with this data are operator codes, variable pointers, constant * The bytecode contains the formula converted to revers polish notation stored in a continious
values and function pointers. Those are necessary in order to calculate the result. * memory area. Associated with this data are operator codes, variable pointers, constant
All those data items will be casted to the underlying datatype of the bytecode. * values and function pointers. Those are necessary in order to calculate the result.
* All those data items will be casted to the underlying datatype of the bytecode.
\author (C) 2004-2013 Ingo Berg *
* @author (C) 2004-2013 Ingo Berg
*/ */
class QmuParserByteCode class QmuParserByteCode
{ {
private: private:
/** @brief Token type for internal use only. */
/** \brief Token type for internal use only. */
typedef QmuParserToken<qreal, string_type> token_type; typedef QmuParserToken<qreal, string_type> token_type;
/** \brief Token vector for storing the RPN. */ /** @brief Token vector for storing the RPN. */
typedef QVector<SToken> rpn_type; typedef QVector<SToken> rpn_type;
/** \brief Position in the Calculation array. */ /** @brief Position in the Calculation array. */
unsigned m_iStackPos; unsigned m_iStackPos;
/** \brief Maximum size needed for the stack. */ /** @brief Maximum size needed for the stack. */
std::size_t m_iMaxStackSize; std::size_t m_iMaxStackSize;
/** \brief The actual rpn storage. */ /** @brief The actual rpn storage. */
rpn_type m_vRPN; rpn_type m_vRPN;
bool m_bEnableOptimizer; bool m_bEnableOptimizer;
void ConstantFolding(ECmdCode a_Oprt); void ConstantFolding(ECmdCode a_Oprt);
public: public:
QmuParserByteCode(); QmuParserByteCode();
QmuParserByteCode(const QmuParserByteCode &a_ByteCode); QmuParserByteCode(const QmuParserByteCode &a_ByteCode);
QmuParserByteCode& operator=(const QmuParserByteCode &a_ByteCode); QmuParserByteCode& operator=(const QmuParserByteCode &a_ByteCode);
void Assign(const QmuParserByteCode &a_ByteCode); void Assign(const QmuParserByteCode &a_ByteCode);
void AddVar(qreal *a_pVar); void AddVar(qreal *a_pVar);
void AddVal(qreal a_fVal); void AddVal(qreal a_fVal);
void AddOp(ECmdCode a_Oprt); void AddOp(ECmdCode a_Oprt);
@ -119,20 +112,15 @@ public:
void AddFun(generic_fun_type a_pFun, int a_iArgc); void AddFun(generic_fun_type a_pFun, int a_iArgc);
void AddBulkFun(generic_fun_type a_pFun, int a_iArgc); void AddBulkFun(generic_fun_type a_pFun, int a_iArgc);
void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx); void AddStrFun(generic_fun_type a_pFun, int a_iArgc, int a_iIdx);
void EnableOptimizer(bool bStat); void EnableOptimizer(bool bStat);
void Finalize(); void Finalize();
void clear(); void clear();
std::size_t GetMaxStackSize() const; std::size_t GetMaxStackSize() const;
std::size_t GetSize() const; std::size_t GetSize() const;
const SToken* GetBase() const; const SToken* GetBase() const;
void AsciiDump(); void AsciiDump();
}; };
} // namespace qmu } // namespace qmu
#endif #endif

View file

@ -22,355 +22,209 @@
#include "qmuparsercallback.h" #include "qmuparsercallback.h"
/** \file /**
\brief Implementation of the parser callback class. * @file
* @brief Implementation of the parser callback class.
*/ */
namespace qmu namespace qmu
{ {
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type0 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type0 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 0 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(0) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode ) QmuParserCallback::QmuParserCallback ( fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 1 ), m_iPri ( a_iPrec ), m_eOprtAsct ( oaNONE ), m_iCode ( a_iCode ),
,m_iArgc(1) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(a_iPrec)
,m_eOprtAsct(oaNONE)
,m_iCode(a_iCode)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Constructor for constructing funcstion callbacks taking two arguments. /**
\throw nothrow * @brief Constructor for constructing funcstion callbacks taking two arguments.
* @throw nothrow
*/ */
QmuParserCallback::QmuParserCallback ( fun_type2 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type2 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(2) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Constructor for constructing binary operator callbacks. /**
\param a_pFun Pointer to a static function taking two arguments * @brief Constructor for constructing binary operator callbacks.
\param a_bAllowOpti A flag indicating this funcation can be optimized * @param a_pFun Pointer to a static function taking two arguments
\param a_iPrec The operator precedence * @param a_bAllowOpti A flag indicating this funcation can be optimized
\param a_eOprtAsct The operators associativity * @param a_iPrec The operator precedence
\throw nothrow * @param a_eOprtAsct The operators associativity
* @throw nothrow
*/ */
QmuParserCallback::QmuParserCallback(fun_type2 a_pFun, QmuParserCallback::QmuParserCallback ( fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec,
bool a_bAllowOpti,
int a_iPrec,
EOprtAssociativity a_eOprtAsct ) EOprtAssociativity a_eOprtAsct )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), m_iPri ( a_iPrec ), m_eOprtAsct ( a_eOprtAsct ),
,m_iArgc(2) m_iCode ( cmOPRT_BIN ), m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(a_iPrec)
,m_eOprtAsct(a_eOprtAsct)
,m_iCode(cmOPRT_BIN)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type3 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type3 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 3 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(3) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type4 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type4 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 4 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(4) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type5 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type5 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 5 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(5) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type6 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type6 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 6 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(6) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type7 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type7 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 7 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(7) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type8 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type8 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 8 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(8) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type9 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type9 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 9 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(9) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( fun_type10 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( fun_type10 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 10 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(10) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type0 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type0 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 0 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(0) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type1 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type1 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 1 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(1) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Constructor for constructing funcstion callbacks taking two arguments. * @brief Constructor for constructing funcstion callbacks taking two arguments.
\throw nothrow * @throw nothrow
*/ */
QmuParserCallback::QmuParserCallback ( bulkfun_type2 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type2 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(2) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type3 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type3 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 3 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(3) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type4 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type4 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 4 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(4) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type5 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type5 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 5 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(5) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type6 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type6 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 6 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(6) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type7 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type7 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 7 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(7) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type8 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type8 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 8 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(8) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type9 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type9 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 9 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(9) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( bulkfun_type10 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( bulkfun_type10 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 10 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_BULK ),
,m_iArgc(10) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_BULK)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( multfun_type a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( multfun_type a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( -1 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
,m_iArgc(-1) m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC)
,m_iType(tpDBL)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( strfun_type1 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( strfun_type1 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 0 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ),
,m_iArgc(0) m_iCode ( cmFUNC_STR ), m_iType ( tpSTR ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_STR)
,m_iType(tpSTR)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( strfun_type2 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( strfun_type2 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 1 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_STR ),
,m_iArgc(1) m_iType ( tpSTR ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_STR)
,m_iType(tpSTR)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
QmuParserCallback::QmuParserCallback ( strfun_type3 a_pFun, bool a_bAllowOpti ) QmuParserCallback::QmuParserCallback ( strfun_type3 a_pFun, bool a_bAllowOpti )
:m_pFun((void*)a_pFun) : m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_STR ),
,m_iArgc(2) m_iType ( tpSTR ), m_bAllowOpti ( a_bAllowOpti )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmFUNC_STR)
,m_iType(tpSTR)
,m_bAllowOpti(a_bAllowOpti)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Default constructor. * @brief Default constructor.
\throw nothrow * @throw nothrow
*/ */
QmuParserCallback::QmuParserCallback() QmuParserCallback::QmuParserCallback()
:m_pFun(0) : m_pFun ( 0 ), m_iArgc ( 0 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmUNKNOWN ), m_iType ( tpVOID ),
,m_iArgc(0) m_bAllowOpti ( 0 )
,m_iPri(-1)
,m_eOprtAsct(oaNONE)
,m_iCode(cmUNKNOWN)
,m_iType(tpVOID)
,m_bAllowOpti(0)
{} {}
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Copy constructor. * @brief Copy constructor.
\throw nothrow * @throw nothrow
*/ */
QmuParserCallback::QmuParserCallback ( const QmuParserCallback &ref ) QmuParserCallback::QmuParserCallback ( const QmuParserCallback &ref )
{ {
@ -383,76 +237,84 @@ namespace qmu
m_eOprtAsct = ref.m_eOprtAsct; m_eOprtAsct = ref.m_eOprtAsct;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Clone this instance and return a pointer to the new instance. */ /**
* @brief Clone this instance and return a pointer to the new instance.
*/
QmuParserCallback* QmuParserCallback::Clone() const QmuParserCallback* QmuParserCallback::Clone() const
{ {
return new QmuParserCallback ( *this ); return new QmuParserCallback ( *this );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Return tru if the function is conservative. /**
* @brief Return tru if the function is conservative.
Conservative functions return always the same result for the same argument. *
\throw nothrow * Conservative functions return always the same result for the same argument.
* @throw nothrow
*/ */
bool QmuParserCallback::IsOptimizable() const bool QmuParserCallback::IsOptimizable() const
{ {
return m_bAllowOpti; return m_bAllowOpti;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Get the callback address for the parser function. /**
* @brief Get the callback address for the parser function.
The type of the address is void. It needs to be recasted according to the *
argument number to the right type. * The type of the address is void. It needs to be recasted according to the argument number to the right type.
*
\throw nothrow * @throw nothrow
\return #pFun * @return #pFun
*/ */
void* QmuParserCallback::GetAddr() const void* QmuParserCallback::GetAddr() const
{ {
return m_pFun; return m_pFun;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Return the callback code. */ /**
* @brief Return the callback code.
*/
ECmdCode QmuParserCallback::GetCode() const ECmdCode QmuParserCallback::GetCode() const
{ {
return m_iCode; return m_iCode;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
ETypeCode QmuParserCallback::GetType() const ETypeCode QmuParserCallback::GetType() const
{ {
return m_iType; return m_iType;
} }
//----------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------- /**
/** \brief Return the operator precedence. * @brief Return the operator precedence.
\throw nothrown * @throw nothrown
*
Only valid if the callback token is an operator token (binary or infix). * Only valid if the callback token is an operator token (binary or infix).
*/ */
int QmuParserCallback::GetPri() const int QmuParserCallback::GetPri() const
{ {
return m_iPri; return m_iPri;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Return the operators associativity. /**
\throw nothrown * @brief Return the operators associativity.
* @throw nothrown
Only valid if the callback token is a binary operator token. *
* Only valid if the callback token is a binary operator token.
*/ */
EOprtAssociativity QmuParserCallback::GetAssociativity() const EOprtAssociativity QmuParserCallback::GetAssociativity() const
{ {
return m_eOprtAsct; return m_eOprtAsct;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Returns the number of function Arguments. */ /**
* @brief Returns the number of function Arguments.
*/
int QmuParserCallback::GetArgc() const int QmuParserCallback::GetArgc() const
{ {
return m_iArgc; return m_iArgc;

View file

@ -25,24 +25,23 @@
#include "qmuparserdef.h" #include "qmuparserdef.h"
/** \file /**
\brief Definition of the parser callback class. * @file
* @brief Definition of the parser callback class.
*/ */
namespace qmu namespace qmu
{ {
/** \brief Encapsulation of prototypes for a numerical parser function. /**
* @brief Encapsulation of prototypes for a numerical parser function.
Encapsulates the prototyp for numerical parser functions. The class *
stores the number of arguments for parser functions as well * Encapsulates the prototyp for numerical parser functions. The class stores the number of arguments for parser
as additional flags indication the function is non optimizeable. * functions as well as additional flags indication the function is non optimizeable. The pointer to the callback
The pointer to the callback function pointer is stored as void* * function pointer is stored as void* and needs to be casted according to the argument count. Negative argument counts
and needs to be casted according to the argument count. * indicate a parser function with a variable number of arguments.
Negative argument counts indicate a parser function with a variable number *
of arguments. * @author (C) 2004-2011 Ingo Berg
\author (C) 2004-2011 Ingo Berg
*/ */
class QmuParserCallback class QmuParserCallback
{ {
@ -80,7 +79,6 @@ public:
QmuParserCallback(const QmuParserCallback &a_Fun); QmuParserCallback(const QmuParserCallback &a_Fun);
QmuParserCallback* Clone() const; QmuParserCallback* Clone() const;
bool IsOptimizable() const; bool IsOptimizable() const;
void* GetAddr() const; void* GetAddr() const;
ECmdCode GetCode() const; ECmdCode GetCode() const;
@ -88,14 +86,14 @@ public:
int GetPri() const; int GetPri() const;
EOprtAssociativity GetAssociativity() const; EOprtAssociativity GetAssociativity() const;
int GetArgc() const; int GetArgc() const;
private: private:
void *m_pFun; ///< Pointer to the callback function, casted to void void *m_pFun; ///< Pointer to the callback function, casted to void
/** \brief Number of numeric function arguments /**
* @brief Number of numeric function arguments
This number is negative for functions with variable number of arguments. in this cases *
they represent the actual number of arguments found. * This number is negative for functions with variable number of arguments. in this cases
* they represent the actual number of arguments found.
*/ */
int m_iArgc; int m_iArgc;
int m_iPri; ///< Valid only for binary and infix operators; Operator precedence. int m_iPri; ///< Valid only for binary and infix operators; Operator precedence.
@ -105,8 +103,10 @@ private:
bool m_bAllowOpti; ///< Flag indication optimizeability bool m_bAllowOpti; ///< Flag indication optimizeability
}; };
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Container for Callback objects. */ /**
* @brief Container for Callback objects.
*/
typedef std::map<QString, QmuParserCallback> funmap_type; typedef std::map<QString, QmuParserCallback> funmap_type;
} // namespace qmu } // namespace qmu

View file

@ -23,17 +23,13 @@
#ifndef QMUPDEF_H #ifndef QMUPDEF_H
#define QMUPDEF_H #define QMUPDEF_H
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <QMap> #include <QMap>
#include <QString> #include <QString>
#include "qmuparserfixes.h" #include "qmuparserfixes.h"
/** \file /** @file
\brief This file contains standard definitions used by the parser. @brief This file contains standard definitions used by the parser.
*/ */
#define QMUP_VERSION "2.2.3" #define QMUP_VERSION "2.2.3"
@ -41,27 +37,27 @@
#define QMUP_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" #define QMUP_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
/** \brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */ /** @brief If this macro is defined mathematical exceptions (div by zero) will be thrown as exceptions. */
//#define QMUP_MATH_EXCEPTIONS //#define QMUP_MATH_EXCEPTIONS
/** \brief Activate this option in order to compile with OpenMP support. /** @brief Activate this option in order to compile with OpenMP support.
OpenMP is used only in the bulk mode it may increase the performance a bit. OpenMP is used only in the bulk mode it may increase the performance a bit.
*/ */
//#define MUP_USE_OPENMP //#define MUP_USE_OPENMP
#if defined(_UNICODE) #if defined(_UNICODE)
/** \brief Definition of the basic parser string type. */ /** @brief Definition of the basic parser string type. */
#define QMUP_STRING_TYPE std::wstring #define QMUP_STRING_TYPE std::wstring
#else #else
/** \brief Definition of the basic parser string type. */ /** @brief Definition of the basic parser string type. */
#define QMUP_STRING_TYPE std::string #define QMUP_STRING_TYPE std::string
#endif #endif
namespace qmu namespace qmu
{ {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Bytecode values. /** @brief Bytecode values.
\attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt! \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!
*/ */
@ -113,7 +109,7 @@ namespace qmu
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Types internally used by the parser. /** @brief Types internally used by the parser.
*/ */
enum ETypeCode enum ETypeCode
{ {
@ -130,7 +126,7 @@ namespace qmu
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Parser operator precedence values. */ /** @brief Parser operator precedence values. */
enum EOprtAssociativity enum EOprtAssociativity
{ {
oaLEFT = 0, oaLEFT = 0,
@ -139,7 +135,7 @@ namespace qmu
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Parser operator precedence values. */ /** @brief Parser operator precedence values. */
enum EOprtPrecedence enum EOprtPrecedence
{ {
// binary operators // binary operators
@ -159,121 +155,119 @@ namespace qmu
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// basic types // basic types
/** \brief The stringtype used by the parser. /** @brief The stringtype used by the parser.
Depends on wether UNICODE is used or not. Depends on wether UNICODE is used or not.
*/ */
typedef QMUP_STRING_TYPE string_type; typedef QMUP_STRING_TYPE string_type;
/** \brief The character type used by the parser. /** @brief The character type used by the parser.
Depends on wether UNICODE is used or not. Depends on wether UNICODE is used or not.
*/ */
typedef string_type::value_type char_type; typedef string_type::value_type char_type;
/** \brief Typedef for easily using stringstream that respect the parser stringtype. */ /** @brief Typedef for easily using stringstream that respect the parser stringtype. */
typedef std::basic_stringstream<char_type, typedef std::basic_stringstream < char_type, std::char_traits<char_type>, std::allocator<char_type> > stringstream_type;
std::char_traits<char_type>,
std::allocator<char_type> > stringstream_type;
// Data container types // Data container types
/** \brief Type used for storing variables. */ /** @brief Type used for storing variables. */
typedef std::map<QString, qreal*> varmap_type; typedef std::map<QString, qreal*> varmap_type;
/** \brief Type used for storing constants. */ /** @brief Type used for storing constants. */
typedef std::map<QString, qreal> valmap_type; typedef std::map<QString, qreal> valmap_type;
/** \brief Type for assigning a string name to an index in the internal string table. */ /** @brief Type for assigning a string name to an index in the internal string table. */
typedef std::map<QString, int> strmap_type; typedef std::map<QString, int> strmap_type;
// Parser callbacks // Parser callbacks
/** \brief Callback type used for functions without arguments. */ /** @brief Callback type used for functions without arguments. */
typedef qreal ( *generic_fun_type ) (); typedef qreal ( *generic_fun_type ) ();
/** \brief Callback type used for functions without arguments. */ /** @brief Callback type used for functions without arguments. */
typedef qreal ( *fun_type0 ) (); typedef qreal ( *fun_type0 ) ();
/** \brief Callback type used for functions with a single arguments. */ /** @brief Callback type used for functions with a single arguments. */
typedef qreal ( *fun_type1 ) ( qreal ); typedef qreal ( *fun_type1 ) ( qreal );
/** \brief Callback type used for functions with two arguments. */ /** @brief Callback type used for functions with two arguments. */
typedef qreal ( *fun_type2 ) ( qreal, qreal ); typedef qreal ( *fun_type2 ) ( qreal, qreal );
/** \brief Callback type used for functions with three arguments. */ /** @brief Callback type used for functions with three arguments. */
typedef qreal ( *fun_type3 ) ( qreal, qreal, qreal ); typedef qreal ( *fun_type3 ) ( qreal, qreal, qreal );
/** \brief Callback type used for functions with four arguments. */ /** @brief Callback type used for functions with four arguments. */
typedef qreal ( *fun_type4 ) ( qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type4 ) ( qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *fun_type5 ) ( qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type5 ) ( qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *fun_type6 ) ( qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type6 ) ( qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *fun_type7 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type7 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *fun_type8 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type8 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *fun_type9 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type9 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *fun_type10 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *fun_type10 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions without arguments. */ /** @brief Callback type used for functions without arguments. */
typedef qreal ( *bulkfun_type0 ) ( int, int ); typedef qreal ( *bulkfun_type0 ) ( int, int );
/** \brief Callback type used for functions with a single arguments. */ /** @brief Callback type used for functions with a single arguments. */
typedef qreal ( *bulkfun_type1 ) ( int, int, qreal ); typedef qreal ( *bulkfun_type1 ) ( int, int, qreal );
/** \brief Callback type used for functions with two arguments. */ /** @brief Callback type used for functions with two arguments. */
typedef qreal ( *bulkfun_type2 ) ( int, int, qreal, qreal ); typedef qreal ( *bulkfun_type2 ) ( int, int, qreal, qreal );
/** \brief Callback type used for functions with three arguments. */ /** @brief Callback type used for functions with three arguments. */
typedef qreal ( *bulkfun_type3 ) ( int, int, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type3 ) ( int, int, qreal, qreal, qreal );
/** \brief Callback type used for functions with four arguments. */ /** @brief Callback type used for functions with four arguments. */
typedef qreal ( *bulkfun_type4 ) ( int, int, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type4 ) ( int, int, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *bulkfun_type5 ) ( int, int, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type5 ) ( int, int, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *bulkfun_type6 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type6 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *bulkfun_type7 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type7 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *bulkfun_type8 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type8 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *bulkfun_type9 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type9 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with five arguments. */ /** @brief Callback type used for functions with five arguments. */
typedef qreal ( *bulkfun_type10 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal ); typedef qreal ( *bulkfun_type10 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
/** \brief Callback type used for functions with a variable argument list. */ /** @brief Callback type used for functions with a variable argument list. */
typedef qreal ( *multfun_type ) ( const qreal*, int ); typedef qreal ( *multfun_type ) ( const qreal*, int );
/** \brief Callback type used for functions taking a string as an argument. */ /** @brief Callback type used for functions taking a string as an argument. */
typedef qreal ( *strfun_type1 ) ( const QString & ); typedef qreal ( *strfun_type1 ) ( const QString & );
/** \brief Callback type used for functions taking a string and a value as arguments. */ /** @brief Callback type used for functions taking a string and a value as arguments. */
typedef qreal ( *strfun_type2 ) ( const QString &, qreal ); typedef qreal ( *strfun_type2 ) ( const QString &, qreal );
/** \brief Callback type used for functions taking a string and two values as arguments. */ /** @brief Callback type used for functions taking a string and two values as arguments. */
typedef qreal ( *strfun_type3 ) ( const QString &, qreal, qreal ); typedef qreal ( *strfun_type3 ) ( const QString &, qreal, qreal );
/** \brief Callback used for functions that identify values in a string. */ /** @brief Callback used for functions that identify values in a string. */
typedef int ( *identfun_type ) ( const QString &sExpr, int *nPos, qreal *fVal ); typedef int ( *identfun_type ) ( const QString &sExpr, int *nPos, qreal *fVal );
/** \brief Callback used for variable creation factory functions. */ /** @brief Callback used for variable creation factory functions. */
typedef qreal* ( *facfun_type ) ( const QString &, void* ); typedef qreal* ( *facfun_type ) ( const QString &, void* );
} // end of namespace } // end of namespace

View file

@ -24,29 +24,29 @@
#include <QTextStream> #include <QTextStream>
namespace qmu namespace qmu
{ {
const QmuParserErrorMsg QmuParserErrorMsg::m_Instance; const QmuParserErrorMsg QmuParserErrorMsg::m_Instance;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
const QmuParserErrorMsg& QmuParserErrorMsg::Instance() const QmuParserErrorMsg& QmuParserErrorMsg::Instance()
{ {
return m_Instance; return m_Instance;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
QString QmuParserErrorMsg::operator[] ( unsigned a_iIdx ) const QString QmuParserErrorMsg::operator[] ( unsigned a_iIdx ) const
{ {
return ( a_iIdx < m_vErrMsg.size() ) ? m_vErrMsg[a_iIdx] : QString(); return ( a_iIdx < m_vErrMsg.size() ) ? m_vErrMsg[a_iIdx] : QString();
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserErrorMsg::~QmuParserErrorMsg() QmuParserErrorMsg::~QmuParserErrorMsg()
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Assignement operator is deactivated. /**
* @brief Assignement operator is deactivated.
*/ */
QmuParserErrorMsg& QmuParserErrorMsg::operator= ( const QmuParserErrorMsg& ) QmuParserErrorMsg& QmuParserErrorMsg::operator= ( const QmuParserErrorMsg& )
{ {
@ -54,11 +54,11 @@ namespace qmu
return *this; return *this;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserErrorMsg::QmuParserErrorMsg ( const QmuParserErrorMsg& ) QmuParserErrorMsg::QmuParserErrorMsg ( const QmuParserErrorMsg& )
{} {}
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserErrorMsg::QmuParserErrorMsg() QmuParserErrorMsg::QmuParserErrorMsg()
: m_vErrMsg ( 0 ) : m_vErrMsg ( 0 )
{ {
@ -103,48 +103,49 @@ namespace qmu
#if defined(_DEBUG) #if defined(_DEBUG)
for ( int i = 0; i < ecCOUNT; ++i ) for ( int i = 0; i < ecCOUNT; ++i )
{
if ( !m_vErrMsg[i].length() ) if ( !m_vErrMsg[i].length() )
{
assert ( false ); assert ( false );
}
}
#endif #endif
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// //
// QParserError class // QParserError class
// //
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Default constructor. */ /**
* @brief Default constructor.
*/
QmuParserError::QmuParserError() QmuParserError::QmuParserError()
:m_strMsg() : m_strMsg(), m_strFormula(), m_strTok(), m_iPos ( -1 ), m_iErrc ( ecUNDEFINED ),
,m_strFormula() m_ErrMsg ( QmuParserErrorMsg::Instance() )
,m_strTok()
,m_iPos(-1)
,m_iErrc(ecUNDEFINED)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief This Constructor is used for internal exceptions only. /**
* @brief This Constructor is used for internal exceptions only.
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_strMsg() : m_strMsg(), m_strFormula(), m_strTok(), m_iPos ( -1 ), m_iErrc ( a_iErrc ),
,m_strFormula() m_ErrMsg ( QmuParserErrorMsg::Instance() )
,m_strTok()
,m_iPos(-1)
,m_iErrc(a_iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
m_strMsg = m_ErrMsg[m_iErrc]; m_strMsg = m_ErrMsg[m_iErrc];
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) ); ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok ); ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \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_ErrMsg ( QmuParserErrorMsg::Instance() ) : m_ErrMsg ( QmuParserErrorMsg::Instance() )
{ {
@ -152,84 +153,72 @@ namespace qmu
m_strMsg = sMsg; m_strMsg = sMsg;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Construct an error object. /**
\param [in] a_iErrc the error code. * @brief Construct an error object.
\param [in] sTok The token string related to this error. * @param [in] a_iErrc the error code.
\param [in] sExpr The expression related to the error. * @param [in] sTok The token string related to this error.
\param [in] a_iPos the position in the expression where the error occured. * @param [in] sExpr The expression related to the error.
* @param [in] a_iPos the position in the expression where the error occured.
*/ */
QmuParserError::QmuParserError ( EErrorCodes iErrc, QmuParserError::QmuParserError ( EErrorCodes iErrc,
const QString &sTok, const QString &sTok,
const QString &sExpr, const QString &sExpr,
int iPos ) int iPos )
:m_strMsg() : m_strMsg(), m_strFormula ( sExpr ), m_strTok ( sTok ), m_iPos ( iPos ), m_iErrc ( iErrc ),
,m_strFormula(sExpr) m_ErrMsg ( QmuParserErrorMsg::Instance() )
,m_strTok(sTok)
,m_iPos(iPos)
,m_iErrc(iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
m_strMsg = m_ErrMsg[m_iErrc]; m_strMsg = m_ErrMsg[m_iErrc];
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) ); ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok ); ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Construct an error object. /**
\param [in] iErrc the error code. * @brief Construct an error object.
\param [in] iPos the position in the expression where the error occured. * @param [in] iErrc the error code.
\param [in] sTok The token string related to this error. * @param [in] iPos the position in the expression where the error occured.
* @param [in] sTok The token string related to this error.
*/ */
QmuParserError::QmuParserError ( EErrorCodes iErrc, int iPos, const QString &sTok ) QmuParserError::QmuParserError ( EErrorCodes iErrc, int iPos, const QString &sTok )
:m_strMsg() : m_strMsg(), m_strFormula(), m_strTok ( sTok ), m_iPos ( iPos ), m_iErrc ( iErrc ),
,m_strFormula() m_ErrMsg ( QmuParserErrorMsg::Instance() )
,m_strTok(sTok)
,m_iPos(iPos)
,m_iErrc(iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
m_strMsg = m_ErrMsg[m_iErrc]; m_strMsg = m_ErrMsg[m_iErrc];
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) ); ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok ); ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Construct an error object. /** @brief Construct an error object.
\param [in] szMsg The error message text. * @param [in] szMsg The error message text.
\param [in] iPos the position related to the error. * @param [in] iPos the position related to the error.
\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_strMsg(szMsg) : m_strMsg ( szMsg ), m_strFormula(), m_strTok ( sTok ), m_iPos ( iPos ), m_iErrc ( ecGENERIC ),
,m_strFormula() m_ErrMsg ( QmuParserErrorMsg::Instance() )
,m_strTok(sTok)
,m_iPos(iPos)
,m_iErrc(ecGENERIC)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) ); ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok ); ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Copy constructor. */ /** @brief Copy constructor. */
QmuParserError::QmuParserError ( const QmuParserError &a_Obj ) QmuParserError::QmuParserError ( const QmuParserError &a_Obj )
:m_strMsg(a_Obj.m_strMsg) : m_strMsg ( a_Obj.m_strMsg ), m_strFormula ( a_Obj.m_strFormula ), m_strTok ( a_Obj.m_strTok ),
,m_strFormula(a_Obj.m_strFormula) m_iPos ( a_Obj.m_iPos ), m_iErrc ( a_Obj.m_iErrc ), m_ErrMsg ( QmuParserErrorMsg::Instance() )
,m_strTok(a_Obj.m_strTok)
,m_iPos(a_Obj.m_iPos)
,m_iErrc(a_Obj.m_iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Assignment operator. */ /** @brief Assignment operator. */
QmuParserError& QmuParserError::operator= ( const QmuParserError &a_Obj ) QmuParserError& QmuParserError::operator= ( const QmuParserError &a_Obj )
{ {
if ( this == &a_Obj ) if ( this == &a_Obj )
{
return *this; return *this;
}
m_strMsg = a_Obj.m_strMsg; m_strMsg = a_Obj.m_strMsg;
m_strFormula = a_Obj.m_strFormula; m_strFormula = a_Obj.m_strFormula;
@ -239,14 +228,15 @@ namespace qmu
return *this; return *this;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
QmuParserError::~QmuParserError() QmuParserError::~QmuParserError()
{} {}
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Replace all ocuurences of a substring with another string. /**
\param strFind The string that shall be replaced. * @brief Replace all ocuurences of a substring with another string.
\param strReplaceWith The string that should be inserted instead of strFind * @param strFind The string that shall be replaced.
* @param strReplaceWith The string that should be inserted instead of strFind
*/ */
void QmuParserError::ReplaceSubString ( QString &strSource, const QString &strFind, const QString &strReplaceWith ) void QmuParserError::ReplaceSubString ( QString &strSource, const QString &strFind, const QString &strReplaceWith )
{ {
@ -268,8 +258,10 @@ void QmuParserError::ReplaceSubString( QString &strSource, const QString &strFin
strSource.swap ( strResult ); strSource.swap ( strResult );
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Reset the erro object. */ /**
* @brief Reset the erro object.
*/
void QmuParserError::Reset() void QmuParserError::Reset()
{ {
m_strMsg = ""; m_strMsg = "";
@ -279,46 +271,57 @@ void QmuParserError::ReplaceSubString( QString &strSource, const QString &strFin
m_iErrc = ecUNDEFINED; m_iErrc = ecUNDEFINED;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Set the expression related to this error. */ /**
* @brief Set the expression related to this error.
*/
void QmuParserError::SetFormula ( const QString &a_strFormula ) void QmuParserError::SetFormula ( const QString &a_strFormula )
{ {
m_strFormula = a_strFormula; m_strFormula = a_strFormula;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief gets the expression related tp this error.*/ /**
* @brief gets the expression related tp this error.
*/
const QString& QmuParserError::GetExpr() const const QString& QmuParserError::GetExpr() const
{ {
return m_strFormula; return m_strFormula;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Returns the message string for this error. */ /**
* @brief Returns the message string for this error.
*/
const QString& QmuParserError::GetMsg() const const QString& QmuParserError::GetMsg() const
{ {
return m_strMsg; return m_strMsg;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Return the formula position related to the error. /**
* @brief Return the formula position related to the error.
If the error is not related to a distinct position this will return -1 *
* If the error is not related to a distinct position this will return -1
*/ */
std::size_t QmuParserError::GetPos() const std::size_t QmuParserError::GetPos() const
{ {
return m_iPos; return m_iPos;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Return string related with this token (if available). */ /**
* @brief Return string related with this token (if available).
*/
const QString& QmuParserError::GetToken() const const QString& QmuParserError::GetToken() const
{ {
return m_strTok; return m_strTok;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Return the error code. */ /**
* @brief Return the error code.
*/
EErrorCodes QmuParserError::GetCode() const EErrorCodes QmuParserError::GetCode() const
{ {
return m_iErrc; return m_iErrc;

View file

@ -31,14 +31,14 @@
#include "qmuparserdef.h" #include "qmuparserdef.h"
/** \file /** @file
\brief This file defines the error class used by the parser. @brief This file defines the error class used by the parser.
*/ */
namespace qmu namespace qmu
{ {
/** \brief Error codes. */ /** @brief Error codes. */
enum EErrorCodes enum EErrorCodes
{ {
// Formula syntax errors // Formula syntax errors
@ -92,7 +92,7 @@ enum EErrorCodes
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief A class that handles the error messages. /** @brief A class that handles the error messages.
*/ */
class QmuParserErrorMsg class QmuParserErrorMsg
{ {
@ -102,7 +102,6 @@ public:
QmuParserErrorMsg& operator= ( const QmuParserErrorMsg & ); QmuParserErrorMsg& operator= ( const QmuParserErrorMsg & );
QmuParserErrorMsg ( const QmuParserErrorMsg& ); QmuParserErrorMsg ( const QmuParserErrorMsg& );
QmuParserErrorMsg(); QmuParserErrorMsg();
~QmuParserErrorMsg(); ~QmuParserErrorMsg();
static const QmuParserErrorMsg& Instance(); static const QmuParserErrorMsg& Instance();
@ -114,21 +113,13 @@ private:
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief Error class of the parser. /** @brief Error class of the parser.
\author Ingo Berg @author Ingo Berg
Part of the math parser package. Part of the math parser package.
*/ */
class QmuParserError class QmuParserError
{ {
private:
/** \brief Replace all ocuurences of a substring with another string. */
void ReplaceSubString(QString &strSource,
const QString &strFind,
const QString &strReplaceWith);
void Reset();
public: public:
QmuParserError(); QmuParserError();
@ -155,6 +146,11 @@ private:
int m_iPos; ///< Formula position related to the error int m_iPos; ///< Formula position related to the error
EErrorCodes m_iErrc; ///< Error code EErrorCodes m_iErrc; ///< Error code
const QmuParserErrorMsg &m_ErrMsg; const QmuParserErrorMsg &m_ErrMsg;
/**
* @brief Replace all ocuurences of a substring with another string.
*/
void ReplaceSubString ( QString &strSource, const QString &strFind, const QString &strReplaceWith );
void Reset();
}; };
} // namespace qmu } // namespace qmu

View file

@ -23,8 +23,8 @@
#ifndef QMUPARSERFIXES_H #ifndef QMUPARSERFIXES_H
#define QMUPARSERFIXES_H #define QMUPARSERFIXES_H
/** \file /** @file
\brief This file contains compatibility fixes for some platforms. @brief This file contains compatibility fixes for some platforms.
*/ */
// //

View file

@ -30,8 +30,9 @@
using namespace std; using namespace std;
/** \file /**
\brief This file contains the implementation of parser test cases. * @file
* @brief This file contains the implementation of parser test cases.
*/ */
namespace qmu namespace qmu
@ -40,7 +41,7 @@ namespace qmu
{ {
int QmuParserTester::c_iCount = 0; int QmuParserTester::c_iCount = 0;
//--------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserTester::QmuParserTester() QmuParserTester::QmuParserTester()
: m_vTestFun() : m_vTestFun()
{ {
@ -60,11 +61,13 @@ namespace qmu
QmuParserTester::c_iCount = 0; QmuParserTester::c_iCount = 0;
} }
//--------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
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[1] == 0 || ( a_szExpr[0] != '0' || a_szExpr[1] != 'x' ) )
{
return 0; return 0;
}
unsigned iVal ( 0 ); unsigned iVal ( 0 );
bool ok = false; bool ok = false;
@ -74,7 +77,9 @@ namespace qmu
{ {
int nPos = a_szExpr.indexOf ( QString().setNum ( iVal, 16 ) ); int nPos = a_szExpr.indexOf ( QString().setNum ( iVal, 16 ) );
if ( nPos == 0 ) if ( nPos == 0 )
{
return 1; return 1;
}
*a_iPos += ( int ) ( 2 + nPos ); *a_iPos += ( int ) ( 2 + nPos );
*a_fVal = ( qreal ) iVal; *a_fVal = ( qreal ) iVal;
@ -87,7 +92,7 @@ namespace qmu
} }
//--------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestInterface() int QmuParserTester::TestInterface()
{ {
int iStat = 0; int iStat = 0;
@ -122,14 +127,18 @@ namespace qmu
} }
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestStrArg() int QmuParserTester::TestStrArg()
{ {
int iStat = 0; int iStat = 0;
@ -147,14 +156,18 @@ namespace qmu
iStat += EqnTest ( "strfun3(\"99\",1,2)", 102, true ); iStat += EqnTest ( "strfun3(\"99\",1,2)", 102, true );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestBinOprt() int QmuParserTester::TestBinOprt()
{ {
int iStat = 0; int iStat = 0;
@ -218,15 +231,19 @@ namespace qmu
iStat += EqnTest ( "3+4*2/(1-5)^2^3", 3.0001220703125, true ); iStat += EqnTest ( "3+4*2/(1-5)^2^3", 3.0001220703125, true );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check muParser name restriction enforcement. */ /** @brief Check muParser name restriction enforcement. */
int QmuParserTester::TestNames() int QmuParserTester::TestNames()
{ {
int iStat = 0, int iStat = 0,
@ -327,14 +344,18 @@ namespace qmu
#undef PARSER_THROWCHECK #undef PARSER_THROWCHECK
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestSyntax() int QmuParserTester::TestSyntax()
{ {
int iStat = 0; int iStat = 0;
@ -376,14 +397,18 @@ namespace qmu
iStat += EqnTest ( "sin()", 0, false ); // unexpected closing bracket iStat += EqnTest ( "sin()", 0, false ); // unexpected closing bracket
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestVarConst() int QmuParserTester::TestVarConst()
{ {
int iStat = 0; int iStat = 0;
@ -437,46 +462,66 @@ namespace qmu
qmu::varmap_type UsedVar = p.GetUsedVar(); qmu::varmap_type UsedVar = p.GetUsedVar();
int iCount = ( int ) UsedVar.size(); int iCount = ( int ) UsedVar.size();
if ( iCount != 4 ) if ( iCount != 4 )
{
throw false; throw false;
}
// the next check will fail if the parser // the next check will fail if the parser
// erroneousely creates new variables internally // erroneousely creates new variables internally
if ( p.GetVar().size() != 5 ) if ( p.GetVar().size() != 5 )
{
throw false; throw false;
}
qmu::varmap_type::const_iterator item = UsedVar.begin(); qmu::varmap_type::const_iterator item = UsedVar.begin();
for ( idx = 0; item != UsedVar.end(); ++item ) for ( idx = 0; item != UsedVar.end(); ++item )
{ {
if ( &vVarVal[idx++] != item->second ) if ( &vVarVal[idx++] != item->second )
{
throw false; throw false;
} }
}
// Test lookup of undefined variables // Test lookup of undefined variables
p.SetExpr ( "undef1+undef2+undef3" ); p.SetExpr ( "undef1+undef2+undef3" );
UsedVar = p.GetUsedVar(); UsedVar = p.GetUsedVar();
iCount = ( int ) UsedVar.size(); iCount = ( int ) UsedVar.size();
if ( iCount != 3 ) if ( iCount != 3 )
{
throw false; throw false;
}
// the next check will fail if the parser // the next check will fail if the parser
// erroneousely creates new variables internally // erroneousely creates new variables internally
if ( p.GetVar().size() != 5 ) if ( p.GetVar().size() != 5 )
{
throw false; throw false;
}
for ( item = UsedVar.begin(); item != UsedVar.end(); ++item ) for ( item = UsedVar.begin(); item != UsedVar.end(); ++item )
{ {
if ( item->second != 0 ) if ( item->second != 0 )
{
throw false; // all pointers to undefined variables must be null throw false; // all pointers to undefined variables must be null
} }
}
// 1 used variables // 1 used variables
p.SetExpr ( "a+b" ); p.SetExpr ( "a+b" );
UsedVar = p.GetUsedVar(); UsedVar = p.GetUsedVar();
iCount = ( int ) UsedVar.size(); iCount = ( int ) UsedVar.size();
if (iCount!=2) throw false; if ( iCount != 2 )
{
throw false;
}
item = UsedVar.begin(); item = UsedVar.begin();
for ( idx = 0; item != UsedVar.end(); ++item ) for ( idx = 0; item != UsedVar.end(); ++item )
if (&vVarVal[idx++]!=item->second) throw false; {
if ( &vVarVal[idx++] != item->second )
{
throw false;
}
}
} }
catch ( ... ) catch ( ... )
@ -485,14 +530,18 @@ namespace qmu
} }
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestMultiArg() int QmuParserTester::TestMultiArg()
{ {
int iStat = 0; int iStat = 0;
@ -579,15 +628,19 @@ namespace qmu
iStat += EqnTest ( "sum(,1,2)", 0, false ); iStat += EqnTest ( "sum(,1,2)", 0, false );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestInfixOprt() int QmuParserTester::TestInfixOprt()
{ {
int iStat ( 0 ); int iStat ( 0 );
@ -644,15 +697,19 @@ namespace qmu
iStat += EqnTest ( "~~ 123", 123 + 2, true ); iStat += EqnTest ( "~~ 123", 123 + 2, true );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestPostFix() int QmuParserTester::TestPostFix()
{ {
int iStat = 0; int iStat = 0;
@ -696,14 +753,18 @@ namespace qmu
iStat += ThrowTest ( "multi*1.0", ecUNASSIGNABLE_TOKEN ); iStat += ThrowTest ( "multi*1.0", ecUNASSIGNABLE_TOKEN );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestExpression() int QmuParserTester::TestExpression()
{ {
int iStat = 0; int iStat = 0;
@ -756,7 +817,8 @@ namespace qmu
iStat += EqnTest ( "(cos(2.41)/b)", -0.372056, true ); iStat += EqnTest ( "(cos(2.41)/b)", -0.372056, true );
iStat += EqnTest ( "(1*(2*(3*(4*(5*(6*(a+b)))))))", 2160, true ); iStat += EqnTest ( "(1*(2*(3*(4*(5*(6*(a+b)))))))", 2160, true );
iStat += EqnTest ( "(1*(2*(3*(4*(5*(6*(7*(a+b))))))))", 15120, true ); iStat += EqnTest ( "(1*(2*(3*(4*(5*(6*(7*(a+b))))))))", 15120, true );
iStat += EqnTest( "(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))", 0.00377999, true); iStat += EqnTest ( "(a/((((b+(((e*(((((pi*((((3.45*((pi+a)+pi))+b)+b)*a))+0.68)+e)+a)/a))+a)+b))+b)*a)-pi))",
0.00377999, true );
// long formula (Reference: Matlab) // long formula (Reference: Matlab)
iStat += EqnTest ( iStat += EqnTest (
@ -776,16 +838,20 @@ namespace qmu
iStat += EqnTest ( "1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12", -7995810.09926, true ); iStat += EqnTest ( "1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12", -7995810.09926, true );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestIfThenElse() int QmuParserTester::TestIfThenElse()
{ {
int iStat = 0; int iStat = 0;
@ -884,14 +950,18 @@ namespace qmu
iStat += EqnTest ( "a=0?5:b=1?3:4, b", 3, true ); iStat += EqnTest ( "a=0?5:b=1?3:4, b", 3, true );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed"; qDebug() << "passed";
}
else else
{
qDebug() << "\n failed with " << iStat << " errors"; qDebug() << "\n failed with " << iStat << " errors";
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::TestException() int QmuParserTester::TestException()
{ {
int iStat = 0; int iStat = 0;
@ -978,29 +1048,35 @@ namespace qmu
iStat += ThrowTest ( "a=\"tttt\"", ecOPRT_TYPE_CONFLICT ); iStat += ThrowTest ( "a=\"tttt\"", ecOPRT_TYPE_CONFLICT );
if ( iStat == 0 ) if ( iStat == 0 )
{
qDebug() << "passed" ; qDebug() << "passed" ;
}
else else
{
qDebug() << "\n failed with " << iStat << " errors" ; qDebug() << "\n failed with " << iStat << " errors" ;
}
return iStat; return iStat;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserTester::AddTest ( testfun_type a_pFun ) void QmuParserTester::AddTest ( testfun_type a_pFun )
{ {
m_vTestFun.push_back ( a_pFun ); m_vTestFun.push_back ( a_pFun );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserTester::Run() void QmuParserTester::Run()
{ {
int iStat = 0; int iStat = 0;
try try
{ {
for ( int i = 0; i < ( int ) m_vTestFun.size(); ++i ) for ( int i = 0; i < ( int ) m_vTestFun.size(); ++i )
{
iStat += ( this->*m_vTestFun[i] ) (); iStat += ( this->*m_vTestFun[i] ) ();
} }
}
catch ( QmuParser::exception_type &e ) catch ( QmuParser::exception_type &e )
{ {
qDebug() << "\n" << e.GetMsg() ; qDebug() << "\n" << e.GetMsg() ;
@ -1032,7 +1108,7 @@ namespace qmu
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
int QmuParserTester::ThrowTest ( const QString &a_str, int a_iErrc, bool a_bFail ) int QmuParserTester::ThrowTest ( const QString &a_str, int a_iErrc, bool a_bFail )
{ {
QmuParserTester::c_iCount++; QmuParserTester::c_iCount++;
@ -1081,15 +1157,13 @@ namespace qmu
return bRet; return bRet;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Evaluate a tet expression. /**
* @brief Evaluate a tet expression.
\return 1 in case of a failure, 0 otherwise. *
* @return 1 in case of a failure, 0 otherwise.
*/ */
int QmuParserTester::EqnTestWithVarChange(const QString &a_str, int QmuParserTester::EqnTestWithVarChange ( const QString &a_str, double a_fVar1, double a_fRes1, double a_fVar2,
double a_fVar1,
double a_fRes1,
double a_fVar2,
double a_fRes2 ) double a_fRes2 )
{ {
QmuParserTester::c_iCount++; QmuParserTester::c_iCount++;
@ -1111,11 +1185,15 @@ namespace qmu
fVal[1] = p.Eval(); fVal[1] = p.Eval();
if ( fabs ( a_fRes1 - fVal[0] ) > 0.0000000001 ) if ( fabs ( a_fRes1 - fVal[0] ) > 0.0000000001 )
{
throw std::runtime_error ( "incorrect result (first pass)" ); throw std::runtime_error ( "incorrect result (first pass)" );
}
if ( fabs ( a_fRes2 - fVal[1] ) > 0.0000000001 ) if ( fabs ( a_fRes2 - fVal[1] ) > 0.0000000001 )
{
throw std::runtime_error ( "incorrect result (second pass)" ); throw std::runtime_error ( "incorrect result (second pass)" );
} }
}
catch ( QmuParser::exception_type &e ) catch ( QmuParser::exception_type &e )
{ {
qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")"; qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")";
@ -1135,10 +1213,11 @@ namespace qmu
return 0; return 0;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Evaluate a tet expression. /**
* @brief Evaluate a tet expression.
\return 1 in case of a failure, 0 otherwise. *
* @return 1 in case of a failure, 0 otherwise.
*/ */
int QmuParserTester::EqnTest ( const QString &a_str, double a_fRes, bool a_fPass ) int QmuParserTester::EqnTest ( const QString &a_str, double a_fRes, bool a_fPass )
{ {
@ -1228,7 +1307,9 @@ namespace qmu
fVal[0] = p1->Eval(); // result from stringparsing fVal[0] = p1->Eval(); // result from stringparsing
fVal[1] = p1->Eval(); // result from bytecode fVal[1] = p1->Eval(); // result from bytecode
if ( fVal[0] != fVal[1] ) if ( fVal[0] != fVal[1] )
{
throw QmuParser::exception_type ( "Bytecode / string parsing mismatch." ); throw QmuParser::exception_type ( "Bytecode / string parsing mismatch." );
}
// Test copy and assignement operators // Test copy and assignement operators
try try
@ -1272,8 +1353,10 @@ namespace qmu
// reference: // reference:
// http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825 // http://sourceforge.net/projects/muparser/forums/forum/462843/topic/5037825
if ( numeric_limits<qreal>::has_infinity ) if ( numeric_limits<qreal>::has_infinity )
{
bCloseEnough &= ( fabs ( fVal[i] ) != numeric_limits<qreal>::infinity() ); bCloseEnough &= ( fabs ( fVal[i] ) != numeric_limits<qreal>::infinity() );
} }
}
iRet = ( ( bCloseEnough && a_fPass ) || ( !bCloseEnough && !a_fPass ) ) ? 0 : 1; iRet = ( ( bCloseEnough && a_fPass ) || ( !bCloseEnough && !a_fPass ) ) ? 0 : 1;
@ -1294,9 +1377,13 @@ namespace qmu
if ( a_fPass ) if ( a_fPass )
{ {
if ( fVal[0] != fVal[2] && fVal[0] != -999 && fVal[1] != -998 ) if ( fVal[0] != fVal[2] && fVal[0] != -999 && fVal[1] != -998 )
{
qDebug() << "\n fail: " << a_str << " (copy construction)"; qDebug() << "\n fail: " << a_str << " (copy construction)";
}
else else
{
qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")"; qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")";
}
return 1; return 1;
} }
} }
@ -1314,8 +1401,10 @@ namespace qmu
return iRet; return iRet;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Internal error in test class Test is going to be aborted. */ /**
* @brief Internal error in test class Test is going to be aborted.
*/
void QmuParserTester::Abort() const void QmuParserTester::Abort() const
{ {
qDebug() << "Test failed (internal error in test class)" ; qDebug() << "Test failed (internal error in test class)" ;

View file

@ -29,61 +29,164 @@
#include "qmuparser.h" #include "qmuparser.h"
#include <QString> #include <QString>
/** \file /**
\brief This file contains the parser test class. * @file
* @brief This file contains the parser test class.
*/ */
namespace qmu namespace qmu
{ {
/** \brief Namespace for test cases. */ /**
* @brief Namespace for test cases.
*/
namespace Test namespace Test
{ {
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
/** \brief Test cases for unit testing. /**
* @brief Test cases for unit testing.
(C) 2004-2011 Ingo Berg *
* (C) 2004-2011 Ingo Berg
*/ */
class QmuParserTester // final class QmuParserTester // final
{ {
public:
typedef int ( QmuParserTester::*testfun_type ) ();
QmuParserTester();
void Run();
private: private:
QVector<testfun_type> m_vTestFun;
static int c_iCount; static int c_iCount;
void AddTest ( testfun_type a_pFun );
// Test Double Parser
int EqnTest ( const QString &a_str, double a_fRes, bool a_fPass );
int EqnTestWithVarChange ( const QString &a_str, double a_fRes1, double a_fVar1, double a_fRes2, double a_fVar2 );
int ThrowTest ( const QString &a_str, int a_iErrc, bool a_bFail = true );
// Multiarg callbacks // Multiarg callbacks
static qreal f1of1(qreal v) { return v;} static qreal f1of1 ( qreal v )
{
return v;
}
static qreal f1of2(qreal v, qreal ) {return v;} static qreal f1of2 ( qreal v, qreal )
static qreal f2of2(qreal , qreal v) {return v;} {
return v;
}
static qreal f1of3(qreal v, qreal , qreal ) {return v;} static qreal f2of2 ( qreal , qreal v )
static qreal f2of3(qreal , qreal v, qreal ) {return v;} {
static qreal f3of3(qreal , qreal , qreal v) {return v;} return v;
}
static qreal f1of4(qreal v, qreal, qreal , qreal ) {return v;} static qreal f1of3 ( qreal v, qreal , qreal )
static qreal f2of4(qreal , qreal v, qreal , qreal ) {return v;} {
static qreal f3of4(qreal , qreal, qreal v, qreal ) {return v;} return v;
static qreal f4of4(qreal , qreal, qreal , qreal v) {return v;} }
static qreal f1of5(qreal v, qreal, qreal , qreal , qreal ) { return v; } static qreal f2of3 ( qreal , qreal v, qreal )
static qreal f2of5(qreal , qreal v, qreal , qreal , qreal ) { return v; } {
static qreal f3of5(qreal , qreal, qreal v, qreal , qreal ) { return v; } return v;
static qreal f4of5(qreal , qreal, qreal , qreal v, qreal ) { return v; } }
static qreal f5of5(qreal , qreal, qreal , qreal , qreal v) { return v; }
static qreal Min(qreal a_fVal1, qreal a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; } static qreal f3of3 ( qreal , qreal , qreal v )
static qreal Max(qreal a_fVal1, qreal a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; } {
return v;
}
static qreal plus2(qreal v1) { return v1+2; } static qreal f1of4 ( qreal v, qreal, qreal , qreal )
static qreal times3(qreal v1) { return v1*3; } {
static qreal sqr(qreal v1) { return v1*v1; } return v;
static qreal sign(qreal v) { return -v; } }
static qreal add(qreal v1, qreal v2) { return v1+v2; }
static qreal land(qreal v1, qreal v2) { return (int)v1 & (int)v2; }
static qreal f2of4 ( qreal , qreal v, qreal , qreal )
{
return v;
}
static qreal f3of4 ( qreal , qreal, qreal v, qreal )
{
return v;
}
static qreal f4of4 ( qreal , qreal, qreal , qreal v )
{
return v;
}
static qreal f1of5 ( qreal v, qreal, qreal , qreal , qreal )
{
return v;
}
static qreal f2of5 ( qreal , qreal v, qreal , qreal , qreal )
{
return v;
}
static qreal f3of5 ( qreal , qreal, qreal v, qreal , qreal )
{
return v;
}
static qreal f4of5 ( qreal , qreal, qreal , qreal v, qreal )
{
return v;
}
static qreal f5of5 ( qreal , qreal, qreal , qreal , qreal v )
{
return v;
}
static qreal Min ( qreal a_fVal1, qreal a_fVal2 )
{
return ( a_fVal1 < a_fVal2 ) ? a_fVal1 : a_fVal2;
}
static qreal Max ( qreal a_fVal1, qreal a_fVal2 )
{
return ( a_fVal1 > a_fVal2 ) ? a_fVal1 : a_fVal2;
}
static qreal plus2 ( qreal v1 )
{
return v1 + 2;
}
static qreal times3 ( qreal v1 )
{
return v1 * 3;
}
static qreal sqr ( qreal v1 )
{
return v1 * v1;
}
static qreal sign ( qreal v )
{
return -v;
}
static qreal add ( qreal v1, qreal v2 )
{
return v1 + v2;
}
static qreal land ( qreal v1, qreal v2 )
{
return ( int ) v1 & ( int ) v2;
}
static qreal FirstArg ( const qreal* a_afArg, int a_iArgc ) static qreal FirstArg ( const qreal* a_afArg, int a_iArgc )
{ {
if ( !a_iArgc ) if ( !a_iArgc )
{
throw qmu::QmuParser::exception_type ( "too few arguments for function FirstArg." ); throw qmu::QmuParser::exception_type ( "too few arguments for function FirstArg." );
}
return a_afArg[0]; return a_afArg[0];
} }
@ -91,7 +194,9 @@ namespace qmu
static qreal LastArg ( const qreal* a_afArg, int a_iArgc ) static qreal LastArg ( const qreal* a_afArg, int a_iArgc )
{ {
if ( !a_iArgc ) if ( !a_iArgc )
{
throw qmu::QmuParser::exception_type ( "too few arguments for function LastArg." ); throw qmu::QmuParser::exception_type ( "too few arguments for function LastArg." );
}
return a_afArg[a_iArgc - 1]; return a_afArg[a_iArgc - 1];
} }
@ -99,10 +204,15 @@ namespace qmu
static qreal Sum ( const qreal* a_afArg, int a_iArgc ) static qreal Sum ( const qreal* a_afArg, int a_iArgc )
{ {
if ( !a_iArgc ) if ( !a_iArgc )
{
throw qmu::QmuParser::exception_type ( "too few arguments for function sum." ); throw qmu::QmuParser::exception_type ( "too few arguments for function sum." );
}
qreal fRes = 0; qreal fRes = 0;
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i]; for ( int i = 0; i < a_iArgc; ++i )
{
fRes += a_afArg[i];
}
return fRes; return fRes;
} }
@ -151,9 +261,20 @@ namespace qmu
} }
// postfix operator callback // postfix operator callback
static qreal Mega(qreal a_fVal) { return a_fVal * (qreal)1e6; } static qreal Mega ( qreal a_fVal )
static qreal Micro(qreal a_fVal) { return a_fVal * (qreal)1e-6; } {
static qreal Milli(qreal a_fVal) { return a_fVal / (qreal)1e3; } return a_fVal * ( qreal ) 1e6;
}
static qreal Micro ( qreal a_fVal )
{
return a_fVal * ( qreal ) 1e-6;
}
static qreal Milli ( qreal a_fVal )
{
return a_fVal / ( qreal ) 1e3;
}
// Custom value recognition // Custom value recognition
static int IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal ); static int IsHexVal ( const QString &a_szExpr, int *a_iPos, qreal *a_fVal );
@ -172,25 +293,6 @@ namespace qmu
int TestIfThenElse(); int TestIfThenElse();
void Abort() const; void Abort() const;
public:
typedef int (QmuParserTester::*testfun_type)();
QmuParserTester();
void Run();
private:
QVector<testfun_type> m_vTestFun;
void AddTest(testfun_type a_pFun);
// Test Double Parser
int EqnTest(const QString &a_str, double a_fRes, bool a_fPass);
int EqnTestWithVarChange(const QString &a_str,
double a_fRes1,
double a_fVar1,
double a_fRes2,
double a_fVar2);
int ThrowTest(const QString &a_str, int a_iErrc, bool a_bFail = true);
}; };
} // namespace Test } // namespace Test
} // namespace qmu } // namespace qmu

View file

@ -32,13 +32,13 @@
#include "qmuparsererror.h" #include "qmuparsererror.h"
#include "qmuparsercallback.h" #include "qmuparsercallback.h"
/** \file /** @file
\brief This file contains the parser token definition. @brief This file contains the parser token definition.
*/ */
namespace qmu namespace qmu
{ {
/** \brief Encapsulation of the data for a single formula token. /** @brief Encapsulation of the data for a single formula token.
Formula token implementation. Part of the Math Parser Package. Formula token implementation. Part of the Math Parser Package.
Formula tokens can be either one of the following: Formula tokens can be either one of the following:
@ -52,7 +52,7 @@ namespace qmu
<li>binary operator</li> <li>binary operator</li>
</ul> </ul>
\author (C) 2004-2013 Ingo Berg @author (C) 2004-2013 Ingo Berg
*/ */
template<typename TBase, typename TString> template<typename TBase, typename TString>
class QmuParserToken class QmuParserToken
@ -71,11 +71,11 @@ namespace qmu
public: public:
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/** \brief Constructor (default). /** @brief Constructor (default).
Sets token to an neutral state of type cmUNKNOWN. Sets token to an neutral state of type cmUNKNOWN.
\throw nothrow @throw nothrow
\sa ECmdCode @sa ECmdCode
*/ */
QmuParserToken() QmuParserToken()
:m_iCode(cmUNKNOWN) :m_iCode(cmUNKNOWN)
@ -87,12 +87,12 @@ namespace qmu
{} {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Create token from another one. /** @brief Create token from another one.
Implemented by calling Assign(...) Implemented by calling Assign(...)
\throw nothrow @throw nothrow
\post m_iType==cmUNKNOWN @post m_iType==cmUNKNOWN
\sa #Assign @sa #Assign
*/ */
QmuParserToken(const QmuParserToken &a_Tok) QmuParserToken(const QmuParserToken &a_Tok)
{ {
@ -100,11 +100,11 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Assignement operator. /** @brief Assignement operator.
Copy token state from another token and return this. Copy token state from another token and return this.
Implemented by calling Assign(...). Implemented by calling Assign(...).
\throw nothrow @throw nothrow
*/ */
QmuParserToken& operator=(const QmuParserToken &a_Tok) QmuParserToken& operator=(const QmuParserToken &a_Tok)
{ {
@ -113,9 +113,9 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Copy token information from argument. /** @brief Copy token information from argument.
\throw nothrow @throw nothrow
*/ */
void Assign(const QmuParserToken &a_Tok) void Assign(const QmuParserToken &a_Tok)
{ {
@ -131,15 +131,15 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Assign a token type. /** @brief Assign a token type.
Token may not be of type value, variable or function. Those have seperate set functions. Token may not be of type value, variable or function. Those have seperate set functions.
\pre [assert] a_iType!=cmVAR \pre [assert] a_iType!=cmVAR
\pre [assert] a_iType!=cmVAL \pre [assert] a_iType!=cmVAL
\pre [assert] a_iType!=cmFUNC \pre [assert] a_iType!=cmFUNC
\post m_fVal = 0 @post m_fVal = 0
\post m_pTok = 0 @post m_pTok = 0
*/ */
QmuParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString()) QmuParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())
{ {
@ -158,7 +158,7 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Set Callback type. */ /** @brief Set Callback type. */
QmuParserToken& Set(const QmuParserCallback &a_pCallback, const TString &a_sTok) QmuParserToken& Set(const QmuParserCallback &a_pCallback, const TString &a_sTok)
{ {
assert(a_pCallback.GetAddr()); assert(a_pCallback.GetAddr());
@ -175,10 +175,10 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Make this token a value token. /** @brief Make this token a value token.
Member variables not necessary for value tokens will be invalidated. Member variables not necessary for value tokens will be invalidated.
\throw nothrow @throw nothrow
*/ */
QmuParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString()) QmuParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())
{ {
@ -195,10 +195,10 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief make this token a variable token. /** @brief make this token a variable token.
Member variables not necessary for variable tokens will be invalidated. Member variables not necessary for variable tokens will be invalidated.
\throw nothrow @throw nothrow
*/ */
QmuParserToken& SetVar(TBase *a_pVar, const TString &a_strTok) QmuParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)
{ {
@ -212,10 +212,10 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Make this token a variable token. /** @brief Make this token a variable token.
Member variables not necessary for variable tokens will be invalidated. Member variables not necessary for variable tokens will be invalidated.
\throw nothrow @throw nothrow
*/ */
QmuParserToken& SetString(const TString &a_strTok, std::size_t a_iSize) QmuParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)
{ {
@ -230,11 +230,11 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Set an index associated with the token related data. /** @brief Set an index associated with the token related data.
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 exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
*/ */
void SetIdx(int a_iIdx) void SetIdx(int a_iIdx)
{ {
@ -245,12 +245,12 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Return Index associated with the token related data. /** @brief Return Index associated with the token related data.
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 exception_type 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
{ {
@ -261,10 +261,10 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Return the token type. /** @brief Return the token type.
\return #m_iType * @return #m_iType
\throw nothrow @throw nothrow
*/ */
ECmdCode GetCode() const ECmdCode GetCode() const
{ {
@ -313,11 +313,11 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Return the address of the callback function assoziated with /** @brief Return the address of the callback function assoziated with
function and operator tokens. 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 exception_type if token type is non of:
<ul> <ul>
<li>cmFUNC</li> <li>cmFUNC</li>
<li>cmSTRFUNC</li> <li>cmSTRFUNC</li>
@ -325,7 +325,7 @@ namespace qmu
<li>cmINFIXOP</li> <li>cmINFIXOP</li>
<li>cmOPRT_BIN</li> <li>cmOPRT_BIN</li>
</ul> </ul>
\sa ECmdCode @sa ECmdCode
*/ */
generic_fun_type GetFuncAddr() const generic_fun_type GetFuncAddr() const
{ {
@ -336,7 +336,7 @@ namespace qmu
/** \biref Get value of the token. /** \biref 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 exception_type if token is no value/variable token.
*/ */
TBase GetVal() const TBase GetVal() const
{ {
@ -349,10 +349,10 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \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 exception_type if token is no variable token.
*/ */
TBase* GetVar() const TBase* GetVar() const
{ {
@ -363,7 +363,7 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Return the number of function arguments. /** @brief Return the number of function arguments.
Valid only if m_iType==CmdFUNC. Valid only if m_iType==CmdFUNC.
*/ */
@ -378,13 +378,13 @@ namespace qmu
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Return the token identifier. /** @brief Return the token identifier.
If #m_iType is cmSTRING the token identifier is the value of the string argument If #m_iType is cmSTRING the token identifier is the value of the string argument
for a string function. for a string function.
\return #m_strTok * @return #m_strTok
\throw nothrow @throw nothrow
\sa m_strTok @sa m_strTok
*/ */
const TString& GetAsString() const const TString& GetAsString() const
{ {

View file

@ -20,22 +20,15 @@
** **
******************************************************************************************************/ ******************************************************************************************************/
#include <cassert>
#include <cstdio>
#include <cstring>
#include <map>
#include <stack>
#include <string>
#include <QStringList>
#include "qmuparsertokenreader.h" #include "qmuparsertokenreader.h"
#include "qmuparserbase.h" #include "qmuparserbase.h"
/** \file #include <QStringList>
\brief This file contains the parser token reader implementation.
*/
/**
* @file
* @brief This file contains the parser token reader implementation.
*/
namespace qmu namespace qmu
{ {
@ -43,38 +36,43 @@ namespace qmu
// Forward declaration // Forward declaration
class QmuParserBase; class QmuParserBase;
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Copy constructor. /**
* @brief Copy constructor.
\sa Assign *
\throw nothrow * @sa Assign
* @throw nothrow
*/ */
QmuParserTokenReader::QmuParserTokenReader ( const QmuParserTokenReader &a_Reader ) QmuParserTokenReader::QmuParserTokenReader ( const QmuParserTokenReader &a_Reader )
{ {
Assign ( a_Reader ); Assign ( a_Reader );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Assignement operator. /**
* @brief Assignement operator.
Self assignement will be suppressed otherwise #Assign is called. *
* Self assignement will be suppressed otherwise #Assign is called.
\param a_Reader Object to copy to this token reader. *
\throw nothrow * @param a_Reader Object to copy to this token reader.
* @throw nothrow
*/ */
QmuParserTokenReader& QmuParserTokenReader::operator= ( const QmuParserTokenReader &a_Reader ) QmuParserTokenReader& QmuParserTokenReader::operator= ( const QmuParserTokenReader &a_Reader )
{ {
if ( &a_Reader != this ) if ( &a_Reader != this )
{
Assign ( a_Reader ); Assign ( a_Reader );
}
return *this; return *this;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Assign state of a token reader to this token reader. /**
* @brief Assign state of a token reader to this token reader.
\param a_Reader Object from which the state should be copied. *
\throw nothrow * @param a_Reader Object from which the state should be copied.
* @throw nothrow
*/ */
void QmuParserTokenReader::Assign ( const QmuParserTokenReader &a_Reader ) void QmuParserTokenReader::Assign ( const QmuParserTokenReader &a_Reader )
{ {
@ -99,49 +97,34 @@ namespace qmu
m_cArgSep = a_Reader.m_cArgSep; m_cArgSep = a_Reader.m_cArgSep;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Constructor. /**
* @brief Constructor.
Create a Token reader and bind it to a parser object. *
* Create a Token reader and bind it to a parser object.
\pre [assert] a_pParser may not be NULL *
\post #m_pParser==a_pParser * @pre [assert] a_pParser may not be NULL
\param a_pParent Parent parser object of the token reader. * @post #m_pParser==a_pParser
* @param a_pParent Parent parser object of the token reader.
*/ */
QmuParserTokenReader::QmuParserTokenReader ( QmuParserBase *a_pParent ) QmuParserTokenReader::QmuParserTokenReader ( QmuParserBase *a_pParent )
:m_pParser(a_pParent) : m_pParser ( a_pParent ), m_strFormula(), m_iPos ( 0 ), m_iSynFlags ( 0 ), m_bIgnoreUndefVar ( false ),
,m_strFormula() m_pFunDef ( NULL ), m_pPostOprtDef ( NULL ), m_pInfixOprtDef ( NULL ), m_pOprtDef ( NULL ), m_pConstDef ( NULL ),
,m_iPos(0) m_pStrVarDef ( NULL ), m_pVarDef ( NULL ), m_pFactory ( NULL ), m_pFactoryData ( NULL ), m_vIdentFun(),
,m_iSynFlags(0) m_UsedVar(), m_fZero ( 0 ), m_iBrackets ( 0 ), m_lastTok(), m_cArgSep ( ',' )
,m_bIgnoreUndefVar(false)
,m_pFunDef(NULL)
,m_pPostOprtDef(NULL)
,m_pInfixOprtDef(NULL)
,m_pOprtDef(NULL)
,m_pConstDef(NULL)
,m_pStrVarDef(NULL)
,m_pVarDef(NULL)
,m_pFactory(NULL)
,m_pFactoryData(NULL)
,m_vIdentFun()
,m_UsedVar()
,m_fZero(0)
,m_iBrackets(0)
,m_lastTok()
,m_cArgSep(',')
{ {
assert ( m_pParser ); assert ( m_pParser );
SetParent ( m_pParser ); SetParent ( m_pParser );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Create instance of a QParserTokenReader identical with this /**
and return its pointer. * @brief Create instance of a QParserTokenReader identical with this and return its pointer.
*
This is a factory method the calling function must take care of the object destruction. * This is a factory method the calling function must take care of the object destruction.
*
\return A new QParserTokenReader object. * @return A new QParserTokenReader object.
\throw nothrow * @throw nothrow
*/ */
QmuParserTokenReader* QmuParserTokenReader::Clone ( QmuParserBase *a_pParent ) const QmuParserTokenReader* QmuParserTokenReader::Clone ( QmuParserBase *a_pParent ) const
{ {
@ -150,14 +133,14 @@ namespace qmu
return ptr.release(); return ptr.release();
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QmuParserTokenReader::token_type& QmuParserTokenReader::SaveBeforeReturn ( const token_type &tok ) QmuParserTokenReader::token_type& QmuParserTokenReader::SaveBeforeReturn ( const token_type &tok )
{ {
m_lastTok = tok; m_lastTok = tok;
return m_lastTok; return m_lastTok;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserTokenReader::AddValIdent ( identfun_type a_pCallback ) void QmuParserTokenReader::AddValIdent ( identfun_type a_pCallback )
{ {
// Use push_front is used to give user defined callbacks a higher priority than // Use push_front is used to give user defined callbacks a higher priority than
@ -169,47 +152,52 @@ namespace qmu
m_vIdentFun.push_front ( a_pCallback ); m_vIdentFun.push_front ( a_pCallback );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserTokenReader::SetVarCreator ( facfun_type a_pFactory, void *pUserData ) void QmuParserTokenReader::SetVarCreator ( facfun_type a_pFactory, void *pUserData )
{ {
m_pFactory = a_pFactory; m_pFactory = a_pFactory;
m_pFactoryData = pUserData; m_pFactoryData = pUserData;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Return the current position of the token reader in the formula string. /**
* @brief Return the current position of the token reader in the formula string.
\return #m_iPos *
\throw nothrow * @return #m_iPos
* @throw nothrow
*/ */
int QmuParserTokenReader::GetPos() const int QmuParserTokenReader::GetPos() const
{ {
return m_iPos; return m_iPos;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Return a reference to the formula. /**
* @brief Return a reference to the formula.
\return #m_strFormula *
\throw nothrow * @return #m_strFormula
* @throw nothrow
*/ */
const QString& QmuParserTokenReader::GetExpr() const const QString& QmuParserTokenReader::GetExpr() const
{ {
return m_strFormula; return m_strFormula;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Return a map containing the used variables only. */ /**
* @brief Return a map containing the used variables only.
*/
varmap_type& QmuParserTokenReader::GetUsedVar() varmap_type& QmuParserTokenReader::GetUsedVar()
{ {
return m_UsedVar; return m_UsedVar;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Initialize the token Reader. /**
* @brief Initialize the token Reader.
Sets the formula position index to zero and set Syntax flags to default for initial formula parsing. *
\pre [assert] triggered if a_szFormula==0 * Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
* @pre [assert] triggered if a_szFormula==0
*/ */
void QmuParserTokenReader::SetFormula ( const QString &a_strFormula ) void QmuParserTokenReader::SetFormula ( const QString &a_strFormula )
{ {
@ -217,28 +205,28 @@ namespace qmu
ReInit(); ReInit();
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Set Flag that contronls behaviour in case of undefined variables beeing found. /**
* @brief Set Flag that contronls behaviour in case of undefined variables beeing found.
If true, the parser does not throw an exception if an undefined variable is found. *
otherwise it does. This variable is used internally only! * If true, the parser does not throw an exception if an undefined variable is found. Otherwise it does. This variable
It supresses a "undefined variable" exception in GetUsedVar(). * is used internally only! It supresses a "undefined variable" exception in GetUsedVar().
Those function should return a complete list of variables including * Those function should return a complete list of variables including
those the are not defined by the time of it's call. * those the are not defined by the time of it's call.
*/ */
void QmuParserTokenReader::IgnoreUndefVar ( bool bIgnore ) void QmuParserTokenReader::IgnoreUndefVar ( bool bIgnore )
{ {
m_bIgnoreUndefVar = bIgnore; m_bIgnoreUndefVar = bIgnore;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Reset the token reader to the start of the formula. /**
* @brief Reset the token reader to the start of the formula.
The syntax flags will be reset to a value appropriate for the *
start of a formula. * The syntax flags will be reset to a value appropriate for the start of a formula.
\post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR * @post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR
\throw nothrow * @throw nothrow
\sa ESynCodes * @sa ESynCodes
*/ */
void QmuParserTokenReader::ReInit() void QmuParserTokenReader::ReInit()
{ {
@ -249,13 +237,14 @@ namespace qmu
m_lastTok = token_type(); m_lastTok = token_type();
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Read the next token from the string. */ /**
* @brief Read the next token from the string.
*/
QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken() QmuParserTokenReader::token_type QmuParserTokenReader::ReadNextToken()
{ {
assert ( m_pParser ); assert ( m_pParser );
//std::stack<int> FunArgs;
#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
@ -308,7 +297,7 @@ namespace qmu
return token_type(); // never reached return token_type(); // never reached
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserTokenReader::SetParent ( QmuParserBase *a_pParent ) void QmuParserTokenReader::SetParent ( QmuParserBase *a_pParent )
{ {
m_pParser = a_pParent; m_pParser = a_pParent;
@ -321,14 +310,15 @@ namespace qmu
m_pConstDef = &a_pParent->m_ConstDef; m_pConstDef = &a_pParent->m_ConstDef;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Extract all characters that belong to a certain charset. /**
* @brief Extract all characters that belong to a certain charset.
\param a_szCharSet [in] Const char array of the characters allowed in the token. *
\param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. * @param a_szCharSet [in] Const char array of the characters allowed in the token.
\param a_iPos [in] Position in the string from where to start reading. * @param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.
\return The Position of the first character not listed in a_szCharSet. * @param a_iPos [in] Position in the string from where to start reading.
\throw nothrow * @return The Position of the first character not listed in a_szCharSet.
* @throw nothrow
*/ */
int QmuParserTokenReader::ExtractToken ( const QString &a_szCharSet, QString &a_sTok, int a_iPos ) const int QmuParserTokenReader::ExtractToken ( const QString &a_szCharSet, QString &a_sTok, int a_iPos ) const
{ {
@ -360,13 +350,13 @@ int QmuParserTokenReader::ExtractToken(const QString &a_szCharSet, QString &a_sT
return iEnd; return iEnd;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check Expression for the presence of a binary operator token. /**
* @brief Check Expression for the presence of a binary operator token.
Userdefined binary operator "++" gives inconsistent parsing result for *
the equations "a++b" and "a ++ b" if alphabetic characters are allowed * Userdefined binary operator "++" gives inconsistent parsing result for the equations "a++b" and "a ++ b" if
in operator tokens. To avoid this this function checks specifically * alphabetic characters are allowed in operator tokens. To avoid this this function checks specifically
for operator tokens. * for operator tokens.
*/ */
int QmuParserTokenReader::ExtractOperatorToken ( QString &a_sTok, int a_iPos ) const int QmuParserTokenReader::ExtractOperatorToken ( QString &a_sTok, int a_iPos ) const
{ {
@ -402,10 +392,11 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
} }
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check if a built in operator or other token can be found /**
\param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. * @brief Check if a built in operator or other token can be found
\return true if an operator token has been found. * @param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
* @return true if an operator token has been found.
*/ */
bool QmuParserTokenReader::IsBuiltIn ( token_type &a_Tok ) bool QmuParserTokenReader::IsBuiltIn ( token_type &a_Tok )
{ {
@ -509,7 +500,7 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return false; return false;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
bool QmuParserTokenReader::IsArgSep ( token_type &a_Tok ) bool QmuParserTokenReader::IsArgSep ( token_type &a_Tok )
{ {
if ( m_strFormula.at ( m_iPos ) == m_cArgSep ) if ( m_strFormula.at ( m_iPos ) == m_cArgSep )
@ -533,13 +524,14 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return false; return false;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check for End of Formula. /**
* @brief Check for End of Formula.
\return true if an end of formula is found false otherwise. *
\param a_Tok [out] If an eof is found the corresponding token will be stored there. * @return true if an end of formula is found false otherwise.
\throw nothrow * @param a_Tok [out] If an eof is found the corresponding token will be stored there.
\sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok * @throw nothrow
* @sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok
*/ */
bool QmuParserTokenReader::IsEOF ( token_type &a_Tok ) bool QmuParserTokenReader::IsEOF ( token_type &a_Tok )
{ {
@ -566,9 +558,10 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return false; return false;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check if a string position contains a unary infix operator. /**
\return true if a function token has been found false otherwise. * @brief Check if a string position contains a unary infix operator.
* @return true if a function token has been found false otherwise.
*/ */
bool QmuParserTokenReader::IsInfixOpTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsInfixOpTok ( token_type &a_Tok )
{ {
@ -608,12 +601,13 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
*/ */
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check whether the token at a given position is a function token. /**
\param a_Tok [out] If a value token is found it will be placed here. * @brief Check whether the token at a given position is a function token.
\throw ParserException if Syntaxflags do not allow a function at a_iPos * @param a_Tok [out] If a value token is found it will be placed here.
\return true if a function token has been found false otherwise. * @throw ParserException if Syntaxflags do not allow a function at a_iPos
\pre [assert] m_pParser!=0 * @return true if a function token has been found false otherwise.
* @pre [assert] m_pParser!=0
*/ */
bool QmuParserTokenReader::IsFunTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsFunTok ( token_type &a_Tok )
{ {
@ -640,10 +634,11 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return true; return true;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check if a string position contains a binary operator. /**
\param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token. * @brief Check if a string position contains a binary operator.
\return true if an operator token has been found. * @param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
* @return true if an operator token has been found.
*/ */
bool QmuParserTokenReader::IsOprt ( token_type &a_Tok ) bool QmuParserTokenReader::IsOprt ( token_type &a_Tok )
{ {
@ -704,8 +699,10 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return false; return false;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check if a string position contains a unary post value operator. */ /**
* @brief Check if a string position contains a unary post value operator.
*/
bool QmuParserTokenReader::IsPostOpTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsPostOpTok ( token_type &a_Tok )
{ {
// <ibg 20110629> Do not check for postfix operators if they are not allowed at // <ibg 20110629> Do not check for postfix operators if they are not allowed at
@ -750,13 +747,14 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return false; return false;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check whether the token at a given position is a value token. /**
* @brief Check whether the token at a given position is a value token.
Value tokens are either values or constants. *
* Value tokens are either values or constants.
\param a_Tok [out] If a value token is found it will be placed here. *
\return true if a value token has been found. * @param a_Tok [out] If a value token is found it will be placed here.
* @return true if a value token has been found.
*/ */
bool QmuParserTokenReader::IsValTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsValTok ( token_type &a_Tok )
{ {
@ -807,10 +805,11 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return false; return false;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check wheter a token at a given position is a variable token. /**
\param a_Tok [out] If a variable token has been found it will be placed here. * @brief Check wheter a token at a given position is a variable token.
\return true if a variable token has been found. * @param a_Tok [out] If a variable token has been found it will be placed here.
* @return true if a variable token has been found.
*/ */
bool QmuParserTokenReader::IsVarTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsVarTok ( token_type &a_Tok )
{ {
@ -842,7 +841,7 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return true; return true;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
bool QmuParserTokenReader::IsStrVarTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsStrVarTok ( token_type &a_Tok )
{ {
if ( !m_pStrVarDef || !m_pStrVarDef->size() ) if ( !m_pStrVarDef || !m_pStrVarDef->size() )
@ -871,19 +870,22 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check wheter a token at a given position is an undefined variable. /**
* @brief Check wheter a token at a given position is an undefined variable.
\param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. *
\return true if a variable token has been found. * @param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.
\throw nothrow * @return true if a variable token has been found.
* @throw nothrow
*/ */
bool QmuParserTokenReader::IsUndefVarTok ( token_type &a_Tok ) bool QmuParserTokenReader::IsUndefVarTok ( token_type &a_Tok )
{ {
QString strTok; QString strTok;
int iEnd ( ExtractToken ( m_pParser->ValidNameChars(), strTok, m_iPos ) ); int iEnd ( ExtractToken ( m_pParser->ValidNameChars(), strTok, m_iPos ) );
if ( iEnd == m_iPos ) if ( iEnd == m_iPos )
{
return false; return false;
}
if ( m_iSynFlags & noVAR ) if ( m_iSynFlags & noVAR )
{ {
@ -923,12 +925,13 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Check wheter a token at a given position is a string. /**
\param a_Tok [out] If a variable token has been found it will be placed here. * @brief Check wheter a token at a given position is a string.
\return true if a string token has been found. * @param a_Tok [out] If a variable token has been found it will be placed here.
\sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok * @return true if a string token has been found.
\throw nothrow * @sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok
* @throw nothrow
*/ */
bool QmuParserTokenReader::IsString ( token_type &a_Tok ) bool QmuParserTokenReader::IsString ( token_type &a_Tok )
{ {
@ -963,30 +966,29 @@ int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) cons
return true; return true;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
/** \brief Create an error containing the parse error position. /**
* @brief Create an error containing the parse error position.
This function will create an Parser Exception object containing the error text and its position. *
* This function will create an Parser Exception object containing the error text and its position.
\param a_iErrc [in] The error code of type #EErrorCodes. *
\param a_iPos [in] The position where the error was detected. * @param a_iErrc [in] The error code of type #EErrorCodes.
\param a_strTok [in] The token string representation associated with the error. * @param a_iPos [in] The position where the error was detected.
\throw ParserException always throws thats the only purpose of this function. * @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, void QmuParserTokenReader::Error ( EErrorCodes a_iErrc, int a_iPos, const QString &a_sTok ) const
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 );
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void QmuParserTokenReader::SetArgSep ( char_type cArgSep ) void QmuParserTokenReader::SetArgSep ( char_type cArgSep )
{ {
m_cArgSep = cArgSep; m_cArgSep = cArgSep;
} }
//--------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
QChar QmuParserTokenReader::GetArgSep() const QChar QmuParserTokenReader::GetArgSep() const
{ {
return m_cArgSep; return m_cArgSep;

View file

@ -35,8 +35,8 @@
#include "qmuparserdef.h" #include "qmuparserdef.h"
#include "qmuparsertoken.h" #include "qmuparsertoken.h"
/** \file /** @file
\brief This file contains the parser token reader definition. @brief This file contains the parser token reader definition.
*/ */
@ -45,7 +45,7 @@ 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 class QmuParserTokenReader
@ -75,7 +75,7 @@ namespace qmu
private: private:
/** \brief Syntax codes. /** @brief Syntax codes.
The syntax codes control the syntax check done during the first time parsing of 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 the expression string. They are flags that indicate which tokens are allowed next