Apply project code style.
--HG-- branch : feature
This commit is contained in:
parent
0b49785255
commit
2c77a73343
|
@ -24,112 +24,149 @@
|
|||
#include <QtMath>
|
||||
#include <QtGlobal>
|
||||
|
||||
//--- Standard includes ------------------------------------------------------------------------
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
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
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
// Trigonometric function
|
||||
qreal QmuParser::Sinh(qreal v) { return sinh(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))); }
|
||||
// Trigonometric function
|
||||
qreal QmuParser::Sinh(qreal v)
|
||||
{
|
||||
return sinh(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Logarithm functions
|
||||
qreal QmuParser::Cosh(qreal v)
|
||||
{
|
||||
return cosh(v);
|
||||
}
|
||||
|
||||
// Logarithm base 2
|
||||
qreal QmuParser::Log2(qreal v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
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 base 2
|
||||
qreal QmuParser::Log2(qreal v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
if (v<=0)
|
||||
{
|
||||
throw QmuParserError(ecDOMAIN_ERROR, "Log2");
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
return log(v)/log((qreal)2);
|
||||
}
|
||||
}
|
||||
|
||||
// Logarithm base 10
|
||||
qreal QmuParser::Log10(qreal v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
// Logarithm base 10
|
||||
qreal QmuParser::Log10(qreal v)
|
||||
{
|
||||
#ifdef MUP_MATH_EXCEPTIONS
|
||||
if (v<=0)
|
||||
{
|
||||
throw QmuParserError(ecDOMAIN_ERROR, "Log10");
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
return log10(v);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// misc
|
||||
qreal QmuParser::Abs(qreal v) { return qAbs(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); }
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// misc
|
||||
qreal QmuParser::Abs(qreal v)
|
||||
{
|
||||
return qAbs(v);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for the unary minus operator.
|
||||
\param v The value to negate
|
||||
\return -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);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for adding multiple values.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Callback for adding multiple values.
|
||||
* @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)
|
||||
{
|
||||
throw exception_type("too few arguments for function sum.");
|
||||
|
||||
}
|
||||
qreal fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
|
||||
return fRes;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for averaging multiple values.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Callback for averaging multiple values.
|
||||
* @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)
|
||||
{
|
||||
throw exception_type("too few arguments for function sum.");
|
||||
|
||||
}
|
||||
qreal fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
|
||||
return fRes/(qreal)a_iArgc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for determining the minimum value out of a vector.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Callback for determining the minimum value out of a vector.
|
||||
* @param [in] a_afArg Vector with the function arguments
|
||||
* @param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
{
|
||||
throw exception_type("too few arguments for function min.");
|
||||
}
|
||||
|
||||
qreal fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
{
|
||||
|
@ -138,18 +175,18 @@ qreal QmuParser::Min(const qreal *a_afArg, int a_iArgc)
|
|||
return fRes;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Callback for determining the maximum value out of a vector.
|
||||
\param [in] a_afArg Vector with the function arguments
|
||||
\param [in] a_iArgc The size of a_afArg
|
||||
*/
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Callback for determining the maximum value out of a vector.
|
||||
* @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)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
{
|
||||
throw exception_type("too few arguments for function min.");
|
||||
}
|
||||
|
||||
qreal fRes=a_afArg[0];
|
||||
for (int i=0; i<a_iArgc; ++i)
|
||||
{
|
||||
|
@ -158,23 +195,23 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
|
|||
return fRes;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Default value recognition callback.
|
||||
\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 [out] a_fVal Pointer where the value should be stored in case one is found.
|
||||
\return 1 if a value was found 0 otherwise.
|
||||
*/
|
||||
int QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal)
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Default value recognition callback.
|
||||
* @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 [out] a_fVal Pointer where the value should be stored in case one is found.
|
||||
* @return 1 if a value was found 0 otherwise.
|
||||
*/
|
||||
int QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal)
|
||||
{
|
||||
qreal fVal(0);
|
||||
|
||||
#if defined(_UNICODE)
|
||||
#if defined(_UNICODE)
|
||||
std::wstring a_szExprStd = a_szExpr.toStdWString();
|
||||
#else
|
||||
#else
|
||||
std::string a_szExprStd = a_szExpr.toStdString();
|
||||
#endif
|
||||
#endif
|
||||
stringstream_type stream(a_szExprStd);
|
||||
stream.seekg(0); // todo: check if this really is necessary
|
||||
stream.imbue(QmuParser::s_locale);
|
||||
|
@ -182,46 +219,50 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
|
|||
stringstream_type::pos_type iEnd = stream.tellg(); // Position after reading
|
||||
|
||||
if (iEnd==(stringstream_type::pos_type)-1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*a_iPos += (int)iEnd;
|
||||
*a_fVal = fVal;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor.
|
||||
|
||||
Call QmuParserBase class constructor and trigger Function, Operator and Constant initialization.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* Call QmuParserBase class constructor and trigger Function, Operator and Constant initialization.
|
||||
*/
|
||||
QmuParser::QmuParser()
|
||||
:QmuParserBase()
|
||||
{
|
||||
QmuParser::QmuParser():QmuParserBase()
|
||||
{
|
||||
AddValIdent(IsVal);
|
||||
|
||||
InitCharSets();
|
||||
InitFun();
|
||||
InitConst();
|
||||
InitOprt();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \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.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
void QmuParser::InitCharSets()
|
||||
{
|
||||
void QmuParser::InitCharSets()
|
||||
{
|
||||
DefineNameChars( "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" );
|
||||
DefineOprtChars( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_{}" );
|
||||
DefineInfixOprtChars( "/+-*^?<>=#!$%&|~'_" );
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize the default functions. */
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Initialize the default functions.
|
||||
*/
|
||||
void QmuParser::InitFun()
|
||||
{
|
||||
// trigonometric functions
|
||||
|
@ -259,31 +300,33 @@ void QmuParser::InitFun()
|
|||
DefineFun("max", Max);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize constants.
|
||||
|
||||
By default the QmuParser recognizes two constants. Pi ("pi") and the eulerian
|
||||
number ("_e").
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Initialize constants.
|
||||
*
|
||||
* By default the QmuParser recognizes two constants. Pi ("pi") and the eulerian
|
||||
* number ("_e").
|
||||
*/
|
||||
void QmuParser::InitConst()
|
||||
{
|
||||
void QmuParser::InitConst()
|
||||
{
|
||||
DefineConst("_pi", (qreal)M_PI);
|
||||
DefineConst("_e", (qreal)M_E);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Initialize operators.
|
||||
|
||||
By default only the unary minus operator is added.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Initialize operators.
|
||||
*
|
||||
* By default only the unary minus operator is added.
|
||||
*/
|
||||
void QmuParser::InitOprt()
|
||||
{
|
||||
void QmuParser::InitOprt()
|
||||
{
|
||||
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.
|
||||
// I'm not sure anyone really needs such a feature...
|
||||
/*
|
||||
|
@ -304,25 +347,24 @@ void QmuParser::InitFun()
|
|||
pExpr->replace(pExpr->begin()+nStart, pExpr->begin()+nOrigVarEnd, sRepl);
|
||||
cout << " New expr: " << *pExpr << "\n";
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Numerically differentiate with regard to a variable.
|
||||
\param [in] a_Var Pointer to the differentiation variable.
|
||||
\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
|
||||
numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muQmuParser
|
||||
forum:
|
||||
|
||||
http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Numerically differentiate with regard to a variable.
|
||||
* @param [in] a_Var Pointer to the differentiation variable.
|
||||
* @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
|
||||
* numeric_limits<double>::epsilon() ^ (1/5) as suggested in the muQmuParser
|
||||
* forum:
|
||||
*
|
||||
* http://sourceforge.net/forum/forum.php?thread_id=1994611&forum_id=462843
|
||||
*/
|
||||
qreal QmuParser::Diff(qreal *a_Var,
|
||||
qreal a_fPos,
|
||||
qreal a_fEpsilon) const
|
||||
{
|
||||
qreal QmuParser::Diff(qreal *a_Var, qreal a_fPos, qreal a_fEpsilon) const
|
||||
{
|
||||
qreal fRes(0),
|
||||
fBuf(*a_Var),
|
||||
f[4] = {0,0,0,0},
|
||||
|
@ -331,7 +373,9 @@ void QmuParser::InitFun()
|
|||
// Backwards compatible calculation of epsilon inc case the user doesnt provide
|
||||
// his own epsilon
|
||||
if (fEpsilon==0)
|
||||
{
|
||||
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+1 * fEpsilon; f[1] = Eval();
|
||||
|
@ -341,5 +385,5 @@ void QmuParser::InitFun()
|
|||
|
||||
fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);
|
||||
return fRes;
|
||||
}
|
||||
}
|
||||
} // namespace qmu
|
||||
|
|
|
@ -24,39 +24,37 @@
|
|||
#define QMUPARSER_H
|
||||
|
||||
#include "qmuparser_global.h"
|
||||
|
||||
//--- Parser includes --------------------------------------------------------------------------
|
||||
#include "qmuparserbase.h"
|
||||
|
||||
/** \file
|
||||
\brief Definition of the standard floating point parser.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief Definition of the standard floating point parser.
|
||||
*/
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
/** \brief Mathematical expressions parser.
|
||||
|
||||
Standard implementation of the mathematical expressions parser.
|
||||
Can be used as a reference implementation for subclassing the parser.
|
||||
|
||||
<small>
|
||||
(C) 2011 Ingo Berg<br>
|
||||
muparser(at)gmx.de
|
||||
</small>
|
||||
/** @brief Mathematical expressions parser.
|
||||
*
|
||||
* Standard implementation of the mathematical expressions parser.
|
||||
* Can be used as a reference implementation for subclassing the parser.
|
||||
*
|
||||
* <small>
|
||||
* (C) 2011 Ingo Berg<br>
|
||||
* muparser(at)gmx.de
|
||||
* </small>
|
||||
*/
|
||||
/* final */ class QMUPARSERSHARED_EXPORT QmuParser : public QmuParserBase
|
||||
{
|
||||
|
||||
public:
|
||||
/* final */ class QMUPARSERSHARED_EXPORT QmuParser : public QmuParserBase
|
||||
{
|
||||
public:
|
||||
QmuParser();
|
||||
virtual void InitCharSets();
|
||||
virtual void InitFun();
|
||||
virtual void InitConst();
|
||||
virtual void InitOprt();
|
||||
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
|
||||
|
||||
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
|
||||
static qreal Tan2(qreal, qreal);
|
||||
// hyperbolic functions
|
||||
|
@ -82,9 +80,7 @@ protected:
|
|||
static qreal Avg(const qreal*, int); // mean value
|
||||
static qreal Min(const qreal*, int); // minimum
|
||||
static qreal Max(const qreal*, int); // maximum
|
||||
|
||||
static int IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace qmu
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,18 +23,10 @@
|
|||
#ifndef QMUQPARSERBASE_H
|
||||
#define QMUQPARSERBASE_H
|
||||
|
||||
//--- Standard includes ------------------------------------------------------------------------
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <locale>
|
||||
#include <QStack>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
//--- Parser includes --------------------------------------------------------------------------
|
||||
#include "qmuparserdef.h"
|
||||
#include "qmuparsertokenreader.h"
|
||||
#include "qmuparserbytecode.h"
|
||||
|
@ -43,108 +35,60 @@
|
|||
|
||||
namespace qmu
|
||||
{
|
||||
/** \file
|
||||
\brief This file contains the class definition of the qmuparser engine.
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/** \brief Mathematical expressions parser (base parser engine).
|
||||
\author (C) 2013 Ingo Berg
|
||||
|
||||
This is the implementation of a bytecode based mathematical expressions parser.
|
||||
The formula will be parsed from string and converted into a bytecode.
|
||||
Future calculations will be done with the bytecode instead the formula string
|
||||
resulting in a significant performance increase.
|
||||
Complementary to a set of internally implemented functions the parser is able to handle
|
||||
user defined functions and variables.
|
||||
*/
|
||||
class QmuParserBase
|
||||
{
|
||||
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)
|
||||
/**
|
||||
* @file
|
||||
* @brief This file contains the class definition of the qmuparser engine.
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* @brief Mathematical expressions parser (base parser engine).
|
||||
* @author (C) 2013 Ingo Berg
|
||||
*
|
||||
* This is the implementation of a bytecode based mathematical expressions parser.
|
||||
* The formula will be parsed from string and converted into a bytecode.
|
||||
* Future calculations will be done with the bytecode instead the formula string
|
||||
* resulting in a significant performance increase.
|
||||
* Complementary to a set of internally implemented functions the parser is able to handle
|
||||
* user defined functions and variables.
|
||||
*/
|
||||
class QmuParserBase
|
||||
{
|
||||
friend class QmuParserTokenReader;
|
||||
public:
|
||||
|
||||
/** \brief Type of the error class.
|
||||
|
||||
Included for backwards compatibility.
|
||||
/**
|
||||
* @brief Type of the error class.
|
||||
*
|
||||
* Included for backwards compatibility.
|
||||
*/
|
||||
typedef QmuParserError exception_type;
|
||||
|
||||
static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
|
||||
|
||||
QmuParserBase();
|
||||
QmuParserBase(const QmuParserBase &a_Parser);
|
||||
QmuParserBase& operator=(const QmuParserBase &a_Parser);
|
||||
|
||||
virtual ~QmuParserBase();
|
||||
|
||||
static void EnableDebugDump(bool bDumpCmd, bool bDumpStack);
|
||||
qreal Eval() const;
|
||||
qreal* Eval(int &nStackSize) const;
|
||||
void Eval(qreal *results, int nBulkSize);
|
||||
|
||||
int GetNumResults() const;
|
||||
|
||||
void SetExpr(const QString &a_sExpr);
|
||||
void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
|
||||
|
||||
void SetDecSep(char_type cDecSep);
|
||||
void SetThousandsSep(char_type cThousandsSep = 0);
|
||||
void ResetLocale();
|
||||
|
||||
void EnableOptimizer(bool a_bIsOn=true);
|
||||
void EnableBuiltInOprt(bool a_bIsOn=true);
|
||||
|
||||
bool HasBuiltInOprt() const;
|
||||
void AddValIdent(identfun_type a_pCallback);
|
||||
|
||||
/** \fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun, bool a_bAllowOpt = true)
|
||||
\brief Define a parser function without arguments.
|
||||
\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 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 DefineStrConst(const QString &a_sName, const QString &a_strVal);
|
||||
void DefineVar(const QString &a_sName, qreal *a_fVar);
|
||||
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
|
||||
void ClearVar();
|
||||
void ClearFun();
|
||||
|
@ -152,62 +96,58 @@ private:
|
|||
void ClearInfixOprt();
|
||||
void ClearPostfixOprt();
|
||||
void ClearOprt();
|
||||
|
||||
void RemoveVar(const QString &a_strVarName);
|
||||
const varmap_type& GetUsedVar() const;
|
||||
const varmap_type& GetVar() const;
|
||||
const valmap_type& GetConst() const;
|
||||
const QString &GetExpr() const;
|
||||
const QString& GetExpr() const;
|
||||
const funmap_type& GetFunDef() const;
|
||||
string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
|
||||
|
||||
const QStringList &GetOprtDef() const;
|
||||
QString GetVersion(EParserVersionInfo eInfo = pviFULL) const;
|
||||
const QStringList& GetOprtDef() const;
|
||||
void DefineNameChars(const QString &a_szCharset);
|
||||
void DefineOprtChars(const QString &a_szCharset);
|
||||
void DefineInfixOprtChars(const QString &a_szCharset);
|
||||
|
||||
const QString& ValidNameChars() const;
|
||||
const QString &ValidOprtChars() const;
|
||||
const QString &ValidInfixOprtChars() const;
|
||||
|
||||
const QString& ValidOprtChars() const;
|
||||
const QString& ValidInfixOprtChars() const;
|
||||
void SetArgSep(char_type cArgSep);
|
||||
QChar GetArgSep() const;
|
||||
|
||||
void Error(EErrorCodes a_iErrc,
|
||||
int a_iPos = -1,
|
||||
const QString &a_strTok = QString() ) const;
|
||||
|
||||
void Error(EErrorCodes a_iErrc, int a_iPos = -1, const QString &a_strTok = QString() ) const;
|
||||
/**
|
||||
* @fn void qmu::QmuParserBase::DefineFun(const string_type &a_strName, fun_type0 a_pFun,
|
||||
* bool a_bAllowOpt = true)
|
||||
* @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:
|
||||
|
||||
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 std::locale s_locale; ///< The locale used by the parser
|
||||
static bool g_DbgDumpCmdCode;
|
||||
static bool g_DbgDumpStack;
|
||||
|
||||
/** \brief A facet class used to change decimal and thousands separator. */
|
||||
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);
|
||||
/**
|
||||
* @brief A facet class used to change decimal and thousands separator.
|
||||
*/
|
||||
template<class TChar>
|
||||
class change_dec_sep : public std::numpunct<TChar>
|
||||
{
|
||||
public:
|
||||
|
||||
explicit change_dec_sep(char_type cDecSep, char_type cThousandsSep = 0, int nGroup = 3)
|
||||
:std::numpunct<TChar>()
|
||||
,m_nGroup(nGroup)
|
||||
,m_cDecPoint(cDecSep)
|
||||
,m_cThousandsSep(cThousandsSep)
|
||||
:std::numpunct<TChar>(), m_nGroup(nGroup), m_cDecPoint(cDecSep), m_cThousandsSep(cThousandsSep)
|
||||
{}
|
||||
|
||||
protected:
|
||||
|
||||
virtual char_type do_decimal_point() const
|
||||
{
|
||||
return m_cDecPoint;
|
||||
|
@ -222,53 +162,50 @@ private:
|
|||
{
|
||||
return std::string(1, m_nGroup);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_nGroup;
|
||||
char_type m_cDecPoint;
|
||||
char_type m_cThousandsSep;
|
||||
};
|
||||
|
||||
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();
|
||||
void ReInit() const;
|
||||
/**
|
||||
* @brief Type used for storing an array of values.
|
||||
*/
|
||||
typedef QVector<qreal> valbuf_type;
|
||||
|
||||
void AddCallback(const QString &a_strName,
|
||||
const QmuParserCallback &a_Callback,
|
||||
funmap_type &a_Storage,
|
||||
const QString &a_szCharSet );
|
||||
/**
|
||||
* @brief Type for a vector of strings.
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
/**
|
||||
* @brief Typedef for the token reader.
|
||||
*/
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/** \brief Pointer to the parser function.
|
||||
|
||||
Eval() calls the function whose address is stored there.
|
||||
/**
|
||||
* @brief Pointer to the parser function.
|
||||
*
|
||||
* Eval() calls the function whose address is stored there.
|
||||
*/
|
||||
mutable ParseFunction m_pParseFormula;
|
||||
mutable QmuParserByteCode m_vRPN; ///< The Bytecode class.
|
||||
|
@ -296,7 +233,28 @@ private:
|
|||
// 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 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
|
||||
|
||||
|
|
|
@ -35,66 +35,71 @@
|
|||
|
||||
namespace qmu
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Bytecode default constructor. */
|
||||
QmuParserByteCode::QmuParserByteCode()
|
||||
:m_iStackPos(0)
|
||||
,m_iMaxStackSize(0)
|
||||
,m_vRPN()
|
||||
,m_bEnableOptimizer(true)
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Bytecode default constructor.
|
||||
*/
|
||||
QmuParserByteCode::QmuParserByteCode()
|
||||
:m_iStackPos(0), m_iMaxStackSize(0), m_vRPN(), m_bEnableOptimizer(true)
|
||||
{
|
||||
m_vRPN.reserve(50);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy constructor.
|
||||
|
||||
Implemented in Terms of Assign(const QParserByteCode &a_ByteCode)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
*
|
||||
* Implemented in Terms of Assign(const QParserByteCode &a_ByteCode)
|
||||
*/
|
||||
QmuParserByteCode::QmuParserByteCode(const QmuParserByteCode &a_ByteCode)
|
||||
{
|
||||
QmuParserByteCode::QmuParserByteCode(const QmuParserByteCode &a_ByteCode)
|
||||
{
|
||||
Assign(a_ByteCode);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Assignment operator.
|
||||
|
||||
Implemented in Terms of Assign(const QParserByteCode &a_ByteCode)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
*
|
||||
* Implemented in Terms of Assign(const QParserByteCode &a_ByteCode)
|
||||
*/
|
||||
QmuParserByteCode& QmuParserByteCode::operator=(const QmuParserByteCode &a_ByteCode)
|
||||
{
|
||||
QmuParserByteCode& QmuParserByteCode::operator=(const QmuParserByteCode &a_ByteCode)
|
||||
{
|
||||
Assign(a_ByteCode);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void QmuParserByteCode::EnableOptimizer(bool bStat)
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void QmuParserByteCode::EnableOptimizer(bool bStat)
|
||||
{
|
||||
m_bEnableOptimizer = bStat;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy state of another object to this.
|
||||
|
||||
\throw nowthrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Copy state of another object to this.
|
||||
*
|
||||
* @throw nowthrow
|
||||
*/
|
||||
void QmuParserByteCode::Assign(const QmuParserByteCode &a_ByteCode)
|
||||
{
|
||||
void QmuParserByteCode::Assign(const QmuParserByteCode &a_ByteCode)
|
||||
{
|
||||
if (this==&a_ByteCode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_iStackPos = a_ByteCode.m_iStackPos;
|
||||
m_vRPN = a_ByteCode.m_vRPN;
|
||||
m_iMaxStackSize = a_ByteCode.m_iMaxStackSize;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add a Variable pointer to bytecode.
|
||||
\param a_pVar Pointer to be added.
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add a Variable pointer to bytecode.
|
||||
* @param a_pVar Pointer to be added.
|
||||
* @throw nothrow
|
||||
*/
|
||||
void QmuParserByteCode::AddVar(qreal *a_pVar)
|
||||
{
|
||||
void QmuParserByteCode::AddVar(qreal *a_pVar)
|
||||
{
|
||||
++m_iStackPos;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
|
@ -105,23 +110,24 @@ namespace qmu
|
|||
tok.Val.data = 1;
|
||||
tok.Val.data2 = 0;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add a Variable pointer to bytecode.
|
||||
|
||||
Value entries in byte code consist of:
|
||||
<ul>
|
||||
<li>value array position of the value</li>
|
||||
<li>the operator code according to ParserToken::cmVAL</li>
|
||||
<li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
|
||||
</ul>
|
||||
|
||||
\param a_pVal Value to be added.
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add a Variable pointer to bytecode.
|
||||
*
|
||||
* Value entries in byte code consist of:
|
||||
* <ul>
|
||||
* <li>value array position of the value</li>
|
||||
* <li>the operator code according to ParserToken::cmVAL</li>
|
||||
* <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param a_pVal Value to be added.
|
||||
* @throw nothrow
|
||||
*/
|
||||
void QmuParserByteCode::AddVal(qreal a_fVal)
|
||||
{
|
||||
void QmuParserByteCode::AddVal(qreal a_fVal)
|
||||
{
|
||||
++m_iStackPos;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
|
@ -132,60 +138,93 @@ namespace qmu
|
|||
tok.Val.data = 0;
|
||||
tok.Val.data2 = a_fVal;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void QmuParserByteCode::ConstantFolding(ECmdCode a_Oprt)
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void QmuParserByteCode::ConstantFolding(ECmdCode a_Oprt)
|
||||
{
|
||||
std::size_t sz = m_vRPN.size();
|
||||
qreal &x = m_vRPN[sz-2].Val.data2,
|
||||
&y = m_vRPN[sz-1].Val.data2;
|
||||
switch (a_Oprt)
|
||||
{
|
||||
case cmLAND: x = (int)x && (int)y; m_vRPN.pop_back(); break;
|
||||
case cmLOR: x = (int)x || (int)y; m_vRPN.pop_back(); break;
|
||||
case cmLT: x = x < y; 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 cmLAND:
|
||||
x = (int)x && (int)y;
|
||||
m_vRPN.pop_back();
|
||||
break;
|
||||
case cmLOR:
|
||||
x = (int)x || (int)y;
|
||||
m_vRPN.pop_back();
|
||||
break;
|
||||
case cmLT:
|
||||
x = x < y;
|
||||
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:
|
||||
|
||||
#if defined(MUP_MATH_EXCEPTIONS)
|
||||
#if defined(MUP_MATH_EXCEPTIONS)
|
||||
if (y==0)
|
||||
{
|
||||
throw ParserError(ecDIV_BY_ZERO, "0");
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
x = x / y;
|
||||
m_vRPN.pop_back();
|
||||
break;
|
||||
|
||||
case cmPOW: x = std::pow(x, y);
|
||||
case cmPOW:
|
||||
x = qPow(x, y);
|
||||
m_vRPN.pop_back();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch opcode
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add an operator identifier to bytecode.
|
||||
|
||||
Operator entries in byte code consist of:
|
||||
<ul>
|
||||
<li>value array position of the result</li>
|
||||
<li>the operator code according to ParserToken::ECmdCode</li>
|
||||
</ul>
|
||||
|
||||
\sa ParserToken::ECmdCode
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add an operator identifier to bytecode.
|
||||
*
|
||||
* Operator entries in byte code consist of:
|
||||
* <ul>
|
||||
* <li>value array position of the result</li>
|
||||
* <li>the operator code according to ParserToken::ECmdCode</li>
|
||||
* </ul>
|
||||
*
|
||||
* @sa ParserToken::ECmdCode
|
||||
*/
|
||||
void QmuParserByteCode::AddOp(ECmdCode a_Oprt)
|
||||
{
|
||||
void QmuParserByteCode::AddOp(ECmdCode a_Oprt)
|
||||
{
|
||||
bool bOptimized = false;
|
||||
|
||||
if (m_bEnableOptimizer)
|
||||
|
@ -210,14 +249,21 @@ namespace qmu
|
|||
if (m_vRPN[sz-2].Cmd == cmVAR && m_vRPN[sz-1].Cmd == cmVAL)
|
||||
{
|
||||
if (m_vRPN[sz-1].Val.data2==2)
|
||||
{
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW2;
|
||||
}
|
||||
else if (m_vRPN[sz-1].Val.data2==3)
|
||||
{
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW3;
|
||||
}
|
||||
else if (m_vRPN[sz-1].Val.data2==4)
|
||||
{
|
||||
m_vRPN[sz-2].Cmd = cmVARPOW4;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
}
|
||||
m_vRPN.pop_back();
|
||||
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 == cmVARMUL) ||
|
||||
(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 == cmVARMUL && 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) )
|
||||
(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 == cmVARMUL
|
||||
&& 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) ||
|
||||
(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].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.data += ((a_Oprt==cmSUB) ? -1 : 1) * m_vRPN[sz-1].Val.data; // multiplikatior
|
||||
m_vRPN.pop_back();
|
||||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmMUL:
|
||||
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-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.data2 = 0;
|
||||
m_vRPN.pop_back();
|
||||
|
@ -265,7 +316,8 @@ namespace qmu
|
|||
{
|
||||
// Optimization: 2*(3*b+1) or (3*b+1)*2 -> 6*b+2
|
||||
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)
|
||||
{
|
||||
m_vRPN[sz-2].Val.data *= m_vRPN[sz-1].Val.data2;
|
||||
|
@ -288,7 +340,6 @@ namespace qmu
|
|||
bOptimized = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case cmDIV:
|
||||
if (m_vRPN[sz-1].Cmd == cmVAL && m_vRPN[sz-2].Cmd == cmVARMUL && m_vRPN[sz-1].Val.data2!=0)
|
||||
{
|
||||
|
@ -312,45 +363,47 @@ namespace qmu
|
|||
tok.Cmd = a_Oprt;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void QmuParserByteCode::AddIfElse(ECmdCode a_Oprt)
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void QmuParserByteCode::AddIfElse(ECmdCode a_Oprt)
|
||||
{
|
||||
SToken tok;
|
||||
tok.Cmd = a_Oprt;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add an assignement operator
|
||||
|
||||
Operator entries in byte code consist of:
|
||||
<ul>
|
||||
<li>cmASSIGN code</li>
|
||||
<li>the pointer of the destination variable</li>
|
||||
</ul>
|
||||
|
||||
\sa ParserToken::ECmdCode
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add an assignement operator
|
||||
*
|
||||
* Operator entries in byte code consist of:
|
||||
* <ul>
|
||||
* <li>cmASSIGN code</li>
|
||||
* <li>the pointer of the destination variable</li>
|
||||
* </ul>
|
||||
*
|
||||
* @sa ParserToken::ECmdCode
|
||||
*/
|
||||
void QmuParserByteCode::AddAssignOp(qreal *a_pVar)
|
||||
{
|
||||
void QmuParserByteCode::AddAssignOp(qreal *a_pVar)
|
||||
{
|
||||
--m_iStackPos;
|
||||
|
||||
SToken tok;
|
||||
tok.Cmd = cmASSIGN;
|
||||
tok.Val.ptr = a_pVar;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add function to bytecode.
|
||||
|
||||
\param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
|
||||
\param a_pFun Pointer to function callback.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add function to bytecode.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
if (a_iArgc>=0)
|
||||
{
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
|
@ -367,16 +420,17 @@ namespace qmu
|
|||
tok.Fun.argc = a_iArgc;
|
||||
tok.Fun.ptr = a_pFun;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \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.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
void QmuParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
|
||||
{
|
||||
void QmuParserByteCode::AddBulkFun(generic_fun_type a_pFun, int a_iArgc)
|
||||
{
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
|
||||
|
@ -385,18 +439,18 @@ namespace qmu
|
|||
tok.Fun.argc = a_iArgc;
|
||||
tok.Fun.ptr = a_pFun;
|
||||
m_vRPN.push_back(tok);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \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
|
||||
string buffer maintained by the parser.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @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 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)
|
||||
{
|
||||
m_iStackPos = m_iStackPos - a_iArgc + 1;
|
||||
|
||||
SToken tok;
|
||||
|
@ -407,15 +461,16 @@ namespace qmu
|
|||
m_vRPN.push_back(tok);
|
||||
|
||||
m_iMaxStackSize = std::max(m_iMaxStackSize, (size_t)m_iStackPos);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Add end marker to bytecode.
|
||||
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Add end marker to bytecode.
|
||||
*
|
||||
* @throw nothrow
|
||||
*/
|
||||
void QmuParserByteCode::Finalize()
|
||||
{
|
||||
void QmuParserByteCode::Finalize()
|
||||
{
|
||||
SToken tok;
|
||||
tok.Cmd = cmEND;
|
||||
m_vRPN.push_back(tok);
|
||||
|
@ -431,66 +486,71 @@ namespace qmu
|
|||
case cmIF:
|
||||
stIf.push(i);
|
||||
break;
|
||||
|
||||
case cmELSE:
|
||||
stElse.push(i);
|
||||
idx = stIf.pop();
|
||||
m_vRPN[idx].Oprt.offset = i - idx;
|
||||
break;
|
||||
|
||||
case cmENDIF:
|
||||
idx = stElse.pop();
|
||||
m_vRPN[idx].Oprt.offset = i - idx;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
const SToken* QmuParserByteCode::GetBase() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
const SToken* QmuParserByteCode::GetBase() const
|
||||
{
|
||||
if (m_vRPN.size()==0)
|
||||
{
|
||||
throw QmuParserError(ecINTERNAL_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
return &m_vRPN[0];
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
std::size_t QmuParserByteCode::GetMaxStackSize() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
std::size_t QmuParserByteCode::GetMaxStackSize() const
|
||||
{
|
||||
return m_iMaxStackSize+1;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Returns the number of entries in the bytecode. */
|
||||
std::size_t QmuParserByteCode::GetSize() const
|
||||
{
|
||||
return m_vRPN.size();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Delete the bytecode.
|
||||
|
||||
\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
|
||||
intuitive.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Returns the number of entries in the bytecode.
|
||||
*/
|
||||
void QmuParserByteCode::clear()
|
||||
{
|
||||
std::size_t QmuParserByteCode::GetSize() const
|
||||
{
|
||||
return m_vRPN.size();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Delete the bytecode.
|
||||
*
|
||||
* @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 intuitive.
|
||||
*/
|
||||
void QmuParserByteCode::clear()
|
||||
{
|
||||
m_vRPN.clear();
|
||||
m_iStackPos = 0;
|
||||
m_iMaxStackSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Dump bytecode (for debugging only!). */
|
||||
void QmuParserByteCode::AsciiDump()
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Dump bytecode (for debugging only!).
|
||||
*/
|
||||
void QmuParserByteCode::AsciiDump()
|
||||
{
|
||||
if (!m_vRPN.size())
|
||||
{
|
||||
qDebug() << "No bytecode available\n";
|
||||
|
@ -503,66 +563,89 @@ namespace qmu
|
|||
qDebug() << i << " : \t";
|
||||
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;
|
||||
|
||||
case cmVAR: qDebug() << "VAR \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
case cmVAR:
|
||||
qDebug() << "VAR \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
break;
|
||||
|
||||
case cmVARPOW2: qDebug() << "VARPOW2 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
case cmVARPOW2:
|
||||
qDebug() << "VARPOW2 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
break;
|
||||
|
||||
case cmVARPOW3: qDebug() << "VARPOW3 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
case cmVARPOW3:
|
||||
qDebug() << "VARPOW3 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
break;
|
||||
|
||||
case cmVARPOW4: qDebug() << "VARPOW4 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
case cmVARPOW4:
|
||||
qDebug() << "VARPOW4 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
|
||||
break;
|
||||
|
||||
case cmVARMUL: 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";
|
||||
case cmVARMUL:
|
||||
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";
|
||||
break;
|
||||
|
||||
case cmFUNC: qDebug() << "CALL\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[ADDR: 0x"
|
||||
<< m_vRPN[i].Fun.ptr << "]" << "\n";
|
||||
case cmFUNC:
|
||||
qDebug() << "CALL\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]"
|
||||
<< "\n";
|
||||
break;
|
||||
|
||||
case cmFUNC_STR:
|
||||
qDebug() << "CALL STRFUNC\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[IDX:"
|
||||
<< m_vRPN[i].Fun.idx << "]" << "[ADDR: 0x" << m_vRPN[i].Fun.ptr
|
||||
<< "]\n";
|
||||
qDebug() << "CALL STRFUNC\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[IDX:" << m_vRPN[i].Fun.idx
|
||||
<< "]" << "[ADDR: 0x" << m_vRPN[i].Fun.ptr << "]\n";
|
||||
break;
|
||||
|
||||
case cmLT: qDebug() << "LT\n"; break;
|
||||
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";
|
||||
case cmLT:
|
||||
qDebug() << "LT\n";
|
||||
break;
|
||||
|
||||
case cmELSE: qDebug() << "ELSE\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
|
||||
case cmGT:
|
||||
qDebug() << "GT\n";
|
||||
break;
|
||||
|
||||
case cmENDIF: qDebug() << "ENDIF\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;
|
||||
case cmELSE:
|
||||
qDebug() << "ELSE\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
|
||||
break;
|
||||
case cmENDIF:
|
||||
qDebug() << "ENDIF\n"; break;
|
||||
case cmASSIGN:
|
||||
qDebug() << "ASSIGN\t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Oprt.ptr, 'f', 16) << "]\n";
|
||||
break;
|
||||
|
||||
default: qDebug() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
|
||||
default:
|
||||
qDebug() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
|
||||
break;
|
||||
} // switch cmdCode
|
||||
} // while bytecode
|
||||
|
||||
qDebug() << "END";
|
||||
}
|
||||
}
|
||||
} // namespace qmu
|
||||
|
|
|
@ -23,23 +23,19 @@
|
|||
#ifndef QMUPARSERBYTECODE_H
|
||||
#define QMUPARSERBYTECODE_H
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
|
||||
#include "qmuparserdef.h"
|
||||
#include "qmuparsererror.h"
|
||||
#include "qmuparsertoken.h"
|
||||
|
||||
/** \file
|
||||
\brief Definition of the parser bytecode class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Definition of the parser bytecode class.
|
||||
*/
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
struct SToken
|
||||
{
|
||||
struct SToken
|
||||
{
|
||||
ECmdCode Cmd;
|
||||
int StackPos;
|
||||
|
||||
|
@ -69,48 +65,45 @@ namespace qmu
|
|||
int offset;
|
||||
} Oprt;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/** \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
|
||||
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
|
||||
*/
|
||||
/**
|
||||
* @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
|
||||
* 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
|
||||
*/
|
||||
class QmuParserByteCode
|
||||
{
|
||||
private:
|
||||
|
||||
/** \brief Token type for internal use only. */
|
||||
/** @brief Token type for internal use only. */
|
||||
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;
|
||||
|
||||
/** \brief Position in the Calculation array. */
|
||||
/** @brief Position in the Calculation array. */
|
||||
unsigned m_iStackPos;
|
||||
|
||||
/** \brief Maximum size needed for the stack. */
|
||||
/** @brief Maximum size needed for the stack. */
|
||||
std::size_t m_iMaxStackSize;
|
||||
|
||||
/** \brief The actual rpn storage. */
|
||||
/** @brief The actual rpn storage. */
|
||||
rpn_type m_vRPN;
|
||||
|
||||
bool m_bEnableOptimizer;
|
||||
|
||||
void ConstantFolding(ECmdCode a_Oprt);
|
||||
|
||||
public:
|
||||
|
||||
QmuParserByteCode();
|
||||
QmuParserByteCode(const QmuParserByteCode &a_ByteCode);
|
||||
QmuParserByteCode& operator=(const QmuParserByteCode &a_ByteCode);
|
||||
void Assign(const QmuParserByteCode &a_ByteCode);
|
||||
|
||||
void AddVar(qreal *a_pVar);
|
||||
void AddVal(qreal a_fVal);
|
||||
void AddOp(ECmdCode a_Oprt);
|
||||
|
@ -119,20 +112,15 @@ public:
|
|||
void AddFun(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 EnableOptimizer(bool bStat);
|
||||
|
||||
void Finalize();
|
||||
void clear();
|
||||
std::size_t GetMaxStackSize() const;
|
||||
std::size_t GetSize() const;
|
||||
|
||||
const SToken* GetBase() const;
|
||||
void AsciiDump();
|
||||
};
|
||||
|
||||
} // namespace qmu
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -22,358 +22,212 @@
|
|||
|
||||
#include "qmuparsercallback.h"
|
||||
|
||||
/** \file
|
||||
\brief Implementation of the parser callback class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of the parser callback class.
|
||||
*/
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback(fun_type0 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback ( fun_type0 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 0 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(1)
|
||||
,m_iPri(a_iPrec)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(a_iCode)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback ( fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 1 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
QmuParserCallback::QmuParserCallback ( fun_type2 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), 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
|
||||
\param a_bAllowOpti A flag indicating this funcation can be optimized
|
||||
\param a_iPrec The operator precedence
|
||||
\param a_eOprtAsct The operators associativity
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Constructor for constructing binary operator callbacks.
|
||||
* @param a_pFun Pointer to a static function taking two arguments
|
||||
* @param a_bAllowOpti A flag indicating this funcation can be optimized
|
||||
* @param a_iPrec The operator precedence
|
||||
* @param a_eOprtAsct The operators associativity
|
||||
* @throw nothrow
|
||||
*/
|
||||
QmuParserCallback::QmuParserCallback(fun_type2 a_pFun,
|
||||
bool a_bAllowOpti,
|
||||
int a_iPrec,
|
||||
EOprtAssociativity a_eOprtAsct)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(a_iPrec)
|
||||
,m_eOprtAsct(a_eOprtAsct)
|
||||
,m_iCode(cmOPRT_BIN)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
QmuParserCallback::QmuParserCallback ( fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec,
|
||||
EOprtAssociativity a_eOprtAsct )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(3)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback ( fun_type3 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 3 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(4)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 4 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(5)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 5 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(6)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 6 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(7)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 7 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(8)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 8 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(9)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 9 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(10)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 10 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback ( bulkfun_type0 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 0 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(1)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 1 ), 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.
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Constructor for constructing funcstion callbacks taking two arguments.
|
||||
* @throw nothrow
|
||||
*/
|
||||
QmuParserCallback::QmuParserCallback(bulkfun_type2 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
QmuParserCallback::QmuParserCallback ( bulkfun_type2 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(3)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 3 ), 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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 4 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(4)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 5 ), 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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 6 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(5)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 7 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(6)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 8 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(7)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 9 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(8)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 10 ), 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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(9)
|
||||
,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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( -1 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC ),
|
||||
m_iType ( tpDBL ), m_bAllowOpti ( a_bAllowOpti )
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback(bulkfun_type10 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(10)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_BULK)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback ( strfun_type1 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 0 ), 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 )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 1 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_STR ),
|
||||
m_iType ( tpSTR ), m_bAllowOpti ( a_bAllowOpti )
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback(multfun_type a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(-1)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC)
|
||||
,m_iType(tpDBL)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback ( strfun_type3 a_pFun, bool a_bAllowOpti )
|
||||
: m_pFun ( ( void* ) a_pFun ), m_iArgc ( 2 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmFUNC_STR ),
|
||||
m_iType ( tpSTR ), m_bAllowOpti ( a_bAllowOpti )
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
QmuParserCallback::QmuParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(0)
|
||||
,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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(1)
|
||||
,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)
|
||||
:m_pFun((void*)a_pFun)
|
||||
,m_iArgc(2)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmFUNC_STR)
|
||||
,m_iType(tpSTR)
|
||||
,m_bAllowOpti(a_bAllowOpti)
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Default constructor.
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
* @throw nothrow
|
||||
*/
|
||||
QmuParserCallback::QmuParserCallback()
|
||||
:m_pFun(0)
|
||||
,m_iArgc(0)
|
||||
,m_iPri(-1)
|
||||
,m_eOprtAsct(oaNONE)
|
||||
,m_iCode(cmUNKNOWN)
|
||||
,m_iType(tpVOID)
|
||||
,m_bAllowOpti(0)
|
||||
{}
|
||||
QmuParserCallback::QmuParserCallback()
|
||||
: m_pFun ( 0 ), m_iArgc ( 0 ), m_iPri ( -1 ), m_eOprtAsct ( oaNONE ), m_iCode ( cmUNKNOWN ), m_iType ( tpVOID ),
|
||||
m_bAllowOpti ( 0 )
|
||||
{}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Copy constructor.
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
* @throw nothrow
|
||||
*/
|
||||
QmuParserCallback::QmuParserCallback(const QmuParserCallback &ref)
|
||||
{
|
||||
QmuParserCallback::QmuParserCallback ( const QmuParserCallback &ref )
|
||||
{
|
||||
m_pFun = ref.m_pFun;
|
||||
m_iArgc = ref.m_iArgc;
|
||||
m_bAllowOpti = ref.m_bAllowOpti;
|
||||
|
@ -381,80 +235,88 @@ namespace qmu
|
|||
m_iType = ref.m_iType;
|
||||
m_iPri = ref.m_iPri;
|
||||
m_eOprtAsct = ref.m_eOprtAsct;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Clone this instance and return a pointer to the new instance. */
|
||||
QmuParserCallback* QmuParserCallback::Clone() const
|
||||
{
|
||||
return new QmuParserCallback(*this);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return tru if the function is conservative.
|
||||
|
||||
Conservative functions return always the same result for the same argument.
|
||||
\throw nothrow
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Clone this instance and return a pointer to the new instance.
|
||||
*/
|
||||
bool QmuParserCallback::IsOptimizable() const
|
||||
{
|
||||
QmuParserCallback* QmuParserCallback::Clone() const
|
||||
{
|
||||
return new QmuParserCallback ( *this );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return tru if the function is conservative.
|
||||
*
|
||||
* Conservative functions return always the same result for the same argument.
|
||||
* @throw nothrow
|
||||
*/
|
||||
bool QmuParserCallback::IsOptimizable() const
|
||||
{
|
||||
return m_bAllowOpti;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \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.
|
||||
|
||||
\throw nothrow
|
||||
\return #pFun
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* @throw nothrow
|
||||
* @return #pFun
|
||||
*/
|
||||
void* QmuParserCallback::GetAddr() const
|
||||
{
|
||||
void* QmuParserCallback::GetAddr() const
|
||||
{
|
||||
return m_pFun;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the callback code. */
|
||||
ECmdCode QmuParserCallback::GetCode() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return the callback code.
|
||||
*/
|
||||
ECmdCode QmuParserCallback::GetCode() const
|
||||
{
|
||||
return m_iCode;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
ETypeCode QmuParserCallback::GetType() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
ETypeCode QmuParserCallback::GetType() const
|
||||
{
|
||||
return m_iType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the operator precedence.
|
||||
\throw nothrown
|
||||
|
||||
Only valid if the callback token is an operator token (binary or infix).
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return the operator precedence.
|
||||
* @throw nothrown
|
||||
*
|
||||
* Only valid if the callback token is an operator token (binary or infix).
|
||||
*/
|
||||
int QmuParserCallback::GetPri() const
|
||||
{
|
||||
int QmuParserCallback::GetPri() const
|
||||
{
|
||||
return m_iPri;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Return the operators associativity.
|
||||
\throw nothrown
|
||||
|
||||
Only valid if the callback token is a binary operator token.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return the operators associativity.
|
||||
* @throw nothrown
|
||||
*
|
||||
* Only valid if the callback token is a binary operator token.
|
||||
*/
|
||||
EOprtAssociativity QmuParserCallback::GetAssociativity() const
|
||||
{
|
||||
EOprtAssociativity QmuParserCallback::GetAssociativity() const
|
||||
{
|
||||
return m_eOprtAsct;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Returns the number of function Arguments. */
|
||||
int QmuParserCallback::GetArgc() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Returns the number of function Arguments.
|
||||
*/
|
||||
int QmuParserCallback::GetArgc() const
|
||||
{
|
||||
return m_iArgc;
|
||||
}
|
||||
}
|
||||
} // namespace qmu
|
||||
|
|
|
@ -25,25 +25,24 @@
|
|||
|
||||
#include "qmuparserdef.h"
|
||||
|
||||
/** \file
|
||||
\brief Definition of the parser callback class.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief Definition of the parser callback class.
|
||||
*/
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
|
||||
/** \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
|
||||
as additional flags indication the function is non optimizeable.
|
||||
The pointer to the callback function pointer is stored as void*
|
||||
and needs to be casted according to the argument count.
|
||||
Negative argument counts indicate a parser function with a variable number
|
||||
of arguments.
|
||||
|
||||
\author (C) 2004-2011 Ingo Berg
|
||||
*/
|
||||
/**
|
||||
* @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 as additional flags indication the function is non optimizeable. The pointer to the callback
|
||||
* function pointer is stored as void* and needs to be casted according to the argument count. Negative argument counts
|
||||
* indicate a parser function with a variable number of arguments.
|
||||
*
|
||||
* @author (C) 2004-2011 Ingo Berg
|
||||
*/
|
||||
class QmuParserCallback
|
||||
{
|
||||
public:
|
||||
|
@ -80,7 +79,6 @@ public:
|
|||
QmuParserCallback(const QmuParserCallback &a_Fun);
|
||||
|
||||
QmuParserCallback* Clone() const;
|
||||
|
||||
bool IsOptimizable() const;
|
||||
void* GetAddr() const;
|
||||
ECmdCode GetCode() const;
|
||||
|
@ -88,14 +86,14 @@ public:
|
|||
int GetPri() const;
|
||||
EOprtAssociativity GetAssociativity() const;
|
||||
int GetArgc() const;
|
||||
|
||||
private:
|
||||
void *m_pFun; ///< Pointer to the callback function, casted to void
|
||||
|
||||
/** \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.
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
int m_iArgc;
|
||||
int m_iPri; ///< Valid only for binary and infix operators; Operator precedence.
|
||||
|
@ -105,8 +103,10 @@ private:
|
|||
bool m_bAllowOpti; ///< Flag indication optimizeability
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Container for Callback objects. */
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Container for Callback objects.
|
||||
*/
|
||||
typedef std::map<QString, QmuParserCallback> funmap_type;
|
||||
|
||||
} // namespace qmu
|
||||
|
|
|
@ -23,17 +23,13 @@
|
|||
#ifndef QMUPDEF_H
|
||||
#define QMUPDEF_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
#include "qmuparserfixes.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains standard definitions used by the parser.
|
||||
/** @file
|
||||
@brief This file contains standard definitions used by the parser.
|
||||
*/
|
||||
|
||||
#define QMUP_VERSION "2.2.3"
|
||||
|
@ -41,32 +37,32 @@
|
|||
|
||||
#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
|
||||
|
||||
/** \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.
|
||||
*/
|
||||
//#define MUP_USE_OPENMP
|
||||
|
||||
#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
|
||||
#else
|
||||
/** \brief Definition of the basic parser string type. */
|
||||
/** @brief Definition of the basic parser string type. */
|
||||
#define QMUP_STRING_TYPE std::string
|
||||
#endif
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Bytecode values.
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief Bytecode values.
|
||||
|
||||
\attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!
|
||||
*/
|
||||
enum ECmdCode
|
||||
{
|
||||
*/
|
||||
enum ECmdCode
|
||||
{
|
||||
// The following are codes for built in binary operators
|
||||
// apart from built in operators the user has the opportunity to
|
||||
// add user defined operators.
|
||||
|
@ -110,38 +106,38 @@ namespace qmu
|
|||
cmOPRT_INFIX, ///< code for infix operators
|
||||
cmEND, ///< end of formula
|
||||
cmUNKNOWN ///< uninitialized item
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Types internally used by the parser.
|
||||
*/
|
||||
enum ETypeCode
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief Types internally used by the parser.
|
||||
*/
|
||||
enum ETypeCode
|
||||
{
|
||||
tpSTR = 0, ///< String type (Function arguments and constants only, no string variables)
|
||||
tpDBL = 1, ///< Floating point variables
|
||||
tpVOID = 2 ///< Undefined type.
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
enum EParserVersionInfo
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
enum EParserVersionInfo
|
||||
{
|
||||
pviBRIEF,
|
||||
pviFULL
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Parser operator precedence values. */
|
||||
enum EOprtAssociativity
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief Parser operator precedence values. */
|
||||
enum EOprtAssociativity
|
||||
{
|
||||
oaLEFT = 0,
|
||||
oaRIGHT = 1,
|
||||
oaNONE = 2
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Parser operator precedence values. */
|
||||
enum EOprtPrecedence
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief Parser operator precedence values. */
|
||||
enum EOprtPrecedence
|
||||
{
|
||||
// binary operators
|
||||
prLOR = 1,
|
||||
prLAND = 2,
|
||||
|
@ -154,127 +150,125 @@ namespace qmu
|
|||
// infix operators
|
||||
prINFIX = 6, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
|
||||
prPOSTFIX = 6 ///< Postfix operator priority (currently unused)
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
typedef std::basic_stringstream<char_type,
|
||||
std::char_traits<char_type>,
|
||||
std::allocator<char_type> > stringstream_type;
|
||||
/** @brief Typedef for easily using stringstream that respect the parser stringtype. */
|
||||
typedef std::basic_stringstream < char_type, std::char_traits<char_type>, std::allocator<char_type> > stringstream_type;
|
||||
|
||||
// Data container types
|
||||
// Data container types
|
||||
|
||||
/** \brief Type used for storing variables. */
|
||||
typedef std::map<QString, qreal*> varmap_type;
|
||||
/** @brief Type used for storing variables. */
|
||||
typedef std::map<QString, qreal*> varmap_type;
|
||||
|
||||
/** \brief Type used for storing constants. */
|
||||
typedef std::map<QString, qreal> valmap_type;
|
||||
/** @brief Type used for storing constants. */
|
||||
typedef std::map<QString, qreal> valmap_type;
|
||||
|
||||
/** \brief Type for assigning a string name to an index in the internal string table. */
|
||||
typedef std::map<QString, int> strmap_type;
|
||||
/** @brief Type for assigning a string name to an index in the internal string table. */
|
||||
typedef std::map<QString, int> strmap_type;
|
||||
|
||||
// Parser callbacks
|
||||
// Parser callbacks
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef qreal (*generic_fun_type)();
|
||||
/** @brief Callback type used for functions without arguments. */
|
||||
typedef qreal ( *generic_fun_type ) ();
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef qreal (*fun_type0)();
|
||||
/** @brief Callback type used for functions without arguments. */
|
||||
typedef qreal ( *fun_type0 ) ();
|
||||
|
||||
/** \brief Callback type used for functions with a single arguments. */
|
||||
typedef qreal (*fun_type1)(qreal);
|
||||
/** @brief Callback type used for functions with a single arguments. */
|
||||
typedef qreal ( *fun_type1 ) ( qreal );
|
||||
|
||||
/** \brief Callback type used for functions with two arguments. */
|
||||
typedef qreal (*fun_type2)(qreal, qreal);
|
||||
/** @brief Callback type used for functions with two arguments. */
|
||||
typedef qreal ( *fun_type2 ) ( qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with three arguments. */
|
||||
typedef qreal (*fun_type3)(qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with three arguments. */
|
||||
typedef qreal ( *fun_type3 ) ( qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with four arguments. */
|
||||
typedef qreal (*fun_type4)(qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with four arguments. */
|
||||
typedef qreal ( *fun_type4 ) ( qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*fun_type5)(qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *fun_type5 ) ( qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*fun_type6)(qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *fun_type6 ) ( qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*fun_type7)(qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *fun_type7 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*fun_type8)(qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *fun_type8 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*fun_type9)(qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *fun_type9 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*fun_type10)(qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *fun_type10 ) ( qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions without arguments. */
|
||||
typedef qreal (*bulkfun_type0)(int, int);
|
||||
/** @brief Callback type used for functions without arguments. */
|
||||
typedef qreal ( *bulkfun_type0 ) ( int, int );
|
||||
|
||||
/** \brief Callback type used for functions with a single arguments. */
|
||||
typedef qreal (*bulkfun_type1)(int, int, qreal);
|
||||
/** @brief Callback type used for functions with a single arguments. */
|
||||
typedef qreal ( *bulkfun_type1 ) ( int, int, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with two arguments. */
|
||||
typedef qreal (*bulkfun_type2)(int, int, qreal, qreal);
|
||||
/** @brief Callback type used for functions with two arguments. */
|
||||
typedef qreal ( *bulkfun_type2 ) ( int, int, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with three arguments. */
|
||||
typedef qreal (*bulkfun_type3)(int, int, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with three arguments. */
|
||||
typedef qreal ( *bulkfun_type3 ) ( int, int, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with four arguments. */
|
||||
typedef qreal (*bulkfun_type4)(int, int, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with four arguments. */
|
||||
typedef qreal ( *bulkfun_type4 ) ( int, int, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*bulkfun_type5)(int, int, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *bulkfun_type5 ) ( int, int, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*bulkfun_type6)(int, int, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *bulkfun_type6 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*bulkfun_type7)(int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *bulkfun_type7 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*bulkfun_type8)(int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *bulkfun_type8 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \brief Callback type used for functions with five arguments. */
|
||||
typedef qreal (*bulkfun_type9)(int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal);
|
||||
/** @brief Callback type used for functions with five arguments. */
|
||||
typedef qreal ( *bulkfun_type9 ) ( int, int, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal, qreal );
|
||||
|
||||
/** \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);
|
||||
/** @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 );
|
||||
|
||||
/** \brief Callback type used for functions with a variable argument list. */
|
||||
typedef qreal (*multfun_type)(const qreal*, int);
|
||||
/** @brief Callback type used for functions with a variable argument list. */
|
||||
typedef qreal ( *multfun_type ) ( const qreal*, int );
|
||||
|
||||
/** \brief Callback type used for functions taking a string as an argument. */
|
||||
typedef qreal (*strfun_type1)(const QString &);
|
||||
/** @brief Callback type used for functions taking a string as an argument. */
|
||||
typedef qreal ( *strfun_type1 ) ( const QString & );
|
||||
|
||||
/** \brief Callback type used for functions taking a string and a value as arguments. */
|
||||
typedef qreal (*strfun_type2)(const QString &, qreal);
|
||||
/** @brief Callback type used for functions taking a string and a value as arguments. */
|
||||
typedef qreal ( *strfun_type2 ) ( const QString &, qreal );
|
||||
|
||||
/** \brief Callback type used for functions taking a string and two values as arguments. */
|
||||
typedef qreal (*strfun_type3)(const QString &, qreal, qreal);
|
||||
/** @brief Callback type used for functions taking a string and two values as arguments. */
|
||||
typedef qreal ( *strfun_type3 ) ( const QString &, qreal, qreal );
|
||||
|
||||
/** \brief Callback used for functions that identify values in a string. */
|
||||
typedef int (*identfun_type)(const QString &sExpr, int *nPos, qreal *fVal);
|
||||
/** @brief Callback used for functions that identify values in a string. */
|
||||
typedef int ( *identfun_type ) ( const QString &sExpr, int *nPos, qreal *fVal );
|
||||
|
||||
/** \brief Callback used for variable creation factory functions. */
|
||||
typedef qreal* (*facfun_type)(const QString &, void*);
|
||||
/** @brief Callback used for variable creation factory functions. */
|
||||
typedef qreal* ( *facfun_type ) ( const QString &, void* );
|
||||
} // end of namespace
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,45 +24,45 @@
|
|||
|
||||
#include <QTextStream>
|
||||
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
const QmuParserErrorMsg QmuParserErrorMsg::m_Instance;
|
||||
const QmuParserErrorMsg QmuParserErrorMsg::m_Instance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const QmuParserErrorMsg& QmuParserErrorMsg::Instance()
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
const QmuParserErrorMsg& QmuParserErrorMsg::Instance()
|
||||
{
|
||||
return m_Instance;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
QString QmuParserErrorMsg::operator[](unsigned a_iIdx) const
|
||||
{
|
||||
return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : QString();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QString QmuParserErrorMsg::operator[] ( unsigned a_iIdx ) const
|
||||
{
|
||||
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& )
|
||||
{
|
||||
assert(false);
|
||||
QmuParserErrorMsg& QmuParserErrorMsg::operator= ( const QmuParserErrorMsg& )
|
||||
{
|
||||
assert ( false );
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
QmuParserErrorMsg::QmuParserErrorMsg(const QmuParserErrorMsg&)
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserErrorMsg::QmuParserErrorMsg ( const QmuParserErrorMsg& )
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
QmuParserErrorMsg::QmuParserErrorMsg()
|
||||
:m_vErrMsg(0)
|
||||
{
|
||||
m_vErrMsg.resize(ecCOUNT);
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserErrorMsg::QmuParserErrorMsg()
|
||||
: m_vErrMsg ( 0 )
|
||||
{
|
||||
m_vErrMsg.resize ( ecCOUNT );
|
||||
|
||||
m_vErrMsg[ecUNASSIGNABLE_TOKEN] = "Unexpected token \"$TOK$\" found at position $POS$.";
|
||||
m_vErrMsg[ecINTERNAL_ERROR] = "Internal error";
|
||||
|
@ -101,135 +101,124 @@ namespace qmu
|
|||
m_vErrMsg[ecMISSING_ELSE_CLAUSE] = "If-then-else operator is missing an else clause";
|
||||
m_vErrMsg[ecMISPLACED_COLON] = "Misplaced colon at position $POS$";
|
||||
|
||||
#if defined(_DEBUG)
|
||||
for (int i=0; i<ecCOUNT; ++i)
|
||||
if (!m_vErrMsg[i].length())
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// QParserError class
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
/** \brief Default constructor. */
|
||||
QmuParserError::QmuParserError()
|
||||
:m_strMsg()
|
||||
,m_strFormula()
|
||||
,m_strTok()
|
||||
,m_iPos(-1)
|
||||
,m_iErrc(ecUNDEFINED)
|
||||
,m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
#if defined(_DEBUG)
|
||||
for ( int i = 0; i < ecCOUNT; ++i )
|
||||
{
|
||||
if ( !m_vErrMsg[i].length() )
|
||||
{
|
||||
assert ( false );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief This Constructor is used for internal exceptions only.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// QParserError class
|
||||
//
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
It does not contain any information but the error code.
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
QmuParserError::QmuParserError(EErrorCodes a_iErrc)
|
||||
:m_strMsg()
|
||||
,m_strFormula()
|
||||
,m_strTok()
|
||||
,m_iPos(-1)
|
||||
,m_iErrc(a_iErrc)
|
||||
,m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
|
||||
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
|
||||
}
|
||||
QmuParserError::QmuParserError()
|
||||
: m_strMsg(), m_strFormula(), m_strTok(), m_iPos ( -1 ), m_iErrc ( ecUNDEFINED ),
|
||||
m_ErrMsg ( QmuParserErrorMsg::Instance() )
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error from a message text. */
|
||||
QmuParserError::QmuParserError(const QString &sMsg)
|
||||
:m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief This Constructor is used for internal exceptions only.
|
||||
*
|
||||
* It does not contain any information but the error code.
|
||||
*/
|
||||
QmuParserError::QmuParserError ( EErrorCodes a_iErrc )
|
||||
: m_strMsg(), m_strFormula(), m_strTok(), m_iPos ( -1 ), m_iErrc ( a_iErrc ),
|
||||
m_ErrMsg ( QmuParserErrorMsg::Instance() )
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
|
||||
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Construct an error from a message text.
|
||||
*/
|
||||
QmuParserError::QmuParserError ( const QString &sMsg )
|
||||
: m_ErrMsg ( QmuParserErrorMsg::Instance() )
|
||||
{
|
||||
Reset();
|
||||
m_strMsg = sMsg;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error object.
|
||||
\param [in] a_iErrc the error code.
|
||||
\param [in] sTok The token string related to this error.
|
||||
\param [in] sExpr The expression related to the error.
|
||||
\param [in] a_iPos the position in the expression where the error occured.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Construct an error object.
|
||||
* @param [in] a_iErrc the error code.
|
||||
* @param [in] sTok The token string related to this error.
|
||||
* @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 &sExpr,
|
||||
int iPos )
|
||||
:m_strMsg()
|
||||
,m_strFormula(sExpr)
|
||||
,m_strTok(sTok)
|
||||
,m_iPos(iPos)
|
||||
,m_iErrc(iErrc)
|
||||
,m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
{
|
||||
: m_strMsg(), m_strFormula ( sExpr ), m_strTok ( sTok ), m_iPos ( iPos ), m_iErrc ( iErrc ),
|
||||
m_ErrMsg ( QmuParserErrorMsg::Instance() )
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
|
||||
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
|
||||
}
|
||||
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
|
||||
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error object.
|
||||
\param [in] iErrc the error code.
|
||||
\param [in] iPos the position in the expression where the error occured.
|
||||
\param [in] sTok The token string related to this error.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Construct an error object.
|
||||
* @param [in] iErrc the error code.
|
||||
* @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)
|
||||
:m_strMsg()
|
||||
,m_strFormula()
|
||||
,m_strTok(sTok)
|
||||
,m_iPos(iPos)
|
||||
,m_iErrc(iErrc)
|
||||
,m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
{
|
||||
QmuParserError::QmuParserError ( EErrorCodes iErrc, int iPos, const QString &sTok )
|
||||
: m_strMsg(), m_strFormula(), m_strTok ( sTok ), m_iPos ( iPos ), m_iErrc ( iErrc ),
|
||||
m_ErrMsg ( QmuParserErrorMsg::Instance() )
|
||||
{
|
||||
m_strMsg = m_ErrMsg[m_iErrc];
|
||||
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
|
||||
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
|
||||
}
|
||||
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
|
||||
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Construct an error object.
|
||||
\param [in] szMsg The error message text.
|
||||
\param [in] iPos the position related to the error.
|
||||
\param [in] sTok The token string related to this error.
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/** @brief Construct an error object.
|
||||
* @param [in] szMsg The error message text.
|
||||
* @param [in] iPos the position related to the error.
|
||||
* @param [in] sTok The token string related to this error.
|
||||
*/
|
||||
QmuParserError::QmuParserError(const QString &szMsg, int iPos, const QString &sTok)
|
||||
:m_strMsg(szMsg)
|
||||
,m_strFormula()
|
||||
,m_strTok(sTok)
|
||||
,m_iPos(iPos)
|
||||
,m_iErrc(ecGENERIC)
|
||||
,m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
{
|
||||
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
|
||||
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
|
||||
}
|
||||
QmuParserError::QmuParserError ( const QString &szMsg, int iPos, const QString &sTok )
|
||||
: m_strMsg ( szMsg ), m_strFormula(), m_strTok ( sTok ), m_iPos ( iPos ), m_iErrc ( ecGENERIC ),
|
||||
m_ErrMsg ( QmuParserErrorMsg::Instance() )
|
||||
{
|
||||
ReplaceSubString ( m_strMsg, "$POS$", QString().setNum ( m_iPos ) );
|
||||
ReplaceSubString ( m_strMsg, "$TOK$", m_strTok );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Copy constructor. */
|
||||
QmuParserError::QmuParserError(const QmuParserError &a_Obj)
|
||||
:m_strMsg(a_Obj.m_strMsg)
|
||||
,m_strFormula(a_Obj.m_strFormula)
|
||||
,m_strTok(a_Obj.m_strTok)
|
||||
,m_iPos(a_Obj.m_iPos)
|
||||
,m_iErrc(a_Obj.m_iErrc)
|
||||
,m_ErrMsg(QmuParserErrorMsg::Instance())
|
||||
{
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/** @brief Copy constructor. */
|
||||
QmuParserError::QmuParserError ( const QmuParserError &a_Obj )
|
||||
: m_strMsg ( a_Obj.m_strMsg ), m_strFormula ( a_Obj.m_strFormula ), 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. */
|
||||
QmuParserError& QmuParserError::operator=(const QmuParserError &a_Obj)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/** @brief Assignment operator. */
|
||||
QmuParserError& QmuParserError::operator= ( const QmuParserError &a_Obj )
|
||||
{
|
||||
if ( this == &a_Obj )
|
||||
{
|
||||
if (this==&a_Obj)
|
||||
return *this;
|
||||
}
|
||||
|
||||
m_strMsg = a_Obj.m_strMsg;
|
||||
m_strFormula = a_Obj.m_strFormula;
|
||||
|
@ -237,90 +226,104 @@ namespace qmu
|
|||
m_iPos = a_Obj.m_iPos;
|
||||
m_iErrc = a_Obj.m_iErrc;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
QmuParserError::~QmuParserError()
|
||||
{}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
QmuParserError::~QmuParserError()
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Replace all ocuurences of a substring with another string.
|
||||
\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)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Replace all ocuurences of a substring with another string.
|
||||
* @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 )
|
||||
{
|
||||
QString strResult;
|
||||
int iPos(0), iNext(0);
|
||||
int iPos ( 0 ), iNext ( 0 );
|
||||
|
||||
for(;;)
|
||||
for ( ;; )
|
||||
{
|
||||
iNext = strSource.indexOf(strFind, iPos);
|
||||
strResult.append(strSource.mid(iPos, iNext-iPos));
|
||||
iNext = strSource.indexOf ( strFind, iPos );
|
||||
strResult.append ( strSource.mid ( iPos, iNext - iPos ) );
|
||||
|
||||
if( iNext==-1 )
|
||||
if ( iNext == -1 )
|
||||
break;
|
||||
|
||||
strResult.append(strReplaceWith);
|
||||
strResult.append ( strReplaceWith );
|
||||
iPos = iNext + strFind.length();
|
||||
}
|
||||
|
||||
strSource.swap(strResult);
|
||||
strSource.swap ( strResult );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Reset the erro object. */
|
||||
void QmuParserError::Reset()
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Reset the erro object.
|
||||
*/
|
||||
void QmuParserError::Reset()
|
||||
{
|
||||
m_strMsg = "";
|
||||
m_strFormula = "";
|
||||
m_strTok = "";
|
||||
m_iPos = -1;
|
||||
m_iErrc = ecUNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Set the expression related to this error. */
|
||||
void QmuParserError::SetFormula(const QString &a_strFormula)
|
||||
{
|
||||
m_strFormula = a_strFormula;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief gets the expression related tp this error.*/
|
||||
const QString& QmuParserError::GetExpr() const
|
||||
{
|
||||
return m_strFormula;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Returns the message string for this error. */
|
||||
const QString& QmuParserError::GetMsg() const
|
||||
{
|
||||
return m_strMsg;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the formula position related to the error.
|
||||
|
||||
If the error is not related to a distinct position this will return -1
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Set the expression related to this error.
|
||||
*/
|
||||
std::size_t QmuParserError::GetPos() const
|
||||
{
|
||||
void QmuParserError::SetFormula ( const QString &a_strFormula )
|
||||
{
|
||||
m_strFormula = a_strFormula;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief gets the expression related tp this error.
|
||||
*/
|
||||
const QString& QmuParserError::GetExpr() const
|
||||
{
|
||||
return m_strFormula;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Returns the message string for this error.
|
||||
*/
|
||||
const QString& QmuParserError::GetMsg() const
|
||||
{
|
||||
return m_strMsg;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return the formula position related to the error.
|
||||
*
|
||||
* If the error is not related to a distinct position this will return -1
|
||||
*/
|
||||
std::size_t QmuParserError::GetPos() const
|
||||
{
|
||||
return m_iPos;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return string related with this token (if available). */
|
||||
const QString& QmuParserError::GetToken() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return string related with this token (if available).
|
||||
*/
|
||||
const QString& QmuParserError::GetToken() const
|
||||
{
|
||||
return m_strTok;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the error code. */
|
||||
EErrorCodes QmuParserError::GetCode() const
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Return the error code.
|
||||
*/
|
||||
EErrorCodes QmuParserError::GetCode() const
|
||||
{
|
||||
return m_iErrc;
|
||||
}
|
||||
}
|
||||
} // namespace qmu
|
||||
|
|
|
@ -31,14 +31,14 @@
|
|||
|
||||
#include "qmuparserdef.h"
|
||||
|
||||
/** \file
|
||||
\brief This file defines the error class used by the parser.
|
||||
/** @file
|
||||
@brief This file defines the error class used by the parser.
|
||||
*/
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
|
||||
/** \brief Error codes. */
|
||||
/** @brief Error codes. */
|
||||
enum EErrorCodes
|
||||
{
|
||||
// Formula syntax errors
|
||||
|
@ -92,21 +92,20 @@ enum EErrorCodes
|
|||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief A class that handles the error messages.
|
||||
/** @brief A class that handles the error messages.
|
||||
*/
|
||||
class QmuParserErrorMsg
|
||||
{
|
||||
public:
|
||||
typedef QmuParserErrorMsg self_type;
|
||||
|
||||
QmuParserErrorMsg& operator=(const QmuParserErrorMsg &);
|
||||
QmuParserErrorMsg(const QmuParserErrorMsg&);
|
||||
QmuParserErrorMsg& operator= ( const QmuParserErrorMsg & );
|
||||
QmuParserErrorMsg ( const QmuParserErrorMsg& );
|
||||
QmuParserErrorMsg();
|
||||
|
||||
~QmuParserErrorMsg();
|
||||
|
||||
static const QmuParserErrorMsg& Instance();
|
||||
QString operator[](unsigned a_iIdx) const;
|
||||
QString operator[] ( unsigned a_iIdx ) const;
|
||||
|
||||
private:
|
||||
QVector<QString> m_vErrMsg; ///< A vector with the predefined error messages
|
||||
|
@ -114,38 +113,30 @@ private:
|
|||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Error class of the parser.
|
||||
\author Ingo Berg
|
||||
/** @brief Error class of the parser.
|
||||
@author Ingo Berg
|
||||
|
||||
Part of the math parser package.
|
||||
*/
|
||||
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:
|
||||
|
||||
QmuParserError();
|
||||
explicit QmuParserError(EErrorCodes a_iErrc);
|
||||
explicit QmuParserError(const QString &sMsg);
|
||||
QmuParserError( EErrorCodes a_iErrc, const QString &sTok, const QString &sFormula = QString(), int a_iPos = -1);
|
||||
QmuParserError(EErrorCodes a_iErrc, int a_iPos, const QString &sTok);
|
||||
QmuParserError(const QString &a_szMsg, int a_iPos, const QString &sTok = QString());
|
||||
QmuParserError(const QmuParserError &a_Obj);
|
||||
QmuParserError& operator=(const QmuParserError &a_Obj);
|
||||
explicit QmuParserError ( EErrorCodes a_iErrc );
|
||||
explicit QmuParserError ( const QString &sMsg );
|
||||
QmuParserError ( EErrorCodes a_iErrc, const QString &sTok, const QString &sFormula = QString(), int a_iPos = -1 );
|
||||
QmuParserError ( EErrorCodes a_iErrc, int a_iPos, const QString &sTok );
|
||||
QmuParserError ( const QString &a_szMsg, int a_iPos, const QString &sTok = QString() );
|
||||
QmuParserError ( const QmuParserError &a_Obj );
|
||||
QmuParserError& operator= ( const QmuParserError &a_Obj );
|
||||
~QmuParserError();
|
||||
|
||||
void SetFormula(const QString &a_strFormula);
|
||||
const QString &GetExpr() const;
|
||||
const QString &GetMsg() const;
|
||||
void SetFormula ( const QString &a_strFormula );
|
||||
const QString& GetExpr() const;
|
||||
const QString& GetMsg() const;
|
||||
std::size_t GetPos() const;
|
||||
const QString &GetToken() const;
|
||||
const QString& GetToken() const;
|
||||
EErrorCodes GetCode() const;
|
||||
|
||||
private:
|
||||
|
@ -155,6 +146,11 @@ private:
|
|||
int m_iPos; ///< Formula position related to the error
|
||||
EErrorCodes m_iErrc; ///< Error code
|
||||
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
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#ifndef QMUPARSERFIXES_H
|
||||
#define QMUPARSERFIXES_H
|
||||
|
||||
/** \file
|
||||
\brief This file contains compatibility fixes for some platforms.
|
||||
/** @file
|
||||
@brief This file contains compatibility fixes for some platforms.
|
||||
*/
|
||||
|
||||
//
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,91 +29,201 @@
|
|||
#include "qmuparser.h"
|
||||
#include <QString>
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser test class.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief This file contains the parser test class.
|
||||
*/
|
||||
|
||||
namespace qmu
|
||||
{
|
||||
/** \brief Namespace for test cases. */
|
||||
namespace Test
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Test cases for unit testing.
|
||||
|
||||
(C) 2004-2011 Ingo Berg
|
||||
/**
|
||||
* @brief Namespace for test cases.
|
||||
*/
|
||||
class QmuParserTester // final
|
||||
{
|
||||
private:
|
||||
namespace Test
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Test cases for unit testing.
|
||||
*
|
||||
* (C) 2004-2011 Ingo Berg
|
||||
*/
|
||||
class QmuParserTester // final
|
||||
{
|
||||
public:
|
||||
typedef int ( QmuParserTester::*testfun_type ) ();
|
||||
|
||||
QmuParserTester();
|
||||
void Run();
|
||||
private:
|
||||
QVector<testfun_type> m_vTestFun;
|
||||
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
|
||||
static qreal f1of1(qreal v) { return v;}
|
||||
|
||||
static qreal f1of2(qreal v, qreal ) {return v;}
|
||||
static qreal f2of2(qreal , qreal v) {return v;}
|
||||
|
||||
static qreal f1of3(qreal v, qreal , qreal ) {return v;}
|
||||
static qreal f2of3(qreal , qreal v, qreal ) {return v;}
|
||||
static qreal f3of3(qreal , qreal , qreal v) {return v;}
|
||||
|
||||
static qreal f1of4(qreal v, qreal, qreal , qreal ) {return v;}
|
||||
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 f1of1 ( qreal v )
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw qmu::QmuParser::exception_type( "too few arguments for function FirstArg." );
|
||||
return v;
|
||||
}
|
||||
|
||||
static qreal f1of2 ( qreal v, qreal )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static qreal f2of2 ( qreal , qreal v )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static qreal f1of3 ( qreal v, qreal , qreal )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static qreal f2of3 ( qreal , qreal v, qreal )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static qreal f3of3 ( qreal , qreal , qreal v )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
static qreal f1of4 ( qreal v, qreal, qreal , qreal )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
if ( !a_iArgc )
|
||||
{
|
||||
throw qmu::QmuParser::exception_type ( "too few arguments for function FirstArg." );
|
||||
}
|
||||
|
||||
return a_afArg[0];
|
||||
}
|
||||
|
||||
static qreal LastArg(const qreal* a_afArg, int a_iArgc)
|
||||
static qreal LastArg ( const qreal* a_afArg, int a_iArgc )
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw qmu::QmuParser::exception_type( "too few arguments for function LastArg." );
|
||||
|
||||
return a_afArg[a_iArgc-1];
|
||||
if ( !a_iArgc )
|
||||
{
|
||||
throw qmu::QmuParser::exception_type ( "too few arguments for function LastArg." );
|
||||
}
|
||||
|
||||
static qreal Sum(const qreal* a_afArg, int a_iArgc)
|
||||
{
|
||||
if (!a_iArgc)
|
||||
throw qmu::QmuParser::exception_type( "too few arguments for function sum." );
|
||||
return a_afArg[a_iArgc - 1];
|
||||
}
|
||||
|
||||
qreal fRes=0;
|
||||
for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
|
||||
static qreal Sum ( const qreal* a_afArg, int a_iArgc )
|
||||
{
|
||||
if ( !a_iArgc )
|
||||
{
|
||||
throw qmu::QmuParser::exception_type ( "too few arguments for function sum." );
|
||||
}
|
||||
|
||||
qreal fRes = 0;
|
||||
for ( int i = 0; i < a_iArgc; ++i )
|
||||
{
|
||||
fRes += a_afArg[i];
|
||||
}
|
||||
return fRes;
|
||||
}
|
||||
|
||||
static qreal Rnd(qreal v)
|
||||
static qreal Rnd ( qreal v )
|
||||
{
|
||||
return (qreal)(1+(v*std::rand()/(RAND_MAX+1.0)));
|
||||
return ( qreal ) ( 1 + ( v * std::rand() / ( RAND_MAX + 1.0 ) ) );
|
||||
}
|
||||
|
||||
static qreal RndWithString(const char_type*)
|
||||
static qreal RndWithString ( const char_type* )
|
||||
{
|
||||
return (qreal)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );
|
||||
return ( qreal ) ( 1 + ( 1000.0f * std::rand() / ( RAND_MAX + 1.0 ) ) );
|
||||
}
|
||||
|
||||
static qreal Ping()
|
||||
|
@ -121,42 +231,53 @@ namespace qmu
|
|||
return 10;
|
||||
}
|
||||
|
||||
static qreal ValueOf(const QString &)
|
||||
static qreal ValueOf ( const QString & )
|
||||
{
|
||||
return 123;
|
||||
}
|
||||
|
||||
static qreal StrFun1(const QString & v1)
|
||||
static qreal StrFun1 ( const QString & v1 )
|
||||
{
|
||||
int val = v1.toInt();
|
||||
return (qreal)val;
|
||||
return ( qreal ) val;
|
||||
}
|
||||
|
||||
static qreal StrFun2(const QString & v1, qreal v2)
|
||||
static qreal StrFun2 ( const QString & v1, qreal v2 )
|
||||
{
|
||||
int val = v1.toInt();
|
||||
return (qreal)(val + v2);
|
||||
return ( qreal ) ( val + v2 );
|
||||
}
|
||||
|
||||
static qreal StrFun3(const QString & v1, qreal v2, qreal v3)
|
||||
static qreal StrFun3 ( const QString & v1, qreal v2, qreal v3 )
|
||||
{
|
||||
int val = v1.toInt();
|
||||
return val + v2 + v3;
|
||||
}
|
||||
|
||||
static qreal StrToFloat(const QString & a_szMsg)
|
||||
static qreal StrToFloat ( const QString & a_szMsg )
|
||||
{
|
||||
qreal val = a_szMsg.toDouble();
|
||||
return val;
|
||||
}
|
||||
|
||||
// postfix operator callback
|
||||
static qreal Mega(qreal a_fVal) { 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; }
|
||||
static qreal Mega ( qreal a_fVal )
|
||||
{
|
||||
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
|
||||
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 );
|
||||
|
||||
int TestNames();
|
||||
int TestSyntax();
|
||||
|
@ -172,27 +293,8 @@ namespace qmu
|
|||
int TestIfThenElse();
|
||||
|
||||
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
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,13 +32,13 @@
|
|||
#include "qmuparsererror.h"
|
||||
#include "qmuparsercallback.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser token definition.
|
||||
/** @file
|
||||
@brief This file contains the parser token definition.
|
||||
*/
|
||||
|
||||
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 tokens can be either one of the following:
|
||||
|
@ -52,7 +52,7 @@ namespace qmu
|
|||
<li>binary operator</li>
|
||||
</ul>
|
||||
|
||||
\author (C) 2004-2013 Ingo Berg
|
||||
@author (C) 2004-2013 Ingo Berg
|
||||
*/
|
||||
template<typename TBase, typename TString>
|
||||
class QmuParserToken
|
||||
|
@ -71,11 +71,11 @@ namespace qmu
|
|||
public:
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
/** \brief Constructor (default).
|
||||
/** @brief Constructor (default).
|
||||
|
||||
Sets token to an neutral state of type cmUNKNOWN.
|
||||
\throw nothrow
|
||||
\sa ECmdCode
|
||||
@throw nothrow
|
||||
@sa ECmdCode
|
||||
*/
|
||||
QmuParserToken()
|
||||
: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(...)
|
||||
\throw nothrow
|
||||
\post m_iType==cmUNKNOWN
|
||||
\sa #Assign
|
||||
@throw nothrow
|
||||
@post m_iType==cmUNKNOWN
|
||||
@sa #Assign
|
||||
*/
|
||||
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.
|
||||
Implemented by calling Assign(...).
|
||||
\throw nothrow
|
||||
@throw nothrow
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
||||
\pre [assert] a_iType!=cmVAR
|
||||
\pre [assert] a_iType!=cmVAL
|
||||
\pre [assert] a_iType!=cmFUNC
|
||||
\post m_fVal = 0
|
||||
\post m_pTok = 0
|
||||
@post m_fVal = 0
|
||||
@post m_pTok = 0
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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.
|
||||
\throw nothrow
|
||||
@throw nothrow
|
||||
*/
|
||||
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.
|
||||
\throw nothrow
|
||||
@throw nothrow
|
||||
*/
|
||||
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.
|
||||
\throw nothrow
|
||||
@throw nothrow
|
||||
*/
|
||||
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.
|
||||
\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
|
||||
* @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
|
||||
*/
|
||||
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.
|
||||
|
||||
\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).
|
||||
@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).
|
||||
*/
|
||||
int GetIdx() const
|
||||
{
|
||||
|
@ -261,10 +261,10 @@ namespace qmu
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** \brief Return the token type.
|
||||
/** @brief Return the token type.
|
||||
|
||||
\return #m_iType
|
||||
\throw nothrow
|
||||
* @return #m_iType
|
||||
@throw nothrow
|
||||
*/
|
||||
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.
|
||||
|
||||
\return The pointer stored in #m_pTok.
|
||||
\throw exception_type if token type is non of:
|
||||
* @return The pointer stored in #m_pTok.
|
||||
@throw exception_type if token type is non of:
|
||||
<ul>
|
||||
<li>cmFUNC</li>
|
||||
<li>cmSTRFUNC</li>
|
||||
|
@ -325,7 +325,7 @@ namespace qmu
|
|||
<li>cmINFIXOP</li>
|
||||
<li>cmOPRT_BIN</li>
|
||||
</ul>
|
||||
\sa ECmdCode
|
||||
@sa ECmdCode
|
||||
*/
|
||||
generic_fun_type GetFuncAddr() const
|
||||
{
|
||||
|
@ -336,7 +336,7 @@ namespace qmu
|
|||
/** \biref Get value of the token.
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -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.
|
||||
\throw exception_type if token is no variable token.
|
||||
@throw exception_type if token is no variable token.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -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
|
||||
for a string function.
|
||||
\return #m_strTok
|
||||
\throw nothrow
|
||||
\sa m_strTok
|
||||
* @return #m_strTok
|
||||
@throw nothrow
|
||||
@sa m_strTok
|
||||
*/
|
||||
const TString& GetAsString() const
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,8 +35,8 @@
|
|||
#include "qmuparserdef.h"
|
||||
#include "qmuparsertoken.h"
|
||||
|
||||
/** \file
|
||||
\brief This file contains the parser token reader definition.
|
||||
/** @file
|
||||
@brief This file contains the parser token reader definition.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace qmu
|
|||
// Forward declaration
|
||||
class QmuParserBase;
|
||||
|
||||
/** \brief Token reader for the ParserBase class.
|
||||
/** @brief Token reader for the ParserBase class.
|
||||
|
||||
*/
|
||||
class QmuParserTokenReader
|
||||
|
@ -75,7 +75,7 @@ namespace qmu
|
|||
|
||||
private:
|
||||
|
||||
/** \brief Syntax codes.
|
||||
/** @brief Syntax codes.
|
||||
|
||||
The syntax codes control the syntax check done during the first time parsing of
|
||||
the expression string. They are flags that indicate which tokens are allowed next
|
||||
|
|
Loading…
Reference in New Issue
Block a user