Separate class Calculator.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2015-08-09 20:46:21 +03:00
parent 6380471267
commit aec99643b3
9 changed files with 278 additions and 116 deletions

View file

@ -0,0 +1,110 @@
/***************************************************************************************************
**
** Copyright (C) 2015 Roman Telezhynskyi
**
** 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 "qmuformulabase.h"
namespace qmu
{
//---------------------------------------------------------------------------------------------------------------------
QmuFormulaBase::QmuFormulaBase()
:QmuParser()
{
}
//---------------------------------------------------------------------------------------------------------------------
QmuFormulaBase::~QmuFormulaBase()
{
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief InitCharacterSets init character set for parser.
*
* QMuParser require setting character set for legal characters. Because we try make our expresion language independent
* we set all posible unique characters from all alphabets.
*
*/
void QmuFormulaBase::InitCharacterSets()
{
//String with all unique symbols for supported alpabets.
// See script alphabets.py for generation and more information.
//Note. MSVC doen't support normal string concatenation for long string. Thats why we use QStringList in this place.
QStringList symbols = QStringList() << "ցЀĆЈVӧĎАғΕĖӅИқΝĞơРңњΥĦШҫ̆جگĮаҳѕεشԶиһνԾрυلՆӝшËՎҔPÓՖXӛӟŞӣզhëծpóӞնxßվāŁЃֆĉЋ"
<< "CŬđҐГΒęҘЛΚŘġҠУGاհЫدԱҰгβطԹõлκKՁÀуςهՉÈыvیՑÐSOřӘћաőcӐթèkàѓżűðsķչøӥӔĀփїІĈЎ"
<< "ґĐΗЖҙĘȚΟОҡĠآΧЦتЮұİزηжԸغοоÁՀقχцÉՈيюÑՐђӋіәťӆўáŠĺѐfөըnñŰӤӨӹոľЁրăЉŭċБӸēłΔҖ"
<< "ЙŤěΜӜDСձģΤӰЩīņحҮбưԳصδHйԻŇμӲӴсՃمτƠщՋєLQŹՓŕÖYśÞaգĽæiŽիӓîqճöyջþĂօЄӦĊЌΑĒДҗј"
<< "ΙȘĚМΡéĵĢФūӚΩبĪЬүќαذԲдҷιظԺмρՂфÇωوՊьÏՒTŚĻJբdçժlïӪղtպӫAւąЇčŃЏĕӯЗΖEțŮĝПΞأĥ"
<< "ثĹЧΦÆӳЯIسŲԵзζԽпξكՅÄчφNMՍӌяӢՕÔWÎŝÜџёźեägխoӒյôwĶBžսüЂĄև̈ЊČƏљΓВҕĔӮΛКĜΣТҥĤک"
<< "ЪƯخγвŅԴŪضλкԼĴσтÅՄنъÍՌRӕՔZÝŜbåդjíլļrӵմzýռپêЅքćچЍďӱҒЕůėژșΘØҚНğńءΠFҢХħΨҪ"
<< "ЭųįҶرҲеԷňعθҺнԿفπÂхՇψÊэšՏÒUəÚѝŻşҤӑâeէŐımկòuշÕúտŔ";
// Defining identifier character sets
DefineNameChars(QStringLiteral("0123456789_@#") + symbols.join(""));
DefineOprtChars(symbols.join("") + QStringLiteral("+-*^/?<>=!$%&|~_"));
}
//---------------------------------------------------------------------------------------------------------------------
// Factory function for creating new parser variables
// This could as well be a function performing database queries.
qreal *QmuFormulaBase::AddVariable(const QString &a_szName, void *a_pUserData)
{
Q_UNUSED(a_szName)
Q_UNUSED(a_pUserData)
static qreal value = 0;
return &value;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief SetSepForTr set separators for translation expression.
* @param fromUser true if expression come from user (from dialog).
*/
void QmuFormulaBase::SetSepForTr(bool osSeparator, bool fromUser)
{
if (fromUser)
{
if (osSeparator)
{
const QLocale loc = QLocale::system();
SetDecSep(loc.decimalPoint().toLatin1());
SetThousandsSep(loc.groupSeparator().toLatin1());
SetArgSep(';');
return;
}
}
SetSepForEval();//Same separators (internal) as for eval.
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief SetSepForEval set separators for eval. Each expression eval in internal (C) locale.
*/
void QmuFormulaBase::SetSepForEval()
{
SetArgSep(';');
SetThousandsSep(',');
SetDecSep('.');
}
}// namespace qmu

View file

@ -0,0 +1,49 @@
/***************************************************************************************************
**
** Copyright (C) 2015 Roman Telezhynskyi
**
** 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 QMUFORMULABASE_H
#define QMUFORMULABASE_H
#include "qmuparser_global.h"
#include "qmuparser.h"
namespace qmu
{
class QMUPARSERSHARED_EXPORT QmuFormulaBase : public QmuParser
{
public:
QmuFormulaBase();
virtual ~QmuFormulaBase() Q_DECL_OVERRIDE;
protected:
void InitCharacterSets();
static qreal* AddVariable(const QString &a_szName, void *a_pUserData);
void SetSepForTr(bool osSeparator, bool fromUser);
void SetSepForEval();
private:
Q_DISABLE_COPY(QmuFormulaBase)
};
} // namespace qmu
#endif // QMUFORMULABASE_H

View file

@ -10,7 +10,9 @@ SOURCES += \
$$PWD/qmuparserbase.cpp \
$$PWD/qmuparsertest.cpp \
$$PWD/stable.cpp \
$$PWD/qmutranslation.cpp
$$PWD/qmutranslation.cpp \
$$PWD/qmuformulabase.cpp \
$$PWD/qmutokenparser.cpp
HEADERS += \
$$PWD/qmuparser.h\
@ -26,4 +28,6 @@ HEADERS += \
$$PWD/qmuparsertest.h \
$$PWD/stable.h \
$$PWD/qmutranslation.h \
$$PWD/qmudef.h
$$PWD/qmudef.h \
$$PWD/qmuformulabase.h \
$$PWD/qmutokenparser.h

View file

@ -39,7 +39,7 @@ OBJECTS_DIR = obj
include(qmuparser.pri)
VERSION = 2.2.6
VERSION = 2.3.0
# Set "make install" command for Unix-like systems.
unix:!macx{

View file

@ -0,0 +1,62 @@
/***************************************************************************************************
**
** Copyright (C) 2015 Roman Telezhynskyi
**
** 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 "qmutokenparser.h"
namespace qmu
{
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief QmuTokenParser class constructor. Make easy initialization math parser.
*
* This constructor hide initialization variables, operators, character sets.
* Use this constuctor to get tokens from formula. All formulas must be converted to external look.
* Example:
*
* QmuTokenParser *cal = new QmuTokenParser(formula, osSeparator, false);
* tokens = cal->GetTokens();
* numbers = cal->GetNumbers();
* delete cal;
*
* @param formula string with formula.
* @param fromUser true if we parse formula from user
*/
QmuTokenParser::QmuTokenParser(const QString &formula, bool osSeparator, bool fromUser)
:QmuFormulaBase()
{
InitCharacterSets();
setAllowSubexpressions(false);//Only one expression per time
SetVarFactory(AddVariable, this);
SetSepForTr(osSeparator, fromUser);
SetExpr(formula);
//Need run for making tokens. Don't catch exception here, because we want know if formula has error.
Eval();
}
//---------------------------------------------------------------------------------------------------------------------
QmuTokenParser::~QmuTokenParser()
{
}
}// namespace qmu

View file

@ -0,0 +1,43 @@
/***************************************************************************************************
**
** Copyright (C) 2015 Roman Telezhynskyi
**
** 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 QMUTOKENPARSER_H
#define QMUTOKENPARSER_H
#include "qmuparser_global.h"
#include "qmuformulabase.h"
namespace qmu
{
class QMUPARSERSHARED_EXPORT QmuTokenParser : public QmuFormulaBase
{
public:
QmuTokenParser(const QString &formula, bool osSeparator, bool fromUser = true);
virtual ~QmuTokenParser() Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QmuTokenParser)
};
} // namespace qmu
#endif // QMUTOKENPARSER_H

View file

@ -49,7 +49,7 @@ using namespace qmu;
* @param data pointer to a variable container.
*/
Calculator::Calculator(const VContainer *data, MeasurementsType patternType)
:QmuParser(), vVarVal(nullptr), data(data), patternType(patternType)
:QmuFormulaBase(), vVarVal(nullptr), data(data), patternType(patternType)
{
SCASSERT(data != nullptr)
InitCharacterSets();
@ -58,36 +58,6 @@ Calculator::Calculator(const VContainer *data, MeasurementsType patternType)
SetSepForEval();
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Calculator class constructor. Make easy initialization math parser.
*
* This constructor hide initialization variables, operators, character sets.
* Use this constuctor to get tokens from formula. All formulas must be converted to external look.
* Example:
*
* Calculator *cal = new Calculator(formula, osSeparator, false);
* tokens = cal->GetTokens();
* numbers = cal->GetNumbers();
* delete cal;
*
* @param formula string with formula.
* @param fromUser true if we parse formula from user
*/
Calculator::Calculator(const QString &formula, bool osSeparator, bool fromUser)
:QmuParser(), vVarVal(nullptr), data(nullptr), patternType(MeasurementsType::Standard)
{
InitCharacterSets();
setAllowSubexpressions(false);//Only one expression per time
SetVarFactory(AddVariable, this);
SetSepForTr(osSeparator, fromUser);
SetExpr(formula);
//Need run for making tokens. Don't catch exception here, because we want know if formula has error.
Eval();
}
//---------------------------------------------------------------------------------------------------------------------
Calculator::~Calculator()
{
@ -202,78 +172,6 @@ void Calculator::InitVariables(const VContainer *data, const QMap<int, QString>
}
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Calculator::InitCharacterSets init character set for parser.
*
* QMuParser require setting character set for legal characters. Because we try make our expresion language independent
* we set all posible unique characters from all alphabets.
*
*/
void Calculator::InitCharacterSets()
{
//String with all unique symbols for supported alpabets.
// See script alphabets.py for generation and more information.
//Note. MSVC doen't support normal string concatenation for long string. Thats why we use QStringList in this place.
QStringList symbols = QStringList() << "ցЀĆЈVӧĎАғΕĖӅИқΝĞơРңњΥĦШҫ̆جگĮаҳѕεشԶиһνԾрυلՆӝшËՎҔPÓՖXӛӟŞӣզhëծpóӞնxßվāŁЃֆĉЋ"
<< "CŬđҐГΒęҘЛΚŘġҠУGاհЫدԱҰгβطԹõлκKՁÀуςهՉÈыvیՑÐSOřӘћաőcӐթèkàѓżűðsķչøӥӔĀփїІĈЎ"
<< "ґĐΗЖҙĘȚΟОҡĠآΧЦتЮұİزηжԸغοоÁՀقχцÉՈيюÑՐђӋіәťӆўáŠĺѐfөըnñŰӤӨӹոľЁրăЉŭċБӸēłΔҖ"
<< "ЙŤěΜӜDСձģΤӰЩīņحҮбưԳصδHйԻŇμӲӴсՃمτƠщՋєLQŹՓŕÖYśÞaգĽæiŽիӓîqճöyջþĂօЄӦĊЌΑĒДҗј"
<< "ΙȘĚМΡéĵĢФūӚΩبĪЬүќαذԲдҷιظԺмρՂфÇωوՊьÏՒTŚĻJբdçժlïӪղtպӫAւąЇčŃЏĕӯЗΖEțŮĝПΞأĥ"
<< "ثĹЧΦÆӳЯIسŲԵзζԽпξكՅÄчφNMՍӌяӢՕÔWÎŝÜџёźեägխoӒյôwĶBžսüЂĄև̈ЊČƏљΓВҕĔӮΛКĜΣТҥĤک"
<< "ЪƯخγвŅԴŪضλкԼĴσтÅՄنъÍՌRӕՔZÝŜbåդjíլļrӵմzýռپêЅքćچЍďӱҒЕůėژșΘØҚНğńءΠFҢХħΨҪ"
<< "ЭųįҶرҲеԷňعθҺнԿفπÂхՇψÊэšՏÒUəÚѝŻşҤӑâeէŐımկòuշÕúտŔ";
// Defining identifier character sets
DefineNameChars(QStringLiteral("0123456789_@#") + symbols.join(""));
DefineOprtChars(symbols.join("") + QStringLiteral("+-*^/?<>=!$%&|~_"));
}
//---------------------------------------------------------------------------------------------------------------------
// Factory function for creating new parser variables
// This could as well be a function performing database queries.
qreal* Calculator::AddVariable(const QString &a_szName, void *a_pUserData)
{
Q_UNUSED(a_szName)
Q_UNUSED(a_pUserData)
static qreal value = 0;
return &value;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Calculator::SetSepForEval set separators for eval. Each expression eval in internal (C) locale.
*/
void Calculator::SetSepForEval()
{
SetArgSep(';');
SetThousandsSep(',');
SetDecSep('.');
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Calculator::SetSepForTr set separators for translation expression.
* @param fromUser true if expression come from user (from dialog).
*/
void Calculator::SetSepForTr(bool osSeparator, bool fromUser)
{
if (fromUser)
{
if (osSeparator)
{
const QLocale loc = QLocale::system();
SetDecSep(loc.decimalPoint().toLatin1());
SetThousandsSep(loc.groupSeparator().toLatin1());
SetArgSep(';');
return;
}
}
SetSepForEval();//Same separators (internal) as for eval.
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Calculator::RemoveAll remove token from token list.

View file

@ -29,7 +29,7 @@
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include "../qmuparser/qmuparser.h"
#include "../qmuparser/qmuformulabase.h"
#include "../vmisc/def.h"
class VContainer;
@ -53,12 +53,11 @@ class VContainer;
* delete cal;//Here can be memory leak, but dialog already check this formula and probability very low.
* }
*/
class Calculator:public qmu::QmuParser
class Calculator:public qmu::QmuFormulaBase
{
public:
Calculator(const VContainer *data, MeasurementsType patternType);
Calculator(const QString &formula, bool osSeparator, bool fromUser = true);
~Calculator();
virtual ~Calculator();
qreal EvalFormula(const QString &formula);
private:
Q_DISABLE_COPY(Calculator)
@ -66,10 +65,6 @@ private:
const VContainer *data;
MeasurementsType patternType;
void InitVariables(const VContainer *data, const QMap<int, QString> &tokens, const QString &formula);
void InitCharacterSets();
static qreal* AddVariable(const QString &a_szName, void *a_pUserData);
void SetSepForEval();
void SetSepForTr(bool osSeparator, bool fromUser);
static void RemoveAll(QMap<int, QString> &map, const QString &val);
};

View file

@ -30,6 +30,7 @@
#include "calculator.h"
#include "../vmisc/def.h"
#include "../vgeometry/vgeometrydef.h"
#include "../qmuparser/qmutokenparser.h"
using namespace qmu;
@ -713,7 +714,7 @@ QString VTranslateVars::FormulaFromUser(const QString &formula, bool osSeparator
}
QString newFormula = formula;// Local copy for making changes
Calculator *cal = new Calculator(formula, osSeparator);// Eval formula
QmuTokenParser *cal = new QmuTokenParser(formula, osSeparator);// Eval formula
QMap<int, QString> tokens = cal->GetTokens();// Tokens (variables, measurements)
QMap<int, QString> numbers = cal->GetNumbers();// All numbers in expression for changing decimal separator
delete cal;
@ -820,7 +821,7 @@ QString VTranslateVars::FormulaToUser(const QString &formula) const
QMap<int, QString> numbers;
try
{
Calculator *cal = new Calculator(formula, false);// Eval formula
QmuTokenParser *cal = new QmuTokenParser(formula, false);// Eval formula
tokens = cal->GetTokens();// Tokens (variables, measurements)
numbers = cal->GetNumbers();// All numbers in expression for changing decimal separator
delete cal;