valentina/src/libs/qmuparser/qmuparsererror.cpp

327 lines
13 KiB
C++
Raw Normal View History

/***************************************************************************************************
**
** Original work Copyright (C) 2013 Ingo Berg
** Modified work Copyright 2014 Roman Telezhinsky <dismine@gmail.com>
**
** Permission is hereby granted, free of charge, to any person obtaining a copy of this
** software and associated documentation files (the "Software"), to deal in the Software
** without restriction, including without limitation the rights to use, copy, modify,
** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
** permit persons to whom the Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all copies or
** substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
** NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
** DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**
******************************************************************************************************/
#include "qmuparsererror.h"
#include <QTextStream>
namespace qmu
{
const QmuParserErrorMsg QmuParserErrorMsg::m_Instance;
//------------------------------------------------------------------------------
const QmuParserErrorMsg& QmuParserErrorMsg::Instance()
{
return m_Instance;
}
//------------------------------------------------------------------------------
QString QmuParserErrorMsg::operator[](unsigned a_iIdx) const
{
return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : QString();
}
//---------------------------------------------------------------------------
QmuParserErrorMsg::~QmuParserErrorMsg()
{}
//---------------------------------------------------------------------------
/** \brief Assignement operator is deactivated.
*/
QmuParserErrorMsg& QmuParserErrorMsg::operator=(const QmuParserErrorMsg& )
{
assert(false);
return *this;
}
//---------------------------------------------------------------------------
QmuParserErrorMsg::QmuParserErrorMsg(const QmuParserErrorMsg&)
{}
//---------------------------------------------------------------------------
QmuParserErrorMsg::QmuParserErrorMsg()
:m_vErrMsg(0)
{
m_vErrMsg.resize(ecCOUNT);
m_vErrMsg[ecUNASSIGNABLE_TOKEN] = "Unexpected token \"$TOK$\" found at position $POS$.";
m_vErrMsg[ecINTERNAL_ERROR] = "Internal error";
m_vErrMsg[ecINVALID_NAME] = "Invalid function-, variable- or constant name: \"$TOK$\".";
m_vErrMsg[ecINVALID_BINOP_IDENT] = "Invalid binary operator identifier: \"$TOK$\".";
m_vErrMsg[ecINVALID_INFIX_IDENT] = "Invalid infix operator identifier: \"$TOK$\".";
m_vErrMsg[ecINVALID_POSTFIX_IDENT] = "Invalid postfix operator identifier: \"$TOK$\".";
m_vErrMsg[ecINVALID_FUN_PTR] = "Invalid pointer to callback function.";
m_vErrMsg[ecEMPTY_EXPRESSION] = "Expression is empty.";
m_vErrMsg[ecINVALID_VAR_PTR] = "Invalid pointer to variable.";
m_vErrMsg[ecUNEXPECTED_OPERATOR] = "Unexpected operator \"$TOK$\" found at position $POS$";
m_vErrMsg[ecUNEXPECTED_EOF] = "Unexpected end of expression at position $POS$";
m_vErrMsg[ecUNEXPECTED_ARG_SEP] = "Unexpected argument separator at position $POS$";
m_vErrMsg[ecUNEXPECTED_PARENS] = "Unexpected parenthesis \"$TOK$\" at position $POS$";
m_vErrMsg[ecUNEXPECTED_FUN] = "Unexpected function \"$TOK$\" at position $POS$";
m_vErrMsg[ecUNEXPECTED_VAL] = "Unexpected value \"$TOK$\" found at position $POS$";
m_vErrMsg[ecUNEXPECTED_VAR] = "Unexpected variable \"$TOK$\" found at position $POS$";
m_vErrMsg[ecUNEXPECTED_ARG] = "Function arguments used without a function (position: $POS$)";
m_vErrMsg[ecMISSING_PARENS] = "Missing parenthesis";
m_vErrMsg[ecTOO_MANY_PARAMS] = "Too many parameters for function \"$TOK$\" at expression position $POS$";
m_vErrMsg[ecTOO_FEW_PARAMS] = "Too few parameters for function \"$TOK$\" at expression position $POS$";
m_vErrMsg[ecDIV_BY_ZERO] = "Divide by zero";
m_vErrMsg[ecDOMAIN_ERROR] = "Domain error";
m_vErrMsg[ecNAME_CONFLICT] = "Name conflict";
m_vErrMsg[ecOPT_PRI] = "Invalid value for operator priority (must be greater or equal to zero).";
m_vErrMsg[ecBUILTIN_OVERLOAD] = "user defined binary operator \"$TOK$\" conflicts with a built in operator.";
m_vErrMsg[ecUNEXPECTED_STR] = "Unexpected string token found at position $POS$.";
m_vErrMsg[ecUNTERMINATED_STRING] = "Unterminated string starting at position $POS$.";
m_vErrMsg[ecSTRING_EXPECTED] = "String function called with a non string type of argument.";
m_vErrMsg[ecVAL_EXPECTED] = "String value used where a numerical argument is expected.";
m_vErrMsg[ecOPRT_TYPE_CONFLICT] = "No suitable overload for operator \"$TOK$\" at position $POS$.";
m_vErrMsg[ecSTR_RESULT] = "Function result is a string.";
m_vErrMsg[ecGENERIC] = "Parser error.";
m_vErrMsg[ecLOCALE] = "Decimal separator is identic to function argument separator.";
m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = "The \"$TOK$\" operator must be preceeded by a closing bracket.";
m_vErrMsg[ecMISSING_ELSE_CLAUSE] = "If-then-else operator is missing an else clause";
m_vErrMsg[ecMISPLACED_COLON] = "Misplaced colon at position $POS$";
#if defined(_DEBUG)
for (int i=0; i<ecCOUNT; ++i)
if (!m_vErrMsg[i].length())
assert(false);
#endif
}
//---------------------------------------------------------------------------
//
// QParserError class
//
//---------------------------------------------------------------------------
/** \brief Default constructor. */
QmuParserError::QmuParserError()
:m_strMsg()
,m_strFormula()
,m_strTok()
,m_iPos(-1)
,m_iErrc(ecUNDEFINED)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
}
//------------------------------------------------------------------------------
/** \brief This Constructor is used for internal exceptions only.
It does not contain any information but the error code.
*/
QmuParserError::QmuParserError(EErrorCodes a_iErrc)
:m_strMsg()
,m_strFormula()
,m_strTok()
,m_iPos(-1)
,m_iErrc(a_iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
m_strMsg = m_ErrMsg[m_iErrc];
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
//------------------------------------------------------------------------------
/** \brief Construct an error from a message text. */
QmuParserError::QmuParserError(const QString &sMsg)
:m_ErrMsg(QmuParserErrorMsg::Instance())
{
Reset();
m_strMsg = sMsg;
}
//------------------------------------------------------------------------------
/** \brief Construct an error object.
\param [in] a_iErrc the error code.
\param [in] sTok The token string related to this error.
\param [in] sExpr The expression related to the error.
\param [in] a_iPos the position in the expression where the error occured.
*/
QmuParserError::QmuParserError(EErrorCodes iErrc,
const QString &sTok,
const QString &sExpr,
int iPos )
:m_strMsg()
,m_strFormula(sExpr)
,m_strTok(sTok)
,m_iPos(iPos)
,m_iErrc(iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
m_strMsg = m_ErrMsg[m_iErrc];
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
//------------------------------------------------------------------------------
/** \brief Construct an error object.
\param [in] iErrc the error code.
\param [in] iPos the position in the expression where the error occured.
\param [in] sTok The token string related to this error.
*/
QmuParserError::QmuParserError(EErrorCodes iErrc, int iPos, const QString &sTok)
:m_strMsg()
,m_strFormula()
,m_strTok(sTok)
,m_iPos(iPos)
,m_iErrc(iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
m_strMsg = m_ErrMsg[m_iErrc];
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
//------------------------------------------------------------------------------
/** \brief Construct an error object.
\param [in] szMsg The error message text.
\param [in] iPos the position related to the error.
\param [in] sTok The token string related to this error.
*/
QmuParserError::QmuParserError(const QString &szMsg, int iPos, const QString &sTok)
:m_strMsg(szMsg)
,m_strFormula()
,m_strTok(sTok)
,m_iPos(iPos)
,m_iErrc(ecGENERIC)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
ReplaceSubString(m_strMsg, "$POS$", QString().setNum(m_iPos));
ReplaceSubString(m_strMsg, "$TOK$", m_strTok);
}
//------------------------------------------------------------------------------
/** \brief Copy constructor. */
QmuParserError::QmuParserError(const QmuParserError &a_Obj)
:m_strMsg(a_Obj.m_strMsg)
,m_strFormula(a_Obj.m_strFormula)
,m_strTok(a_Obj.m_strTok)
,m_iPos(a_Obj.m_iPos)
,m_iErrc(a_Obj.m_iErrc)
,m_ErrMsg(QmuParserErrorMsg::Instance())
{
}
//------------------------------------------------------------------------------
/** \brief Assignment operator. */
QmuParserError& QmuParserError::operator=(const QmuParserError &a_Obj)
{
if (this==&a_Obj)
return *this;
m_strMsg = a_Obj.m_strMsg;
m_strFormula = a_Obj.m_strFormula;
m_strTok = a_Obj.m_strTok;
m_iPos = a_Obj.m_iPos;
m_iErrc = a_Obj.m_iErrc;
return *this;
}
//------------------------------------------------------------------------------
QmuParserError::~QmuParserError()
{}
//------------------------------------------------------------------------------
/** \brief Replace all ocuurences of a substring with another string.
\param strFind The string that shall be replaced.
\param strReplaceWith The string that should be inserted instead of strFind
*/
void QmuParserError::ReplaceSubString( QString &strSource, const QString &strFind, const QString &strReplaceWith)
{
QString strResult;
int iPos(0), iNext(0);
for(;;)
{
iNext = strSource.indexOf(strFind, iPos);
strResult.append(strSource.mid(iPos, iNext-iPos));
if( iNext==-1 )
break;
strResult.append(strReplaceWith);
iPos = iNext + strFind.length();
}
strSource.swap(strResult);
}
//------------------------------------------------------------------------------
/** \brief Reset the erro object. */
void QmuParserError::Reset()
{
m_strMsg = "";
m_strFormula = "";
m_strTok = "";
m_iPos = -1;
m_iErrc = ecUNDEFINED;
}
//------------------------------------------------------------------------------
/** \brief Set the expression related to this error. */
void QmuParserError::SetFormula(const QString &a_strFormula)
{
m_strFormula = a_strFormula;
}
//------------------------------------------------------------------------------
/** \brief gets the expression related tp this error.*/
const QString& QmuParserError::GetExpr() const
{
return m_strFormula;
}
//------------------------------------------------------------------------------
/** \brief Returns the message string for this error. */
const QString& QmuParserError::GetMsg() const
{
return m_strMsg;
}
//------------------------------------------------------------------------------
/** \brief Return the formula position related to the error.
If the error is not related to a distinct position this will return -1
*/
std::size_t QmuParserError::GetPos() const
{
return m_iPos;
}
//------------------------------------------------------------------------------
/** \brief Return string related with this token (if available). */
const QString& QmuParserError::GetToken() const
{
return m_strTok;
}
//------------------------------------------------------------------------------
/** \brief Return the error code. */
EErrorCodes QmuParserError::GetCode() const
{
return m_iErrc;
}
} // namespace qmu