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. \param [out] a_fVal Pointer where the value should be stored in case one is found.
\return 1 if a value was found 0 otherwise. \return 1 if a value was found 0 otherwise.
*/ */
int QmuParser::IsVal(const 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); 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.seekg(0); // todo: check if this really is necessary
stream.imbue(QmuParser::s_locale); stream.imbue(QmuParser::s_locale);
stream >> fVal; stream >> fVal;

View file

@ -83,7 +83,7 @@ protected:
static qreal Min(const qreal*, int); // minimum static qreal Min(const qreal*, int); // minimum
static qreal Max(const qreal*, int); // maximum static qreal Max(const qreal*, int); // maximum
static int IsVal(const 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 } // namespace qmu

View file

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

View file

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

View file

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

View file

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

View file

@ -27,6 +27,8 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <map> #include <map>
#include <QMap>
#include <QString>
#include "qmuparserfixes.h" #include "qmuparserfixes.h"
@ -49,54 +51,15 @@
//#define MUP_USE_OPENMP //#define MUP_USE_OPENMP
#if defined(_UNICODE) #if defined(_UNICODE)
/** \brief Definition of the basic parser string type. */ /** \brief Definition of the basic parser string type. */
#define MUP_STRING_TYPE std::wstring #define QMUP_STRING_TYPE std::wstring
#else #else
/** \brief Definition of the basic parser string type. */
/** \brief Definition of the basic parser string type. */ #define QMUP_STRING_TYPE std::string
#define MUP_STRING_TYPE std::string
#endif #endif
namespace qmu 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. /** \brief Bytecode values.
@ -200,7 +163,7 @@ namespace qmu
Depends on wether UNICODE is used or not. 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. /** \brief The character type used by the parser.
@ -216,13 +179,13 @@ namespace qmu
// Data container types // Data container types
/** \brief Type used for storing variables. */ /** \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. */ /** \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. */ /** \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 // Parser callbacks
@ -299,19 +262,19 @@ namespace qmu
typedef qreal (*multfun_type)(const qreal*, int); typedef qreal (*multfun_type)(const qreal*, int);
/** \brief Callback type used for functions taking a string as an argument. */ /** \brief Callback type used for functions taking a string as an argument. */
typedef qreal (*strfun_type1)(const char_type*); typedef qreal (*strfun_type1)(const QString &);
/** \brief Callback type used for functions taking a string and a value as arguments. */ /** \brief Callback type used for functions taking a string and a value as arguments. */
typedef qreal (*strfun_type2)(const char_type*, qreal); typedef qreal (*strfun_type2)(const QString &, qreal);
/** \brief Callback type used for functions taking a string and two values as arguments. */ /** \brief Callback type used for functions taking a string and two values as arguments. */
typedef qreal (*strfun_type3)(const char_type*, qreal, qreal); typedef qreal (*strfun_type3)(const QString &, qreal, qreal);
/** \brief Callback used for functions that identify values in a string. */ /** \brief Callback used for functions that identify values in a string. */
typedef int (*identfun_type)(const 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. */ /** \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 } // end of namespace
#endif #endif

View file

@ -22,6 +22,8 @@
#include "qmuparsererror.h" #include "qmuparsererror.h"
#include <QTextStream>
namespace qmu 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_ErrMsg(QmuParserErrorMsg::Instance())
{ {
m_strMsg = m_ErrMsg[m_iErrc]; m_strMsg = m_ErrMsg[m_iErrc];
stringstream_type stream; ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$TOK$", m_strTok); ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Construct an error from a message text. */ /** \brief Construct an error from a message text. */
QmuParserError::QmuParserError(const string_type &sMsg) QmuParserError::QmuParserError(const QString &sMsg)
:m_ErrMsg(QmuParserErrorMsg::Instance()) :m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
Reset(); Reset();
@ -159,9 +159,9 @@ namespace qmu
\param [in] sExpr The expression related to the error. \param [in] sExpr The expression related to the error.
\param [in] a_iPos the position in the expression where the error occured. \param [in] a_iPos the position in the expression where the error occured.
*/ */
QmuParserError::QmuParserError( EErrorCodes iErrc, QmuParserError::QmuParserError(EErrorCodes iErrc,
const string_type &sTok, const QString &sTok,
const string_type &sExpr, const QString &sExpr,
int iPos ) int iPos )
:m_strMsg() :m_strMsg()
,m_strFormula(sExpr) ,m_strFormula(sExpr)
@ -171,9 +171,7 @@ namespace qmu
,m_ErrMsg(QmuParserErrorMsg::Instance()) ,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
m_strMsg = m_ErrMsg[m_iErrc]; m_strMsg = m_ErrMsg[m_iErrc];
stringstream_type stream; ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$TOK$", m_strTok); 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] iPos the position in the expression where the error occured.
\param [in] sTok The token string related to this error. \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_strMsg()
,m_strFormula() ,m_strFormula()
,m_strTok(sTok) ,m_strTok(sTok)
@ -192,9 +190,7 @@ namespace qmu
,m_ErrMsg(QmuParserErrorMsg::Instance()) ,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
m_strMsg = m_ErrMsg[m_iErrc]; m_strMsg = m_ErrMsg[m_iErrc];
stringstream_type stream; ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$TOK$", m_strTok); ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
} }
@ -204,7 +200,7 @@ namespace qmu
\param [in] iPos the position related to the error. \param [in] iPos the position related to the error.
\param [in] sTok The token string related to this error. \param [in] sTok The token string related to this error.
*/ */
QmuParserError::QmuParserError(const char_type *szMsg, int iPos, const string_type &sTok) QmuParserError::QmuParserError(const QString &szMsg, int iPos, const QString &sTok)
:m_strMsg(szMsg) :m_strMsg(szMsg)
,m_strFormula() ,m_strFormula()
,m_strTok(sTok) ,m_strTok(sTok)
@ -212,9 +208,7 @@ namespace qmu
,m_iErrc(ecGENERIC) ,m_iErrc(ecGENERIC)
,m_ErrMsg(QmuParserErrorMsg::Instance()) ,m_ErrMsg(QmuParserErrorMsg::Instance())
{ {
stringstream_type stream; ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
stream << (int)m_iPos;
ReplaceSubString(m_strMsg, "$POS$", stream.str());
ReplaceSubString(m_strMsg, "$TOK$", m_strTok); ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
} }
@ -249,32 +243,30 @@ namespace qmu
QmuParserError::~QmuParserError() QmuParserError::~QmuParserError()
{} {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Replace all ocuurences of a substring with another string. /** \brief Replace all ocuurences of a substring with another string.
\param strFind The string that shall be replaced. \param strFind The string that shall be replaced.
\param strReplaceWith The string that should be inserted instead of strFind \param strReplaceWith The string that should be inserted instead of strFind
*/ */
void QmuParserError::ReplaceSubString( string_type &strSource, void QmuParserError::ReplaceSubString( QString &strSource, const QString &strFind, const QString &strReplaceWith)
const string_type &strFind, {
const string_type &strReplaceWith) QString strResult;
{ int iPos(0), iNext(0);
string_type strResult;
string_type::size_type iPos(0), iNext(0);
for(;;) for(;;)
{ {
iNext = strSource.find(strFind, iPos); iNext = strSource.indexOf(strFind, iPos);
strResult.append(strSource, iPos, iNext-iPos); strResult.append(strSource.mid(iPos, iNext-iPos));
if( iNext==string_type::npos ) if( iNext==-1 )
break; break;
strResult.append(strReplaceWith); strResult.append(strReplaceWith);
iPos = iNext + strFind.length(); iPos = iNext + strFind.length();
} }
strSource.swap(strResult); strSource.swap(strResult);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Reset the erro object. */ /** \brief Reset the erro object. */
@ -289,21 +281,21 @@ namespace qmu
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Set the expression related to this error. */ /** \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; m_strFormula = a_strFormula;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief gets the expression related tp this error.*/ /** \brief gets the expression related tp this error.*/
const string_type& QmuParserError::GetExpr() const const QString& QmuParserError::GetExpr() const
{ {
return m_strFormula; return m_strFormula;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Returns the message string for this error. */ /** \brief Returns the message string for this error. */
const string_type& QmuParserError::GetMsg() const const QString& QmuParserError::GetMsg() const
{ {
return m_strMsg; return m_strMsg;
} }
@ -320,7 +312,7 @@ namespace qmu
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** \brief Return string related with this token (if available). */ /** \brief Return string related with this token (if available). */
const string_type& QmuParserError::GetToken() const const QString& QmuParserError::GetToken() const
{ {
return m_strTok; return m_strTok;
} }

View file

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

View file

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

View file

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

View file

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

View file

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