First success build after all changes.

--HG--
branch : feature
This commit is contained in:
dismine 2014-04-28 21:41:38 +03:00
parent 7c1d22c5f4
commit 0b49785255
13 changed files with 496 additions and 508 deletions

View file

@ -166,11 +166,16 @@ qreal QmuParser::Max(const qreal *a_afArg, int a_iArgc)
\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 char_type* a_szExpr, int *a_iPos, qreal *a_fVal)
int QmuParser::IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal)
{
qreal fVal(0);
stringstream_type stream(a_szExpr);
#if defined(_UNICODE)
std::wstring a_szExprStd = a_szExpr.toStdWString();
#else
std::string a_szExprStd = a_szExpr.toStdString();
#endif
stringstream_type stream(a_szExprStd);
stream.seekg(0); // todo: check if this really is necessary
stream.imbue(QmuParser::s_locale);
stream >> fVal;

View file

@ -83,7 +83,7 @@ protected:
static qreal Min(const qreal*, int); // minimum
static qreal Max(const qreal*, int); // maximum
static int IsVal(const char_type* a_szExpr, int *a_iPos, qreal *a_fVal);
static int IsVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal);
};
} // namespace qmu

View file

@ -53,15 +53,9 @@ namespace qmu
When defining custom binary operators with #AddOprt(...) make sure not to choose
names conflicting with these definitions.
*/
const char_type* QmuParserBase::c_DefaultOprt[] =
{
"<=", ">=", "!=",
"==", "<", ">",
"+", "-", "*",
"/", "^", "&&",
"||", "=", "(",
")", "?", ":", 0
};
const QStringList QmuParserBase::c_DefaultOprt = QStringList() << "<=" << ">=" << "!=" << "==" << "<" << ">" << "+"
<< "-" << "*" << "/" << "^" << "&&" << "||" << "="
<< "(" << ")" << "?" << ":";
//------------------------------------------------------------------------------
/** \brief Constructor.
@ -247,7 +241,7 @@ namespace qmu
}
//---------------------------------------------------------------------------
void QmuParserBase::OnDetectVar(string_type * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
void QmuParserBase::OnDetectVar(QString * /*pExpr*/, int & /*nStart*/, int & /*nEnd*/)
{}
//---------------------------------------------------------------------------
@ -329,10 +323,10 @@ namespace qmu
//---------------------------------------------------------------------------
/** \brief Add a function or operator callback to the parser. */
void QmuParserBase::AddCallback(const string_type &a_strName,
void QmuParserBase::AddCallback(const QString &a_strName,
const QmuParserCallback &a_Callback,
funmap_type &a_Storage,
const char_type *a_szCharSet )
const QString &a_szCharSet )
{
if (a_Callback.GetAddr()==0)
Error(ecINVALID_FUN_PTR);
@ -362,13 +356,19 @@ namespace qmu
\throw ParserException if the name contains invalid charakters.
*/
void QmuParserBase::CheckOprt(const string_type &a_sName,
void QmuParserBase::CheckOprt(const QString &a_sName,
const QmuParserCallback &a_Callback,
const string_type &a_szCharSet) const
const QString &a_szCharSet) const
{
if ( !a_sName.length() ||
(a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
(a_sName[0]>='0' && a_sName[0]<='9'))
#if defined(_UNICODE)
const std::wstring a_sNameStd = a_sName.toStdWString();
const std::wstring a_szCharSetStd = a_szCharSet.toStdWString();
#else
const std::string a_sNameStd = a_sName.toStdString();
const std::string a_szCharSetStd = a_szCharSet.toStdString();
#endif
if ( !a_sNameStd.length() || (a_sNameStd.find_first_not_of(a_szCharSetStd)!=string_type::npos) ||
(a_sNameStd.at(0)>='0' && a_sNameStd.at(0)<='9'))
{
switch(a_Callback.GetCode())
{
@ -379,21 +379,26 @@ namespace qmu
}
}
//---------------------------------------------------------------------------
/** \brief Check if a name contains invalid characters.
//---------------------------------------------------------------------------
/** \brief Check if a name contains invalid characters.
\throw ParserException if the name contains invalid charakters.
*/
void QmuParserBase::CheckName(const string_type &a_sName,
const string_type &a_szCharSet) const
{
if ( !a_sName.length() ||
(a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
(a_sName[0]>='0' && a_sName[0]<='9'))
\throw ParserException if the name contains invalid charakters.
*/
void QmuParserBase::CheckName(const QString &a_sName, const QString &a_szCharSet) const
{
#if defined(_UNICODE)
std::wstring a_sNameStd = a_sName.toStdWString();
std::wstring a_szCharSetStd = a_szCharSet.toStdWString();
#else
std::string a_sNameStd = a_sName.toStdString();
std::string a_szCharSetStd = a_szCharSet.toStdString();
#endif
if ( !a_sNameStd.length() || (a_sNameStd.find_first_not_of(a_szCharSetStd)!=string_type::npos) ||
(a_sNameStd[0]>='0' && a_sNameStd[0]<='9'))
{
Error(ecINVALID_NAME);
Error(ecINVALID_NAME);
}
}
}
//---------------------------------------------------------------------------
/** \brief Set the formula.
@ -403,7 +408,7 @@ namespace qmu
Triggers first time calculation thus the creation of the bytecode and
scanning of used variables.
*/
void QmuParserBase::SetExpr(const string_type &a_sExpr)
void QmuParserBase::SetExpr(const QString &a_sExpr)
{
// Check locale compatibility
std::locale loc;
@ -415,9 +420,9 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
// <ibg> 20060222: Bugfix for Borland-Kylix:
// adding a space to the expression will keep Borlands KYLIX from going wild
// when calling tellg on a stringstream created from the expression after
// reading a value at the end of an expression. (mu::Parser::IsVal function)
// reading a value at the end of an expression. (qmu::QmuParser::IsVal function)
// (tellg returns -1 otherwise causing the parser to ignore the value)
string_type sBuf(a_sExpr + " " );
QString sBuf(a_sExpr + " " );
m_pTokenReader->SetFormula(sBuf);
ReInit();
}
@ -426,9 +431,9 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
/** \brief Get the default symbols used for the built in operators.
\sa c_DefaultOprt
*/
const char_type** QmuParserBase::GetOprtDef() const
const QStringList &QmuParserBase::GetOprtDef() const
{
return (const char_type **)(&c_DefaultOprt[0]);
return c_DefaultOprt;
}
//---------------------------------------------------------------------------
@ -458,53 +463,41 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
m_sInfixOprtChars = a_szCharset;
}
//---------------------------------------------------------------------------
/** \brief Virtual function that defines the characters allowed in name identifiers.
\sa #ValidOprtChars, #ValidPrefixOprtChars
*/
const char_type* QmuParserBase::ValidNameChars() const
{
//---------------------------------------------------------------------------
/** \brief Virtual function that defines the characters allowed in name identifiers.
\sa #ValidOprtChars, #ValidPrefixOprtChars
*/
const QString& QmuParserBase::ValidNameChars() const
{
assert(m_sNameChars.size());
#if defined(_UNICODE)
return m_sNameChars.toStdWString().c_str();
#else
return m_sNameChars.toStdString().c_str();
#endif
}
return m_sNameChars;
}
//---------------------------------------------------------------------------
/** \brief Virtual function that defines the characters allowed in operator definitions.
\sa #ValidNameChars, #ValidPrefixOprtChars
*/
const char_type* QmuParserBase::ValidOprtChars() const
const QString &QmuParserBase::ValidOprtChars() const
{
assert(m_sOprtChars.size());
#if defined(_UNICODE)
return m_sOprtChars.toStdWString().c_str();
#else
return m_sOprtChars.toStdString().c_str();
#endif
return m_sOprtChars;
}
//---------------------------------------------------------------------------
/** \brief Virtual function that defines the characters allowed in infix operator definitions.
\sa #ValidNameChars, #ValidOprtChars
*/
const char_type* QmuParserBase::ValidInfixOprtChars() const
const QString &QmuParserBase::ValidInfixOprtChars() const
{
assert(m_sInfixOprtChars.size());
#if defined(_UNICODE)
return m_sInfixOprtChars.toStdWString().c_str();
#else
return m_sInfixOprtChars.toStdString().c_str();
#endif
return m_sInfixOprtChars;
}
//---------------------------------------------------------------------------
/** \brief Add a user defined operator.
\post Will reset the Parser to string parsing mode.
*/
void QmuParserBase::DefinePostfixOprt(const string_type &a_sName,
void QmuParserBase::DefinePostfixOprt(const QString &a_sName,
fun_type1 a_pFun,
bool a_bAllowOpt)
{
@ -536,7 +529,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
\param [in] a_bAllowOpt True if operator is volatile (default=false)
\sa EPrec
*/
void QmuParserBase::DefineInfixOprt(const string_type &a_sName,
void QmuParserBase::DefineInfixOprt(const QString &a_sName,
fun_type1 a_pFun,
int a_iPrec,
bool a_bAllowOpt)
@ -558,7 +551,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
Adds a new Binary operator the the parser instance.
*/
void QmuParserBase::DefineOprt( const string_type &a_sName,
void QmuParserBase::DefineOprt( const QString &a_sName,
fun_type2 a_pFun,
unsigned a_iPrec,
EOprtAssociativity a_eAssociativity,
@ -566,8 +559,12 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
{
// Check for conflicts with built in operator names
for (int i=0; m_bBuiltInOp && i<cmENDIF; ++i)
if (a_sName == string_type(c_DefaultOprt[i]))
{
if (a_sName == c_DefaultOprt.at(i))
{
Error(ecBUILTIN_OVERLOAD, -1, a_sName);
}
}
AddCallback(a_sName,
QmuParserCallback(a_pFun, a_bAllowOpt, a_iPrec, a_eAssociativity),
@ -575,24 +572,26 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
ValidOprtChars() );
}
//---------------------------------------------------------------------------
/** \brief Define a new string constant.
\param [in] a_strName The name of the constant.
\param [in] a_strVal the value of the constant.
*/
void QmuParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal)
{
//---------------------------------------------------------------------------
/** \brief Define a new string constant.
\param [in] a_strName The name of the constant.
\param [in] a_strVal the value of the constant.
*/
void QmuParserBase::DefineStrConst(const QString &a_strName, const QString &a_strVal)
{
// Test if a constant with that names already exists
if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())
Error(ecNAME_CONFLICT);
{
Error(ecNAME_CONFLICT);
}
CheckName(a_strName, ValidNameChars());
m_vStringVarBuf.push_back(a_strVal); // Store variable string in internal buffer
m_StrVarDef[a_strName] = m_vStringBuf.size(); // bind buffer index to variable name
ReInit();
}
}
//---------------------------------------------------------------------------
/** \brief Add a user defined variable.
@ -601,14 +600,18 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
\post Will reset the Parser to string parsing mode.
\throw ParserException in case the name contains invalid signs or a_pVar is NULL.
*/
void QmuParserBase::DefineVar(const string_type &a_sName, qreal *a_pVar)
void QmuParserBase::DefineVar(const QString &a_sName, qreal *a_pVar)
{
if (a_pVar==0)
{
Error(ecINVALID_VAR_PTR);
}
// Test if a constant with that names already exists
if (m_ConstDef.find(a_sName)!=m_ConstDef.end())
{
Error(ecNAME_CONFLICT);
}
CheckName(a_sName, ValidNameChars());
m_VarDef[a_sName] = a_pVar;
@ -622,7 +625,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
\post Will reset the Parser to string parsing mode.
\throw ParserException in case the name contains invalid signs.
*/
void QmuParserBase::DefineConst(const string_type &a_sName, qreal a_fVal)
void QmuParserBase::DefineConst(const QString &a_sName, qreal a_fVal)
{
CheckName(a_sName, ValidNameChars());
m_ConstDef[a_sName] = a_fVal;
@ -748,7 +751,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
//---------------------------------------------------------------------------
/** \brief Retrieve the formula. */
const string_type& QmuParserBase::GetExpr() const
const QString& QmuParserBase::GetExpr() const
{
return m_pTokenReader->GetExpr();
}
@ -1129,9 +1132,9 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
switch(pTok->Fun.argc) // switch according to argument count
{
case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str()); continue;
case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx]); continue;
case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf[iIdxStack].c_str(), Stack[sidx], Stack[sidx+1]); continue;
case 0: Stack[sidx] = (*(strfun_type1)pTok->Fun.ptr)(m_vStringBuf.at(iIdxStack)); continue;
case 1: Stack[sidx] = (*(strfun_type2)pTok->Fun.ptr)(m_vStringBuf.at(iIdxStack), Stack[sidx]); continue;
case 2: Stack[sidx] = (*(strfun_type3)pTok->Fun.ptr)(m_vStringBuf.at(iIdxStack), Stack[sidx], Stack[sidx+1]); continue;
}
continue;
@ -1448,7 +1451,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
\param a_strTok [in] The token string representation associated with the error.
\throw ParserException always throws thats the only purpose of this function.
*/
void QmuParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const
void QmuParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const QString &a_sTok) const
{
throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetExpr(), a_iPos);
}
@ -1471,7 +1474,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
Removes a variable if it exists. If the Variable does not exist nothing will be done.
*/
void QmuParserBase::RemoveVar(const string_type &a_strVarName)
void QmuParserBase::RemoveVar(const QString &a_strVarName)
{
varmap_type::iterator item = m_VarDef.find(a_strVarName);
if (item!=m_VarDef.end())
@ -1592,7 +1595,7 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
//------------------------------------------------------------------------------
/** \brief Get the argument separator character.
*/
char_type QmuParserBase::GetArgSep() const
QChar QmuParserBase::GetArgSep() const
{
return m_pTokenReader->GetArgSep();
}
@ -1617,22 +1620,22 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
QStack<token_type> stOprt(a_stOprt),
stVal(a_stVal);
qmu::console() << "\nValue stack:\n";
qDebug() << "\nValue stack:\n";
while ( !stVal.empty() )
{
token_type val = stVal.pop();
if (val.GetType()==tpSTR)
qmu::console() << " \"" << val.GetAsString() << "\" ";
qDebug() << " \"" << val.GetAsString() << "\" ";
else
qmu::console() << " " << val.GetVal() << " ";
qDebug() << " " << val.GetVal() << " ";
}
qmu::console() << "\nOperator stack:\n";
qDebug() << "\nOperator stack:\n";
while ( !stOprt.empty() )
{
if (stOprt.top().GetCode()<=cmASSIGN)
{
qmu::console() << "OPRT_INTRNL \""
qDebug() << "OPRT_INTRNL \""
<< QmuParserBase::c_DefaultOprt[stOprt.top().GetCode()]
<< "\" \n";
}
@ -1640,35 +1643,35 @@ void QmuParserBase::SetExpr(const string_type &a_sExpr)
{
switch(stOprt.top().GetCode())
{
case cmVAR: qmu::console() << "VAR\n"; break;
case cmVAL: qmu::console() << "VAL\n"; break;
case cmFUNC: qmu::console() << "FUNC \""
case cmVAR: qDebug() << "VAR\n"; break;
case cmVAL: qDebug() << "VAL\n"; break;
case cmFUNC: qDebug() << "FUNC \""
<< stOprt.top().GetAsString()
<< "\"\n"; break;
case cmFUNC_BULK: qmu::console() << "FUNC_BULK \""
case cmFUNC_BULK: qDebug() << "FUNC_BULK \""
<< stOprt.top().GetAsString()
<< "\"\n"; break;
case cmOPRT_INFIX: qmu::console() << "OPRT_INFIX \""
case cmOPRT_INFIX: qDebug() << "OPRT_INFIX \""
<< stOprt.top().GetAsString()
<< "\"\n"; break;
case cmOPRT_BIN: qmu::console() << "OPRT_BIN \""
case cmOPRT_BIN: qDebug() << "OPRT_BIN \""
<< stOprt.top().GetAsString()
<< "\"\n"; break;
case cmFUNC_STR: qmu::console() << "FUNC_STR\n"; break;
case cmEND: qmu::console() << "END\n"; break;
case cmUNKNOWN: qmu::console() << "UNKNOWN\n"; break;
case cmBO: qmu::console() << "BRACKET \"(\"\n"; break;
case cmBC: qmu::console() << "BRACKET \")\"\n"; break;
case cmIF: qmu::console() << "IF\n"; break;
case cmELSE: qmu::console() << "ELSE\n"; break;
case cmENDIF: qmu::console() << "ENDIF\n"; break;
default: qmu::console() << stOprt.top().GetCode() << " "; break;
case cmFUNC_STR: qDebug() << "FUNC_STR\n"; break;
case cmEND: qDebug() << "END\n"; break;
case cmUNKNOWN: qDebug() << "UNKNOWN\n"; break;
case cmBO: qDebug() << "BRACKET \"(\"\n"; break;
case cmBC: qDebug() << "BRACKET \")\"\n"; break;
case cmIF: qDebug() << "IF\n"; break;
case cmELSE: qDebug() << "ELSE\n"; break;
case cmENDIF: qDebug() << "ENDIF\n"; break;
default: qDebug() << stOprt.top().GetCode() << " "; break;
}
}
stOprt.pop();
}
qmu::console() << dec << endl;
qDebug() << dec;
}
//------------------------------------------------------------------------------

View file

@ -32,6 +32,7 @@
#include <locale>
#include <QStack>
#include <QString>
#include <QStringList>
//--- Parser includes --------------------------------------------------------------------------
#include "qmuparserdef.h"
@ -75,13 +76,13 @@ private:
typedef QVector<qreal> valbuf_type;
/** \brief Type for a vector of strings. */
typedef QVector<string_type> stringbuf_type;
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, string_type> token_type;
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;
@ -108,7 +109,7 @@ private:
int GetNumResults() const;
void SetExpr(const string_type &a_sExpr);
void SetExpr(const QString &a_sExpr);
void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
void SetDecSep(char_type cDecSep);
@ -128,21 +129,21 @@ private:
\param a_bAllowOpt A flag indicating this function may be optimized
*/
template<typename T>
void DefineFun(const string_type &a_strName, T a_pFun, bool a_bAllowOpt = true)
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 string_type &a_strName,
fun_type2 a_pFun,
unsigned a_iPri=0,
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 string_type &a_sName, qreal a_fVal);
void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);
void DefineVar(const string_type &a_sName, qreal *a_fVar);
void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);
void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);
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);
// Clear user defined variables, constants or functions
void ClearVar();
@ -152,29 +153,29 @@ private:
void ClearPostfixOprt();
void ClearOprt();
void RemoveVar(const string_type &a_strVarName);
void RemoveVar(const QString &a_strVarName);
const varmap_type& GetUsedVar() const;
const varmap_type& GetVar() const;
const valmap_type& GetConst() const;
const string_type& GetExpr() const;
const QString &GetExpr() const;
const funmap_type& GetFunDef() const;
string_type GetVersion(EParserVersionInfo eInfo = pviFULL) const;
const char_type ** GetOprtDef() const;
const QStringList &GetOprtDef() const;
void DefineNameChars(const QString &a_szCharset);
void DefineOprtChars(const QString &a_szCharset);
void DefineInfixOprtChars(const QString &a_szCharset);
const char_type* ValidNameChars() const;
const char_type* ValidOprtChars() const;
const char_type* ValidInfixOprtChars() const;
const QString& ValidNameChars() const;
const QString &ValidOprtChars() const;
const QString &ValidInfixOprtChars() const;
void SetArgSep(char_type cArgSep);
char_type GetArgSep() const;
QChar GetArgSep() const;
void Error(EErrorCodes a_iErrc,
int a_iPos = (int)qmu::string_type::npos,
const string_type &a_strTok = string_type() ) const;
void Error(EErrorCodes a_iErrc,
int a_iPos = -1,
const QString &a_strTok = QString() ) const;
protected:
@ -185,9 +186,9 @@ private:
virtual void InitConst() = 0;
virtual void InitOprt() = 0;
virtual void OnDetectVar(string_type *pExpr, int &nStart, int &nEnd);
virtual void OnDetectVar(QString *pExpr, int &nStart, int &nEnd);
static const char_type *c_DefaultOprt[];
static const QStringList c_DefaultOprt;
static std::locale s_locale; ///< The locale used by the parser
static bool g_DbgDumpCmdCode;
static bool g_DbgDumpStack;
@ -235,10 +236,10 @@ private:
void InitTokenReader();
void ReInit() const;
void AddCallback( const string_type &a_strName,
void AddCallback(const QString &a_strName,
const QmuParserCallback &a_Callback,
funmap_type &a_Storage,
const char_type *a_szCharSet );
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;
@ -257,10 +258,10 @@ private:
qreal ParseCmdCode() const;
qreal ParseCmdCodeBulk(int nOffset, int nThreadID) const;
void CheckName(const string_type &a_strName, const string_type &a_CharSet) const;
void CheckOprt(const string_type &a_sName,
void CheckName(const QString &a_strName, const QString &a_CharSet) const;
void CheckOprt(const QString &a_sName,
const QmuParserCallback &a_Callback,
const string_type &a_szCharSet) const;
const QString &a_szCharSet) const;
void StackDump(const QStack<token_type > &a_stVal,
const QStack<token_type > &a_stOprt) const;

View file

@ -26,6 +26,7 @@
#include <string>
#include <stack>
#include <iostream>
#include <QString>
#include "qmuparserdef.h"
#include "qmuparsererror.h"
@ -492,89 +493,76 @@ namespace qmu
{
if (!m_vRPN.size())
{
qmu::console() << "No bytecode available\n";
qDebug() << "No bytecode available\n";
return;
}
qmu::console() << "Number of RPN tokens:" << (int)m_vRPN.size() << "\n";
qDebug() << "Number of RPN tokens:" << m_vRPN.size() << "\n";
for (std::size_t i=0; i<m_vRPN.size() && m_vRPN[i].Cmd!=cmEND; ++i)
{
qmu::console() << std::dec << i << " : \t";
qDebug() << i << " : \t";
switch (m_vRPN[i].Cmd)
{
case cmVAL: qmu::console() << "VAL \t";
qmu::console() << "[" << m_vRPN[i].Val.data2 << "]\n";
case cmVAL: qDebug() << "VAL \t" << "[" << m_vRPN[i].Val.data2 << "]\n";
break;
case cmVAR: qmu::console() << "VAR \t";
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
case cmVAR: qDebug() << "VAR \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break;
case cmVARPOW2: qmu::console() << "VARPOW2 \t";
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
case cmVARPOW2: qDebug() << "VARPOW2 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break;
case cmVARPOW3: qmu::console() << "VARPOW3 \t";
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
case cmVARPOW3: qDebug() << "VARPOW3 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break;
case cmVARPOW4: qmu::console() << "VARPOW4 \t";
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]\n";
case cmVARPOW4: qDebug() << "VARPOW4 \t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Val.ptr, 'f', 16) << "]\n";
break;
case cmVARMUL: qmu::console() << "VARMUL \t";
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Val.ptr << "]";
qmu::console() << " * [" << m_vRPN[i].Val.data << "]";
qmu::console() << " + [" << 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: qmu::console() << "CALL\t";
qmu::console() << "[ARG:" << std::dec << m_vRPN[i].Fun.argc << "]";
qmu::console() << "[ADDR: 0x" << std::hex << m_vRPN[i].Fun.ptr << "]";
qmu::console() << "\n";
case cmFUNC: qDebug() << "CALL\t" << "[ARG:" << m_vRPN[i].Fun.argc << "]" << "[ADDR: 0x"
<< m_vRPN[i].Fun.ptr << "]" << "\n";
break;
case cmFUNC_STR:
qmu::console() << "CALL STRFUNC\t";
qmu::console() << "[ARG:" << std::dec << m_vRPN[i].Fun.argc << "]";
qmu::console() << "[IDX:" << std::dec << m_vRPN[i].Fun.idx << "]";
qmu::console() << "[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: qmu::console() << "LT\n"; break;
case cmGT: qmu::console() << "GT\n"; break;
case cmLE: qmu::console() << "LE\n"; break;
case cmGE: qmu::console() << "GE\n"; break;
case cmEQ: qmu::console() << "EQ\n"; break;
case cmNEQ: qmu::console() << "NEQ\n"; break;
case cmADD: qmu::console() << "ADD\n"; break;
case cmLAND: qmu::console() << "&&\n"; break;
case cmLOR: qmu::console() << "||\n"; break;
case cmSUB: qmu::console() << "SUB\n"; break;
case cmMUL: qmu::console() << "MUL\n"; break;
case cmDIV: qmu::console() << "DIV\n"; break;
case cmPOW: qmu::console() << "POW\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: qmu::console() << "IF\t";
qmu::console() << "[OFFSET:" << std::dec << m_vRPN[i].Oprt.offset << "]\n";
case cmIF: qDebug() << "IF\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
break;
case cmELSE: qmu::console() << "ELSE\t";
qmu::console() << "[OFFSET:" << std::dec << m_vRPN[i].Oprt.offset << "]\n";
case cmELSE: qDebug() << "ELSE\t" << "[OFFSET:" << m_vRPN[i].Oprt.offset << "]\n";
break;
case cmENDIF: qmu::console() << "ENDIF\n"; break;
case cmENDIF: qDebug() << "ENDIF\n"; break;
case cmASSIGN:
qmu::console() << "ASSIGN\t";
qmu::console() << "[ADDR: 0x" << m_vRPN[i].Oprt.ptr << "]\n";
qDebug() << "ASSIGN\t" << "[ADDR: 0x" << QString::number(*m_vRPN[i].Oprt.ptr, 'f', 16) << "]\n";
break;
default: qmu::console() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
default: qDebug() << "(unknown code: " << m_vRPN[i].Cmd << ")\n";
break;
} // switch cmdCode
} // while bytecode
qmu::console() << "END" << std::endl;
qDebug() << "END";
}
} // namespace qmu

View file

@ -107,7 +107,7 @@ private:
//------------------------------------------------------------------------------
/** \brief Container for Callback objects. */
typedef std::map<string_type, QmuParserCallback> funmap_type;
typedef std::map<QString, QmuParserCallback> funmap_type;
} // namespace qmu

View file

@ -27,6 +27,8 @@
#include <string>
#include <sstream>
#include <map>
#include <QMap>
#include <QString>
#include "qmuparserfixes.h"
@ -49,54 +51,15 @@
//#define MUP_USE_OPENMP
#if defined(_UNICODE)
/** \brief Definition of the basic parser string type. */
#define MUP_STRING_TYPE std::wstring
/** \brief Definition of the basic parser string type. */
#define QMUP_STRING_TYPE std::wstring
#else
/** \brief Definition of the basic parser string type. */
#define MUP_STRING_TYPE std::string
/** \brief Definition of the basic parser string type. */
#define QMUP_STRING_TYPE std::string
#endif
namespace qmu
{
#if defined(_UNICODE)
//------------------------------------------------------------------------------
/** \brief Encapsulate wcout. */
inline std::wostream& console()
{
return std::wcout;
}
/** \brief Encapsulate cin. */
inline std::wistream& console_in()
{
return std::wcin;
}
#else
/** \brief Encapsulate cout.
Used for supporting UNICODE more easily.
*/
inline std::ostream& console()
{
return std::cout;
}
/** \brief Encapsulate cin.
Used for supporting UNICODE more easily.
*/
inline std::istream& console_in()
{
return std::cin;
}
#endif
//------------------------------------------------------------------------------
/** \brief Bytecode values.
@ -200,7 +163,7 @@ namespace qmu
Depends on wether UNICODE is used or not.
*/
typedef MUP_STRING_TYPE string_type;
typedef QMUP_STRING_TYPE string_type;
/** \brief The character type used by the parser.
@ -216,13 +179,13 @@ namespace qmu
// Data container types
/** \brief Type used for storing variables. */
typedef std::map<string_type, qreal*> varmap_type;
typedef std::map<QString, qreal*> varmap_type;
/** \brief Type used for storing constants. */
typedef std::map<string_type, qreal> valmap_type;
typedef std::map<QString, qreal> valmap_type;
/** \brief Type for assigning a string name to an index in the internal string table. */
typedef std::map<string_type, std::size_t> strmap_type;
typedef std::map<QString, int> strmap_type;
// Parser callbacks
@ -299,19 +262,19 @@ namespace qmu
typedef qreal (*multfun_type)(const qreal*, int);
/** \brief Callback type used for functions taking a string as an argument. */
typedef qreal (*strfun_type1)(const char_type*);
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 char_type*, qreal);
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 char_type*, qreal, qreal);
typedef qreal (*strfun_type3)(const QString &, qreal, qreal);
/** \brief Callback used for functions that identify values in a string. */
typedef int (*identfun_type)(const char_type *sExpr, int *nPos, qreal *fVal);
typedef int (*identfun_type)(const QString &sExpr, int *nPos, qreal *fVal);
/** \brief Callback used for variable creation factory functions. */
typedef qreal* (*facfun_type)(const char_type*, void*);
typedef qreal* (*facfun_type)(const QString &, void*);
} // end of namespace
#endif

View file

@ -22,6 +22,8 @@
#include "qmuparsererror.h"
#include <QTextStream>
namespace qmu
{
@ -34,9 +36,9 @@ namespace qmu
}
//------------------------------------------------------------------------------
string_type QmuParserErrorMsg::operator[](unsigned a_iIdx) const
QString QmuParserErrorMsg::operator[](unsigned a_iIdx) const
{
return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();
return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : QString();
}
//---------------------------------------------------------------------------
@ -137,15 +139,13 @@ namespace qmu
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
m_strMsg = m_ErrMsg[m_iErrc];
stringstream_type stream;
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
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 string_type &sMsg)
QmuParserError::QmuParserError(const QString &sMsg)
:m_ErrMsg(QmuParserErrorMsg::Instance())
{
Reset();
@ -159,9 +159,9 @@ namespace qmu
\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,
const string_type &sTok,
const string_type &sExpr,
QmuParserError::QmuParserError(EErrorCodes iErrc,
const QString &sTok,
const QString &sExpr,
int iPos )
:m_strMsg()
,m_strFormula(sExpr)
@ -171,9 +171,7 @@ namespace qmu
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
m_strMsg = m_ErrMsg[m_iErrc];
stringstream_type stream;
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
@ -183,7 +181,7 @@ namespace qmu
\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 string_type &sTok)
QmuParserError::QmuParserError(EErrorCodes iErrc, int iPos, const QString &sTok)
:m_strMsg()
,m_strFormula()
,m_strTok(sTok)
@ -192,9 +190,7 @@ namespace qmu
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
m_strMsg = m_ErrMsg[m_iErrc];
stringstream_type stream;
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
@ -204,7 +200,7 @@ namespace qmu
\param [in] iPos the position related to the error.
\param [in] sTok The token string related to this error.
*/
QmuParserError::QmuParserError(const char_type *szMsg, int iPos, const string_type &sTok)
QmuParserError::QmuParserError(const QString &szMsg, int iPos, const QString &sTok)
:m_strMsg(szMsg)
,m_strFormula()
,m_strTok(sTok)
@ -212,9 +208,7 @@ namespace qmu
,m_iErrc(ecGENERIC)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
stringstream_type stream;
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
@ -249,32 +243,30 @@ namespace qmu
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( string_type &strSource,
const string_type &strFind,
const string_type &strReplaceWith)
{
string_type strResult;
string_type::size_type iPos(0), iNext(0);
//------------------------------------------------------------------------------
/** \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);
for(;;)
{
iNext = strSource.find(strFind, iPos);
strResult.append(strSource, iPos, iNext-iPos);
iNext = strSource.indexOf(strFind, iPos);
strResult.append(strSource.mid(iPos, iNext-iPos));
if( iNext==string_type::npos )
break;
if( iNext==-1 )
break;
strResult.append(strReplaceWith);
iPos = iNext + strFind.length();
}
strResult.append(strReplaceWith);
iPos = iNext + strFind.length();
}
strSource.swap(strResult);
}
}
//------------------------------------------------------------------------------
/** \brief Reset the erro object. */
@ -289,21 +281,21 @@ namespace qmu
//------------------------------------------------------------------------------
/** \brief Set the expression related to this error. */
void QmuParserError::SetFormula(const string_type &a_strFormula)
void QmuParserError::SetFormula(const QString &a_strFormula)
{
m_strFormula = a_strFormula;
}
//------------------------------------------------------------------------------
/** \brief gets the expression related tp this error.*/
const string_type& QmuParserError::GetExpr() const
const QString& QmuParserError::GetExpr() const
{
return m_strFormula;
}
//------------------------------------------------------------------------------
/** \brief Returns the message string for this error. */
const string_type& QmuParserError::GetMsg() const
const QString& QmuParserError::GetMsg() const
{
return m_strMsg;
}
@ -320,7 +312,7 @@ namespace qmu
//------------------------------------------------------------------------------
/** \brief Return string related with this token (if available). */
const string_type& QmuParserError::GetToken() const
const QString& QmuParserError::GetToken() const
{
return m_strTok;
}

View file

@ -106,10 +106,10 @@ public:
~QmuParserErrorMsg();
static const QmuParserErrorMsg& Instance();
string_type operator[](unsigned a_iIdx) const;
QString operator[](unsigned a_iIdx) const;
private:
QVector<string_type> m_vErrMsg; ///< A vector with the predefined error messages
QVector<QString> m_vErrMsg; ///< A vector with the predefined error messages
static const self_type m_Instance; ///< The instance pointer
};
@ -124,41 +124,34 @@ class QmuParserError
private:
/** \brief Replace all ocuurences of a substring with another string. */
void ReplaceSubString( string_type &strSource,
const string_type &strFind,
const string_type &strReplaceWith);
void ReplaceSubString(QString &strSource,
const QString &strFind,
const QString &strReplaceWith);
void Reset();
public:
QmuParserError();
explicit QmuParserError(EErrorCodes a_iErrc);
explicit QmuParserError(const string_type &sMsg);
QmuParserError( EErrorCodes a_iErrc,
const string_type &sTok,
const string_type &sFormula = string_type(),
int a_iPos = -1);
QmuParserError( EErrorCodes a_iErrc,
int a_iPos,
const string_type &sTok);
QmuParserError( const char_type *a_szMsg,
int a_iPos = -1,
const string_type &sTok = string_type());
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 string_type &a_strFormula);
const string_type& GetExpr() const;
const string_type& GetMsg() const;
void SetFormula(const QString &a_strFormula);
const QString &GetExpr() const;
const QString &GetMsg() const;
std::size_t GetPos() const;
const string_type& GetToken() const;
const QString &GetToken() const;
EErrorCodes GetCode() const;
private:
string_type m_strMsg; ///< The message string
string_type m_strFormula; ///< Formula string
string_type m_strTok; ///< Token related with the error
QString m_strMsg; ///< The message string
QString m_strFormula; ///< Formula string
QString m_strTok; ///< Token related with the error
int m_iPos; ///< Formula position related to the error
EErrorCodes m_iErrc; ///< Error code
const QmuParserErrorMsg &m_ErrMsg;

View file

@ -22,6 +22,7 @@
#include "qmuparsertest.h"
#include <QtMath>
#include <QString>
#include <cstdio>
#include <iostream>
@ -60,32 +61,37 @@ namespace qmu
}
//---------------------------------------------------------------------------------------------
int QmuParserTester::IsHexVal(const char_type *a_szExpr, int *a_iPos, qreal *a_fVal)
int QmuParserTester::IsHexVal(const QString &a_szExpr, int *a_iPos, qreal *a_fVal)
{
if (a_szExpr[1]==0 || (a_szExpr[0]!='0' || a_szExpr[1]!='x') )
return 0;
unsigned iVal(0);
bool ok = false;
iVal = a_szExpr.toUInt(&ok, 16);
// New code based on streams for UNICODE compliance:
stringstream_type::pos_type nPos(0);
stringstream_type ss(a_szExpr + 2);
ss >> std::hex >> iVal;
nPos = ss.tellg();
if(ok)
{
int nPos = a_szExpr.indexOf(QString().setNum(iVal, 16));
if(nPos == 0)
return 1;
if (nPos==(stringstream_type::pos_type)0)
*a_iPos += (int)(2 + nPos);
*a_fVal = (qreal)iVal;
return 1;
}
else
{
return 0;
}
*a_iPos += (int)(2 + nPos);
*a_fVal = (qreal)iVal;
return 1;
}
//---------------------------------------------------------------------------------------------
int QmuParserTester::TestInterface()
{
int iStat = 0;
qmu::console() << "testing member functions...";
qDebug() << "testing member functions...";
// Test RemoveVar
qreal afVal[3] = {1,2,3};
@ -116,9 +122,9 @@ namespace qmu
}
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -127,7 +133,7 @@ namespace qmu
int QmuParserTester::TestStrArg()
{
int iStat = 0;
qmu::console() << "testing string arguments...";
qDebug() << "testing string arguments...";
iStat += EqnTest("valueof(\"\")", 123, true); // empty string arguments caused a crash
iStat += EqnTest("valueof(\"aaa\")+valueof(\"bbb\") ", 246, true);
@ -141,9 +147,9 @@ namespace qmu
iStat += EqnTest("strfun3(\"99\",1,2)", 102, true);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -152,7 +158,7 @@ namespace qmu
int QmuParserTester::TestBinOprt()
{
int iStat = 0;
qmu::console() << "testing binary operators...";
qDebug() << "testing binary operators...";
// built in operators
// xor operator
@ -212,9 +218,9 @@ namespace qmu
iStat += EqnTest("3+4*2/(1-5)^2^3", 3.0001220703125, true);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -226,7 +232,7 @@ namespace qmu
int iStat= 0,
iErr = 0;
qmu::console() << "testing name restriction enforcement...";
qDebug() << "testing name restriction enforcement...";
QmuParser p;
@ -321,9 +327,9 @@ namespace qmu
#undef PARSER_THROWCHECK
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -332,7 +338,7 @@ namespace qmu
int QmuParserTester::TestSyntax()
{
int iStat = 0;
qmu::console() << "testing syntax engine...";
qDebug() << "testing syntax engine...";
iStat += ThrowTest("1,", ecUNEXPECTED_EOF); // incomplete hex definition
iStat += ThrowTest("a,", ecUNEXPECTED_EOF); // incomplete hex definition
@ -370,9 +376,9 @@ namespace qmu
iStat += EqnTest("sin()", 0, false); // unexpected closing bracket
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -381,7 +387,7 @@ namespace qmu
int QmuParserTester::TestVarConst()
{
int iStat = 0;
qmu::console() << "testing variable/constant detection...";
qDebug() << "testing variable/constant detection...";
// Test if the result changes when a variable changes
iStat += EqnTestWithVarChange( "a", 1, 1, 2, 2 );
@ -479,9 +485,9 @@ namespace qmu
}
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -490,7 +496,7 @@ namespace qmu
int QmuParserTester::TestMultiArg()
{
int iStat = 0;
qmu::console() << "testing multiarg functions...";
qDebug() << "testing multiarg functions...";
// Compound expressions
iStat += EqnTest( "1,2,3", 3, true);
@ -573,9 +579,9 @@ namespace qmu
iStat += EqnTest( "sum(,1,2)", 0, false);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -585,7 +591,7 @@ namespace qmu
int QmuParserTester::TestInfixOprt()
{
int iStat(0);
qmu::console() << "testing infix operators...";
qDebug() << "testing infix operators...";
iStat += EqnTest( "-1", -1, true);
iStat += EqnTest( "-(-1)", 1, true);
@ -638,9 +644,9 @@ namespace qmu
iStat += EqnTest( "~~ 123", 123+2, true);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -650,7 +656,7 @@ namespace qmu
int QmuParserTester::TestPostFix()
{
int iStat = 0;
qmu::console() << "testing postfix operators...";
qDebug() << "testing postfix operators...";
// application
iStat += EqnTest( "3{m}+5", 5.003, true);
@ -690,9 +696,9 @@ namespace qmu
iStat += ThrowTest( "multi*1.0", ecUNASSIGNABLE_TOKEN);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -701,7 +707,7 @@ namespace qmu
int QmuParserTester::TestExpression()
{
int iStat = 0;
qmu::console() << "testing expression samples...";
qDebug() << "testing expression samples...";
qreal b = 2;
@ -770,9 +776,9 @@ namespace qmu
iStat += EqnTest( "1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12", -7995810.09926, true);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -783,7 +789,7 @@ namespace qmu
int QmuParserTester::TestIfThenElse()
{
int iStat = 0;
qmu::console() << "testing if-then-else operator...";
qDebug() << "testing if-then-else operator...";
// Test error detection
iStat += ThrowTest(":3", ecUNEXPECTED_CONDITIONAL);
@ -878,9 +884,9 @@ namespace qmu
iStat += EqnTest("a=0?5:b=1?3:4, b", 3, true);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed";
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors";
return iStat;
}
@ -889,7 +895,7 @@ namespace qmu
int QmuParserTester::TestException()
{
int iStat = 0;
qmu::console() << "testing error codes...";
qDebug() << "testing error codes...";
iStat += ThrowTest("3+", ecUNEXPECTED_EOF);
iStat += ThrowTest("3+)", ecUNEXPECTED_PARENS);
@ -972,9 +978,9 @@ namespace qmu
iStat += ThrowTest( "a=\"tttt\"", ecOPRT_TYPE_CONFLICT);
if (iStat==0)
qmu::console() << "passed" << endl;
qDebug() << "passed" ;
else
qmu::console() << "\n failed with " << iStat << " errors" << endl;
qDebug() << "\n failed with " << iStat << " errors" ;
return iStat;
}
@ -997,37 +1003,37 @@ namespace qmu
}
catch(QmuParser::exception_type &e)
{
qmu::console() << "\n" << e.GetMsg() << endl;
qmu::console() << e.GetToken() << endl;
qDebug() << "\n" << e.GetMsg() ;
qDebug() << e.GetToken() ;
Abort();
}
catch(std::exception &e)
{
qmu::console() << e.what() << endl;
qDebug() << e.what() ;
Abort();
}
catch(...)
{
qmu::console() << "Internal error";
qDebug() << "Internal error";
Abort();
}
if (iStat==0)
{
qmu::console() << "Test passed (" << QmuParserTester::c_iCount << " expressions)" << endl;
qDebug() << "Test passed (" << QmuParserTester::c_iCount << " expressions)" ;
}
else
{
qmu::console() << "Test failed with " << iStat
qDebug() << "Test failed with " << iStat
<< " errors (" << QmuParserTester::c_iCount
<< " expressions)" << endl;
<< " expressions)" ;
}
QmuParserTester::c_iCount = 0;
}
//---------------------------------------------------------------------------
int QmuParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)
int QmuParserTester::ThrowTest(const QString &a_str, int a_iErrc, bool a_bFail)
{
QmuParserTester::c_iCount++;
@ -1054,7 +1060,7 @@ namespace qmu
// output the formula in case of an failed test
if (a_bFail==false || (a_bFail==true && a_iErrc!=e.GetCode()) )
{
qmu::console() << "\n "
qDebug() << "\n "
<< "Expression: " << a_str
<< " Code:" << e.GetCode() << "(" << e.GetMsg() << ")"
<< " Expected:" << a_iErrc;
@ -1067,7 +1073,7 @@ namespace qmu
bool bRet((a_bFail==false) ? 0 : 1);
if (bRet==1)
{
qmu::console() << "\n "
qDebug() << "\n "
<< "Expression: " << a_str
<< " did evaluate; Expected error:" << a_iErrc;
}
@ -1080,7 +1086,7 @@ namespace qmu
\return 1 in case of a failure, 0 otherwise.
*/
int QmuParserTester::EqnTestWithVarChange(const string_type &a_str,
int QmuParserTester::EqnTestWithVarChange(const QString &a_str,
double a_fVar1,
double a_fRes1,
double a_fVar2,
@ -1112,17 +1118,17 @@ namespace qmu
}
catch(QmuParser::exception_type &e)
{
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.GetMsg() << ")";
qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")";
return 1;
}
catch(std::exception &e)
{
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.what() << ")";
qDebug() << "\n fail: " << a_str << " (" << e.what() << ")";
return 1; // always return a failure since this exception is not expected
}
catch(...)
{
qmu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
qDebug() << "\n fail: " << a_str << " (unexpected exception)";
return 1; // exceptions other than ParserException are not allowed
}
@ -1134,7 +1140,7 @@ namespace qmu
\return 1 in case of a failure, 0 otherwise.
*/
int QmuParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
int QmuParserTester::EqnTest(const QString &a_str, double a_fRes, bool a_fPass)
{
QmuParserTester::c_iCount++;
int iRet(0);
@ -1253,7 +1259,7 @@ namespace qmu
}
catch(std::exception &e)
{
qmu::console() << "\n " << e.what() << "\n";
qDebug() << "\n " << e.what() << "\n";
}
// limited floating point accuracy requires the following test
@ -1274,7 +1280,7 @@ namespace qmu
if (iRet==1)
{
qmu::console() << "\n fail: " << a_str.c_str()
qDebug() << "\n fail: " << a_str
<< " (incorrect result; expected: " << a_fRes
<< " ;calculated: " << fVal[0] << ","
<< fVal[1] << ","
@ -1288,20 +1294,20 @@ namespace qmu
if (a_fPass)
{
if (fVal[0]!=fVal[2] && fVal[0]!=-999 && fVal[1]!=-998)
qmu::console() << "\n fail: " << a_str.c_str() << " (copy construction)";
qDebug() << "\n fail: " << a_str << " (copy construction)";
else
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.GetMsg() << ")";
qDebug() << "\n fail: " << a_str << " (" << e.GetMsg() << ")";
return 1;
}
}
catch(std::exception &e)
{
qmu::console() << "\n fail: " << a_str.c_str() << " (" << e.what() << ")";
qDebug() << "\n fail: " << a_str << " (" << e.what() << ")";
return 1; // always return a failure since this exception is not expected
}
catch(...)
{
qmu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
qDebug() << "\n fail: " << a_str << " (unexpected exception)";
return 1; // exceptions other than ParserException are not allowed
}
@ -1312,7 +1318,7 @@ namespace qmu
/** \brief Internal error in test class Test is going to be aborted. */
void QmuParserTester::Abort() const
{
qmu::console() << "Test failed (internal error in test class)" << endl;
qDebug() << "Test failed (internal error in test class)" ;
while (!getchar());
exit(-1);
}

View file

@ -27,6 +27,7 @@
#include <cstdlib>
#include <numeric> // for accumulate
#include "qmuparser.h"
#include <QString>
/** \file
\brief This file contains the parser test class.
@ -48,14 +49,14 @@ namespace qmu
static int c_iCount;
// Multiarg callbacks
static qreal f1of1(qreal v) { return v;};
static qreal f1of1(qreal v) { return v;}
static qreal f1of2(qreal v, qreal ) {return v;};
static qreal f2of2(qreal , 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 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;}
@ -120,36 +121,32 @@ namespace qmu
return 10;
}
static qreal ValueOf(const char_type*)
static qreal ValueOf(const QString &)
{
return 123;
}
static qreal StrFun1(const char_type* v1)
static qreal StrFun1(const QString & v1)
{
int val(0);
stringstream_type(v1) >> val;
int val = v1.toInt();
return (qreal)val;
}
static qreal StrFun2(const char_type* v1, qreal v2)
static qreal StrFun2(const QString & v1, qreal v2)
{
int val(0);
stringstream_type(v1) >> val;
int val = v1.toInt();
return (qreal)(val + v2);
}
static qreal StrFun3(const char_type* v1, qreal v2, qreal v3)
static qreal StrFun3(const QString & v1, qreal v2, qreal v3)
{
int val(0);
stringstream_type(v1) >> val;
int val = v1.toInt();
return val + v2 + v3;
}
static qreal StrToFloat(const char_type* a_szMsg)
static qreal StrToFloat(const QString & a_szMsg)
{
qreal val(0);
stringstream_type(a_szMsg) >> val;
qreal val = a_szMsg.toDouble();
return val;
}
@ -159,7 +156,7 @@ namespace qmu
static qreal Milli(qreal a_fVal) { return a_fVal / (qreal)1e3; }
// Custom value recognition
static int IsHexVal(const char_type *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();
@ -187,13 +184,13 @@ namespace qmu
void AddTest(testfun_type a_pFun);
// Test Double Parser
int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);
int EqnTestWithVarChange(const string_type& a_str,
double a_fRes1,
double a_fVar1,
double a_fRes2,
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 string_type& a_str, int a_iErrc, bool a_bFail = true);
int ThrowTest(const QString &a_str, int a_iErrc, bool a_bFail = true);
};
} // namespace Test
} // namespace qmu

View file

@ -27,6 +27,8 @@
#include <stack>
#include <string>
#include <QStringList>
#include "qmuparsertokenreader.h"
#include "qmuparserbase.h"
@ -191,7 +193,7 @@ namespace qmu
\return #m_strFormula
\throw nothrow
*/
const string_type& QmuParserTokenReader::GetExpr() const
const QString& QmuParserTokenReader::GetExpr() const
{
return m_strFormula;
}
@ -209,7 +211,7 @@ namespace qmu
Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
\pre [assert] triggered if a_szFormula==0
*/
void QmuParserTokenReader::SetFormula(const string_type &a_strFormula)
void QmuParserTokenReader::SetFormula(const QString &a_strFormula)
{
m_strFormula = a_strFormula;
ReInit();
@ -253,13 +255,19 @@ namespace qmu
{
assert(m_pParser);
std::stack<int> FunArgs;
const char_type *szFormula = m_strFormula.c_str();
//std::stack<int> FunArgs;
#if defined(_UNICODE)
const char_type *szFormula = m_strFormula.toStdWString().c_str();
#else
const char_type *szFormula = m_strFormula.toStdString().c_str();
#endif
token_type tok;
// Ignore all non printable characters when reading the expression
while (szFormula[m_iPos]>0 && szFormula[m_iPos]<=0x20)
{
++m_iPos;
}
if ( IsEOF(tok) ) return SaveBeforeReturn(tok); // Check for end of formula
if ( IsOprt(tok) ) return SaveBeforeReturn(tok); // Check for user defined binary operator
@ -280,19 +288,23 @@ namespace qmu
// (The GetUsedVar function must suppress the error for
// undefined variables in order to collect all variable
// names including the undefined ones.)
if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )
if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) )
{
return SaveBeforeReturn(tok);
}
// Check for unknown token
//
// !!! From this point on there is no exit without an exception possible...
//
string_type strTok;
QString strTok;
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
if (iEnd!=m_iPos)
{
Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
}
Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.mid(m_iPos));
return token_type(); // never reached
}
@ -309,59 +321,86 @@ namespace qmu
m_pConstDef = &a_pParent->m_ConstDef;
}
//---------------------------------------------------------------------------
/** \brief Extract all characters that belong to a certain charset.
//---------------------------------------------------------------------------
/** \brief Extract all characters that belong to a certain charset.
\param a_szCharSet [in] Const char array of the characters allowed in the token.
\param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.
\param a_iPos [in] Position in the string from where to start reading.
\return The Position of the first character not listed in a_szCharSet.
\throw nothrow
*/
int QmuParserTokenReader::ExtractToken(const char_type *a_szCharSet,
string_type &a_sTok,
int a_iPos) const
{
int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
\param a_szCharSet [in] Const char array of the characters allowed in the token.
\param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.
\param a_iPos [in] Position in the string from where to start reading.
\return The Position of the first character not listed in a_szCharSet.
\throw nothrow
*/
int QmuParserTokenReader::ExtractToken(const QString &a_szCharSet, QString &a_sTok, int a_iPos) const
{
#if defined(_UNICODE)
const std::wstring m_strFormulaStd = m_strFormula.toStdWString();
const std::wstring a_szCharSetstd = a_szCharSet.toStdWString();
#else
const std::string m_strFormulaStd = m_strFormula.toStdString();
const std::string a_szCharSetStd = a_szCharSet.toStdString();
#endif
int iEnd = (int)m_strFormulaStd.find_first_not_of(a_szCharSetStd, a_iPos);
if (iEnd==(int)string_type::npos)
iEnd = (int)m_strFormula.length();
// Assign token string if there was something found
if (a_iPos!=iEnd)
a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);
return iEnd;
}
//---------------------------------------------------------------------------
/** \brief Check Expression for the presence of a binary operator token.
Userdefined binary operator "++" gives inconsistent parsing result for
the equations "a++b" and "a ++ b" if alphabetic characters are allowed
in operator tokens. To avoid this this function checks specifically
for operator tokens.
*/
int QmuParserTokenReader::ExtractOperatorToken(string_type &a_sTok,
int a_iPos) const
{
int iEnd = (int)m_strFormula.find_first_not_of(m_pParser->ValidInfixOprtChars(), a_iPos);
if (iEnd==(int)string_type::npos)
iEnd = (int)m_strFormula.length();
{
iEnd = (int)m_strFormulaStd.length();
}
// Assign token string if there was something found
if (a_iPos!=iEnd)
{
a_sTok = string_type( m_strFormula.begin() + a_iPos, m_strFormula.begin() + iEnd);
return iEnd;
#if defined(_UNICODE)
a_sTok = QString().fromStdWString(std::wstring( m_strFormulaStd.begin()+a_iPos, m_strFormulaStd.begin()+iEnd));
#else
a_sTok = QString().fromStdString(std::string( m_strFormulaStd.begin()+a_iPos, m_strFormulaStd.begin()+iEnd));
#endif
}
return iEnd;
}
//---------------------------------------------------------------------------
/** \brief Check Expression for the presence of a binary operator token.
Userdefined binary operator "++" gives inconsistent parsing result for
the equations "a++b" and "a ++ b" if alphabetic characters are allowed
in operator tokens. To avoid this this function checks specifically
for operator tokens.
*/
int QmuParserTokenReader::ExtractOperatorToken(QString &a_sTok, int a_iPos) const
{
#if defined(_UNICODE)
const std::wstring m_strFormulaStd = m_strFormula.toStdWString();
const std::wstring oprtCharsStd = m_pParser->ValidInfixOprtChars().toStdWString();
#else
const std::string m_strFormulaStd = m_strFormula.toStdString();
const std::string oprtCharsStd = m_pParser->ValidInfixOprtChars().toStdString();
#endif
int iEnd = (int)m_strFormulaStd.find_first_not_of(oprtCharsStd, a_iPos);
if (iEnd==(int)string_type::npos)
{
iEnd = (int)m_strFormulaStd.length();
}
// Assign token string if there was something found
if (a_iPos!=iEnd)
{
#if defined(_UNICODE)
a_sTok = QString().fromStdWString(string_type(m_strFormulaStd.begin() + a_iPos,
m_strFormulaStd.begin() + iEnd));
#else
a_sTok = QString().fromStdString(string_type(m_strFormulaStd.begin() + a_iPos, m_strFormulaStd.begin() + iEnd));
#endif
return iEnd;
}
else
{
// There is still the chance of having to deal with an operator consisting exclusively
// of alphabetic characters.
return ExtractToken(QMUP_CHARS, a_sTok, a_iPos);
// There is still the chance of having to deal with an operator consisting exclusively
// of alphabetic characters.
return ExtractToken(QMUP_CHARS, a_sTok, a_iPos);
}
}
}
//---------------------------------------------------------------------------
/** \brief Check if a built in operator or other token can be found
@ -370,15 +409,14 @@ namespace qmu
*/
bool QmuParserTokenReader::IsBuiltIn(token_type &a_Tok)
{
const char_type **const pOprtDef = m_pParser->GetOprtDef(),
*const szFormula = m_strFormula.c_str();
const QStringList pOprtDef = m_pParser->GetOprtDef();
// Compare token with function and operator strings
// check string for operator/function
for (int i=0; pOprtDef[i]; i++)
for (int i=0; i < pOprtDef.size(); ++i)
{
std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
int len = pOprtDef.at(i).length();
if ( pOprtDef.at(i) == m_strFormula.mid(m_iPos, m_iPos + len) )
{
switch(i)
{
@ -404,7 +442,7 @@ namespace qmu
// The assignement operator need special treatment
if (i==cmASSIGN && m_iSynFlags & noASSIGN)
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef.at(i));
if (!m_pParser->HasBuiltInOprt()) continue;
if (m_iSynFlags & noOPT)
@ -415,7 +453,7 @@ namespace qmu
if ( IsInfixOpTok(a_Tok) )
return true;
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef.at(i));
}
m_iSynFlags = noBC | noOPT | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
@ -424,7 +462,7 @@ namespace qmu
case cmBO:
if (m_iSynFlags & noBO)
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef.at(i));
if (m_lastTok.GetCode()==cmFUNC)
m_iSynFlags = noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN | noIF | noELSE;
@ -436,24 +474,24 @@ namespace qmu
case cmBC:
if (m_iSynFlags & noBC)
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef.at(i));
m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
if (--m_iBrackets<0)
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef.at(i));
break;
case cmELSE:
if (m_iSynFlags & noELSE)
Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef.at(i));
m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
break;
case cmIF:
if (m_iSynFlags & noIF)
Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]);
Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef.at(i));
m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE;
break;
@ -462,8 +500,8 @@ namespace qmu
Error(ecINTERNAL_ERROR);
} // switch operator id
m_iPos += (int)len;
a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
m_iPos += len;
a_Tok.Set( (ECmdCode)i, pOprtDef.at(i) );
return true;
} // if operator string found
} // end of for all operator strings
@ -474,17 +512,17 @@ namespace qmu
//---------------------------------------------------------------------------
bool QmuParserTokenReader::IsArgSep(token_type &a_Tok)
{
const char_type* szFormula = m_strFormula.c_str();
if (szFormula[m_iPos]==m_cArgSep)
if (m_strFormula.at(m_iPos)==m_cArgSep)
{
// copy the separator into null terminated string
char_type szSep[2];
QString szSep;
szSep[0] = m_cArgSep;
szSep[1] = 0;
if (m_iSynFlags & noARG_SEP)
{
Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep);
}
m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN;
m_iPos++;
@ -505,7 +543,11 @@ namespace qmu
*/
bool QmuParserTokenReader::IsEOF(token_type &a_Tok)
{
const char_type* szFormula = m_strFormula.c_str();
#if defined(_UNICODE)
const char_type* szFormula = m_strFormula.toStdWString().c_str();
#else
const char_type* szFormula = m_strFormula.toStdString().c_str();
#endif
// check for EOF
if ( !szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/)
@ -530,7 +572,7 @@ namespace qmu
*/
bool QmuParserTokenReader::IsInfixOpTok(token_type &a_Tok)
{
string_type sTok;
QString sTok;
int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);
if (iEnd==m_iPos)
return false;
@ -539,7 +581,7 @@ namespace qmu
funmap_type::const_reverse_iterator it = m_pInfixOprtDef->rbegin();
for ( ; it!=m_pInfixOprtDef->rend(); ++it)
{
if (sTok.find(it->first)!=0)
if (sTok.indexOf(it->first)!=0)
continue;
a_Tok.Set(it->second, it->first);
@ -575,7 +617,7 @@ namespace qmu
*/
bool QmuParserTokenReader::IsFunTok(token_type &a_Tok)
{
string_type strTok;
QString strTok;
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
if (iEnd==m_iPos)
return false;
@ -585,13 +627,12 @@ namespace qmu
return false;
// Check if the next sign is an opening bracket
const char_type *szFormula = m_strFormula.c_str();
if (szFormula[iEnd]!='(')
if (m_strFormula.at(iEnd)!='(')
return false;
a_Tok.Set(item->second, strTok);
m_iPos = (int)iEnd;
m_iPos = iEnd;
if (m_iSynFlags & noFUN)
Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
@ -606,18 +647,19 @@ namespace qmu
*/
bool QmuParserTokenReader::IsOprt(token_type &a_Tok)
{
const char_type *const szExpr = m_strFormula.c_str();
string_type strTok;
QString strTok;
int iEnd = ExtractOperatorToken(strTok, m_iPos);
if (iEnd==m_iPos)
return false;
// Check if the operator is a built in operator, if so ignore it here
const char_type **const pOprtDef = m_pParser->GetOprtDef();
for (int i=0; m_pParser->HasBuiltInOprt() && pOprtDef[i]; ++i)
const QStringList pOprtDef = m_pParser->GetOprtDef();
QStringList::const_iterator constIterator;
for (constIterator = pOprtDef.constBegin(); m_pParser->HasBuiltInOprt() && constIterator != pOprtDef.constEnd();
++constIterator)
{
if (string_type(pOprtDef[i])==strTok)
if ((*constIterator)==strTok)
return false;
}
@ -630,8 +672,8 @@ namespace qmu
funmap_type::const_reverse_iterator it = m_pOprtDef->rbegin();
for ( ; it!=m_pOprtDef->rend(); ++it)
{
const string_type &sID = it->first;
if ( sID == string_type(szExpr + m_iPos, szExpr + m_iPos + sID.length()) )
const QString &sID = it->first;
if ( sID == m_strFormula.mid(m_iPos, m_iPos + sID.length()) )
{
a_Tok.Set(it->second, strTok);
@ -686,7 +728,7 @@ namespace qmu
// token readers.
// Test if there could be a postfix operator
string_type sTok;
QString sTok;
int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);
if (iEnd==m_iPos)
return false;
@ -695,11 +737,11 @@ namespace qmu
funmap_type::const_reverse_iterator it = m_pPostOprtDef->rbegin();
for ( ; it!=m_pPostOprtDef->rend(); ++it)
{
if (sTok.find(it->first)!=0)
if (sTok.indexOf(it->first)!=0)
continue;
a_Tok.Set(it->second, sTok);
m_iPos += (int)it->first.length();
m_iPos += it->first.length();
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;
return true;
@ -721,7 +763,7 @@ namespace qmu
assert(m_pConstDef);
assert(m_pParser);
string_type strTok;
QString strTok;
qreal fVal(0);
int iEnd(0);
@ -737,7 +779,7 @@ namespace qmu
a_Tok.SetVal(item->second, strTok);
if (m_iSynFlags & noVAL)
Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
Error(ecUNEXPECTED_VAL, m_iPos - strTok.length(), strTok);
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
return true;
@ -750,11 +792,11 @@ namespace qmu
for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)
{
int iStart = m_iPos;
if ( (*item)(m_strFormula.c_str() + m_iPos, &m_iPos, &fVal)==1 )
if ( (*item)(m_strFormula.mid(m_iPos), &m_iPos, &fVal)==1 )
{
strTok.assign(m_strFormula.c_str(), iStart, m_iPos);
strTok = m_strFormula.mid(iStart, m_iPos);
if (m_iSynFlags & noVAL)
Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
Error(ecUNEXPECTED_VAL, m_iPos - strTok.length(), strTok);
a_Tok.SetVal(fVal, strTok);
m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
@ -775,7 +817,7 @@ namespace qmu
if (!m_pVarDef->size())
return false;
string_type strTok;
QString strTok;
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
if (iEnd==m_iPos)
return false;
@ -806,7 +848,7 @@ namespace qmu
if (!m_pStrVarDef || !m_pStrVarDef->size())
return false;
string_type strTok;
QString strTok;
int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
if (iEnd==m_iPos)
return false;
@ -838,7 +880,7 @@ namespace qmu
*/
bool QmuParserTokenReader::IsUndefVarTok(token_type &a_Tok)
{
string_type strTok;
QString strTok;
int iEnd( ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos) );
if ( iEnd==m_iPos )
return false;
@ -855,7 +897,7 @@ namespace qmu
// If a factory is available implicitely create new variables
if (m_pFactory)
{
qreal *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
qreal *fVar = m_pFactory(strTok, m_pFactoryData);
a_Tok.SetVar(fVar, strTok );
// Do not use m_pParser->DefineVar( strTok, fVar );
@ -893,21 +935,21 @@ namespace qmu
if (m_strFormula[m_iPos]!='"')
return false;
string_type strBuf(&m_strFormula[m_iPos+1]);
std::size_t iEnd(0), iSkip(0);
QString strBuf(m_strFormula[m_iPos+1]);
int iEnd(0), iSkip(0);
// parser over escaped '\"' end replace them with '"'
for(iEnd=(int)strBuf.find( "\"" ); iEnd!=0 && iEnd!=string_type::npos; iEnd=(int)strBuf.find( "\"", iEnd))
for(iEnd=strBuf.indexOf( "\"" ); iEnd!=0 && iEnd!=-1; iEnd=strBuf.indexOf( "\"", iEnd))
{
if (strBuf[iEnd-1]!='\\') break;
strBuf.replace(iEnd-1, 2, "\"" );
iSkip++;
}
if (iEnd==string_type::npos)
if (iEnd==-1)
Error(ecUNTERMINATED_STRING, m_iPos, "\"" );
string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);
QString strTok = strBuf.mid(0, iEnd);
if (m_iSynFlags & noSTR)
Error(ecUNEXPECTED_STR, m_iPos, strTok);
@ -915,7 +957,7 @@ namespace qmu
m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anfhrungszeichen; +iSkip fr entfernte escape zeichen
m_iPos += (int)strTok.length() + 2 + iSkip; // +2 wg Anfhrungszeichen; +iSkip fr entfernte escape zeichen
m_iSynFlags = noANY ^ ( noARG_SEP | noBC | noOPT | noEND );
return true;
@ -933,7 +975,7 @@ namespace qmu
*/
void QmuParserTokenReader::Error( EErrorCodes a_iErrc,
int a_iPos,
const string_type &a_sTok) const
const QString &a_sTok) const
{
m_pParser->Error(a_iErrc, a_iPos, a_sTok);
}
@ -945,7 +987,7 @@ namespace qmu
}
//---------------------------------------------------------------------------
char_type QmuParserTokenReader::GetArgSep() const
QChar QmuParserTokenReader::GetArgSep() const
{
return m_cArgSep;
}

View file

@ -52,7 +52,7 @@ namespace qmu
{
private:
typedef QmuParserToken<qreal, string_type> token_type;
typedef QmuParserToken<qreal, QString> token_type;
public:
@ -61,13 +61,13 @@ namespace qmu
void AddValIdent(identfun_type a_pCallback);
void SetVarCreator(facfun_type a_pFactory, void *pUserData);
void SetFormula(const string_type &a_strFormula);
void SetFormula(const QString &a_strFormula);
void SetArgSep(char_type cArgSep);
int GetPos() const;
const string_type& GetExpr() const;
const QString &GetExpr() const;
varmap_type& GetUsedVar();
char_type GetArgSep() const;
QChar GetArgSep() const;
void IgnoreUndefVar(bool bIgnore);
void ReInit();
@ -106,10 +106,8 @@ namespace qmu
void Assign(const QmuParserTokenReader &a_Reader);
void SetParent(QmuParserBase *a_pParent);
int ExtractToken(const char_type *a_szCharSet,
string_type &a_strTok,
int a_iPos) const;
int ExtractOperatorToken(string_type &a_sTok, int a_iPos) const;
int ExtractToken(const QString &a_szCharSet, QString &a_strTok, int a_iPos) const;
int ExtractOperatorToken(QString &a_sTok, int a_iPos) const;
bool IsBuiltIn(token_type &a_Tok);
bool IsArgSep(token_type &a_Tok);
@ -123,14 +121,14 @@ namespace qmu
bool IsStrVarTok(token_type &a_Tok);
bool IsUndefVarTok(token_type &a_Tok);
bool IsString(token_type &a_Tok);
void Error(EErrorCodes a_iErrc,
int a_iPos = -1,
const string_type &a_sTok = string_type() ) const;
void Error(EErrorCodes a_iErrc,
int a_iPos = -1,
const QString &a_sTok = QString() ) const;
token_type& SaveBeforeReturn(const token_type &tok);
QmuParserBase *m_pParser;
string_type m_strFormula;
QString m_strFormula;
int m_iPos;
int m_iSynFlags;
bool m_bIgnoreUndefVar;
@ -149,7 +147,7 @@ namespace qmu
qreal m_fZero; ///< Dummy value of zero, referenced by undefined variables
int m_iBrackets;
token_type m_lastTok;
char_type m_cArgSep; ///< The character used for separating function arguments
QChar m_cArgSep; ///< The character used for separating function arguments
};
} // namespace qmu