2014-05-01 13:33:40 +02:00
|
|
|
/***************************************************************************************************
|
|
|
|
**
|
2015-02-27 11:21:09 +01:00
|
|
|
** Copyright (C) 2013 Ingo Berg
|
2014-05-01 13:33:40 +02:00
|
|
|
**
|
|
|
|
** 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.
|
|
|
|
**
|
|
|
|
******************************************************************************************************/
|
|
|
|
|
|
|
|
#ifndef QMUPARSERTOKENREADER_H
|
|
|
|
#define QMUPARSERTOKENREADER_H
|
|
|
|
|
2016-08-08 13:44:49 +02:00
|
|
|
#include <qcompilerdetection.h>
|
|
|
|
#include <QChar>
|
|
|
|
#include <QString>
|
|
|
|
#include <QtGlobal>
|
|
|
|
#include <list>
|
|
|
|
#include <locale>
|
|
|
|
|
|
|
|
#include "qmuparsercallback.h"
|
2014-05-01 13:33:40 +02:00
|
|
|
#include "qmuparserdef.h"
|
2016-08-08 13:44:49 +02:00
|
|
|
#include "qmuparsererror.h"
|
2014-05-01 13:33:40 +02:00
|
|
|
#include "qmuparsertoken.h"
|
|
|
|
|
2014-05-06 11:45:21 +02:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief This file contains the parser token reader definition.
|
|
|
|
*/
|
2014-05-01 13:33:40 +02:00
|
|
|
|
|
|
|
namespace qmu
|
|
|
|
{
|
2014-05-06 11:45:21 +02:00
|
|
|
// Forward declaration
|
|
|
|
class QmuParserBase;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Token reader for the ParserBase class.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
class QmuParserTokenReader
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
typedef QmuParserToken<qreal, QString> token_type;
|
|
|
|
public:
|
2015-10-12 13:52:48 +02:00
|
|
|
explicit QmuParserTokenReader(QmuParserBase *a_pParent);
|
2014-05-22 14:11:14 +02:00
|
|
|
QmuParserTokenReader* Clone(QmuParserBase *a_pParent) const;
|
2014-05-06 11:45:21 +02:00
|
|
|
|
|
|
|
void AddValIdent(identfun_type a_pCallback);
|
2014-05-22 14:11:14 +02:00
|
|
|
void SetVarCreator(facfun_type a_pFactory, void *pUserData);
|
|
|
|
void SetFormula(const QString &a_strFormula);
|
|
|
|
void SetArgSep(char_type cArgSep);
|
|
|
|
int GetPos() const;
|
|
|
|
const QString& GetExpr() const;
|
|
|
|
varmap_type& GetUsedVar();
|
|
|
|
QChar GetArgSep() const;
|
|
|
|
void IgnoreUndefVar(bool bIgnore);
|
|
|
|
void ReInit();
|
2017-01-03 10:14:32 +01:00
|
|
|
token_type ReadNextToken(const QLocale &locale, const QChar &decimal, const QChar &thousand);
|
2014-05-06 11:45:21 +02:00
|
|
|
private:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Syntax codes.
|
|
|
|
*
|
|
|
|
* The syntax codes control the syntax check done during the first time parsing of
|
|
|
|
* the expression string. They are flags that indicate which tokens are allowed next
|
|
|
|
* if certain tokens are identified.
|
|
|
|
*/
|
|
|
|
enum ESynCodes
|
|
|
|
{
|
2014-05-01 13:33:40 +02:00
|
|
|
noBO = 1 << 0, ///< to avoid i.e. "cos(7)("
|
|
|
|
noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"
|
|
|
|
noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
|
|
|
|
noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a"
|
|
|
|
noARG_SEP = 1 << 4, ///< to avoid i.e. ",," or "+," ...
|
|
|
|
noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin"
|
|
|
|
noOPT = 1 << 6, ///< to avoid i.e. "(+)"
|
|
|
|
noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!"
|
|
|
|
noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4"
|
|
|
|
noEND = 1 << 9, ///< to avoid unexpected end of formula
|
|
|
|
noSTR = 1 << 10, ///< to block numeric arguments on string functions
|
|
|
|
noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7"
|
|
|
|
noIF = 1 << 12,
|
|
|
|
noELSE = 1 << 13,
|
|
|
|
sfSTART_OF_LINE = noOPT | noBC | noPOSTOP | noASSIGN | noIF | noELSE | noARG_SEP,
|
|
|
|
noANY = ~0 ///< All of he above flags set
|
2014-05-06 11:45:21 +02:00
|
|
|
};
|
|
|
|
|
2014-05-22 14:11:14 +02:00
|
|
|
QmuParserTokenReader(const QmuParserTokenReader &a_Reader);
|
|
|
|
QmuParserTokenReader& operator=(const QmuParserTokenReader &a_Reader);
|
|
|
|
void Assign(const QmuParserTokenReader &a_Reader);
|
2014-05-06 11:45:21 +02:00
|
|
|
|
2014-05-22 14:11:14 +02:00
|
|
|
void SetParent(QmuParserBase *a_pParent);
|
|
|
|
int ExtractToken(const QString &a_szCharSet, QString &a_strTok, int a_iPos) const;
|
2014-05-06 11:45:21 +02:00
|
|
|
int ExtractOperatorToken(QString &a_sTok, int a_iPos) const;
|
|
|
|
|
|
|
|
bool IsBuiltIn(token_type &a_Tok);
|
|
|
|
bool IsArgSep(token_type &a_Tok);
|
|
|
|
bool IsEOF(token_type &a_Tok);
|
|
|
|
bool IsInfixOpTok(token_type &a_Tok);
|
|
|
|
bool IsFunTok(token_type &a_Tok);
|
|
|
|
bool IsPostOpTok(token_type &a_Tok);
|
|
|
|
bool IsOprt(token_type &a_Tok);
|
2017-01-03 10:14:32 +01:00
|
|
|
bool IsValTok(token_type &a_Tok, const QLocale &locale, const QChar &decimal, const QChar &thousand);
|
2014-05-06 11:45:21 +02:00
|
|
|
bool IsVarTok(token_type &a_Tok);
|
|
|
|
bool IsStrVarTok(token_type &a_Tok);
|
2014-05-22 14:11:14 +02:00
|
|
|
bool IsUndefVarTok(token_type &a_Tok);
|
2014-05-06 11:45:21 +02:00
|
|
|
bool IsString(token_type &a_Tok);
|
|
|
|
void Q_NORETURN Error(EErrorCodes a_iErrc, int a_iPos = -1, const QString &a_sTok = QString() ) const;
|
|
|
|
|
2014-05-22 14:11:14 +02:00
|
|
|
token_type& SaveBeforeReturn(const token_type &tok);
|
2014-05-06 11:45:21 +02:00
|
|
|
|
|
|
|
QmuParserBase *m_pParser;
|
|
|
|
QString m_strFormula;
|
|
|
|
int m_iPos;
|
|
|
|
int m_iSynFlags;
|
|
|
|
bool m_bIgnoreUndefVar;
|
|
|
|
|
|
|
|
const funmap_type *m_pFunDef;
|
|
|
|
const funmap_type *m_pPostOprtDef;
|
|
|
|
const funmap_type *m_pInfixOprtDef;
|
|
|
|
const funmap_type *m_pOprtDef;
|
|
|
|
const valmap_type *m_pConstDef;
|
|
|
|
const strmap_type *m_pStrVarDef;
|
|
|
|
varmap_type *m_pVarDef; ///< The only non const pointer to parser internals
|
|
|
|
facfun_type m_pFactory;
|
|
|
|
void *m_pFactoryData;
|
|
|
|
std::list<identfun_type> m_vIdentFun; ///< Value token identification function
|
|
|
|
varmap_type m_UsedVar;
|
|
|
|
qreal m_fZero; ///< Dummy value of zero, referenced by undefined variables
|
|
|
|
int m_iBrackets; ///< Keep count open brackets
|
|
|
|
token_type m_lastTok;
|
|
|
|
QChar m_cArgSep; ///< The character used for separating function arguments
|
|
|
|
};
|
2014-05-06 16:36:42 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief Return the current position of the token reader in the formula string.
|
|
|
|
*
|
|
|
|
* @return #m_iPos
|
|
|
|
* @throw nothrow
|
|
|
|
*/
|
2014-05-22 14:11:14 +02:00
|
|
|
inline int QmuParserTokenReader::GetPos() const
|
2014-05-06 16:36:42 +02:00
|
|
|
{
|
|
|
|
return m_iPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief Return a reference to the formula.
|
|
|
|
*
|
|
|
|
* @return #m_strFormula
|
|
|
|
* @throw nothrow
|
|
|
|
*/
|
2014-05-22 14:11:14 +02:00
|
|
|
inline const QString& QmuParserTokenReader::GetExpr() const
|
2014-05-06 16:36:42 +02:00
|
|
|
{
|
|
|
|
return m_strFormula;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief Return a map containing the used variables only.
|
|
|
|
*/
|
2014-05-22 14:11:14 +02:00
|
|
|
inline varmap_type& QmuParserTokenReader::GetUsedVar()
|
2014-05-06 16:36:42 +02:00
|
|
|
{
|
|
|
|
return m_UsedVar;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
|
|
* @brief Set Flag that contronls behaviour in case of undefined variables beeing found.
|
|
|
|
*
|
|
|
|
* If true, the parser does not throw an exception if an undefined variable is found. Otherwise it does. This variable
|
|
|
|
* is used internally only! It supresses a "undefined variable" exception in GetUsedVar().
|
|
|
|
* Those function should return a complete list of variables including
|
|
|
|
* those the are not defined by the time of it's call.
|
|
|
|
*/
|
2014-05-22 14:11:14 +02:00
|
|
|
inline void QmuParserTokenReader::IgnoreUndefVar ( bool bIgnore )
|
2014-05-06 16:36:42 +02:00
|
|
|
{
|
|
|
|
m_bIgnoreUndefVar = bIgnore;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2014-05-22 14:11:14 +02:00
|
|
|
inline void QmuParserTokenReader::SetArgSep ( char_type cArgSep )
|
2014-05-06 16:36:42 +02:00
|
|
|
{
|
|
|
|
m_cArgSep = cArgSep;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
2014-05-22 14:11:14 +02:00
|
|
|
inline QChar QmuParserTokenReader::GetArgSep() const
|
2014-05-06 16:36:42 +02:00
|
|
|
{
|
|
|
|
return m_cArgSep;
|
|
|
|
}
|
2014-05-01 13:33:40 +02:00
|
|
|
} // namespace qmu
|
|
|
|
|
|
|
|
#endif
|