Custom math expressions + bugfix harmonic mixing

This commit is contained in:
Jan Käberich 2020-12-18 18:52:38 +01:00
parent 49e0b901fd
commit 9614c9d850
97 changed files with 18173 additions and 11 deletions

View File

@ -25,7 +25,56 @@ HEADERS += \
Tools/eseries.h \
Tools/impedancematchdialog.h \
Traces/Math/dft.h \
Traces/Math/expression.h \
Traces/Math/medianfilter.h \
Traces/Math/parser/mpCompat.h \
Traces/Math/parser/mpDefines.h \
Traces/Math/parser/mpError.h \
Traces/Math/parser/mpFuncCmplx.h \
Traces/Math/parser/mpFuncCommon.h \
Traces/Math/parser/mpFuncMatrix.h \
Traces/Math/parser/mpFuncNonCmplx.h \
Traces/Math/parser/mpFuncStr.h \
Traces/Math/parser/mpFwdDecl.h \
Traces/Math/parser/mpICallback.h \
Traces/Math/parser/mpIOprt.h \
Traces/Math/parser/mpIPackage.h \
Traces/Math/parser/mpIPrecedence.h \
Traces/Math/parser/mpIToken.h \
Traces/Math/parser/mpIValReader.h \
Traces/Math/parser/mpIValue.h \
Traces/Math/parser/mpIfThenElse.h \
Traces/Math/parser/mpMatrix.h \
Traces/Math/parser/mpMatrixError.h \
Traces/Math/parser/mpOprtBinAssign.h \
Traces/Math/parser/mpOprtBinCommon.h \
Traces/Math/parser/mpOprtCmplx.h \
Traces/Math/parser/mpOprtIndex.h \
Traces/Math/parser/mpOprtMatrix.h \
Traces/Math/parser/mpOprtNonCmplx.h \
Traces/Math/parser/mpOprtPostfixCommon.h \
Traces/Math/parser/mpPackageCmplx.h \
Traces/Math/parser/mpPackageCommon.h \
Traces/Math/parser/mpPackageMatrix.h \
Traces/Math/parser/mpPackageNonCmplx.h \
Traces/Math/parser/mpPackageStr.h \
Traces/Math/parser/mpPackageUnit.h \
Traces/Math/parser/mpParser.h \
Traces/Math/parser/mpParserBase.h \
Traces/Math/parser/mpParserMessageProvider.h \
Traces/Math/parser/mpRPN.h \
Traces/Math/parser/mpScriptTokens.h \
Traces/Math/parser/mpStack.h \
Traces/Math/parser/mpTest.h \
Traces/Math/parser/mpTokenReader.h \
Traces/Math/parser/mpTypes.h \
Traces/Math/parser/mpValReader.h \
Traces/Math/parser/mpValue.h \
Traces/Math/parser/mpValueCache.h \
Traces/Math/parser/mpVariable.h \
Traces/Math/parser/suSortPred.h \
Traces/Math/parser/suStringTokens.h \
Traces/Math/parser/utGeneric.h \
Traces/Math/tdr.h \
Traces/Math/tracemath.h \
Traces/Math/tracematheditdialog.h \
@ -87,7 +136,45 @@ SOURCES += \
Tools/eseries.cpp \
Tools/impedancematchdialog.cpp \
Traces/Math/dft.cpp \
Traces/Math/expression.cpp \
Traces/Math/medianfilter.cpp \
Traces/Math/parser/mpError.cpp \
Traces/Math/parser/mpFuncCmplx.cpp \
Traces/Math/parser/mpFuncCommon.cpp \
Traces/Math/parser/mpFuncMatrix.cpp \
Traces/Math/parser/mpFuncNonCmplx.cpp \
Traces/Math/parser/mpFuncStr.cpp \
Traces/Math/parser/mpICallback.cpp \
Traces/Math/parser/mpIOprt.cpp \
Traces/Math/parser/mpIPackage.cpp \
Traces/Math/parser/mpIToken.cpp \
Traces/Math/parser/mpIValReader.cpp \
Traces/Math/parser/mpIValue.cpp \
Traces/Math/parser/mpIfThenElse.cpp \
Traces/Math/parser/mpOprtBinAssign.cpp \
Traces/Math/parser/mpOprtBinCommon.cpp \
Traces/Math/parser/mpOprtCmplx.cpp \
Traces/Math/parser/mpOprtIndex.cpp \
Traces/Math/parser/mpOprtMatrix.cpp \
Traces/Math/parser/mpOprtNonCmplx.cpp \
Traces/Math/parser/mpOprtPostfixCommon.cpp \
Traces/Math/parser/mpPackageCmplx.cpp \
Traces/Math/parser/mpPackageCommon.cpp \
Traces/Math/parser/mpPackageMatrix.cpp \
Traces/Math/parser/mpPackageNonCmplx.cpp \
Traces/Math/parser/mpPackageStr.cpp \
Traces/Math/parser/mpPackageUnit.cpp \
Traces/Math/parser/mpParser.cpp \
Traces/Math/parser/mpParserBase.cpp \
Traces/Math/parser/mpParserMessageProvider.cpp \
Traces/Math/parser/mpRPN.cpp \
Traces/Math/parser/mpScriptTokens.cpp \
Traces/Math/parser/mpTest.cpp \
Traces/Math/parser/mpTokenReader.cpp \
Traces/Math/parser/mpValReader.cpp \
Traces/Math/parser/mpValue.cpp \
Traces/Math/parser/mpValueCache.cpp \
Traces/Math/parser/mpVariable.cpp \
Traces/Math/tdr.cpp \
Traces/Math/tracemath.cpp \
Traces/Math/tracematheditdialog.cpp \
@ -140,6 +227,8 @@ FORMS += \
Tools/impedancematchdialog.ui \
Traces/Math/dftdialog.ui \
Traces/Math/dftexplanationwidget.ui \
Traces/Math/expressiondialog.ui \
Traces/Math/expressionexplanationwidget.ui \
Traces/Math/medianexplanationwidget.ui \
Traces/Math/medianfilterdialog.ui \
Traces/Math/newtracemathdialog.ui \

View File

@ -137,6 +137,7 @@ static constexpr Protocol::DeviceInfo defaultInfo = {
.limits_minRBW = 1,
.limits_maxRBW = 1000000,
.limits_maxAmplitudePoints = 255,
.limits_maxFreqHarmonic = 18000000000,
};
Protocol::DeviceInfo Device::lastInfo = defaultInfo;

View File

@ -0,0 +1,120 @@
#include "expression.h"
#include <QWidget>
#include "ui_expressiondialog.h"
#include <QWidget>
#include <QDebug>
#include "Traces/trace.h"
#include "ui_expressionexplanationwidget.h"
using namespace mup;
using namespace std;
Math::Expression::Expression()
{
parser = new ParserX(pckCOMMON | pckUNIT | pckCOMPLEX);
parser->DefineVar("x", Variable(&x));
expressionChanged();
}
Math::Expression::~Expression()
{
delete parser;
}
TraceMath::DataType Math::Expression::outputType(TraceMath::DataType inputType)
{
return inputType;
}
QString Math::Expression::description()
{
return "Custom expression: " + exp;
}
void Math::Expression::edit()
{
auto d = new QDialog();
auto ui = new Ui::ExpressionDialog;
ui->setupUi(d);
ui->expEdit->setText(exp);
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){
exp = ui->expEdit->text();
expressionChanged();
});
if(dataType == DataType::Time) {
// select the label explaining the time domain variables (frequency label is the default)
ui->stackedWidget->setCurrentIndex(1);
}
d->show();
}
QWidget *Math::Expression::createExplanationWidget()
{
auto w = new QWidget();
auto ui = new Ui::ExpressionExplanationWidget;
ui->setupUi(w);
return w;
}
nlohmann::json Math::Expression::toJSON()
{
nlohmann::json j;
j["exp"] = exp.toStdString();
return j;
}
void Math::Expression::fromJSON(nlohmann::json j)
{
exp = QString::fromStdString(j.value("exp", ""));
expressionChanged();
}
void Math::Expression::inputSamplesChanged(unsigned int begin, unsigned int end)
{
auto in = input->rData();
data.resize(in.size());
try {
for(unsigned int i=begin;i<end;i++) {
t = in[i].x;
f = in[i].x;
w = in[i].x * 2 * M_PI;
d = root()->timeToDistance(t);
x = in[i].y;
Value res = parser->Eval();
data[i].x = in[i].x;
data[i].y = res.GetComplex();
}
success();
emit outputSamplesChanged(begin, end);
} catch (const ParserError &e) {
error(QString::fromStdString(e.GetMsg()));
}
}
void Math::Expression::expressionChanged()
{
if(exp.isEmpty()) {
error("Empty expression");
return;
}
parser->SetExpr(exp.toStdString());
parser->RemoveVar("t");
parser->RemoveVar("d");
parser->RemoveVar("f");
parser->RemoveVar("w");
switch(dataType) {
case DataType::Time:
parser->DefineVar("t", Variable(&t));
parser->DefineVar("d", Variable(&d));
break;
case DataType::Frequency:
parser->DefineVar("f", Variable(&f));
parser->DefineVar("w", Variable(&w));
break;
default:
break;
}
if(input) {
inputSamplesChanged(0, input->rData().size());
}
}

View File

@ -0,0 +1,38 @@
#ifndef EXPRESSION_H
#define EXPRESSION_H
#include "tracemath.h"
#include "parser/mpParser.h"
namespace Math {
class Expression : public TraceMath
{
public:
Expression();
~Expression();
DataType outputType(DataType inputType) override;
QString description() override;
void edit() override;
static QWidget* createExplanationWidget();
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;
Type getType() override {return Type::Expression;};
public slots:
void inputSamplesChanged(unsigned int begin, unsigned int end) override;
private slots:
void expressionChanged();
private:
QString exp;
mup::ParserX *parser;
mup::Value t, d, f, w, x;
};
}
#endif // EXPRESSION_H

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExpressionDialog</class>
<widget class="QDialog" name="ExpressionDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>637</width>
<height>313</height>
</rect>
</property>
<property name="windowTitle">
<string>Custom Expression</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Expression:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="expEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="frequencyPage">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available variables:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;x: the S parameter as a (complex) voltage vector. &lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;f: measurement frequency in Hz&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;w: angular measurement frequency (w = 2πf)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Examples:&lt;br/&gt;Add 10db to the trace (10db = exp10(10/20) = sqrt(10)):&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;x * sqrt(10)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Clip trace at 0db (0db = exp10(0/20) = 1) while preserving phase:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;abs(x) &amp;lt; 1 ? x : exp(i*arg(x))&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="timePage">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available variables:&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;x: the impulse response as a (complex) vector. &lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;t: time in seconds&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;d: distance in meters&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ExpressionDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExpressionExplanationWidget</class>
<widget class="QWidget" name="ExpressionExplanationWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>417</width>
<height>421</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="widget">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Custom Expression&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Create your own math function by defining a custom expression that is applied to the data. Depending on the input domain, the expression works in the time or frequency domain.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>251</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,51 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MUP_COMPAT_H
#define MUP_COMPAT_H
// This file contains code to maintain backwards compatibility with older compilers.
// Note: This does not work on windows since the lazy bums at microsoft are unable to assign a macro value properly and
// don't give a shit in general:
//
// https ://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l
//
// I'll hereby officially announce that i also stopped giving a shit whether this library runs on anything older then VS2013. This
// is not a bug, please refrein from reporting it. Seriousely, report it to Microsoft.
#if !defined(_MSC_VER) && __cplusplus <= 199711L
// Warning: If you activate this in a project on windows all hell will break loose and Satan himself will come out of hell to eat
// your soul whilst reciting verses from the Microsoft MFC programming manual.
#define override
#define unique_ptr auto_ptr
#define nullptr NULL
#endif
#endif

View File

@ -0,0 +1,106 @@
/** \file
\brief A file containing macros used by muParserX
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_DEFINES_H
#define MUP_DEFINES_H
#include <cassert>
#if defined(_UNICODE)
#if !defined(_T)
#define _T(x) L##x
#endif // not defined _T
#define MUP_STRING_TYPE std::wstring
#else
#ifndef _T
/** \brief Macro needed for the "unicodification" of strings. */
#define _T(x) x
#endif
/** \brief The string type used by muParserX.
This macro is needed for UNICODE support.
*/
#define MUP_STRING_TYPE std::string
#endif
/** \brief A macro containing the version of muParserX. */
#define MUP_PARSER_VERSION _T("4.0.9 (2020-06-19; Dev)")
/** \brief A macro for setting the parser namespace. */
#define MUP_NAMESPACE_START namespace mup {
/** \brief Closing bracket for the parser namespace macro. */
#define MUP_NAMESPACE_END }
/** \brief Floating point type used by the parser. */
#define MUP_FLOAT_TYPE double
#define MUP_INT_TYPE int
/** \brief Verifies whether a given condition is met.
If the condition is not met an exception is thrown otherwise nothing happens.
This macro is used for implementing asserts. Unlike MUP_ASSERT, MUP_VERIFY
will not be removed in release builds.
*/
#define MUP_VERIFY(COND) \
if (!(COND)) \
{ \
stringstream_type ss; \
ss << _T("Assertion \"") _T(#COND) _T("\" failed: ") \
<< __FILE__ << _T(" line ") \
<< __LINE__ << _T("."); \
throw ParserError( ss.str() ); \
}
#if defined(_DEBUG)
#define MUP_TOK_CAST(TYPE, POINTER) dynamic_cast<TYPE>(POINTER);
/** \brief Debug macro to force an abortion of the programm with a certain message.
*/
#define MUP_FAIL(MSG) \
bool MSG=false; \
assert(MSG);
#define MUP_LEAKAGE_REPORT
#else
#define MUP_FAIL(MSG)
#define MUP_TOK_CAST(TYPE, POINTER) static_cast<TYPE>(POINTER);
#endif
#endif

View File

@ -0,0 +1,260 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpError.h"
#include "mpIToken.h"
#include "mpParserMessageProvider.h"
MUP_NAMESPACE_START
std::unique_ptr<ParserMessageProviderBase> ParserErrorMsg::m_pInstance;
const ParserMessageProviderBase& ParserErrorMsg::Instance()
{
if (!m_pInstance.get())
{
m_pInstance.reset(new ParserMessageProviderEnglish);
m_pInstance->Init();
}
return *m_pInstance;
}
void ParserErrorMsg::Reset(ParserMessageProviderBase* pProvider)
{
if (pProvider != nullptr)
{
m_pInstance.reset(pProvider);
m_pInstance->Init();
}
}
string_type ParserErrorMsg::GetErrorMsg(EErrorCodes eError) const
{
if (!m_pInstance.get())
return string_type();
else
return m_pInstance->GetErrorMsg(eError);
}
ParserErrorMsg::~ParserErrorMsg()
{}
ParserErrorMsg::ParserErrorMsg()
{}
//---------------------------------------------------------------------------
//
// Error context
//
//---------------------------------------------------------------------------
/** \brief Constructs an empty Error context structure. */
ErrorContext::ErrorContext(EErrorCodes a_iErrc, int a_iPos, string_type a_sIdent)
:Expr()
, Ident(a_sIdent)
, Hint()
, Errc(a_iErrc)
, Type1(0)
, Type2(0)
, Arg(-1)
, Pos(a_iPos)
{}
ErrorContext::ErrorContext(EErrorCodes iErrc, int iPos, string_type sIdent, char_type cType1, char_type cType2, int nArg)
:Expr()
, Ident(sIdent)
, Hint()
, Errc(iErrc)
, Type1(cType1)
, Type2(cType2)
, Arg(nArg)
, Pos(iPos)
{}
//---------------------------------------------------------------------------
//
// ParserError class
//
//---------------------------------------------------------------------------
ParserError::ParserError()
:m_Err()
, m_sMsg()
, m_ErrMsg(ParserErrorMsg::Instance())
{}
ParserError::ParserError(const string_type& sMsg, EErrorCodes ec)
:m_Err()
,m_sMsg(sMsg)
,m_ErrMsg(ParserErrorMsg::Instance())
{
m_Err.Errc = ec;
}
ParserError::ParserError(const ErrorContext& a_Err)
:m_Err(a_Err)
, m_sMsg()
, m_ErrMsg(ParserErrorMsg::Instance())
{
m_sMsg = m_ErrMsg.GetErrorMsg(a_Err.Errc);
}
ParserError::ParserError(const ParserError& a_Obj)
:m_Err(a_Obj.m_Err)
, m_sMsg(a_Obj.m_sMsg)
, m_ErrMsg(ParserErrorMsg::Instance())
{}
ParserError& ParserError::operator=(const ParserError& a_Obj)
{
if (this == &a_Obj)
return *this;
m_sMsg = a_Obj.m_sMsg;
m_Err = a_Obj.m_Err;
return *this;
}
/** \brief Replace all occurences of a substring with another string. */
void ParserError::ReplaceSubString(string_type& sSource,
const string_type& sFind,
const string_type& sReplaceWith) const
{
string_type sResult;
string_type::size_type iPos(0), iNext(0);
for (;;)
{
iNext = sSource.find(sFind, iPos);
sResult.append(sSource, iPos, iNext - iPos);
if (iNext == string_type::npos)
break;
sResult.append(sReplaceWith);
iPos = iNext + sFind.length();
}
sSource.swap(sResult);
}
/** \brief Replace all occurences of a substring with another string. */
void ParserError::ReplaceSubString(string_type& sSource,
const string_type& sFind,
int iReplaceWith) const
{
stringstream_type stream;
stream << iReplaceWith;
ReplaceSubString(sSource, sFind, stream.str());
}
/** \brief Replace all occurences of a substring with another string. */
void ParserError::ReplaceSubString(string_type& sSource,
const string_type& sFind,
char_type cReplaceWith) const
{
stringstream_type stream;
stream << cReplaceWith;
ReplaceSubString(sSource, sFind, stream.str());
}
void ParserError::Reset()
{
m_sMsg = _T("");
m_Err = ErrorContext();
}
const string_type& ParserError::GetExpr() const
{
return m_Err.Expr;
}
string_type ParserError::GetMsg() const
{
string_type sMsg(m_sMsg);
ReplaceSubString(sMsg, _T("$EXPR$"), m_Err.Expr);
ReplaceSubString(sMsg, _T("$IDENT$"), m_Err.Ident);
ReplaceSubString(sMsg, _T("$POS$"), m_Err.Pos);
ReplaceSubString(sMsg, _T("$ARG$"), m_Err.Arg);
ReplaceSubString(sMsg, _T("$TYPE1$"), m_Err.Type1);
ReplaceSubString(sMsg, _T("$TYPE2$"), m_Err.Type2);
ReplaceSubString(sMsg, _T("$HINT$"), m_Err.Hint);
return sMsg;
}
ErrorContext& ParserError::GetContext()
{
return m_Err;
}
/** \brief Return the expression position related to the error.
If the error is not related to a distinct position this will return -1
*/
int ParserError::GetPos() const
{
return m_Err.Pos;
}
/** \brief Return string related with this token (if available). */
const string_type& ParserError::GetToken() const
{
return m_Err.Ident;
}
/** \brief Return the error code. */
EErrorCodes ParserError::GetCode() const
{
return m_Err.Errc;
}
} // namespace mu

View File

@ -0,0 +1,140 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MUP_ERROR_H
#define MUP_ERROR_H
#include <cassert>
#include <stdexcept>
#include <string>
#include <sstream>
#include <vector>
#include <memory>
#include "mpTypes.h"
#include "mpParserMessageProvider.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------------------------
class ParserErrorMsg
{
public:
~ParserErrorMsg();
static const ParserMessageProviderBase& Instance();
static void Reset(ParserMessageProviderBase *pProvider);
string_type GetErrorMsg(EErrorCodes eError) const;
private:
static std::unique_ptr<ParserMessageProviderBase> m_pInstance;
ParserErrorMsg& operator=(const ParserErrorMsg &);
ParserErrorMsg(const ParserErrorMsg&);
ParserErrorMsg();
};
//---------------------------------------------------------------------------
/** \brief Error context class.
This struct contains the data associated with parser erros.
*/
struct ErrorContext
{
/** \brief Creates an empty ErrorContext object.
All Members are initialised to an invalid state.
*/
ErrorContext(EErrorCodes a_iErrc = ecUNDEFINED, int a_iPos = -1, string_type a_sIdent = string_type() );
ErrorContext(EErrorCodes a_iErrc,
int a_iPos,
string_type a_sIdent,
char_type cType1,
char_type cType2,
int nArg);
string_type Expr; ///> The expression string.
string_type Ident; ///> The identifier of the token that caused the error.
string_type Hint; ///> Additional message
EErrorCodes Errc; ///> The error code
char_type Type1; ///> For type conflicts only! This is the type that was actually found.
char_type Type2; ///> For type conflicts only! This is the type that was expected.
int Arg; ///> The number of arguments that were expected.
int Pos; ///> Position inside the expression where the error occured.
};
//---------------------------------------------------------------------------
/** \brief Error class of the parser.
\author IngecMISSINGo Berg
Part of the math parser package.
*/
class ParserError
{
private:
//------------------------------------------------------------------------------
/** \brief Replace all ocuurences of a substring with another string. */
void ReplaceSubString(string_type &strSource,
const string_type &strFind,
const string_type &strReplaceWith) const;
void ReplaceSubString(string_type &sSource,
const string_type &sFind,
int iReplaceWith) const;
void ReplaceSubString(string_type &sSource,
const string_type &sFind,
char_type cReplaceWith) const;
void Reset();
public:
ParserError();
ParserError(const string_type &sMsg, EErrorCodes ec = ecUNDEFINED);
ParserError(const ErrorContext &a_Err);
ParserError(const ParserError &a_Obj);
ParserError& operator=(const ParserError &a_Obj);
const string_type& GetExpr() const;
string_type GetMsg() const;
int GetPos() const;
const string_type& GetToken() const;
EErrorCodes GetCode() const;
ErrorContext& GetContext();
private:
ErrorContext m_Err; ///< Error context data
string_type m_sMsg; ///< The message string with all wildcards still in place.
const ParserMessageProviderBase &m_ErrMsg;
};
} // namespace mu
#endif

View File

@ -0,0 +1,635 @@
/** \file
\brief Definition of functions for complex valued operations.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpFuncCmplx.h"
//--- Standard includes ----------------------------------------------------
#include <cmath>
#include <cassert>
#include <complex>
#include <iostream>
//--- Parser framework -----------------------------------------------------
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------
//
// class FunCmplxReal
//
//-----------------------------------------------------------------------
FunCmplxReal::FunCmplxReal()
:ICallback(cmFUNC, _T("real"), 1)
{}
//-----------------------------------------------------------------------
FunCmplxReal::~FunCmplxReal()
{}
//-----------------------------------------------------------------------
void FunCmplxReal::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
float_type v = a_pArg[0]->GetFloat();
*ret = v;
}
//-----------------------------------------------------------------------
const char_type* FunCmplxReal::GetDesc() const
{
return _T("real(x) - Returns the real part of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxReal::Clone() const
{
return new FunCmplxReal(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxImag
//
//-----------------------------------------------------------------------
FunCmplxImag::FunCmplxImag()
:ICallback(cmFUNC, _T("imag"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxImag::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
float_type v = a_pArg[0]->GetImag();
*ret = v;
}
//-----------------------------------------------------------------------
const char_type* FunCmplxImag::GetDesc() const
{
return _T("imag(x) - Returns the imaginary part of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxImag::Clone() const
{
return new FunCmplxImag(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxConj
//
//-----------------------------------------------------------------------
FunCmplxConj::FunCmplxConj()
:ICallback(cmFUNC, _T("conj"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxConj::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
*ret = cmplx_type(a_pArg[0]->GetFloat(), -a_pArg[0]->GetImag());
}
//-----------------------------------------------------------------------
const char_type* FunCmplxConj::GetDesc() const
{
return _T("conj(x) - Returns the complex conjugate of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxConj::Clone() const
{
return new FunCmplxConj(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxArg
//
//-----------------------------------------------------------------------
FunCmplxArg::FunCmplxArg()
:ICallback(cmFUNC, _T("arg"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxArg::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = std::arg(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxArg::GetDesc() const
{
return _T("arg(x) - Returns the phase angle (or angular component) of the complex number x, expressed in radians.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxArg::Clone() const
{
return new FunCmplxArg(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxNorm
//
//-----------------------------------------------------------------------
FunCmplxNorm::FunCmplxNorm()
:ICallback(cmFUNC, _T("norm"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxNorm::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = std::norm(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxNorm::GetDesc() const
{
return _T("norm(x) - Returns the norm value of the complex number x.")
_T(" The norm value of a complex number is the squared magnitude,")
_T(" defined as the addition of the square of both the real part")
_T(" and the imaginary part (without the imaginary unit). This is")
_T(" the square of abs (x).");
}
//-----------------------------------------------------------------------
IToken* FunCmplxNorm::Clone() const
{
return new FunCmplxNorm(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxCos
//
//-----------------------------------------------------------------------
FunCmplxCos::FunCmplxCos()
:ICallback(cmFUNC, _T("cos"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxCos::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
if (a_pArg[0]->IsNonComplexScalar())
{
*ret = std::cos(a_pArg[0]->GetFloat());
}
else
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = std::cos(v);
}
}
//-----------------------------------------------------------------------
const char_type* FunCmplxCos::GetDesc() const
{
return _T("cos(x) - Returns the cosine of the number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxCos::Clone() const
{
return new FunCmplxCos(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxSin
//
//-----------------------------------------------------------------------
FunCmplxSin::FunCmplxSin()
:ICallback(cmFUNC, _T("sin"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxSin::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
if (a_pArg[0]->IsNonComplexScalar())
{
*ret = std::sin(a_pArg[0]->GetFloat());
}
else
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = std::sin(v);
}
}
//-----------------------------------------------------------------------
const char_type* FunCmplxSin::GetDesc() const
{
return _T("sin(x) - Returns the sine of the number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxSin::Clone() const
{
return new FunCmplxSin(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxCosH
//
//-----------------------------------------------------------------------
FunCmplxCosH::FunCmplxCosH()
:ICallback(cmFUNC, _T("cosh"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxCosH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = cosh(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxCosH::GetDesc() const
{
return _T("cosh(x) - Returns the hyperbolic cosine of the number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxCosH::Clone() const
{
return new FunCmplxCosH(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxSinH
//
//-----------------------------------------------------------------------
FunCmplxSinH::FunCmplxSinH()
:ICallback(cmFUNC, _T("sinh"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxSinH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = sinh(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxSinH::GetDesc() const
{
return _T("sinh(x) - Returns the hyperbolic sine of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxSinH::Clone() const
{
return new FunCmplxSinH(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxTan
//
//-----------------------------------------------------------------------
FunCmplxTan::FunCmplxTan()
:ICallback(cmFUNC, _T("tan"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxTan::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
if (a_pArg[0]->IsNonComplexScalar())
{
*ret = std::tan(a_pArg[0]->GetFloat());
}
else
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = std::tan(v);
}
}
//-----------------------------------------------------------------------
const char_type* FunCmplxTan::GetDesc() const
{
return _T("tan(x) - Returns the tangens of the number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxTan::Clone() const
{
return new FunCmplxTan(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxTanH
//
//-----------------------------------------------------------------------
FunCmplxTanH::FunCmplxTanH()
:ICallback(cmFUNC, _T("tanh"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxTanH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = tanh(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxTanH::GetDesc() const
{
return _T("tanh(x) - Returns the hyperbolic tangent of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxTanH::Clone() const
{
return new FunCmplxTanH(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxSqrt
//
//-----------------------------------------------------------------------
FunCmplxSqrt::FunCmplxSqrt()
:ICallback(cmFUNC, _T("sqrt"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxSqrt::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
*ret = sqrt((*a_pArg[0]).GetComplex());
}
//-----------------------------------------------------------------------
const char_type* FunCmplxSqrt::GetDesc() const
{
return _T("sqrt(x) - Returns the square root of x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxSqrt::Clone() const
{
return new FunCmplxSqrt(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxExp
//
//-----------------------------------------------------------------------
FunCmplxExp::FunCmplxExp()
:ICallback(cmFUNC, _T("exp"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxExp::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = exp(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxExp::GetDesc() const
{
return _T("exp(x) - Returns the base-e exponential of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxExp::Clone() const
{
return new FunCmplxExp(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxLn
//
//-----------------------------------------------------------------------
FunCmplxLn::FunCmplxLn()
:ICallback(cmFUNC, _T("ln"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxLn::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = log(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxLn::GetDesc() const
{
return _T("ln(x) - Returns the natural (base-e) logarithm of the complex number x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxLn::Clone() const
{
return new FunCmplxLn(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxLog
//
//-----------------------------------------------------------------------
FunCmplxLog::FunCmplxLog()
:ICallback(cmFUNC, _T("log"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxLog::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = log(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxLog::GetDesc() const
{
return _T("log(x) - Common logarithm of x, for values of x greater than zero.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxLog::Clone() const
{
return new FunCmplxLog(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxLog10
//
//-----------------------------------------------------------------------
FunCmplxLog10::FunCmplxLog10()
:ICallback(cmFUNC, _T("log10"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxLog10::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = log10(v);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxLog10::GetDesc() const
{
return _T("log10(x) - Common logarithm of x, for values of x greater than zero.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxLog10::Clone() const
{
return new FunCmplxLog10(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxLog2
//
//-----------------------------------------------------------------------
FunCmplxLog2::FunCmplxLog2()
:ICallback(cmFUNC, _T("log2"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxLog2::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
std::complex<float_type> v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
*ret = std::log(v) * (float_type)1.0/std::log((float_type)2.0);
}
//-----------------------------------------------------------------------
const char_type* FunCmplxLog2::GetDesc() const
{
return _T("log2(x) - Logarithm to base 2 of x, for values of x greater than zero.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxLog2::Clone() const
{
return new FunCmplxLog2(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxAbs
//
//-----------------------------------------------------------------------
FunCmplxAbs::FunCmplxAbs()
:ICallback(cmFUNC, _T("abs"), 1)
{}
//-----------------------------------------------------------------------
void FunCmplxAbs::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
float_type v = sqrt(a_pArg[0]->GetFloat()*a_pArg[0]->GetFloat() +
a_pArg[0]->GetImag()*a_pArg[0]->GetImag());
*ret = v;
}
//-----------------------------------------------------------------------
const char_type* FunCmplxAbs::GetDesc() const
{
return _T("abs(x) - Returns the absolute value of x.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxAbs::Clone() const
{
return new FunCmplxAbs(*this);
}
//-----------------------------------------------------------------------
//
// class FunCmplxPow
//
//-----------------------------------------------------------------------
FunCmplxPow::FunCmplxPow()
:ICallback(cmFUNC, _T("pow"), 2)
{}
//-----------------------------------------------------------------------
void FunCmplxPow::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
*ret = std::pow(a_pArg[0]->GetComplex(), a_pArg[1]->GetComplex());
}
//-----------------------------------------------------------------------
const char_type* FunCmplxPow::GetDesc() const
{
return _T("pox(x, y) - Raise x to the power of y.");
}
//-----------------------------------------------------------------------
IToken* FunCmplxPow::Clone() const
{
return new FunCmplxPow(*this);
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,262 @@
/** \file
\brief Definition of functions for complex valued operations.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_COMPLEX_FUNCTIONS_H
#define MUP_COMPLEX_FUNCTIONS_H
#include "mpICallback.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------
/** \brief Parser callback object for returning the real part of a complex number.
\ingroup functions
*/
class FunCmplxReal : public ICallback
{
public:
FunCmplxReal();
virtual ~FunCmplxReal();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Parser callback object for returning the imaginary part of a complex number.
\ingroup functions
*/
class FunCmplxImag : public ICallback
{
public:
FunCmplxImag();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Parser callback object for returning the complex conjugate of
the complex number.
\ingroup functions
*/
class FunCmplxConj : public ICallback
{
public:
FunCmplxConj();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Parser callback object for returning the phase angle
(or angular component) of a complex number, expressed in radians.
\ingroup functions
*/
class FunCmplxArg : public ICallback
{
public:
FunCmplxArg();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Parser callback object for returning the norm value of the
complex number phase angle.
\ingroup functions
*/
class FunCmplxNorm : public ICallback
{
public:
FunCmplxNorm();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxCos : public ICallback
{
public:
FunCmplxCos();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxSin : public ICallback
{
public:
FunCmplxSin();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxCosH : public ICallback
{
public:
FunCmplxCosH();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxSinH : public ICallback
{
public:
FunCmplxSinH();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxTan : public ICallback
{
public:
FunCmplxTan();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxTanH : public ICallback
{
public:
FunCmplxTanH();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxSqrt : public ICallback
{
public:
FunCmplxSqrt();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxExp : public ICallback
{
public:
FunCmplxExp();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxLn : public ICallback
{
public:
FunCmplxLn();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxLog : public ICallback
{
public:
FunCmplxLog();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxLog10 : public ICallback
{
public:
FunCmplxLog10();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxLog2 : public ICallback
{
public:
FunCmplxLog2();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxAbs : public ICallback
{
public:
FunCmplxAbs();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
class FunCmplxPow : public ICallback
{
public:
FunCmplxPow();
virtual void Eval(ptr_val_type& ret, const ptr_val_type* a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
} // namespace mu
#endif

View File

@ -0,0 +1,272 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpFuncCommon.h"
#include <cassert>
#include <string>
#include <iostream>
#include "mpValue.h"
#include "mpParserBase.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
//
// FunParserID
//
//------------------------------------------------------------------------------
FunParserID::FunParserID()
:ICallback(cmFUNC, _T("parserid"), 0)
{}
//------------------------------------------------------------------------------
void FunParserID::Eval(ptr_val_type &ret, const ptr_val_type * /*a_pArg*/, int /*a_iArgc*/)
{
string_type sVer = _T("muParserX V") + GetParent()->GetVersion();
*ret = sVer;
}
//------------------------------------------------------------------------------
const char_type* FunParserID::GetDesc() const
{
return _T("parserid() - muParserX version information");
}
//------------------------------------------------------------------------------
IToken* FunParserID::Clone() const
{
return new FunParserID(*this);
}
//------------------------------------------------------------------------------
//
// Max Function
//
//------------------------------------------------------------------------------
FunMax::FunMax() : ICallback(cmFUNC, _T("max"), -1)
{}
//------------------------------------------------------------------------------
void FunMax::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
if (a_iArgc < 1)
throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent()));
float_type max(-1e30), val(0);
for (int i=0; i<a_iArgc; ++i)
{
switch(a_pArg[i]->GetType())
{
case 'f':
case 'i': val = a_pArg[i]->GetFloat(); break;
case 'n': break; // ignore not in list entries (missing parameter)
case 'c':
default:
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = i+1;
err.Type1 = a_pArg[i]->GetType();
err.Type2 = 'f';
throw ParserError(err);
}
}
max = std::max(max, val);
}
*ret = max;
}
//------------------------------------------------------------------------------
const char_type* FunMax::GetDesc() const
{
return _T("max(x,y,...,z) - Returns the maximum value from all of its function arguments.");
}
//------------------------------------------------------------------------------
IToken* FunMax::Clone() const
{
return new FunMax(*this);
}
//------------------------------------------------------------------------------
//
// Min Function
//
//------------------------------------------------------------------------------
FunMin::FunMin() : ICallback(cmFUNC, _T("min"), -1)
{}
//------------------------------------------------------------------------------
/** \brief Returns the minimum value of all values.
\param a_pArg Pointer to an array of Values
\param a_iArgc Number of values stored in a_pArg
*/
void FunMin::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
if (a_iArgc < 1)
throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent()));
float_type min(1e30), val(min);
for (int i=0; i<a_iArgc; ++i)
{
switch(a_pArg[i]->GetType())
{
case 'f':
case 'i': val = a_pArg[i]->GetFloat(); break;
default:
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = i+1;
err.Type1 = a_pArg[i]->GetType();
err.Type2 = 'f';
throw ParserError(err);
}
}
min = std::min(min, val);
}
*ret = min;
}
//------------------------------------------------------------------------------
const char_type* FunMin::GetDesc() const
{
return _T("min(x,y,...,z) - Returns the minimum value from all of its function arguments.");
}
//------------------------------------------------------------------------------
IToken* FunMin::Clone() const
{
return new FunMin(*this);
}
//------------------------------------------------------------------------------
//
// class FunSum
//
//------------------------------------------------------------------------------
FunSum::FunSum()
:ICallback(cmFUNC, _T("sum"), -1)
{}
//------------------------------------------------------------------------------
/** \brief Returns the minimum value of all values.
\param a_pArg Pointer to an array of Values
\param a_iArgc Number of values stored in a_pArg
*/
void FunSum::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
if (a_iArgc < 1)
throw ParserError(ErrorContext(ecTOO_FEW_PARAMS, GetExprPos(), GetIdent()));
float_type sum(0);
for (int i=0; i<a_iArgc; ++i)
{
switch(a_pArg[i]->GetType())
{
case 'f':
case 'i': sum += a_pArg[i]->GetFloat(); break;
default:
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = i+1;
err.Type1 = a_pArg[i]->GetType();
err.Type2 = 'f';
throw ParserError(err);
}
}
}
*ret = sum;
}
//------------------------------------------------------------------------------
const char_type* FunSum::GetDesc() const
{
return _T("sum(x,y,...,z) - Returns the sum of all arguments.");
}
//------------------------------------------------------------------------------
IToken* FunSum::Clone() const
{
return new FunSum(*this);
}
//------------------------------------------------------------------------------
//
// SizeOf
//
//------------------------------------------------------------------------------
FunSizeOf::FunSizeOf()
:ICallback(cmFUNC, _T("sizeof"), 1)
{}
//------------------------------------------------------------------------------
FunSizeOf::~FunSizeOf()
{}
//------------------------------------------------------------------------------
/** \brief Returns the number of elements stored in the first parameter. */
void FunSizeOf::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
assert(a_iArgc==1);
*ret = (float_type)a_pArg[0]->GetArray().GetRows();
}
//------------------------------------------------------------------------------
const char_type* FunSizeOf::GetDesc() const
{
return _T("sizeof(a) - Returns the number of elements in a.");
}
//------------------------------------------------------------------------------
IToken* FunSizeOf::Clone() const
{
return new FunSizeOf(*this);
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,111 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MUP_FUNC_COMMON_H
#define MUP_FUNC_COMMON_H
#include "mpICallback.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Parser function callback for determining the size of an array.
\ingroup functions
*/
class FunParserID : public ICallback
{
public:
FunParserID ();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunParserID
//------------------------------------------------------------------------------
/** \brief Determine maximal value from the parameter list.
\ingroup functions
*/
class FunMax : public ICallback
{
public:
FunMax();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunMax
//------------------------------------------------------------------------------
/** \brief Determine minimal value from the parameter list.
\ingroup functions
*/
class FunMin : public ICallback
{
public:
FunMin();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunMin
//------------------------------------------------------------------------------
/** \brief Parser callback for summing up all function arguments.
\ingroup functions
*/
class FunSum : public ICallback
{
public:
FunSum();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunSum
//------------------------------------------------------------------------------
/** \brief Parser function callback for determining the size of an array.
\ingroup functions
*/
class FunSizeOf : public ICallback
{
public:
FunSizeOf();
virtual ~FunSizeOf();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunSizeOf
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,249 @@
/** \file
\brief Definition of functions for complex valued operations.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpFuncMatrix.h"
//--- Standard includes ----------------------------------------------------
#include <cmath>
#include <cassert>
#include <complex>
#include <iostream>
//--- Parser framework -----------------------------------------------------
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------
//
// class FunMatrixOnes
//
//-----------------------------------------------------------------------
FunMatrixOnes::FunMatrixOnes()
:ICallback(cmFUNC, _T("ones"), -1)
{}
//-----------------------------------------------------------------------
FunMatrixOnes::~FunMatrixOnes()
{}
//-----------------------------------------------------------------------
void FunMatrixOnes::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc)
{
if (argc < 1 || argc>2)
{
ErrorContext err;
err.Errc = ecINVALID_NUMBER_OF_PARAMETERS;
err.Arg = argc;
err.Ident = GetIdent();
throw ParserError(err);
}
int_type m = a_pArg[0]->GetInteger(),
n = (argc == 1) ? m : a_pArg[1]->GetInteger();
if (m == n && n == 1)
{
*ret = 1.0; // unboxing of 1x1 matrices
}
else
{
*ret = matrix_type(m, n, 1.0);
}
}
//-----------------------------------------------------------------------
const char_type* FunMatrixOnes::GetDesc() const
{
return _T("ones(x [, y]) - Returns a matrix whose elements are all 1.");
}
//-----------------------------------------------------------------------
IToken* FunMatrixOnes::Clone() const
{
return new FunMatrixOnes(*this);
}
//-----------------------------------------------------------------------
//
// class FunMatrixZeros
//
//-----------------------------------------------------------------------
FunMatrixZeros::FunMatrixZeros()
:ICallback(cmFUNC, _T("zeros"), -1)
{}
//-----------------------------------------------------------------------
FunMatrixZeros::~FunMatrixZeros()
{}
//-----------------------------------------------------------------------
void FunMatrixZeros::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc)
{
if (argc < 1 || argc>2)
{
ErrorContext err;
err.Errc = ecINVALID_NUMBER_OF_PARAMETERS;
err.Arg = argc;
err.Ident = GetIdent();
throw ParserError(err);
}
int_type m = a_pArg[0]->GetInteger(),
n = (argc == 1) ? m : a_pArg[1]->GetInteger();
if (m == n && n == 1)
{
*ret = 0.0; // unboxing of 1x1 matrices
}
else
{
*ret = matrix_type(m, n, 0.0);
}
}
//-----------------------------------------------------------------------
const char_type* FunMatrixZeros::GetDesc() const
{
return _T("zeros(x [, y]) - Returns a matrix whose elements are all 0.");
}
//-----------------------------------------------------------------------
IToken* FunMatrixZeros::Clone() const
{
return new FunMatrixZeros(*this);
}
//-----------------------------------------------------------------------
//
// class FunMatrixEye
//
//-----------------------------------------------------------------------
FunMatrixEye::FunMatrixEye()
:ICallback(cmFUNC, _T("eye"), -1)
{}
//-----------------------------------------------------------------------
FunMatrixEye::~FunMatrixEye()
{}
//-----------------------------------------------------------------------
void FunMatrixEye::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc)
{
if (argc < 1 || argc>2)
{
ErrorContext err;
err.Errc = ecINVALID_NUMBER_OF_PARAMETERS;
err.Arg = argc;
err.Ident = GetIdent();
throw ParserError(err);
}
int_type m = a_pArg[0]->GetInteger(),
n = (argc == 1) ? m : a_pArg[1]->GetInteger();
matrix_type eye(m, n, 0.0);
for (int i = 0; i < std::min(m, n); ++i)
{
eye.At(i, i) = 1.0;
}
*ret = eye;
}
//-----------------------------------------------------------------------
const char_type* FunMatrixEye::GetDesc() const
{
return _T("eye(x, y) - returns a matrix with ones on its diagonal and zeros elsewhere.");
}
//-----------------------------------------------------------------------
IToken* FunMatrixEye::Clone() const
{
return new FunMatrixEye(*this);
}
//-----------------------------------------------------------------------
//
// class FunMatrixSize
//
//-----------------------------------------------------------------------
FunMatrixSize::FunMatrixSize()
:ICallback(cmFUNC, _T("size"), -1)
{}
//-----------------------------------------------------------------------
FunMatrixSize::~FunMatrixSize()
{}
//-----------------------------------------------------------------------
void FunMatrixSize::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int argc)
{
if (argc != 1)
{
ErrorContext err;
err.Errc = ecINVALID_NUMBER_OF_PARAMETERS;
err.Arg = argc;
err.Ident = GetIdent();
throw ParserError(err);
}
matrix_type sz(1, 2, 0.0);
sz.At(0, 0) = (float_type)a_pArg[0]->GetRows();
sz.At(0, 1) = (float_type)a_pArg[0]->GetCols();
*ret = sz;
}
//-----------------------------------------------------------------------
const char_type* FunMatrixSize::GetDesc() const
{
return _T("size(x) - returns the matrix dimensions.");
}
//-----------------------------------------------------------------------
IToken* FunMatrixSize::Clone() const
{
return new FunMatrixSize(*this);
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,103 @@
/** \file
\brief Definition of functions for complex valued operations.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_FUNC_MATRIX_H
#define MUP_FUNC_MATRIX_H
#include "mpICallback.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------
/** \brief Parser callback object for creating matrices consisting
entirely of ones.
\ingroup functions
*/
class FunMatrixOnes : public ICallback
{
public:
FunMatrixOnes();
virtual ~FunMatrixOnes();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Parser callback object for creating matrices consisting
entirely of zeros.
\ingroup functions
*/
class FunMatrixZeros : public ICallback
{
public:
FunMatrixZeros();
virtual ~FunMatrixZeros();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Parser callback object for creating unity matrices.
\ingroup functions
*/
class FunMatrixEye : public ICallback
{
public:
FunMatrixEye();
virtual ~FunMatrixEye();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------
/** \brief Determines the dimensions of a matrix.
\ingroup functions
*/
class FunMatrixSize : public ICallback
{
public:
FunMatrixSize();
virtual ~FunMatrixSize();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
} // namespace mu
#endif

View File

@ -0,0 +1,126 @@
/** \file
\brief Implementation of basic functions used by muParserX.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpFuncNonCmplx.h"
//--- Standard includes ----------------------------------------------------
#include <cmath>
#include <cassert>
#include <iostream>
//--- muParserX framework --------------------------------------------------
#include "mpValue.h"
#include "mpError.h"
#undef log
#undef log2
MUP_NAMESPACE_START
#define MUP_UNARY_FUNC(CLASS, IDENT, FUNC, DESC) \
CLASS::CLASS() \
:ICallback(cmFUNC, _T(IDENT), 1) \
{} \
\
void CLASS::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) \
{ \
*ret = FUNC(a_pArg[0]->GetFloat()); \
} \
\
const char_type* CLASS::GetDesc() const \
{ \
return _T(DESC); \
} \
\
IToken* CLASS::Clone() const \
{ \
return new CLASS(*this); \
}
// trigonometric functions
MUP_UNARY_FUNC(FunTan, "sin", std::sin, "sine function")
MUP_UNARY_FUNC(FunCos, "cos", std::cos, "cosine function")
MUP_UNARY_FUNC(FunSin, "tan", std::tan, "tangens function")
// arcus functions
MUP_UNARY_FUNC(FunASin, "asin", std::asin, "arcus sine")
MUP_UNARY_FUNC(FunACos, "acos", std::acos, "arcus cosine")
MUP_UNARY_FUNC(FunATan, "atan", std::atan, "arcus tangens")
// hyperbolic functions
MUP_UNARY_FUNC(FunSinH, "sinh", std::sinh, "hyperbolic sine")
MUP_UNARY_FUNC(FunCosH, "cosh", std::cosh, "hyperbolic cosine")
MUP_UNARY_FUNC(FunTanH, "tanh", std::tanh, "hyperbolic tangens")
// hyperbolic arcus functions
MUP_UNARY_FUNC(FunASinH, "asinh", std::asinh, "hyperbolic arcus sine")
MUP_UNARY_FUNC(FunACosH, "acosh", std::acosh, "hyperbolic arcus cosine")
MUP_UNARY_FUNC(FunATanH, "atanh", std::atanh, "hyperbolic arcus tangens")
// logarithm functions
MUP_UNARY_FUNC(FunLog, "log", std::log, "Natural logarithm")
MUP_UNARY_FUNC(FunLog10, "log10", std::log10, "Logarithm base 10")
MUP_UNARY_FUNC(FunLog2, "log2", std::log2, "Logarithm base 2")
MUP_UNARY_FUNC(FunLn, "ln", std::log, "Natural logarithm")
// square root
MUP_UNARY_FUNC(FunSqrt, "sqrt", std::sqrt, "sqrt(x) - square root of x")
MUP_UNARY_FUNC(FunCbrt, "cbrt", std::cbrt, "cbrt(x) - cubic root of x")
MUP_UNARY_FUNC(FunExp, "exp", std::exp, "exp(x) - e to the power of x")
MUP_UNARY_FUNC(FunAbs, "abs", std::fabs, "abs(x) - absolute value of x")
#undef MUP_UNARY_FUNC
#define MUP_BINARY_FUNC(CLASS, IDENT, FUNC, DESC) \
CLASS::CLASS() \
:ICallback(cmFUNC, _T(IDENT), 2) \
{} \
\
void CLASS::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) \
{ \
*ret = FUNC(a_pArg[0]->GetFloat(), a_pArg[1]->GetFloat()); \
} \
\
const char_type* CLASS::GetDesc() const \
{ \
return _T(DESC); \
} \
\
IToken* CLASS::Clone() const \
{ \
return new CLASS(*this); \
}
MUP_BINARY_FUNC(FunPow, "pow", std::pow, "pow(x, y) - raise x to the power of y")
MUP_BINARY_FUNC(FunHypot, "hypot", std::hypot, "hypot(x, y) - compute the length of the vector x,y")
MUP_BINARY_FUNC(FunAtan2, "atan2", std::atan2, "arcus tangens with quadrant fix")
MUP_BINARY_FUNC(FunFmod, "fmod", std::fmod, "fmod(x, y) - floating point remainder of x / y")
MUP_BINARY_FUNC(FunRemainder, "remainder", std::remainder, "remainder(x, y) - IEEE remainder of x / y")
#undef MUP_BINARY_FUNC
MUP_NAMESPACE_END

View File

@ -0,0 +1,104 @@
/** \file
\brief Implementation of basic functions used by muParserX.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_FUNC_NON_CMPLX_H
#define MUP_FUNC_NON_CMPLX_H
#include "mpICallback.h"
/** \defgroup functions Function callback objects.
This group lists the objects representing parser functions.
*/
MUP_NAMESPACE_START
#define MUP_UNARY_FUNC_DEF(CLASS) \
class CLASS : public ICallback \
{ \
public: \
CLASS(); \
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; \
virtual const char_type* GetDesc() const override; \
virtual IToken* Clone() const override; \
};
MUP_UNARY_FUNC_DEF(FunSin)
MUP_UNARY_FUNC_DEF(FunCos)
MUP_UNARY_FUNC_DEF(FunTan)
// arcus functions
MUP_UNARY_FUNC_DEF(FunASin)
MUP_UNARY_FUNC_DEF(FunACos)
MUP_UNARY_FUNC_DEF(FunATan)
// hyperbolic functions
MUP_UNARY_FUNC_DEF(FunSinH)
MUP_UNARY_FUNC_DEF(FunCosH)
MUP_UNARY_FUNC_DEF(FunTanH)
// hyperbolic arcus functions
MUP_UNARY_FUNC_DEF(FunASinH)
MUP_UNARY_FUNC_DEF(FunACosH)
MUP_UNARY_FUNC_DEF(FunATanH)
// logarithm functions
MUP_UNARY_FUNC_DEF(FunLog)
MUP_UNARY_FUNC_DEF(FunLog10)
MUP_UNARY_FUNC_DEF(FunLog2)
MUP_UNARY_FUNC_DEF(FunLn)
// square root
MUP_UNARY_FUNC_DEF(FunSqrt)
MUP_UNARY_FUNC_DEF(FunCbrt)
MUP_UNARY_FUNC_DEF(FunExp)
MUP_UNARY_FUNC_DEF(FunAbs)
#undef MUP_UNARY_FUNC_DEF
#define MUP_BINARY_FUNC_DEF(CLASS) \
class CLASS : public ICallback \
{ \
public: \
CLASS(); \
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override; \
virtual const char_type* GetDesc() const override; \
virtual IToken* Clone() const override; \
};
MUP_BINARY_FUNC_DEF(FunPow)
MUP_BINARY_FUNC_DEF(FunHypot)
MUP_BINARY_FUNC_DEF(FunAtan2)
MUP_BINARY_FUNC_DEF(FunFmod)
MUP_BINARY_FUNC_DEF(FunRemainder)
#undef MUP_BINARY_FUNC_DEF
} // namespace mu
#endif

View File

@ -0,0 +1,180 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpFuncStr.h"
#include <cmath>
#include <cassert>
#include <cstdio>
#include <cwchar>
#include <algorithm>
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
//
// Strlen function
//
//------------------------------------------------------------------------------
FunStrLen::FunStrLen()
:ICallback(cmFUNC, _T("strlen"), 1)
{}
//------------------------------------------------------------------------------
void FunStrLen::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
string_type str = a_pArg[0]->GetString();
*ret = (float_type)str.length();
}
//------------------------------------------------------------------------------
const char_type* FunStrLen::GetDesc() const
{
return _T("strlen(s) - Returns the length of the string s.");
}
//------------------------------------------------------------------------------
IToken* FunStrLen::Clone() const
{
return new FunStrLen(*this);
}
//------------------------------------------------------------------------------
//
// ToUpper function
//
//------------------------------------------------------------------------------
FunStrToUpper::FunStrToUpper()
:ICallback(cmFUNC, _T("toupper"), 1)
{}
//------------------------------------------------------------------------------
void FunStrToUpper::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
using namespace std;
string_type str = a_pArg[0]->GetString();
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
*ret = str;
}
//------------------------------------------------------------------------------
const char_type* FunStrToUpper::GetDesc() const
{
return _T("toupper(s) - Converts the string s to uppercase characters.");
}
//------------------------------------------------------------------------------
IToken* FunStrToUpper::Clone() const
{
return new FunStrToUpper(*this);
}
//------------------------------------------------------------------------------
//
// ToLower function
//
//------------------------------------------------------------------------------
FunStrToLower::FunStrToLower()
:ICallback(cmFUNC, _T("tolower"), 1)
{}
//------------------------------------------------------------------------------
void FunStrToLower::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
using namespace std;
string_type str = a_pArg[0]->GetString();
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
*ret = str;
}
//------------------------------------------------------------------------------
const char_type* FunStrToLower::GetDesc() const
{
return _T("tolower(s) - Converts the string s to lowercase characters.");
}
//------------------------------------------------------------------------------
IToken* FunStrToLower::Clone() const
{
return new FunStrToLower(*this);
}
//------------------------------------------------------------------------------
//
// String to double conversion
//
//------------------------------------------------------------------------------
FunStrToDbl::FunStrToDbl()
:ICallback(cmFUNC, _T("str2dbl"), 1)
{}
//------------------------------------------------------------------------------
void FunStrToDbl::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
assert(a_iArgc==1);
string_type in;
double out; // <- Ich will hier wirklich double, auch wenn der Type long double
// ist. sscanf und long double geht nicht mit GCC!
in = a_pArg[0]->GetString();
#ifndef _UNICODE
sscanf(in.c_str(), "%lf", &out);
#else
swscanf(in.c_str(), _T("%lf"), &out);
#endif
*ret = (float_type)out;
}
//------------------------------------------------------------------------------
const char_type* FunStrToDbl::GetDesc() const
{
return _T("str2dbl(s) - Converts the string stored in s into a floating foint value.");
}
//------------------------------------------------------------------------------
IToken* FunStrToDbl::Clone() const
{
return new FunStrToDbl(*this);
}
} // namespace mu

View File

@ -0,0 +1,92 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MUP_FUNC_STR_H
#define MUP_FUNC_STR_H
#include "mpICallback.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Callback object for determining the length of a string.
\ingroup functions
*/
class FunStrLen : public ICallback
{
public:
FunStrLen();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Convert a string to upper case letters.
\ingroup functions
*/
class FunStrToUpper : public ICallback
{
public:
FunStrToUpper();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Convert a string to lower case letters.
\ingroup functions
*/
class FunStrToLower : public ICallback
{
public:
FunStrToLower();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Parse string to a floating point value.
\ingroup functions
*/
class FunStrToDbl : public ICallback
{
public:
FunStrToDbl ();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class FunStrToDbl
} // namespace mu
#endif

View File

@ -0,0 +1,55 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MUP_FWD_DECL_H
#define MUP_FWD_DECL_H
#include "mpDefines.h"
MUP_NAMESPACE_START
class ParserXBase;
class ParserMessageProviderBase;
class ICallback;
class IToken;
class IValue;
class IValueReader;
class IPrecedence;
class IOprtIndex;
class Value;
class ValueCache;
template<typename T>
class TokenPtr;
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,141 @@
/** \file
\brief Implementation of the interface for parser callback objects.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpICallback.h"
#include <cassert>
#include "mpParserBase.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
ICallback::ICallback(ECmdCode a_iCode,
const char_type *a_szName,
int a_nArgc)
:IToken(a_iCode, a_szName)
,m_pParent(nullptr)
,m_nArgc(a_nArgc)
,m_nArgsPresent(-1)
{}
//------------------------------------------------------------------------------
ICallback::~ICallback()
{}
//---------------------------------------------------------------------------
ICallback* ICallback::AsICallback()
{
return this;
}
//---------------------------------------------------------------------------
IValue* ICallback::AsIValue()
{
return nullptr;
}
//------------------------------------------------------------------------------
/** \brief Returns a pointer to the parser object owning this callback.
\pre [assert] m_pParent must be defined
*/
ParserXBase* ICallback::GetParent()
{
assert(m_pParent);
return m_pParent;
}
//------------------------------------------------------------------------------
void ICallback::SetArgc(int argc)
{
m_nArgc = argc;
}
//------------------------------------------------------------------------------
/** \brief Returns the m´number of arguments required by this callback.
\return Number of arguments or -1 if the number of arguments is variable.
*/
int ICallback::GetArgc() const
{
return m_nArgc;
}
//------------------------------------------------------------------------------
/** \brief Assign a parser object to the callback.
\param a_pParent The parser that belongs to this callback object.
The parent object can be used in order to access internals of the parser
from within a callback object. Thus enabling callbacks to delete
variables or functions if this is desired.
*/
void ICallback::SetParent(parent_type *a_pParent)
{
assert(a_pParent);
m_pParent = a_pParent;
}
//------------------------------------------------------------------------------
string_type ICallback::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; id=\"") << GetIdent() << "\"";
ss << _T("; argc=") << GetArgc() << " (found: " << m_nArgsPresent << ")";
ss << _T("]");
return ss.str();
}
//------------------------------------------------------------------------------
void ICallback::SetNumArgsPresent(int argc)
{
m_nArgsPresent = argc;
}
//------------------------------------------------------------------------------
int ICallback::GetArgsPresent() const
{
if (m_nArgc!=-1)
return m_nArgc;
else
return m_nArgsPresent;
}
} // namespace mu

View File

@ -0,0 +1,88 @@
/** \file
\brief Definition of the interface for parser callback objects.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MU_IPARSER_CALLBACK_H
#define MU_IPARSER_CALLBACK_H
//--- muParserX framework --------------------------------------------
#include "mpIToken.h"
#include "mpIPackage.h"
MUP_NAMESPACE_START
/** \brief Interface for callback objects.
All Parser functions and operators must implement this interface.
*/
class ICallback : public IToken
{
public:
typedef ParserXBase parent_type;
ICallback(ECmdCode a_iCode,
const char_type *a_szName,
int a_nArgNum = 1);
virtual ~ICallback();
virtual ICallback* AsICallback();
virtual IValue* AsIValue();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) = 0;
virtual const char_type* GetDesc() const = 0;
virtual string_type AsciiDump() const;
int GetArgc() const;
int GetArgsPresent() const;
void SetParent(parent_type *a_pParent);
void SetNumArgsPresent(int argc);
protected:
parent_type* GetParent();
void SetArgc(int argc);
private:
parent_type *m_pParent; ///< Pointer to the parser object using this callback
int m_nArgc; ///< Number of this function can take Arguments.
int m_nArgsPresent; ///< Number of arguments actually submitted
}; // class ICallback
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,170 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpIOprt.h"
#include "mpError.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
//
// Binary Operators
//
//------------------------------------------------------------------------------
IOprtBin::IOprtBin(const char_type *a_szIdent, int nPrec, EOprtAsct eAsc)
:ICallback(cmOPRT_BIN, a_szIdent, 2)
,IPrecedence()
,m_nPrec(nPrec)
,m_eAsc(eAsc)
{}
//------------------------------------------------------------------------------
IOprtBin::~IOprtBin()
{}
//------------------------------------------------------------------------------
string_type IOprtBin::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; id=\"") << GetIdent() << _T("\"");
ss << _T("; prec=") << GetPri();
ss << _T("; argc=") << GetArgc();
ss << _T("]");
return ss.str();
}
//------------------------------------------------------------------------------
int IOprtBin::GetPri() const
{
return m_nPrec;
}
//------------------------------------------------------------------------------
EOprtAsct IOprtBin::GetAssociativity() const
{
return m_eAsc;
}
//---------------------------------------------------------------------------
IPrecedence* IOprtBin::AsIPrecedence()
{
return this;
}
//------------------------------------------------------------------------------
//
// Unary Postfix Operators
//
//------------------------------------------------------------------------------
IOprtPostfix::IOprtPostfix(const char_type *a_szIdent)
:ICallback(cmOPRT_POSTFIX, a_szIdent, 1)
{}
//------------------------------------------------------------------------------
IOprtPostfix::~IOprtPostfix()
{}
//------------------------------------------------------------------------------
string_type IOprtPostfix::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; id=\"") << GetIdent() << _T("\"");
ss << _T("; argc=") << GetArgc();
ss << _T("]");
return ss.str();
}
//------------------------------------------------------------------------------
//
// Unary Infix Operators
//
//------------------------------------------------------------------------------
IOprtInfix::IOprtInfix(const char_type *a_szIdent, int nPrec)
:ICallback(cmOPRT_INFIX, a_szIdent, 1)
,IPrecedence()
,m_nPrec(nPrec)
{}
//------------------------------------------------------------------------------
IOprtInfix::~IOprtInfix()
{}
//------------------------------------------------------------------------------
string_type IOprtInfix::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; id=\"") << GetIdent() << _T("\"");
ss << _T("; argc=") << GetArgc();
ss << _T("]");
return ss.str();
}
//---------------------------------------------------------------------------
IPrecedence* IOprtInfix::AsIPrecedence()
{
return this;
}
//------------------------------------------------------------------------------
int IOprtInfix::GetPri() const
{
return m_nPrec;
}
//------------------------------------------------------------------------------
EOprtAsct IOprtInfix::GetAssociativity() const
{
return oaNONE;
}
} // namespace mu

View File

@ -0,0 +1,117 @@
/** \file mpIOprt.h
\brief Definition of base classes needed for parser operator definitions.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_IPARSER_OPERATOR_H
#define MUP_IPARSER_OPERATOR_H
#include "mpICallback.h"
#include "mpIPrecedence.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Interface for binary operators.
\ingroup binop
All classes representing binary operator callbacks must be derived from
this base class.
*/
class IOprtBin : public ICallback,
public IPrecedence
{
public:
IOprtBin(const char_type *a_szIdent, int nPrec, EOprtAsct eAsc);
virtual ~IOprtBin();
virtual string_type AsciiDump() const;
//------------------------------------------
// IPrecedence implementation
//------------------------------------------
virtual IPrecedence* AsIPrecedence();
virtual EOprtAsct GetAssociativity() const;
virtual int GetPri() const;
private:
int m_nPrec;
EOprtAsct m_eAsc;
}; // class IOperator
//------------------------------------------------------------------------------
/** \brief Interface for unary postfix operators.
\ingroup postfix
*/
class IOprtPostfix : public ICallback
{
public:
IOprtPostfix(const char_type *a_szIdent);
virtual ~IOprtPostfix();
virtual string_type AsciiDump() const;
}; // class IOperator
//------------------------------------------------------------------------------
/** \brief Interface for unary infix operators.
\ingroup infix
*/
class IOprtInfix : public ICallback,
public IPrecedence
{
public:
IOprtInfix(const char_type *a_szIdent, int nPrec);
virtual ~IOprtInfix();
virtual string_type AsciiDump() const;
//------------------------------------------
// IPrecedence implementation
//------------------------------------------
virtual IPrecedence* AsIPrecedence();
virtual int GetPri() const;
virtual EOprtAsct GetAssociativity() const;
private:
int m_nPrec;
}; // class IOperator
} // namespace mu
#endif

View File

@ -0,0 +1,51 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpIPackage.h"
#include "mpDefines.h"
#include "mpParserBase.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
IPackage::IPackage()
{}
//------------------------------------------------------------------------------
IPackage::~IPackage()
{}
MUP_NAMESPACE_END

View File

@ -0,0 +1,62 @@
#ifndef MU_IPACKAGE_H
#define MU_IPACKAGE_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <vector>
#include "mpFwdDecl.h"
#include "mpTypes.h"
MUP_NAMESPACE_START
class IPackage
{
public:
virtual void AddToParser(ParserXBase *pParser) = 0;
virtual string_type GetDesc() const = 0;
virtual string_type GetPrefix() const = 0;
protected:
IPackage();
virtual ~IPackage();
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,61 @@
/** \file mpIPrecedence.h
\brief Definition of base classes needed for parser operator definitions.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_IPRECEDENCE_H
#define MUP_IPRECEDENCE_H
#include "mpTypes.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Interface for binary and ternary operators
\ingroup binop
*/
class IPrecedence
{
public:
virtual ~IPrecedence(){}
virtual int GetPri() const = 0;
virtual EOprtAsct GetAssociativity() const = 0;
};
} // namespace mu
#endif

View File

@ -0,0 +1,325 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpIToken.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
#include <cassert>
#include "mpIPrecedence.h"
MUP_NAMESPACE_START
#ifdef MUP_LEAKAGE_REPORT
std::list<IToken*> IToken::s_Tokens;
#endif
#ifndef _UNICODE
//---------------------------------------------------------------------------
/** \brief Overloaded streaming operator for outputting the value type
into an std::ostream.
\param a_Stream The stream object
\param a_Val The value object to be streamed
This function is only present if _UNICODE is not defined.
*/
std::ostream& operator<<(std::ostream &a_Stream, const IToken &tok)
{
return a_Stream << tok.ToString();
}
#else
//---------------------------------------------------------------------------
/** \brief Overloaded streaming operator for outputting the value type
into an std::ostream.
\param a_Stream The stream object
\param a_Val The value object to be streamed
This function is only present if _UNICODE is defined.
*/
std::wostream& operator<<(std::wostream &a_Stream, const IToken &tok)
{
return a_Stream << tok.ToString();
}
#endif
#ifdef MUP_LEAKAGE_REPORT
void IToken::LeakageReport()
{
using namespace std;
console() << "\n";
console() << "Memory leakage report:\n\n";
if (IToken::s_Tokens.size())
{
list<IToken*>::const_iterator item = IToken::s_Tokens.begin();
std::vector<int> stat(cmCOUNT, 0);
for (; item!=IToken::s_Tokens.end(); ++item)
{
console() << "Addr: 0x" << hex << *item << " Ident: \"" << (*item)->GetIdent() << "\"";
console() << "\tCode: " << g_sCmdCode[(*item)->GetCode()] << "\n";
stat[(*item)->GetCode()]++;
}
console() << "Leaked tokens: " << dec << (int)IToken::s_Tokens.size() << std::endl;
for (int i=0; i<cmCOUNT; ++i)
console() << g_sCmdCode[i] << ":" << stat[i] << "\n";
console() << endl;
}
else
{
console() << "No tokens leaked!\n";
}
}
#endif
//------------------------------------------------------------------------------
IToken::IToken(ECmdCode a_iCode)
:m_eCode(a_iCode)
,m_sIdent()
,m_nPosExpr(-1)
,m_nRefCount(0)
,m_flags(0)
{
#ifdef MUP_LEAKAGE_REPORT
IToken::s_Tokens.push_back(this);
#endif
}
//------------------------------------------------------------------------------
IToken::IToken(ECmdCode a_iCode, string_type a_sIdent)
:m_eCode(a_iCode)
,m_sIdent(a_sIdent)
,m_nPosExpr(-1)
,m_nRefCount(0)
,m_flags(0)
{
#ifdef MUP_LEAKAGE_REPORT
IToken::s_Tokens.push_back(this);
#endif
}
/** \brief Destructor (trivial). */
IToken::~IToken()
{
#ifdef MUP_LEAKAGE_REPORT
std::list<IToken*>::iterator it = std::find(IToken::s_Tokens.begin(), IToken::s_Tokens.end(), this);
IToken::s_Tokens.remove(this);
#endif
}
//------------------------------------------------------------------------------
/** \brief Copy constructor.
\param ref The token to copy basic state information from.
The copy constructor must be implemented in order not to screw up
the reference count of the created object. CC's are used in the
Clone function and they would start with a reference count != 0
introducing memory leaks if the default CC where used.
*/
IToken::IToken(const IToken &ref)
{
m_eCode = ref.m_eCode;
m_sIdent = ref.m_sIdent;
m_flags = ref.m_flags;
m_nPosExpr = ref.m_nPosExpr;
// The following items must be initialised
// (rather than just beeing copied)
m_nRefCount = 0;
}
//------------------------------------------------------------------------------
void IToken::ResetRef()
{
m_nRefCount = 0;
}
//------------------------------------------------------------------------------
void IToken::Release()
{
delete this;
}
//------------------------------------------------------------------------------
string_type IToken::ToString() const
{
return AsciiDump();
}
//------------------------------------------------------------------------------
int IToken::GetExprPos() const
{
return m_nPosExpr;
}
//------------------------------------------------------------------------------
void IToken::SetExprPos(int nPos)
{
m_nPosExpr = nPos;
}
//------------------------------------------------------------------------------
/** \brief return the token code.
\sa ECmdCode
*/
ECmdCode IToken::GetCode() const
{
return m_eCode;
}
//------------------------------------------------------------------------------
/** \brief Return the token identifier string. */
const string_type& IToken::GetIdent() const
{
return m_sIdent;
}
//------------------------------------------------------------------------------
void IToken::SetIdent(const string_type &a_sIdent)
{
m_sIdent = a_sIdent;
}
//------------------------------------------------------------------------------
string_type IToken::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[m_eCode];
return ss.str().c_str();
}
//------------------------------------------------------------------------------
void IToken::IncRef() const
{
++m_nRefCount;
}
//------------------------------------------------------------------------------
long IToken::DecRef() const
{
return --m_nRefCount;
}
//------------------------------------------------------------------------------
long IToken::GetRef() const
{
return m_nRefCount;
}
//---------------------------------------------------------------------------
void IToken::AddFlags(int flags)
{
m_flags |= flags;
}
//---------------------------------------------------------------------------
bool IToken::IsFlagSet(int flags) const
{
return (m_flags & flags)==flags;
}
//---------------------------------------------------------------------------
ICallback* IToken::AsICallback()
{
return nullptr;
}
//---------------------------------------------------------------------------
IValue* IToken::AsIValue()
{
return nullptr;
}
//---------------------------------------------------------------------------
IPrecedence* IToken::AsIPrecedence()
{
return nullptr;
}
//------------------------------------------------------------------------------
void IToken::Compile(const string_type & /*sArg*/)
{
}
//---------------------------------------------------------------------------
//
// Generic token implementation
//
//---------------------------------------------------------------------------
GenericToken::GenericToken(ECmdCode a_iCode, string_type a_sIdent)
:IToken(a_iCode, a_sIdent)
{}
//---------------------------------------------------------------------------
GenericToken::GenericToken(ECmdCode a_iCode)
:IToken(a_iCode, _T(""))
{}
//---------------------------------------------------------------------------
GenericToken::~GenericToken()
{}
//---------------------------------------------------------------------------
GenericToken::GenericToken(const GenericToken &a_Tok)
:IToken(a_Tok)
{}
//---------------------------------------------------------------------------
IToken* GenericToken::Clone() const
{
return new GenericToken(*this);
}
//------------------------------------------------------------------------------
string_type GenericToken::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << _T("]");
return ss.str();
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,235 @@
/*
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_ITOKEN_H
#define MUP_ITOKEN_H
#include <list>
#include "mpTypes.h"
#include "mpFwdDecl.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Generic token interface for expression tokens.
\author (C) 2010 Ingo Berg
Tokens can either be Functions, operators, values, variables or necessary
base tokens like brackets. ´The IToken baseclass implements reference
counting. Only TokenPtr<...> templates may be used as pointers to tokens.
*/
class IToken
{
friend std::ostream& operator<<(std::ostream &a_Stream, const IToken &a_Val);
friend std::wostream& operator<<(std::wostream &a_Stream, const IToken &a_Val);
friend class TokenPtr<IToken>;
friend class TokenPtr<IValue>;
friend class TokenPtr<IOprtBin>;
friend class TokenPtr<IOprtInfix>;
friend class TokenPtr<IOprtPostfix>;
friend class TokenPtr<IFunction>;
friend class TokenPtr<Value>;
friend class TokenPtr<Variable>;
friend class TokenPtr<ICallback>;
public:
enum EFlags
{
flNONE = 0,
flVOLATILE = 1
};
virtual IToken* Clone() const = 0;
virtual string_type ToString() const;
virtual string_type AsciiDump() const;
virtual ICallback* AsICallback();
virtual IValue* AsIValue();
virtual IPrecedence* AsIPrecedence();
virtual void Compile(const string_type &sArg);
ECmdCode GetCode() const;
int GetExprPos() const;
const string_type& GetIdent() const;
long GetRef() const;
void SetIdent(const string_type &a_sIdent);
void SetExprPos(int nPos);
void AddFlags(int flags);
bool IsFlagSet(int flags) const;
protected:
explicit IToken(ECmdCode a_iCode);
virtual ~IToken();
IToken(ECmdCode a_iCode, string_type a_sIdent);
IToken(const IToken &ref);
void ResetRef();
private:
/** \brief Release the token.
This Function either deletes the token or releases it to
the value cache for reuse without deletion.
*/
virtual void Release();
void IncRef() const;
long DecRef() const;
ECmdCode m_eCode;
string_type m_sIdent;
int m_nPosExpr; ///< Original position of the token in the expression
mutable long m_nRefCount; ///< Reference counter.
int m_flags;
#ifdef MUP_LEAKAGE_REPORT
static std::list<IToken*> s_Tokens;
public:
static void LeakageReport();
#endif
};
//---------------------------------------------------------------------------
/** \brief Default token implentation.
*/
class GenericToken : public IToken
{
public:
GenericToken(ECmdCode a_iCode, string_type a_sIdent);
explicit GenericToken(ECmdCode a_iCode);
GenericToken(const GenericToken &a_Tok);
virtual ~GenericToken();
virtual IToken* Clone() const;
virtual string_type AsciiDump() const;
};
//------------------------------------------------------------------------------
template<typename T>
class TokenPtr
{
public:
typedef T* token_type;
//---------------------------------------------------------------------------
TokenPtr(token_type p = 0)
:m_pTok(p)
{
if (m_pTok)
m_pTok->IncRef();
}
//---------------------------------------------------------------------------
TokenPtr(const TokenPtr &p)
:m_pTok(p.m_pTok)
{
if (m_pTok)
m_pTok->IncRef();
}
//---------------------------------------------------------------------------
~TokenPtr()
{
if (m_pTok && m_pTok->DecRef()==0)
m_pTok->Release();
}
//---------------------------------------------------------------------------
token_type operator->() const
{
return static_cast<token_type>(m_pTok);
}
//---------------------------------------------------------------------------
T& operator*() const
{
assert(m_pTok);
return *(static_cast<token_type>(m_pTok));
}
//---------------------------------------------------------------------------
token_type Get() const
{
return static_cast<token_type>(m_pTok);
}
//---------------------------------------------------------------------------
/** \brief Release the managed pointer and assign a new pointer. */
void Reset(token_type tok)
{
if (m_pTok && m_pTok->DecRef()==0)
{
m_pTok->Release();
//delete m_pTok;
}
tok->IncRef();
m_pTok = tok;
}
//---------------------------------------------------------------------------
TokenPtr& operator=(const TokenPtr &p)
{
if (p.m_pTok)
p.m_pTok->IncRef();
if (m_pTok && m_pTok->DecRef()==0)
{
m_pTok->Release();
//delete m_pTok;
}
m_pTok = p.m_pTok;
return *this;
}
private:
IToken *m_pTok;
};
MUP_NAMESPACE_END
#endif // include guard

View File

@ -0,0 +1,72 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpIValReader.h"
#include "mpTokenReader.h"
#include <cassert>
MUP_NAMESPACE_START
//--------------------------------------------------------------------------------------------
IValueReader::IValueReader()
:m_pTokenReader(nullptr)
{}
//--------------------------------------------------------------------------------------------
IValueReader::~IValueReader()
{}
//--------------------------------------------------------------------------------------------
IValueReader::IValueReader(const IValueReader &ref)
{
m_pTokenReader = ref.m_pTokenReader;
}
//--------------------------------------------------------------------------------------------
void IValueReader::SetParent(TokenReader *pTokenReader)
{
assert(pTokenReader);
m_pTokenReader = pTokenReader;
}
//--------------------------------------------------------------------------------------------
const IToken* IValueReader::TokenHistory(std::size_t pos) const
{
const TokenReader::token_buf_type &buf = m_pTokenReader->GetTokens();
std::size_t size = buf.size();
return (pos>=size) ? nullptr : buf[size-1-pos].Get();
}
}

View File

@ -0,0 +1,101 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MU_IPARSER_VALUE_READER_H
#define MU_IPARSER_VALUE_READER_H
#include "mpValue.h"
#include "mpIToken.h"
#include "mpTokenReader.h"
/** \defgroup valreader Value reader classes
This group lists all classes that detect and parse values in an expression string.
*/
MUP_NAMESPACE_START
class TokenReader;
/** \brief Interface for custom value reader objects.
\ingroup valreader
Value readers are objects used for identifying values
in an expression.
*/
class IValueReader
{
public:
IValueReader();
IValueReader(const IValueReader &ref);
virtual ~IValueReader();
/** \brief Check a certain position in an expression for the presence of a value.
\param a_iPos [in/out] Reference to an integer value representing the current
position of the parser in the expression.
\param a_Val If a value is found it is stored in a_Val
\return true if a value was found
*/
virtual bool IsValue(const char_type *a_szExpr,
int &a_iPos,
Value &a_Val ) = 0;
/** \brief Clone this ValueReader object.
\return Pointer to the cloned value reader object.
*/
virtual IValueReader* Clone(TokenReader *pParent) const = 0;
/** \brief Assign this value reader object to a token
reader object.
The token reader does the tokenization of the expression.
It uses this value reader to detect values.
*/
virtual void SetParent(TokenReader *pTokenReader);
protected:
const IToken* TokenHistory(std::size_t pos) const;
private:
TokenReader *m_pTokenReader; ///< Pointer to the TokenReader class used for token recognition
}; // class IValueReader
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,449 @@
/** \file
\brief Implementation of the virtual base class used for all parser values.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpIValue.h"
//--- Standard includes ------------------------------------------------------
#include <cassert>
#include <iostream>
#include <iomanip>
#include <limits>
//--- muParserX framework -----------------------------------------------------
#include "mpValue.h"
#include "mpError.h"
#include "mpValue.h"
MUP_NAMESPACE_START
#ifndef _UNICODE
//---------------------------------------------------------------------------
/** \brief Overloaded streaming operator for outputting the value type
into an std::ostream.
\param a_Stream The stream object
\param a_Val The value object to be streamed
This function is only present if _UNICODE is not defined.
*/
std::ostream& operator<<(std::ostream &a_Stream, const IValue &a_Val)
{
return a_Stream << a_Val.ToString();
}
#else
//---------------------------------------------------------------------------
/** \brief Overloaded streaming operator for outputting the value type
into an std::ostream.
\param a_Stream The stream object
\param a_Val The value object to be streamed
This function is only present if _UNICODE is defined.
*/
std::wostream& operator<<(std::wostream &a_Stream, const IValue &a_Val)
{
return a_Stream << a_Val.ToString();
}
#endif
//---------------------------------------------------------------------------------------------
Value operator*(const IValue& lhs, const IValue& rhs)
{
return Value(lhs) *= rhs;
}
//---------------------------------------------------------------------------
IValue::IValue(ECmdCode a_iCode)
:IToken(a_iCode)
{
assert(a_iCode == cmVAL);
}
//---------------------------------------------------------------------------
IValue::IValue(ECmdCode a_iCode, const string_type &a_sIdent)
:IToken(a_iCode, a_sIdent)
{
assert(a_iCode == cmVAL);
}
//---------------------------------------------------------------------------
IValue::~IValue()
{}
//---------------------------------------------------------------------------
ICallback* IValue::AsICallback()
{
return nullptr;
}
//---------------------------------------------------------------------------
IValue* IValue::AsIValue()
{
return this;
}
//---------------------------------------------------------------------------
string_type IValue::ToString() const
{
stringstream_type ss;
switch (GetType())
{
case 'm':
{
const matrix_type &arr(GetArray());
if (arr.GetRows() > 1)
ss << _T("{");
for (int i = 0; i < arr.GetRows(); ++i)
{
if (arr.GetCols()>1)
ss << _T("{");
for (int j = 0; j < arr.GetCols(); ++j)
{
ss << arr.At(i, j).ToString();
if (j != arr.GetCols() - 1)
ss << _T(", ");
}
if (arr.GetCols()>1)
ss << _T("}");
if (i != arr.GetRows() - 1)
ss << _T("; ");
}
if (arr.GetRows() > 1)
ss << _T("} ");
}
break;
case 'c':
{
float_type re = GetFloat(),
im = GetImag();
// realteil nicht ausgeben, wenn es eine rein imaginäre Zahl ist
if (im == 0 || re != 0 || (im == 0 && re == 0))
ss << re;
if (im != 0)
{
if (im > 0 && re != 0)
ss << _T("+");
if (im != 1)
ss << im;
ss << _T("i");
}
}
break;
case 'i':
case 'f': ss << std::setprecision(std::numeric_limits<float_type>::digits10) << GetFloat(); break;
case 's': ss << _T("\"") << GetString() << _T("\""); break;
case 'b': ss << ((GetBool() == true) ? _T("true") : _T("false")); break;
case 'v': ss << _T("void"); break;
default: ss << _T("internal error: unknown value type."); break;
}
return ss.str();
}
//---------------------------------------------------------------------------
bool IValue::operator==(const IValue &a_Val) const
{
char_type type1 = GetType(),
type2 = a_Val.GetType();
if (type1 == type2 || (IsScalar() && a_Val.IsScalar()))
{
switch (GetType())
{
case 'i':
case 'f': return GetFloat() == a_Val.GetFloat();
case 'c': return GetComplex() == a_Val.GetComplex();
case 's': return GetString() == a_Val.GetString();
case 'b': return GetBool() == a_Val.GetBool();
case 'v': return false;
case 'm': if (GetRows() != a_Val.GetRows() || GetCols() != a_Val.GetCols())
{
return false;
}
else
{
for (int i = 0; i < GetRows(); ++i)
{
if (const_cast<IValue*>(this)->At(i) != const_cast<IValue&>(a_Val).At(i))
return false;
}
return true;
}
default:
ErrorContext err;
err.Errc = ecINTERNAL_ERROR;
err.Pos = -1;
err.Type1 = GetType();
err.Type2 = a_Val.GetType();
throw ParserError(err);
} // switch this type
}
else
{
return false;
}
}
//---------------------------------------------------------------------------
bool IValue::operator!=(const IValue &a_Val) const
{
char_type type1 = GetType(),
type2 = a_Val.GetType();
if (type1 == type2 || (IsScalar() && a_Val.IsScalar()))
{
switch (GetType())
{
case 's': return GetString() != a_Val.GetString();
case 'i':
case 'f': return GetFloat() != a_Val.GetFloat();
case 'c': return (GetFloat() != a_Val.GetFloat()) || (GetImag() != a_Val.GetImag());
case 'b': return GetBool() != a_Val.GetBool();
case 'v': return true;
case 'm': if (GetRows() != a_Val.GetRows() || GetCols() != a_Val.GetCols())
{
return true;
}
else
{
for (int i = 0; i < GetRows(); ++i)
{
if (const_cast<IValue*>(this)->At(i) != const_cast<IValue&>(a_Val).At(i))
return true;
}
return false;
}
default:
ErrorContext err;
err.Errc = ecINTERNAL_ERROR;
err.Pos = -1;
err.Type2 = GetType();
err.Type1 = a_Val.GetType();
throw ParserError(err);
} // switch this type
}
else
{
return true;
}
}
//---------------------------------------------------------------------------
bool IValue::operator<(const IValue &a_Val) const
{
char_type type1 = GetType();
char_type type2 = a_Val.GetType();
if (type1 == type2 || (IsScalar() && a_Val.IsScalar()))
{
switch (GetType())
{
case 's': return GetString() < a_Val.GetString();
case 'i':
case 'f':
case 'c': return GetFloat() < a_Val.GetFloat();
case 'b': return GetBool() < a_Val.GetBool();
default:
ErrorContext err;
err.Errc = ecINTERNAL_ERROR;
err.Pos = -1;
err.Type1 = GetType();
err.Type2 = a_Val.GetType();
throw ParserError(err);
} // switch this type
}
else
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = (type1 != 'f' && type1 != 'i') ? 1 : 2;
err.Type1 = type2;
err.Type2 = type1;
throw ParserError(err);
}
}
//---------------------------------------------------------------------------
bool IValue::operator> (const IValue &a_Val) const
{
char_type type1 = GetType(),
type2 = a_Val.GetType();
if (type1 == type2 || (IsScalar() && a_Val.IsScalar()))
{
switch (GetType())
{
case 's': return GetString() > a_Val.GetString();
case 'i':
case 'f':
case 'c': return GetFloat() > a_Val.GetFloat();
case 'b': return GetBool() > a_Val.GetBool();
default:
ErrorContext err;
err.Errc = ecINTERNAL_ERROR;
err.Pos = -1;
err.Type1 = GetType();
err.Type2 = a_Val.GetType();
throw ParserError(err);
} // switch this type
}
else
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = (type1 != 'f' && type1 != 'i') ? 1 : 2;
err.Type1 = type2;
err.Type2 = type1;
throw ParserError(err);
}
}
//---------------------------------------------------------------------------
bool IValue::operator>=(const IValue &a_Val) const
{
char_type type1 = GetType(),
type2 = a_Val.GetType();
if (type1 == type2 || (IsScalar() && a_Val.IsScalar()))
{
switch (GetType())
{
case 's': return GetString() >= a_Val.GetString();
case 'i':
case 'f':
case 'c': return GetFloat() >= a_Val.GetFloat();
case 'b': return GetBool() >= a_Val.GetBool();
default:
ErrorContext err;
err.Errc = ecINTERNAL_ERROR;
err.Pos = -1;
err.Type1 = GetType();
err.Type2 = a_Val.GetType();
throw ParserError(err);
} // switch this type
}
else
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = (type1 != 'f' && type1 != 'i') ? 1 : 2;
err.Type1 = type2;
err.Type2 = type1;
throw ParserError(err);
}
}
//---------------------------------------------------------------------------
bool IValue::operator<=(const IValue &a_Val) const
{
char_type type1 = GetType(),
type2 = a_Val.GetType();
if (type1 == type2 || (IsScalar() && a_Val.IsScalar()))
{
switch (GetType())
{
case 's': return GetString() <= a_Val.GetString();
case 'i':
case 'f':
case 'c': return GetFloat() <= a_Val.GetFloat();
case 'b': return GetBool() <= a_Val.GetBool();
default:
ErrorContext err;
err.Errc = ecINTERNAL_ERROR;
err.Pos = -1;
err.Type1 = GetType();
err.Type2 = a_Val.GetType();
throw ParserError(err);
} // switch this type
}
else
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT_FUN;
err.Arg = (type1 != 'f' && type1 != 'i') ? 1 : 2;
err.Type1 = type2;
err.Type2 = type1;
throw ParserError(err);
}
}
//---------------------------------------------------------------------------
IValue& IValue::operator=(const IValue &ref)
{
if (this == &ref)
return *this;
switch (ref.GetType())
{
case 'i':
case 'f':
case 'c': return *this = cmplx_type(ref.GetFloat(), ref.GetImag());
case 's': return *this = ref.GetString();
case 'm': return *this = ref.GetArray();
case 'b': return *this = ref.GetBool();
case 'v':
throw ParserError(_T("Assignment from void type is not possible"));
default:
throw ParserError(_T("Internal error: unexpected data type identifier in IValue& operator=(const IValue &ref)"));
}
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,187 @@
/** \file
\brief Definition of the virtual base class used for all parser values.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_IVALUE_H
#define MUP_IVALUE_H
#include "mpIToken.h"
#include "mpFwdDecl.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Interface to be implemented by all classes representing values.
IValue is the common base class of both the Value and Variable classes.
*/
class IValue : public IToken
{
friend std::ostream& operator<<(std::ostream &a_Stream, const IValue &a_Val);
friend std::wostream& operator<<(std::wostream &a_Stream, const IValue &a_Val);
public:
explicit IValue(ECmdCode a_iCode);
IValue(ECmdCode a_iCode, const string_type &a_sIdent);
bool operator==(const IValue &a_Val) const;
bool operator!=(const IValue &a_Val) const;
bool operator< (const IValue &a_Val) const;
bool operator> (const IValue &a_Val) const;
bool operator<=(const IValue &a_Val) const;
bool operator>=(const IValue &a_Val) const;
virtual ICallback* AsICallback();
virtual IValue* AsIValue();
virtual Value* AsValue() = 0;
virtual IValue& operator=(int_type val) = 0;
virtual IValue& operator=(float_type val) = 0;
virtual IValue& operator=(string_type val) = 0;
virtual IValue& operator=(bool_type val) = 0;
virtual IValue& operator=(const cmplx_type &val) = 0;
virtual IValue& operator=(const matrix_type &val) = 0;
IValue& operator=(const IValue &ref);
virtual IValue& operator+=(const IValue &ref) = 0;
virtual IValue& operator-=(const IValue &ref) = 0;
virtual IValue& operator*=(const IValue &ref) = 0;
virtual IValue& At(int nRow, int nCol = 0) = 0;
virtual IValue& At(const IValue &nRows, const IValue &nCols) = 0;
virtual int_type GetInteger() const = 0;
virtual float_type GetFloat() const = 0;
virtual float_type GetImag() const = 0;
virtual bool GetBool() const = 0;
virtual const cmplx_type& GetComplex() const = 0;
virtual const string_type& GetString() const = 0;
virtual const matrix_type& GetArray() const = 0;
virtual char_type GetType() const = 0;
virtual int GetRows() const = 0;
virtual int GetCols() const = 0;
virtual string_type ToString() const;
//---------------------------------------------------------------------------
/** \brief Returns the dimension of the value represented by a value object.
The value represents the dimension of the object. Possible value are:
<ul>
<li>0 - scalar</li>
<li>1 - vector</li>
<li>2 - matrix</li>
</ul>
*/
inline int GetDim() const
{
return (IsMatrix()) ? GetArray().GetDim() : 0;
}
//---------------------------------------------------------------------------
virtual bool IsVariable() const = 0;
//---------------------------------------------------------------------------
/** \brief Returns true if the type is either floating point or interger.
\throw nothrow
*/
inline bool IsNonComplexScalar() const
{
char_type t = GetType();
return t=='f' || t=='i';
}
//---------------------------------------------------------------------------
/** \brief Returns true if the type is not a vector and not a string.
\throw nothrow
*/
inline bool IsScalar() const
{
char_type t = GetType();
return t=='f' || t=='i' || t=='c';
}
//---------------------------------------------------------------------------
/** \brief Returns true if this value is a noncomplex integer.
\throw nothrow
*/
inline bool IsInteger() const
{
// checking the type is is insufficient. The integer could be disguised
// as a float or a complex value
return IsScalar() && GetImag()==0 && GetFloat()==(int_type)GetFloat();
}
//---------------------------------------------------------------------------
/** \brief Returns true if this value is an array.
\throw nothrow
*/
inline bool IsMatrix() const
{
return GetType() == 'm';
}
//---------------------------------------------------------------------------
/** \brief Returns true if this value is a complex value.
\throw nothrow
*/
inline bool IsComplex() const
{
return GetType() == 'c' && GetImag()!=0;
}
//---------------------------------------------------------------------------
/** \brief Returns true if this value is a string value.
\throw nothrow
*/
inline bool IsString() const
{
return GetType() == 's';
}
protected:
virtual ~IValue();
}; // class IValue
//---------------------------------------------------------------------------------------------
Value operator*(const IValue& lhs, const IValue& rhs);
} // namespace mu
#endif

View File

@ -0,0 +1,100 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpIfThenElse.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
//
// If part of if-then-else clauses
//
//---------------------------------------------------------------------------
TokenIfThenElse::TokenIfThenElse(ECmdCode eCode)
:IToken(eCode, g_sCmdCode[ eCode ])
,IPrecedence()
,m_nOffset()
{}
//---------------------------------------------------------------------------
IToken* TokenIfThenElse::Clone() const
{
return new TokenIfThenElse(*this);
}
//---------------------------------------------------------------------------
void TokenIfThenElse::SetOffset(int nOffset)
{
m_nOffset = nOffset;
}
//---------------------------------------------------------------------------
int TokenIfThenElse::GetOffset() const
{
return m_nOffset;
}
//---------------------------------------------------------------------------
string_type TokenIfThenElse::AsciiDump() const
{
stringstream_type ss;
ss << GetIdent();
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; offset=") << m_nOffset;
ss << _T("]");
return ss.str();
}
//---------------------------------------------------------------------------
int TokenIfThenElse::GetPri() const
{
return (int)prIF_THEN_ELSE;
}
//---------------------------------------------------------------------------
EOprtAsct TokenIfThenElse::GetAssociativity() const
{
return oaNONE;
}
//---------------------------------------------------------------------------
IPrecedence* TokenIfThenElse::AsIPrecedence()
{
return this;
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,80 @@
/** \file
\brief Definition of basic types used by muParserX
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_IF_THEN_ELSE_H
#define MUP_IF_THEN_ELSE_H
#include "mpIToken.h"
#include "mpIPrecedence.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
/** \brief A class for encapsulation if-then-else tokens. */
class TokenIfThenElse : public IToken,
public IPrecedence
{
public:
TokenIfThenElse(ECmdCode eCmd);
void SetOffset(int nOffset);
int GetOffset() const;
//---------------------------------------------
// IToken interface
//---------------------------------------------
virtual IToken* Clone() const override;
virtual string_type AsciiDump() const override;
virtual IPrecedence* AsIPrecedence() override;
//---------------------------------------------
// IPrecedence interface
//---------------------------------------------
virtual int GetPri() const override;
virtual EOprtAsct GetAssociativity() const override;
private:
int m_nOffset;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,448 @@
#ifndef MU_MATRIX_H
#define MU_MATRIX_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <algorithm>
#include <cassert>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <vector>
#include "mpMatrixError.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
template<class T>
class Matrix
{
template<class T2>
friend Matrix operator+(const Matrix& lhs, const Matrix& rhs);
template<class T2>
friend Matrix operator-(const Matrix& lhs, const Matrix& rhs);
public:
//---------------------------------------------------------------------------------------------
enum EMatrixStorageScheme
{
mssROWS_FIRST,
mssCOLS_FIRST
};
//---------------------------------------------------------------------------------------------
Matrix()
:m_nRows(1)
, m_nCols(1)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(1)
{}
//---------------------------------------------------------------------------------------------
Matrix(int nRows, const T &value = T())
:m_nRows(nRows)
, m_nCols(1)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(m_nRows, value)
{}
//---------------------------------------------------------------------------------------------
/* \brief Constructs a Matrix object representing a scalar value
*/
Matrix(const T &v)
:m_nRows(1)
, m_nCols(1)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(1, v)
{}
//---------------------------------------------------------------------------------------------
/* \brief Constructs a Matrix object representing a vector
*/
Matrix(const std::vector<T> &v)
:m_nRows(v.size())
, m_nCols(1)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(v)
{}
//---------------------------------------------------------------------------------------------
/* Constructs a Matrix object representing a vector
*/
template<size_t TSize>
Matrix(T(&v)[TSize])
:m_nRows(TSize)
, m_nCols(1)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(v, v + TSize)
{}
//---------------------------------------------------------------------------------------------
template<size_t TRows, size_t TCols>
Matrix(T(&v)[TRows][TCols])
:m_nRows(TRows)
, m_nCols(TCols)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(TRows*TCols, 0)
{
for (int m = 0; m < TRows; ++m)
{
for (int n = 0; n < TCols; ++n)
{
At(m, n) = v[m][n];
}
}
}
//---------------------------------------------------------------------------------------------
Matrix(int nRows, int nCols, const T &value = T())
:m_nRows(nRows)
, m_nCols(nCols)
, m_eStorageScheme(mssROWS_FIRST)
, m_vData(m_nRows*m_nCols, value)
{}
//---------------------------------------------------------------------------------------------
Matrix(const Matrix &ref)
{
Assign(ref);
}
//---------------------------------------------------------------------------------------------
Matrix& operator=(const Matrix &ref)
{
if (this != &ref)
Assign(ref);
return *this;
}
//---------------------------------------------------------------------------------------------
Matrix& operator=(const T &v)
{
m_nCols = 1;
m_nRows = 1;
m_eStorageScheme = mssROWS_FIRST;
m_vData.assign(1, v);
return *this;
}
//---------------------------------------------------------------------------------------------
Matrix& operator+=(const Matrix &lhs)
{
if (m_nRows != lhs.m_nRows || m_nCols != lhs.m_nCols)
throw MatrixError("Matrix dimension mismatch");
for (int i = 0; i < m_nRows; ++i)
{
for (int j = 0; j < m_nCols; ++j)
{
At(i, j) += lhs.At(i, j);
}
}
return *this;
}
//---------------------------------------------------------------------------------------------
Matrix& operator-=(const Matrix &lhs)
{
if (m_nRows != lhs.m_nRows || m_nCols != lhs.m_nCols)
throw MatrixError("Matrix dimension mismatch");
for (int i = 0; i < m_nRows; ++i)
{
for (int j = 0; j < m_nCols; ++j)
{
At(i, j) -= lhs.At(i, j);
}
}
return *this;
}
//---------------------------------------------------------------------------------------------
Matrix& operator*=(const T &rhs)
{
// Matrix x Matrix multiplication
for (int m = 0; m < m_nRows; ++m)
{
for (int n = 0; n < m_nCols; ++n)
{
At(m, n) *= rhs;
}
}
return *this;
}
//---------------------------------------------------------------------------------------------
Matrix& operator*=(const Matrix &rhs)
{
// Matrix x Matrix multiplication
if (rhs.GetRows() == 0)
{
T v = rhs.At(0, 0);
for (int m = 0; m < m_nRows; ++m)
{
for (int n = 0; n < m_nCols; ++n)
{
At(m, n) *= v;
}
}
}
else if (GetRows() == 0)
{
T v = At(0, 0);
Assign(rhs);
for (int m = 0; m < m_nRows; ++m)
{
for (int n = 0; n < m_nCols; ++n)
{
At(m, n) *= v;
}
}
}
else if (m_nCols == rhs.m_nRows)
{
Matrix<T> out(m_nRows, rhs.m_nCols);
// For each cell in the output matrix
for (int m = 0; m < m_nRows; ++m)
{
for (int n = 0; n < rhs.m_nCols; ++n)
{
T buf = 0.0;
for (int i = 0; i < m_nCols; ++i)
{
buf += At(m, i) * rhs.At(i, n);
}
out.At(m, n) = buf;
} // for all rows
} // for all columns
Assign(out);
}
else
throw MatrixError("Matrix dimensions don't allow multiplication");
return *this;
}
//---------------------------------------------------------------------------------------------
void AsciiDump(const char *szTitle) const
{
using namespace std;
cout << szTitle << _T("\n");
cout << _T("------------------\n");
cout << _T("Cols: ") << GetCols() << _T("\n");
cout << _T("Rows: ") << GetRows() << _T("\n");
cout << _T("Dim: ") << GetDim() << _T("\n");
for (int i = 0; i < m_nRows; ++i)
{
for (int j = 0; j < m_nCols; ++j)
{
cout << At(i, j) << _T(" ");
}
cout << _T("\n");
}
cout << _T("\n\n");
}
//---------------------------------------------------------------------------------------------
std::string ToString() const
{
std::stringstream ss;
for (int i = 0; i < m_nRows; ++i)
{
for (int j = 0; j < m_nCols; ++j)
{
ss << At(i, j) << " ";
}
ss << "\n";
}
return ss.str();
}
//---------------------------------------------------------------------------------------------
~Matrix()
{
m_vData.clear();
}
//---------------------------------------------------------------------------------------------
int GetRows() const
{
return m_nRows;
}
//---------------------------------------------------------------------------------------------
int GetCols() const
{
return m_nCols;
}
//---------------------------------------------------------------------------------------------
int GetDim() const
{
if (m_nCols == 1)
{
return (m_nRows == 1) ? 0 : 1;
}
else
return 2;
}
//---------------------------------------------------------------------------------------------
T& At(int nRow, int nCol = 0)
{
int i;
if (m_eStorageScheme == mssROWS_FIRST)
{
i = nRow * m_nCols + nCol;
}
else
{
i = nCol * m_nRows + nRow;
}
assert(i < (int)m_vData.size());
return m_vData[i];
}
//---------------------------------------------------------------------------------------------
const T& At(int nRow, int nCol = 0) const
{
int i;
if (m_eStorageScheme == mssROWS_FIRST)
{
i = nRow * m_nCols + nCol;
}
else
{
i = nCol * m_nRows + nRow;
}
assert(i < (int)m_vData.size());
return m_vData[i];
}
//---------------------------------------------------------------------------------------------
const T* GetData() const
{
assert(m_vData.size());
return &m_vData[0];
}
//---------------------------------------------------------------------------------------------
void SetStorageScheme(EMatrixStorageScheme eScheme)
{
m_eStorageScheme = eScheme;
}
//---------------------------------------------------------------------------------------------
EMatrixStorageScheme GetStorageScheme() const
{
return m_eStorageScheme;
}
//---------------------------------------------------------------------------------------------
Matrix<T>& Transpose()
{
if (GetDim() == 0)
return *this;
m_eStorageScheme = (m_eStorageScheme == mssROWS_FIRST) ? mssCOLS_FIRST : mssROWS_FIRST;
std::swap(m_nRows, m_nCols);
return *this;
}
//---------------------------------------------------------------------------------------------
void Fill(const T &v)
{
m_vData.assign(m_vData.size(), v);
}
private:
int m_nRows;
int m_nCols;
EMatrixStorageScheme m_eStorageScheme;
std::vector<T> m_vData;
//---------------------------------------------------------------------------------------------
void Assign(const Matrix &ref)
{
m_nCols = ref.m_nCols;
m_nRows = ref.m_nRows;
m_eStorageScheme = ref.m_eStorageScheme;
m_vData = ref.m_vData;
}
};
//---------------------------------------------------------------------------------------------
template<class T>
Matrix<T> operator*(const Matrix<T>& lhs, const T& rhs)
{
return Matrix<T>(lhs) *= rhs;
}
//---------------------------------------------------------------------------------------------
template<class T>
Matrix<T> operator*(const Matrix<T>& lhs, const Matrix<T>& rhs)
{
return Matrix<T>(lhs) *= rhs;
}
//---------------------------------------------------------------------------------------------
template<class T>
Matrix<T> operator+(const Matrix<T>& lhs, const Matrix<T>& rhs)
{
return Matrix<T>(lhs) += rhs;
}
//---------------------------------------------------------------------------------------------
template<class T>
Matrix<T> operator-(const Matrix<T>& lhs, const Matrix<T>& rhs)
{
return Matrix<T>(lhs) -= rhs;
}
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,50 @@
#ifndef MU_MATRIX_ERROR_H
#define MU_MATRIX_ERROR_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdexcept>
#include <string>
MUP_NAMESPACE_START
class MatrixError : public std::runtime_error
{
public:
explicit MatrixError(const std::string &sMsg)
:std::runtime_error(sMsg)
{}
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,249 @@
/** \file
\brief This file contains the implementation of binary assignment
operators used in muParser.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpOprtBinAssign.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------
//
// class OprtAssign
//
//---------------------------------------------------------------------
OprtAssign::OprtAssign()
:IOprtBin(_T("="), (int)prASSIGN, oaLEFT)
{}
//---------------------------------------------------------------------
const char_type* OprtAssign::GetDesc() const
{
return _T("'=' assignement operator");
}
//---------------------------------------------------------------------
IToken* OprtAssign::Clone() const
{
return new OprtAssign(*this);
}
//---------------------------------------------------------------------
void OprtAssign::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
// assigment to non variable type
if (!pVar)
{
ErrorContext err;
err.Arg = 1;
err.Ident = _T("=");
err.Errc = ecASSIGNEMENT_TO_VALUE;
throw ParserError(err);
}
*pVar = *a_pArg[1]; //pVar->SetFloat(a_pArg[1]->GetFloat());
*ret = *pVar;
}
//---------------------------------------------------------------------
//
// class OprtAssignAdd
//
//---------------------------------------------------------------------
OprtAssignAdd::OprtAssignAdd()
:IOprtBin(_T("+="), (int)prASSIGN, oaLEFT)
{}
//---------------------------------------------------------------------
void OprtAssignAdd::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
// assigment to non variable type
if (!pVar)
{
ErrorContext err;
err.Arg = 1;
err.Ident = _T("+=");
err.Errc = ecASSIGNEMENT_TO_VALUE;
throw ParserError(err);
}
*pVar = cmplx_type(a_pArg[0]->GetFloat() + a_pArg[1]->GetFloat(),
a_pArg[0]->GetImag() + a_pArg[1]->GetImag());
*ret = *pVar;
}
//---------------------------------------------------------------------
const char_type* OprtAssignAdd::GetDesc() const
{
return _T("assignement operator");
}
//---------------------------------------------------------------------
IToken* OprtAssignAdd::Clone() const
{
return new OprtAssignAdd(*this);
}
//---------------------------------------------------------------------
//
// class OprtAssignAdd
//
//---------------------------------------------------------------------
OprtAssignSub::OprtAssignSub()
:IOprtBin(_T("-="), (int)prASSIGN, oaLEFT)
{}
//---------------------------------------------------------------------
void OprtAssignSub::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
if (!pVar)
{
ErrorContext err;
err.Arg = 1;
err.Ident = _T("-=");
err.Errc = ecASSIGNEMENT_TO_VALUE;
throw ParserError(err);
}
*pVar = cmplx_type(a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat(),
a_pArg[0]->GetImag() - a_pArg[1]->GetImag());
*ret = *pVar;
}
//---------------------------------------------------------------------
const char_type* OprtAssignSub::GetDesc() const
{
return _T("assignement operator");
}
//---------------------------------------------------------------------
IToken* OprtAssignSub::Clone() const
{
return new OprtAssignSub(*this);
}
//---------------------------------------------------------------------
//
// class OprtAssignAdd
//
//---------------------------------------------------------------------
OprtAssignMul::OprtAssignMul()
:IOprtBin(_T("*="), (int)prASSIGN, oaLEFT)
{}
//---------------------------------------------------------------------
void OprtAssignMul::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
if (!pVar)
{
ErrorContext err;
err.Arg = 1;
err.Ident = _T("*=");
err.Errc = ecASSIGNEMENT_TO_VALUE;
throw ParserError(err);
}
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[0]->GetImag(),
c = a_pArg[1]->GetFloat(),
d = a_pArg[1]->GetImag();
*pVar = cmplx_type(a*c-b*d, a*d-b*c);
*ret = *pVar;
}
//---------------------------------------------------------------------
const char_type* OprtAssignMul::GetDesc() const
{
return _T("multiply and assign operator");
}
//---------------------------------------------------------------------
IToken* OprtAssignMul::Clone() const
{
return new OprtAssignMul(*this);
}
//---------------------------------------------------------------------
//
// class OprtAssignDiv
//
//---------------------------------------------------------------------
OprtAssignDiv::OprtAssignDiv() : IOprtBin(_T("/="), (int)prASSIGN, oaLEFT)
{}
//------------------------------------------------------------------------------
void OprtAssignDiv::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
{
Variable *pVar = dynamic_cast<Variable*>(a_pArg[0].Get());
if (!pVar)
{
ErrorContext err;
err.Arg = 1;
err.Ident = _T("/=");
err.Errc = ecASSIGNEMENT_TO_VALUE;
throw ParserError(err);
}
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[0]->GetImag(),
c = a_pArg[1]->GetFloat(),
d = a_pArg[1]->GetImag(),
n = c*c + d*d;
*pVar = cmplx_type((a*c+b*d)/n, (b*c-a*d)/n);
*ret = *pVar;
}
//------------------------------------------------------------------------------
const char_type* OprtAssignDiv::GetDesc() const
{
return _T("multiply and divide operator");
}
//------------------------------------------------------------------------------
IToken* OprtAssignDiv::Clone() const
{
return new OprtAssignDiv(*this);
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,126 @@
/** \file
\brief This file contains the definition of binary assignment
operators used in muParser.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_OPRT_BIN_ASSIGN_H
#define MUP_OPRT_BIN_ASSIGN_H
//--- Standard includes ----------------------------------------------------------
#include <cmath>
//--- muParserX framework --------------------------------------------------------
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpVariable.h"
#include "mpError.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Assignement operator.
This operator can only be applied to variable items.
*/
class OprtAssign : public IOprtBin
{
public:
OprtAssign();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Assignement operator.
This operator can only be applied to variable items.
*/
class OprtAssignAdd : public IOprtBin
{
public:
OprtAssignAdd();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Assignement operator.
This operator can only be applied to variable items.
*/
class OprtAssignSub : public IOprtBin
{
public:
OprtAssignSub();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Assignement operator.
This operator can only be applied to variable items.
*/
class OprtAssignMul : public IOprtBin
{
public:
OprtAssignMul();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Assignement operator.
This operator can only be applied to variable items.
*/
class OprtAssignDiv : public IOprtBin
{
public:
OprtAssignDiv();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,589 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpOprtBinCommon.h"
#include <cmath>
#include <limits>
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
//
// class OprtStrAdd
//
//-----------------------------------------------------------------------------------------------
OprtStrAdd::OprtStrAdd()
:IOprtBin(_T("//"), (int)prADD_SUB, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtStrAdd::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc)
{
MUP_VERIFY(argc == 2);
string_type a = arg[0]->GetString();
string_type b = arg[1]->GetString();
*ret = a + b;
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtStrAdd::GetDesc() const
{
return _T("string concatenation");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtStrAdd::Clone() const
{
return new OprtStrAdd(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtEQ
//
//-----------------------------------------------------------------------------------------------
OprtEQ::OprtEQ()
:IOprtBin(_T("=="), (int)prRELATIONAL1, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtEQ::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
*ret = *a_pArg[0] == *a_pArg[1];
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtEQ::GetDesc() const
{
return _T("equals operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtEQ::Clone() const
{
return new OprtEQ(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtNEQ
//
//-----------------------------------------------------------------------------------------------
OprtNEQ::OprtNEQ()
:IOprtBin(_T("!="), (int)prRELATIONAL1, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtNEQ::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
*ret = *a_pArg[0] != *a_pArg[1];
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtNEQ::GetDesc() const
{
return _T("not equal operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtNEQ::Clone() const
{
return new OprtNEQ(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtLT
//
//-----------------------------------------------------------------------------------------------
OprtLT::OprtLT()
:IOprtBin(_T("<"), (int)prRELATIONAL2, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtLT::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
*ret = *a_pArg[0] < *a_pArg[1];
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtLT::GetDesc() const
{
return _T("less than operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtLT::Clone() const
{
return new OprtLT(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtGT
//
//-----------------------------------------------------------------------------------------------
OprtGT::OprtGT()
:IOprtBin(_T(">"), (int)prRELATIONAL2, oaLEFT) {}
//-----------------------------------------------------------------------------------------------
void OprtGT::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
*ret = *a_pArg[0] > *a_pArg[1];
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtGT::GetDesc() const
{
return _T("greater than operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtGT::Clone() const
{
return new OprtGT(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtLE
//
//-----------------------------------------------------------------------------------------------
OprtLE::OprtLE()
:IOprtBin(_T("<="), (int)prRELATIONAL2, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtLE::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
*ret = *a_pArg[0] <= *a_pArg[1];
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtLE::GetDesc() const
{
return _T("less or equal operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtLE::Clone() const
{
return new OprtLE(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtGE
//
//-----------------------------------------------------------------------------------------------
OprtGE::OprtGE()
:IOprtBin(_T(">="), (int)prRELATIONAL2, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtGE::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int)
{
*ret = *a_pArg[0] >= *a_pArg[1];
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtGE::GetDesc() const
{
return _T("greater or equal operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtGE::Clone() const
{
return new OprtGE(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtAnd
//
//-----------------------------------------------------------------------------------------------
OprtAnd::OprtAnd()
:IOprtBin(_T("&"), (int)prBIT_AND, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtAnd::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
MUP_VERIFY(num == 2);
if (!a_pArg[0]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (!a_pArg[1]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'i', 2));
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[1]->GetFloat();
if (a != (int_type)a)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (b != (int_type)b)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2));
*ret = (float_type)((int_type)a & (int_type)(b));
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtAnd::GetDesc() const
{
return _T("bitwise and");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtAnd::Clone() const
{
return new OprtAnd(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtOr
//
//-----------------------------------------------------------------------------------------------
OprtOr::OprtOr()
:IOprtBin(_T("|"), (int)prBIT_OR, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtOr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
MUP_VERIFY(num == 2);
if (!a_pArg[0]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (!a_pArg[1]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'i', 2));
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[1]->GetFloat();
if (a != (int_type)a)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (b != (int_type)b)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2));
*ret = (float_type)((int_type)a | (int_type)(b));
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtOr::GetDesc() const
{
return _T("bitwise or");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtOr::Clone() const
{
return new OprtOr(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtLOr
//
//-----------------------------------------------------------------------------------------------
OprtLOr::OprtLOr(const char_type *szIdent)
:IOprtBin(szIdent, (int)prLOGIC_OR, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtLOr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
MUP_VERIFY(num == 2);
*ret = a_pArg[0]->GetBool() || a_pArg[1]->GetBool();
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtLOr::GetDesc() const
{
return _T("logical or");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtLOr::Clone() const
{
return new OprtLOr(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtLAnd
//
//-----------------------------------------------------------------------------------------------
OprtLAnd::OprtLAnd(const char_type *szIdent)
:IOprtBin(szIdent, (int)prLOGIC_AND, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtLAnd::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
MUP_VERIFY(num == 2);
*ret = a_pArg[0]->GetBool() && a_pArg[1]->GetBool();
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtLAnd::GetDesc() const
{
return _T("logical and");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtLAnd::Clone() const
{
return new OprtLAnd(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtShl
//
//-----------------------------------------------------------------------------------------------
OprtShl::OprtShl()
:IOprtBin(_T("<<"), (int)prSHIFT, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtShl::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
MUP_VERIFY(num == 2);
if (!a_pArg[0]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (!a_pArg[1]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[1]->GetType(), 'i', 2));
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[1]->GetFloat();
if (a != (int_type)a)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (b != (int_type)b)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2));
float_type result = a*std::pow(2, b);
int numDigits = std::numeric_limits<float_type>::digits10;
if (std::fabs(result) >= std::fabs(std::pow(10.0, numDigits)))
throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent()));
if (result > 0)
{
*ret = std::floor(result);
}
else
{
*ret = std::ceil(result);
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtShl::GetDesc() const
{
return _T("shift left");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtShl::Clone() const
{
return new OprtShl(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtShr
//
//-----------------------------------------------------------------------------------------------
OprtShr::OprtShr()
:IOprtBin(_T(">>"), (int)prSHIFT, oaLEFT)
{}
//-----------------------------------------------------------
void OprtShr::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
MUP_VERIFY(num == 2);
if (!a_pArg[0]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (!a_pArg[1]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[1]->GetType(), 'i', 2));
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[1]->GetFloat();
if (a != (int_type)a)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), a_pArg[0]->GetIdent(), a_pArg[0]->GetType(), 'i', 1));
if (b != (int_type)b)
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), a_pArg[1]->GetIdent(), a_pArg[1]->GetType(), 'i', 2));
float_type result = a*std::pow(2, -b);
int numDigits = std::numeric_limits<float_type>::digits10;
if (std::fabs(result) >= std::fabs(std::pow(10.0, numDigits)))
throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent()));
if (result > 0)
*ret = std::floor(result);
else
*ret = std::ceil(result);
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtShr::GetDesc() const
{
return _T("shift right");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtShr::Clone() const
{
return new OprtShr(*this);
}
//-----------------------------------------------------------------------------------------------
//
// Cast To Float
//
//-----------------------------------------------------------------------------------------------
OprtCastToFloat::OprtCastToFloat()
:IOprtInfix(_T("(float)"), prINFIX)
{}
//-----------------------------------------------------------------------------------------------
void OprtCastToFloat::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int /*a_iArgc*/)
{
switch (a_pArg[0]->GetType())
{
case 'i':
case 'f':
case 'b':
*ret = a_pArg[0]->GetFloat();
break;
default:
{
ErrorContext err;
err.Errc = ecINVALID_TYPECAST;
err.Type1 = a_pArg[0]->GetType();
err.Type2 = 'f';
throw ParserError(err);
}
} // switch value type
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtCastToFloat::GetDesc() const
{
return _T("cast a value into a floating point number");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtCastToFloat::Clone() const
{
return new OprtCastToFloat(*this);
}
//-----------------------------------------------------------------------------------------------
//
// Cast To Int
//
//-----------------------------------------------------------------------------------------------
OprtCastToInt::OprtCastToInt()
:IOprtInfix(_T("(int)"), prINFIX)
{}
//-----------------------------------------------------------------------------------------------
void OprtCastToInt::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int /*a_iArgc*/)
{
switch (a_pArg[0]->GetType())
{
case 'f':
case 'i':
case 'b':
*ret = (float_type)((int_type)a_pArg[0]->GetFloat());
break;
default:
{
ErrorContext err;
err.Errc = ecINVALID_TYPECAST;
err.Type1 = a_pArg[0]->GetType();
err.Type2 = 'i';
throw ParserError(err);
}
} // switch value type
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtCastToInt::GetDesc() const
{
return _T("cast a value into a floating point number");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtCastToInt::Clone() const
{
return new OprtCastToInt(*this);
}
}

View File

@ -0,0 +1,247 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MP_OPRT_BIN_H
#define MP_OPRT_BIN_H
/** \file
\brief Definitions of classes used as callbacks for standard binary operators.
*/
/** \defgroup binop Binary operator callbacks
This group lists the objects representing the binary operators of muParserX.
*/
#include <cmath>
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
class OprtStrAdd : public IOprtBin
{
public:
OprtStrAdd();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------------------------------
/** \brief Callback object for testing if two values are equal.
\ingroup binop
*/
class OprtEQ : public IOprtBin
{
public:
OprtEQ();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object for testing if two values are not equal.
\ingroup binop
*/
class OprtNEQ : public IOprtBin
{
public:
OprtNEQ();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object class for the "Less than" operator.
\ingroup binop
*/
class OprtLT : public IOprtBin
{
public:
OprtLT();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object class for the "Greater than" operator.
\ingroup binop
*/
class OprtGT : public IOprtBin
{
public:
OprtGT();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object class for the "Less or equal" operator.
\ingroup binop
*/
class OprtLE : public IOprtBin
{
public:
OprtLE();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object class for the "Greater or or equal" operator.
\ingroup binop
*/
class OprtGE : public IOprtBin
{
public:
OprtGE();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback class for a logic and operator.
\ingroup binop
*/
class OprtAnd : public IOprtBin
{
public:
OprtAnd();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback class for a logic or operator.
\ingroup binop
*/
class OprtOr : public IOprtBin
{
public:
OprtOr();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback class for a logical or operator.
\ingroup binop
*/
class OprtLOr : public IOprtBin
{
public:
OprtLOr(const char_type *szIdent = _T("||"));
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback class for a logical and operator.
\ingroup binop
*/
class OprtLAnd : public IOprtBin
{
public:
OprtLAnd(const char_type *szIdent = _T("&&"));
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback class for the shift left operator.
\ingroup binop
*/
class OprtShl : public IOprtBin
{
public:
OprtShl();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback class for the shift right operator.
\ingroup binop
*/
class OprtShr : public IOprtBin
{
public:
OprtShr();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//---------------------------------------------------------------------------
/** \brief Callback for an operator allowing to cast values to floating
point values.
\ingroup infix
*/
class OprtCastToFloat : public IOprtInfix
{
public:
OprtCastToFloat();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class OprtCastToFloat
////---------------------------------------------------------------------------
///** \brief Callback for an operator allowing to cast values to integer values.
// \ingroup infix
//*/
class OprtCastToInt : public IOprtInfix
{
public:
OprtCastToInt();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class OprtCastToInt
} // namespace mu
#endif

View File

@ -0,0 +1,321 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpOprtCmplx.h"
#include <iomanip>
#include <limits>
MUP_NAMESPACE_START
//-------------------------------------------------------------------------------------------------
//
// class OprtSignCmplx
//
//-------------------------------------------------------------------------------------------------
OprtSignCmplx::OprtSignCmplx()
:IOprtInfix(_T("-"), prINFIX)
{}
//-----------------------------------------------------------------------------------------------
void OprtSignCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
MUP_VERIFY(a_iArgc == 1);
if (a_pArg[0]->IsScalar())
{
float_type re = a_pArg[0]->GetFloat();
float_type im = a_pArg[0]->GetImag();
// Do not omit the test for zero! Multiplying 0 with -1
// will yield -0 on IEEE754 compliant implementations!
// This would change the result of complex calculations:
//
// i.e. sqrt(-1 + (-0)i) != sqrt(-1 + 0i)
// -i != i
cmplx_type v((re == 0) ? 0 : -re, (im == 0) ? 0 : -im);
*ret = v;
}
else if (a_pArg[0]->GetType() == 'm')
{
Value v(a_pArg[0]->GetRows(), 0);
for (int i = 0; i < a_pArg[0]->GetRows(); ++i)
{
v.At(i) = a_pArg[0]->At(i).GetComplex() * (float_type)-1.0;
}
*ret = v;
}
else
{
ErrorContext err;
err.Errc = ecINVALID_TYPE;
err.Type1 = a_pArg[0]->GetType();
err.Type2 = 's';
throw ParserError(err);
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtSignCmplx::GetDesc() const
{
return _T("negative sign operator");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtSignCmplx::Clone() const
{
return new OprtSignCmplx(*this);
}
//-------------------------------------------------------------------------------------------------
//
// class OprtAddCmplx
//
//-------------------------------------------------------------------------------------------------
OprtAddCmplx::OprtAddCmplx()
:IOprtBin(_T("+"), (int)prADD_SUB, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtAddCmplx::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int num)
{
assert(num == 2);
const IValue *arg1 = a_pArg[0].Get();
const IValue *arg2 = a_pArg[1].Get();
if (arg1->IsNonComplexScalar() && arg2->IsNonComplexScalar())
{
*ret = arg1->GetFloat() + arg2->GetFloat();
}
else if (arg1->GetType() == 'm' && arg2->GetType() == 'm')
{
// Matrix + Matrix
*ret = arg1->GetArray() + arg2->GetArray();
}
else
{
if (!arg1->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg1->GetType(), 'c', 1));
if (!arg2->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg2->GetType(), 'c', 2));
*ret = cmplx_type(arg1->GetFloat() + arg2->GetFloat(),
arg1->GetImag() + arg2->GetImag());
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtAddCmplx::GetDesc() const
{
return _T("addition");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtAddCmplx::Clone() const
{
return new OprtAddCmplx(*this);
}
//-------------------------------------------------------------------------------------------------
//
// class OprtSubCmplx
//
//-------------------------------------------------------------------------------------------------
OprtSubCmplx::OprtSubCmplx()
:IOprtBin(_T("-"), (int)prADD_SUB, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtSubCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
assert(num == 2);
const IValue *arg1 = a_pArg[0].Get();
const IValue *arg2 = a_pArg[1].Get();
if (a_pArg[0]->IsNonComplexScalar() && a_pArg[1]->IsNonComplexScalar())
{
*ret = arg1->GetFloat() - arg2->GetFloat();
}
else if (a_pArg[0]->GetType() == 'm' && a_pArg[1]->GetType() == 'm')
{
// Matrix + Matrix
*ret = arg1->GetArray() - arg2->GetArray();
}
else
{
if (!a_pArg[0]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[0]->GetType(), 'c', 1));
if (!a_pArg[1]->IsScalar())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), a_pArg[1]->GetType(), 'c', 2));
*ret = cmplx_type(a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat(),
a_pArg[0]->GetImag() - a_pArg[1]->GetImag());
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtSubCmplx::GetDesc() const
{
return _T("subtraction");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtSubCmplx::Clone() const
{
return new OprtSubCmplx(*this);
}
//-------------------------------------------------------------------------------------------------
//
// class OprtMulCmplx
//
//-------------------------------------------------------------------------------------------------
OprtMulCmplx::OprtMulCmplx()
:IOprtBin(_T("*"), (int)prMUL_DIV, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
void OprtMulCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
assert(num == 2);
IValue *arg1 = a_pArg[0].Get();
IValue *arg2 = a_pArg[1].Get();
*ret = (*arg1) * (*arg2);
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtMulCmplx::GetDesc() const
{
return _T("foo*bar - multiplication");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtMulCmplx::Clone() const
{
return new OprtMulCmplx(*this);
}
//-------------------------------------------------------------------------------------------------
//
// class OprtDivCmplx
//
//-------------------------------------------------------------------------------------------------
OprtDivCmplx::OprtDivCmplx()
:IOprtBin(_T("/"), (int)prMUL_DIV, oaLEFT)
{}
//-----------------------------------------------------------------------------------------------
/** \brief Implements the Division operator.
\throw ParserError in case one of the arguments if
nonnumeric or an array.
*/
void OprtDivCmplx::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
assert(num == 2);
if (a_pArg[0]->IsNonComplexScalar() && a_pArg[1]->IsNonComplexScalar())
{
*ret = a_pArg[0]->GetFloat() / a_pArg[1]->GetFloat();
}
else
{
// multiplication of two imaginary numbers
float_type a = a_pArg[0]->GetFloat(),
b = a_pArg[0]->GetImag(),
c = a_pArg[1]->GetFloat(),
d = a_pArg[1]->GetImag(),
n = c*c + d*d;
*ret = cmplx_type((a*c + b*d) / n, (b*c - a*d) / n);
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtDivCmplx::GetDesc() const
{
return _T("division");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtDivCmplx::Clone() const
{
return new OprtDivCmplx(*this);
}
//-------------------------------------------------------------------------------------------------
//
// class OprtPowCmplx
//
//-------------------------------------------------------------------------------------------------
OprtPowCmplx::OprtPowCmplx()
:IOprtBin(_T("^"), (int)prPOW, oaRIGHT)
{}
//-----------------------------------------------------------------------------------------------
void OprtPowCmplx::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc)
{
assert(argc == 2);
if (arg[0]->IsComplex() || arg[1]->IsComplex() || (arg[0]->GetFloat() < 0 && !arg[1]->IsInteger()))
{
*ret = std::pow(arg[0]->GetComplex(), arg[1]->GetComplex());;
}
else
{
*ret = std::pow(arg[0]->GetFloat(), arg[1]->GetFloat());
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtPowCmplx::GetDesc() const
{
return _T("raise x to the power of y");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtPowCmplx::Clone() const
{
return new OprtPowCmplx(*this);
}
} // namespace

View File

@ -0,0 +1,130 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MP_OPRT_CMPLX_H
#define MP_OPRT_CMPLX_H
/** \file
\brief Definitions of classes used as callbacks for standard binary operators.
*/
/** \defgroup binop Binary operator callbacks
This group lists the objects representing the binary operators of muParserX.
*/
#include <cmath>
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
/** \brief Callback for the negative sign operator.
\ingroup infix
*/
class OprtSignCmplx : public IOprtInfix
{
public:
OprtSignCmplx();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class OprtSignCmplx
//------------------------------------------------------------------------------
/** \brief Parser callback for implementing an addition of two complex values.
\ingroup binop
*/
class OprtAddCmplx : public IOprtBin
{
public:
OprtAddCmplx();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Parser callback for implementing the subtraction of two complex values.
\ingroup binop
*/
class OprtSubCmplx : public IOprtBin
{
public:
OprtSubCmplx();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object for implementing the multiplications of complex values.
\ingroup binop
*/
class OprtMulCmplx : public IOprtBin
{
public:
OprtMulCmplx();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object for implementing the division of complex values.
\ingroup binop
*/
class OprtDivCmplx : public IOprtBin
{
public:
OprtDivCmplx();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Raise x to the power of y.
\ingroup binop
*/
class OprtPowCmplx : public IOprtBin
{
public:
OprtPowCmplx();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
} // namespace mu
#endif

View File

@ -0,0 +1,117 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpOprtIndex.h"
#include "mpVariable.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
//
// class OprtIndex
//
//-----------------------------------------------------------------------------------------------
OprtIndex::OprtIndex()
:ICallback(cmIC, _T("Index operator"), -1)
{}
//-----------------------------------------------------------------------------------------------
/** \brief Index operator implementation
\param ret A reference to the return value
\param a_pArg Pointer to an array with the indices as ptr_val_type
\param a_iArgc Number of indices (=dimension) actully used in the expression found. This must
be 1 or 2 since three dimensional data structures are not supported by muParserX.
*/
void OprtIndex::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
try
{
int rows = a_pArg[-1]->GetRows();
int cols = a_pArg[-1]->GetCols();
bool bArgIsVariable = a_pArg[-1]->IsVariable();
// If the index operator is applied to a variable the return value is also a variable
// pointing to a specific cell in the matrix. If the operator is applied to a value
// the return value is also a value.
switch (a_iArgc)
{
case 1:
if (cols == 1)
{
if (bArgIsVariable)
ret.Reset(new Variable(&(ret->At(*a_pArg[0], Value(0.0)))));
else
*ret = ret->At(*a_pArg[0], Value(0.0));
}
else if (rows == 1)
{
if (bArgIsVariable)
ret.Reset(new Variable(&(ret->At(Value(0.0), *a_pArg[0]))));
else
*ret = ret->At(Value(0.0), *a_pArg[0]);
}
else
{
throw ParserError(ErrorContext(ecINDEX_DIMENSION, -1, GetIdent()));
}
break;
case 2:
if (bArgIsVariable)
ret.Reset(new Variable(&(ret->At(*a_pArg[0], *a_pArg[1]))));
else
*ret = ret->At(*a_pArg[0], *a_pArg[1]);
break;
default:
throw ParserError(ErrorContext(ecINDEX_DIMENSION, -1, GetIdent()));
}
}
catch(ParserError &exc)
{
exc.GetContext().Pos = GetExprPos();
throw exc;
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtIndex::GetDesc() const
{
return _T("[,] - The index operator.");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtIndex::Clone() const
{
return new OprtIndex(*this);
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,65 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MP_OPRT_INDEX_H
#define MP_OPRT_INDEX_H
/** \file
\brief Definitions of index operator classes.
*/
/** \defgroup binop Binary operator callbacks
This group lists the objects representing the binary operators of muParserX.
*/
#include <cmath>
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
/** \brief Default implementation of a multidimensional index operator.
*/
class OprtIndex : public ICallback
{
public:
OprtIndex();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,182 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpOprtMatrix.h"
MUP_NAMESPACE_START
//-------------------------------------------------------------------------------------------------
//
// class OprtTranspose
//
//-------------------------------------------------------------------------------------------------
OprtTranspose::OprtTranspose()
:IOprtPostfix(_T("'"))
{}
//-------------------------------------------------------------------------------------------------
void OprtTranspose::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int /*a_iArgc*/)
{
if (a_pArg[0]->IsMatrix())
{
matrix_type matrix = a_pArg[0]->GetArray();
matrix.Transpose();
*ret = matrix;
}
else
*ret = *a_pArg[0];
}
//-------------------------------------------------------------------------------------------------
const char_type* OprtTranspose::GetDesc() const
{
return _T("foo' - An operator for transposing a matrix.");
}
//-------------------------------------------------------------------------------------------------
IToken* OprtTranspose::Clone() const
{
return new OprtTranspose(*this);
}
//-----------------------------------------------------------------------------------------------
//
// class OprtCreateArray
//
//-----------------------------------------------------------------------------------------------
OprtCreateArray::OprtCreateArray()
:ICallback(cmCBC, _T("Array constructor"), -1)
{}
//-----------------------------------------------------------------------------------------------
/** \brief Index operator implementation
\param ret A reference to the return value
\param a_pArg Pointer to an array with the indices as ptr_val_type
\param a_iArgc Number of indices (=dimension) actully used in the expression found. This must
be 1 or 2 since three dimensional data structures are not supported by muParserX.
*/
void OprtCreateArray::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
try
{
// The index is -1.
if (a_iArgc <= 0)
{
throw ParserError(ErrorContext(ecINVALID_PARAMETER, -1, GetIdent()));
}
matrix_type m(a_iArgc, 1, 0.0);
for (int i = 0; i < a_iArgc; ++i)
{
if (a_pArg[i]->GetDim() != 0)
{
// Prevent people from using this constructor for matrix creation.
// This would not work as expected and i dont't want them
// to get used to awkward workarounds. It's just not working right now ok?
ErrorContext errc(ecINVALID_PARAMETER, -1, GetIdent());
errc.Arg = i+1;
throw ParserError(errc);
}
m.At(i) = *a_pArg[i];
}
m.Transpose();
*ret = m;
}
catch (ParserError &exc)
{
exc.GetContext().Pos = GetExprPos();
throw exc;
}
}
//-----------------------------------------------------------------------------------------------
const char_type* OprtCreateArray::GetDesc() const
{
return _T("{,} - Array construction operator.");
}
//-----------------------------------------------------------------------------------------------
IToken* OprtCreateArray::Clone() const
{
return new OprtCreateArray(*this);
}
//-----------------------------------------------------------
//
// class OprtColon
//
//-----------------------------------------------------------
OprtColon::OprtColon()
:IOprtBin(_T("~"), (int)prCOLON, oaLEFT)
{}
//-----------------------------------------------------------
void OprtColon::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int num)
{
assert(num==2);
const IValue *argMin = a_pArg[0].Get();
const IValue *argMax = a_pArg[1].Get();
if (!argMin->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), argMin->GetType(), 'i', 1));
if (!argMax->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), argMax->GetType(), 'i', 1));
if (*argMax < *argMin)
throw ParserError(_T("Colon operator: Maximum value smaller than Minimum!"));
int n = (int)(argMax->GetFloat() - argMin->GetFloat()) + 1;
matrix_type arr(n);
for (int i=0; i<n; ++i)
arr.At(i) = argMin->GetFloat() + i;
*ret = arr;
}
//-----------------------------------------------------------
const char_type* OprtColon::GetDesc() const
{
return _T(": - Colon operator");
}
//-----------------------------------------------------------
IToken* OprtColon::Clone() const
{
return new OprtColon(*this);
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,80 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MP_OPRT_MATRIX_H
#define MP_OPRT_MATRIX_H
/** \file
\brief Definitions of classes used as callbacks for matrix operators.
*/
#include <cmath>
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
class OprtTranspose : public IOprtPostfix
{
public:
OprtTranspose();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------------------------------
/** \brief On the fly array creation using the curly bracket operator.
*/
class OprtCreateArray : public ICallback
{
public:
OprtCreateArray();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//-----------------------------------------------------------------------------------------------
class OprtColon : public IOprtBin
{
public:
OprtColon();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,423 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpOprtNonCmplx.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
//
// Sign operator
//
//------------------------------------------------------------------------------
OprtSign::OprtSign()
:IOprtInfix( _T("-"), prINFIX)
{}
//------------------------------------------------------------------------------
void OprtSign::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
MUP_VERIFY(a_iArgc == 1);
if (a_pArg[0]->IsScalar())
{
*ret = -a_pArg[0]->GetFloat();
}
else if (a_pArg[0]->GetType()=='m')
{
Value v(a_pArg[0]->GetRows(), 0);
for (int i=0; i<a_pArg[0]->GetRows(); ++i)
{
v.At(i) = -a_pArg[0]->At(i).GetFloat();
}
*ret = v;
}
else
{
ErrorContext err;
err.Errc = ecINVALID_TYPE;
err.Type1 = a_pArg[0]->GetType();
err.Type2 = 's';
throw ParserError(err);
}
}
//------------------------------------------------------------------------------
const char_type* OprtSign::GetDesc() const
{
return _T("-x - negative sign operator");
}
//------------------------------------------------------------------------------
IToken* OprtSign::Clone() const
{
return new OprtSign(*this);
}
//------------------------------------------------------------------------------
//
// Sign operator
//
//------------------------------------------------------------------------------
OprtSignPos::OprtSignPos()
:IOprtInfix( _T("+"), prINFIX)
{}
//------------------------------------------------------------------------------
void OprtSignPos::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc)
{
MUP_VERIFY(a_iArgc == 1);
if (a_pArg[0]->IsScalar())
{
*ret = a_pArg[0]->GetFloat();
}
else if (a_pArg[0]->GetType()=='m')
{
Value v(a_pArg[0]->GetRows(), 0);
for (int i=0; i<a_pArg[0]->GetRows(); ++i)
{
v.At(i) = a_pArg[0]->At(i).GetFloat();
}
*ret = v;
}
else
{
ErrorContext err;
err.Errc = ecINVALID_TYPE;
err.Type1 = a_pArg[0]->GetType();
err.Type2 = 's';
throw ParserError(err);
}
}
//------------------------------------------------------------------------------
const char_type* OprtSignPos::GetDesc() const
{
return _T("+x - positive sign operator");
}
//------------------------------------------------------------------------------
IToken* OprtSignPos::Clone() const
{
return new OprtSignPos(*this);
}
//-----------------------------------------------------------
//
// class OprtAdd
//
//-----------------------------------------------------------
OprtAdd::OprtAdd()
:IOprtBin(_T("+"), (int)prADD_SUB, oaLEFT)
{}
//-----------------------------------------------------------
void OprtAdd::Eval(ptr_val_type& ret, const ptr_val_type *a_pArg, int num)
{
assert(num==2);
const IValue *arg1 = a_pArg[0].Get();
const IValue *arg2 = a_pArg[1].Get();
if (arg1->GetType()=='m' && arg2->GetType()=='m')
{
// Vector + Vector
const matrix_type &a1 = arg1->GetArray(),
&a2 = arg2->GetArray();
if (a1.GetRows()!=a2.GetRows())
throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2));
matrix_type rv(a1.GetRows());
for (int i=0; i<a1.GetRows(); ++i)
{
if (!a1.At(i).IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a1.At(i).GetType(), 'f', 1));
if (!a2.At(i).IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a2.At(i).GetType(), 'f', 1));
rv.At(i) = a1.At(i).GetFloat() + a2.At(i).GetFloat();
}
*ret = rv;
}
else
{
if (!arg1->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1->GetType(), 'f', 1));
if (!arg2->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2->GetType(), 'f', 2));
*ret = arg1->GetFloat() + arg2->GetFloat();
}
}
//-----------------------------------------------------------
const char_type* OprtAdd::GetDesc() const
{
return _T("x+y - Addition for noncomplex values");
}
//-----------------------------------------------------------
IToken* OprtAdd::Clone() const
{
return new OprtAdd(*this);
}
//-----------------------------------------------------------
//
// class OprtSub
//
//-----------------------------------------------------------
OprtSub::OprtSub()
:IOprtBin(_T("-"), (int)prADD_SUB, oaLEFT)
{}
//-----------------------------------------------------------
void OprtSub::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
assert(num==2);
if (a_pArg[0]->GetType()=='m' && a_pArg[1]->GetType()=='m')
{
const matrix_type &a1 = a_pArg[0]->GetArray(),
&a2 = a_pArg[1]->GetArray();
if (a1.GetRows()!=a2.GetRows())
throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2));
matrix_type rv(a1.GetRows());
for (int i=0; i<a1.GetRows(); ++i)
{
if (!a1.At(i).IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a1.At(i).GetType(), 'f', 1));
if (!a2.At(i).IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a2.At(i).GetType(), 'f', 1));
rv.At(i) = cmplx_type(a1.At(i).GetFloat() - a2.At(i).GetFloat(),
a1.At(i).GetImag() - a2.At(i).GetImag());
}
*ret = rv;
}
else
{
if (!a_pArg[0]->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'f', 1));
if (!a_pArg[1]->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'f', 2));
*ret = a_pArg[0]->GetFloat() - a_pArg[1]->GetFloat();
}
}
//-----------------------------------------------------------
const char_type* OprtSub::GetDesc() const
{
return _T("subtraction");
}
//-----------------------------------------------------------
IToken* OprtSub::Clone() const
{
return new OprtSub(*this);
}
//-----------------------------------------------------------
//
// class OprtMul
//
//-----------------------------------------------------------
OprtMul::OprtMul()
:IOprtBin(_T("*"), (int)prMUL_DIV, oaLEFT)
{}
//-----------------------------------------------------------
void OprtMul::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
assert(num==2);
IValue *arg1 = a_pArg[0].Get();
IValue *arg2 = a_pArg[1].Get();
if (arg1->GetType()=='m' && arg2->GetType()=='m')
{
// Scalar multiplication
matrix_type a1 = arg1->GetArray();
matrix_type a2 = arg2->GetArray();
if (a1.GetRows()!=a2.GetRows())
throw ParserError(ErrorContext(ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2));
float_type val(0);
for (int i=0; i<a1.GetRows(); ++i)
val += a1.At(i).GetFloat()*a2.At(i).GetFloat();
*ret = val;
}
else if (arg1->GetType()=='m' && arg2->IsNonComplexScalar())
{
// Skalar * Vector
matrix_type out(a_pArg[0]->GetArray());
for (int i=0; i<out.GetRows(); ++i)
out.At(i) = out.At(i).GetFloat() * arg2->GetFloat();
*ret = out;
}
else if (arg2->GetType()=='m' && arg1->IsNonComplexScalar())
{
// Vector * Skalar
matrix_type out(arg2->GetArray());
for (int i=0; i<out.GetRows(); ++i)
out.At(i) = out.At(i).GetFloat() * arg1->GetFloat();
*ret = out;
}
else
{
if (!arg1->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1->GetType(), 'f', 1));
if (!arg2->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2->GetType(), 'f', 2));
*ret = arg1->GetFloat() * arg2->GetFloat();
}
}
//-----------------------------------------------------------
const char_type* OprtMul::GetDesc() const
{
return _T("multiplication");
}
//-----------------------------------------------------------
IToken* OprtMul::Clone() const
{
return new OprtMul(*this);
}
//-----------------------------------------------------------
//
// class OprtDiv
//
//-----------------------------------------------------------
OprtDiv::OprtDiv()
:IOprtBin(_T("/"), (int)prMUL_DIV, oaLEFT)
{}
//-----------------------------------------------------------
/** \brief Implements the Division operator.
\throw ParserError in case one of the arguments if
nonnumeric or an array.
*/
void OprtDiv::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int num)
{
assert(num==2);
if (!a_pArg[0]->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[0]->GetType(), 'f', 1));
if (!a_pArg[1]->IsNonComplexScalar())
throw ParserError( ErrorContext(ecTYPE_CONFLICT_FUN, -1, GetIdent(), a_pArg[1]->GetType(), 'f', 2));
*ret = a_pArg[0]->GetFloat() / a_pArg[1]->GetFloat();
}
//-----------------------------------------------------------
const char_type* OprtDiv::GetDesc() const
{
return _T("division");
}
//-----------------------------------------------------------
IToken* OprtDiv::Clone() const
{
return new OprtDiv(*this);
}
//-----------------------------------------------------------
//
// class OprtPow
//
//-----------------------------------------------------------
OprtPow::OprtPow()
:IOprtBin(_T("^"), (int)prPOW, oaRIGHT)
{}
//-----------------------------------------------------------
void OprtPow::Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc)
{
assert(argc==2);
float_type a = arg[0]->GetFloat();
float_type b = arg[1]->GetFloat();
int ib = (int)b;
if (b-ib==0)
{
switch (ib)
{
case 1: *ret = a; return;
case 2: *ret = a*a; return;
case 3: *ret = a*a*a; return;
case 4: *ret = a*a*a*a; return;
case 5: *ret = a*a*a*a*a; return;
default: *ret = std::pow(a, ib); return;
}
}
else
*ret = std::pow(a, b);
}
//-----------------------------------------------------------
const char_type* OprtPow::GetDesc() const
{
return _T("x^y - Raises x to the power of y.");
}
//-----------------------------------------------------------
IToken* OprtPow::Clone() const
{
return new OprtPow(*this);
}
}

View File

@ -0,0 +1,145 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MP_OPRT_NON_CMPLX_H
#define MP_OPRT_NON_CMPLX_H
/** \file
\brief Definitions of classes used as callbacks for standard binary operators.
*/
/** \defgroup binop Binary operator callbacks
This group lists the objects representing the binary operators of muParserX.
*/
#include <cmath>
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
/** \brief Callback for the negative sign operator for noncomplex values.
\ingroup infix
*/
class OprtSign : public IOprtInfix
{
public:
OprtSign();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class OprtSign
//---------------------------------------------------------------------------
/** \brief Callback for the positive sign operator for noncomplex values.
\ingroup infix
*/
class OprtSignPos : public IOprtInfix
{
public:
OprtSignPos();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
}; // class OprtSignPos
//------------------------------------------------------------------------------
/** \brief Parser callback for implementing an addition of two noncomplex values.
\ingroup binop
*/
class OprtAdd : public IOprtBin
{
public:
OprtAdd();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Parser callback for implementing the subtraction of two noncomplex values.
\ingroup binop
*/
class OprtSub : public IOprtBin
{
public:
OprtSub();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object for implementing the multiplications of noncomplex values.
\ingroup binop
*/
class OprtMul : public IOprtBin
{
public:
OprtMul();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Callback object for implementing the division of noncomplex values.
\ingroup binop
*/
class OprtDiv : public IOprtBin
{
public:
OprtDiv();
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Raise x to the power of y.
\ingroup binop
*/
class OprtPow : public IOprtBin
{
public:
OprtPow();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int argc) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
} // namespace mu
#endif

View File

@ -0,0 +1,112 @@
#include <limits>
#include "mpOprtPostfixCommon.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------
//
// class OprtFact
//
//-----------------------------------------------------------
OprtFact::OprtFact()
:IOprtPostfix(_T("!"))
{}
//-----------------------------------------------------------
void OprtFact::Eval(ptr_val_type& ret, const ptr_val_type *arg, int)
{
if (!arg[0]->IsInteger())
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg[0]->GetType(), 'i', 1));
int_type input = arg[0]->GetInteger();
float_type input_long = float_type(input);
if (input < 0) {
throw ParserError(ErrorContext(ecDOMAIN_ERROR, GetExprPos(),
GetIdent()));
}
float_type result = 1;
for (float_type i = 1.0; i <= input_long; i += 1.0)
{
result *= i;
// <ibg 20130225/> Only throw exceptions if IEEE 754 is not supported. The
// Prefered way of dealing with overflows is relying on:
//
// http://en.wikipedia.org/wiki/IEEE_754-1985
//
// If the compiler does not support IEEE 754, chances are
// you are running on a pretty fucked up system.
//
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4127)
#endif /* _MSC_VER */
if ( !std::numeric_limits<float_type>::is_iec559 &&
(result>std::numeric_limits<float_type>::max() || result < 1.0) )
#ifdef _MSC_VER
#pragma warning(pop)
#endif /* _MSC_VER */
{
throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent()));
}
// </ibg>
}
*ret = result;
}
//-----------------------------------------------------------
const char_type* OprtFact::GetDesc() const
{
return _T("x! - Returns factorial of a non-negative integer.");
}
//-----------------------------------------------------------
IToken* OprtFact::Clone() const
{
return new OprtFact(*this);
}
//-----------------------------------------------------------
//
// class OprtPercentage
//
//-----------------------------------------------------------
OprtPercentage::OprtPercentage()
:IOprtPostfix(_T("%"))
{}
//-----------------------------------------------------------
void OprtPercentage::Eval(ptr_val_type& ret, const ptr_val_type *arg, int)
{
switch (arg[0]->GetType()) {
case 'i':
case 'f': {
float_type input = arg[0]->GetFloat();
*ret = input / 100.0;
break;
}
default:
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, GetExprPos(), GetIdent(), arg[0]->GetType(), 'f', 1));
break;
}
}
//-----------------------------------------------------------
const char_type* OprtPercentage::GetDesc() const
{
return _T("x% - Returns percentage of integer/float.");
}
//-----------------------------------------------------------
IToken* OprtPercentage::Clone() const
{
return new OprtPercentage(*this);
}
}

View File

@ -0,0 +1,51 @@
#ifndef MP_OPRT_POSTFIX_COMMON_H
#define MP_OPRT_POSTFIX_COMMON_H
/** \file
\brief Definitions of classes used as callbacks for standard postfix operators.
*/
/** \defgroup postop Postfix operator callbacks
This group lists the objects representing the postfix operators of muParserX.
*/
#include "mpIOprt.h"
#include "mpValue.h"
#include "mpError.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Calculate factorial of a non-negative integer.
\ingroup postop
*/
class OprtFact : public IOprtPostfix
{
public:
OprtFact();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
//------------------------------------------------------------------------------
/** \brief Returns percentage of given number.
\ingroup postop
*/
class OprtPercentage : public IOprtPostfix
{
public:
OprtPercentage();
virtual void Eval(ptr_val_type& ret, const ptr_val_type *arg, int) override;
virtual const char_type* GetDesc() const override;
virtual IToken* Clone() const override;
};
} // namespace mu
#endif

View File

@ -0,0 +1,102 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpPackageCmplx.h"
#include "mpParserBase.h"
#include "mpFuncCmplx.h"
#include "mpOprtCmplx.h"
#include "mpOprtBinCommon.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
std::unique_ptr<PackageCmplx> PackageCmplx::s_pInstance;
//------------------------------------------------------------------------------
IPackage* PackageCmplx::Instance()
{
if (s_pInstance.get()==nullptr)
{
s_pInstance.reset(new PackageCmplx);
}
return s_pInstance.get();
}
//------------------------------------------------------------------------------
void PackageCmplx::AddToParser(ParserXBase *pParser)
{
// Constants
pParser->DefineConst( _T("i"), cmplx_type(0.0, 1.0) );
// Complex valued functions
pParser->DefineFun(new FunCmplxReal());
pParser->DefineFun(new FunCmplxImag());
pParser->DefineFun(new FunCmplxConj());
pParser->DefineFun(new FunCmplxArg());
pParser->DefineFun(new FunCmplxNorm());
pParser->DefineFun(new FunCmplxSin());
pParser->DefineFun(new FunCmplxCos());
pParser->DefineFun(new FunCmplxTan());
pParser->DefineFun(new FunCmplxSinH());
pParser->DefineFun(new FunCmplxCosH());
pParser->DefineFun(new FunCmplxTanH());
pParser->DefineFun(new FunCmplxSqrt());
pParser->DefineFun(new FunCmplxExp());
pParser->DefineFun(new FunCmplxLn());
pParser->DefineFun(new FunCmplxLog());
pParser->DefineFun(new FunCmplxLog2());
pParser->DefineFun(new FunCmplxLog10());
pParser->DefineFun(new FunCmplxAbs());
pParser->DefineFun(new FunCmplxPow());
// Complex valued operators
pParser->DefineOprt(new OprtAddCmplx());
pParser->DefineOprt(new OprtSubCmplx());
pParser->DefineOprt(new OprtMulCmplx());
pParser->DefineOprt(new OprtDivCmplx());
pParser->DefineOprt(new OprtPowCmplx());
pParser->DefineInfixOprt(new OprtSignCmplx());
}
//------------------------------------------------------------------------------
string_type PackageCmplx::GetDesc() const
{
return _T("");
}
//------------------------------------------------------------------------------
string_type PackageCmplx::GetPrefix() const
{
return _T("");
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,62 @@
#ifndef MU_PACKAGE_CMPLX_H
#define MU_PACKAGE_CMPLX_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <memory>
#include "mpIPackage.h"
#include "mpIOprt.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Package for installing complex functions and operators. */
class PackageCmplx: public IPackage
{
friend class std::unique_ptr<PackageCmplx>;
public:
static IPackage* Instance();
virtual void AddToParser(ParserXBase *pParser);
virtual string_type GetDesc() const;
virtual string_type GetPrefix() const;
private:
static std::unique_ptr<PackageCmplx> s_pInstance;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,141 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpPackageCommon.h"
#include "mpParserBase.h"
#include "mpFuncNonCmplx.h"
#include "mpFuncCommon.h"
#include "mpOprtBinCommon.h"
#include "mpOprtBinAssign.h"
#include "mpOprtPostfixCommon.h"
#include "mpValReader.h"
/** \brief Pi (what else?). */
#define MUP_CONST_PI 3.141592653589793238462643
//#define MUP_CONST_PI 3.14159265358979323846264338327950288419716939937510L
/** \brief The eulerian number. */
#define MUP_CONST_E 2.718281828459045235360287
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
std::unique_ptr<PackageCommon> PackageCommon::s_pInstance;
//------------------------------------------------------------------------------
IPackage* PackageCommon::Instance()
{
if (s_pInstance.get()==nullptr)
{
s_pInstance.reset(new PackageCommon);
}
return s_pInstance.get();
}
//------------------------------------------------------------------------------
void PackageCommon::AddToParser(ParserXBase *pParser)
{
// Readers that need fancy decorations on their values must
// be added first (i.e. hex -> "0x...") Otherwise the
// zero in 0x will be read as a value of zero!
pParser->AddValueReader(new HexValReader);
pParser->AddValueReader(new BinValReader);
pParser->AddValueReader(new DblValReader);
pParser->AddValueReader(new BoolValReader);
// Constants
pParser->DefineConst( _T("pi"), (float_type)MUP_CONST_PI );
pParser->DefineConst( _T("e"), (float_type)MUP_CONST_E );
// Vector
pParser->DefineFun(new FunSizeOf());
// Generic functions
pParser->DefineFun(new FunMax());
pParser->DefineFun(new FunMin());
pParser->DefineFun(new FunSum());
// misc
pParser->DefineFun(new FunParserID);
// integer package
pParser->DefineOprt(new OprtLAnd);
pParser->DefineOprt(new OprtLOr);
pParser->DefineOprt(new OprtAnd);
pParser->DefineOprt(new OprtOr);
pParser->DefineOprt(new OprtShr);
pParser->DefineOprt(new OprtShl);
// booloean package
pParser->DefineOprt(new OprtLE);
pParser->DefineOprt(new OprtGE);
pParser->DefineOprt(new OprtLT);
pParser->DefineOprt(new OprtGT);
pParser->DefineOprt(new OprtEQ);
pParser->DefineOprt(new OprtNEQ);
pParser->DefineOprt(new OprtLAnd(_T("and"))); // add logic and with a different identifier
pParser->DefineOprt(new OprtLOr(_T("or"))); // add logic and with a different identifier
// pParser->DefineOprt(new OprtBXor);
// assignement operators
pParser->DefineOprt(new OprtAssign);
pParser->DefineOprt(new OprtAssignAdd);
pParser->DefineOprt(new OprtAssignSub);
pParser->DefineOprt(new OprtAssignMul);
pParser->DefineOprt(new OprtAssignDiv);
// infix operators
pParser->DefineInfixOprt(new OprtCastToFloat);
pParser->DefineInfixOprt(new OprtCastToInt);
// postfix operators
pParser->DefinePostfixOprt(new OprtFact);
// <ibg 20130708> commented: "%" is a reserved sign for either the
// modulo operator or comment lines.
// pParser->DefinePostfixOprt(new OprtPercentage);
// </ibg>
}
//------------------------------------------------------------------------------
string_type PackageCommon::GetDesc() const
{
return _T("");
}
//------------------------------------------------------------------------------
string_type PackageCommon::GetPrefix() const
{
return _T("");
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,64 @@
#ifndef MU_PACKAGE_COMMON_H
#define MU_PACKAGE_COMMON_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <memory>
#include "mpIPackage.h"
#include "mpIOprt.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Package for installing operators and functions which
are always present.
*/
class PackageCommon: public IPackage
{
friend class std::unique_ptr<PackageCommon>;
public:
static IPackage* Instance();
virtual void AddToParser(ParserXBase *pParser) override;
virtual string_type GetDesc() const override;
virtual string_type GetPrefix() const override;
private:
static std::unique_ptr<PackageCommon> s_pInstance;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,82 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpPackageMatrix.h"
#include "mpParserBase.h"
#include "mpFuncMatrix.h"
#include "mpOprtMatrix.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
std::unique_ptr<PackageMatrix> PackageMatrix::s_pInstance;
//------------------------------------------------------------------------------
IPackage* PackageMatrix::Instance()
{
if (s_pInstance.get()==nullptr)
{
s_pInstance.reset(new PackageMatrix);
}
return s_pInstance.get();
}
//------------------------------------------------------------------------------
void PackageMatrix::AddToParser(ParserXBase *pParser)
{
// Matrix functions
pParser->DefineFun(new FunMatrixOnes());
pParser->DefineFun(new FunMatrixZeros());
pParser->DefineFun(new FunMatrixEye());
pParser->DefineFun(new FunMatrixSize());
// Matrix Operators
pParser->DefinePostfixOprt(new OprtTranspose());
// Colon operator
//pParser->DefineOprt(new OprtColon());
//pParser->DefineAggregator(new AggColon());
}
//------------------------------------------------------------------------------
string_type PackageMatrix::GetDesc() const
{
return _T("Operators and functions for matrix operations");
}
//------------------------------------------------------------------------------
string_type PackageMatrix::GetPrefix() const
{
return _T("");
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,62 @@
#ifndef MU_PACKAGE_MATRIX_H
#define MU_PACKAGE_MATRIX_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <memory>
#include "mpIPackage.h"
#include "mpIOprt.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Package for installing complex functions and operators. */
class PackageMatrix : public IPackage
{
friend class std::unique_ptr<PackageMatrix>;
public:
static IPackage* Instance();
virtual void AddToParser(ParserXBase *pParser);
virtual string_type GetDesc() const;
virtual string_type GetPrefix() const;
private:
static std::unique_ptr<PackageMatrix> s_pInstance;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,108 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpPackageNonCmplx.h"
#include "mpParserBase.h"
#include "mpFuncNonCmplx.h"
#include "mpOprtNonCmplx.h"
#include "mpOprtBinCommon.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
std::unique_ptr<PackageNonCmplx> PackageNonCmplx::s_pInstance;
//------------------------------------------------------------------------------
IPackage* PackageNonCmplx::Instance()
{
if (s_pInstance.get()==nullptr)
{
s_pInstance.reset(new PackageNonCmplx);
}
return s_pInstance.get();
}
//------------------------------------------------------------------------------
void PackageNonCmplx::AddToParser(ParserXBase *pParser)
{
pParser->DefineFun(new FunSin());
pParser->DefineFun(new FunCos());
pParser->DefineFun(new FunTan());
pParser->DefineFun(new FunSinH());
pParser->DefineFun(new FunCosH());
pParser->DefineFun(new FunTanH());
pParser->DefineFun(new FunASin());
pParser->DefineFun(new FunACos());
pParser->DefineFun(new FunATan());
pParser->DefineFun(new FunASinH());
pParser->DefineFun(new FunACosH());
pParser->DefineFun(new FunATanH());
pParser->DefineFun(new FunLog());
pParser->DefineFun(new FunLog10());
pParser->DefineFun(new FunLog2());
pParser->DefineFun(new FunLn());
pParser->DefineFun(new FunExp());
pParser->DefineFun(new FunSqrt());
pParser->DefineFun(new FunCbrt());
pParser->DefineFun(new FunAbs());
// binary functions
pParser->DefineFun(new FunPow());
pParser->DefineFun(new FunHypot());
pParser->DefineFun(new FunAtan2());
pParser->DefineFun(new FunFmod());
pParser->DefineFun(new FunRemainder());
// Operator callbacks
pParser->DefineInfixOprt(new OprtSign());
pParser->DefineInfixOprt(new OprtSignPos());
pParser->DefineOprt(new OprtAdd());
pParser->DefineOprt(new OprtSub());
pParser->DefineOprt(new OprtMul());
pParser->DefineOprt(new OprtDiv());
pParser->DefineOprt(new OprtPow);
}
//------------------------------------------------------------------------------
string_type PackageNonCmplx::GetDesc() const
{
return _T("");
}
//------------------------------------------------------------------------------
string_type PackageNonCmplx::GetPrefix() const
{
return _T("");
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,63 @@
#ifndef MU_PACKAGE_NON_CMPLX_H
#define MU_PACKAGE_NON_CMPLX_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <memory>
#include "mpIPackage.h"
#include "mpIOprt.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Package for installing complex functions and operators. */
class PackageNonCmplx: public IPackage
{
friend class std::unique_ptr<PackageNonCmplx>;
public:
static IPackage* Instance();
virtual void AddToParser(ParserXBase *pParser);
virtual string_type GetDesc() const;
virtual string_type GetPrefix() const;
private:
static std::unique_ptr<PackageNonCmplx> s_pInstance;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,81 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpPackageStr.h"
#include "mpParserBase.h"
#include "mpFuncStr.h"
#include "mpOprtBinCommon.h"
#include "mpValReader.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
std::unique_ptr<PackageStr> PackageStr::s_pInstance;
//------------------------------------------------------------------------------
IPackage* PackageStr::Instance()
{
if (s_pInstance.get()==nullptr)
{
s_pInstance.reset(new PackageStr);
}
return s_pInstance.get();
}
//------------------------------------------------------------------------------
void PackageStr::AddToParser(ParserXBase *pParser)
{
pParser->AddValueReader(new StrValReader());
// Functions
pParser->DefineFun(new FunStrLen());
pParser->DefineFun(new FunStrToDbl());
pParser->DefineFun(new FunStrToUpper());
pParser->DefineFun(new FunStrToLower());
// Operators
pParser->DefineOprt(new OprtStrAdd);
}
//------------------------------------------------------------------------------
string_type PackageStr::GetDesc() const
{
return _T("A package for string operations.");
}
//------------------------------------------------------------------------------
string_type PackageStr::GetPrefix() const
{
return _T("");
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,63 @@
#ifndef MU_PACKAGE_STR_H
#define MU_PACKAGE_STR_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <memory>
#include "mpIPackage.h"
#include "mpIOprt.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Package for installing unit postfix operators into muParserX. */
class PackageStr : public IPackage
{
friend class std::unique_ptr<PackageStr>;
public:
static IPackage* Instance();
virtual void AddToParser(ParserXBase *pParser);
virtual string_type GetDesc() const;
virtual string_type GetPrefix() const;
private:
static std::unique_ptr<PackageStr> s_pInstance;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,119 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpPackageUnit.h"
#include "mpParserBase.h"
MUP_NAMESPACE_START
/** \brief This is a macro for defining scaling postfix operators.
These operators can be used for unit conversions.
*/
#define MUP_POSTFIX_IMLP(CLASS, IDENT, MUL, DESC) \
CLASS::CLASS(IPackage*) \
:IOprtPostfix(_T(IDENT)) \
{} \
\
void CLASS::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int) \
{ \
if (!a_pArg[0]->IsScalar()) \
{ \
ErrorContext err(ecTYPE_CONFLICT, \
GetExprPos(), \
a_pArg[0]->ToString(), \
a_pArg[0]->GetType(), \
'c', \
1); \
throw ParserError(err); \
} \
\
*ret = a_pArg[0]->GetComplex() * MUL; \
} \
\
const char_type* CLASS::GetDesc() const \
{ \
return _T(DESC); \
} \
\
IToken* CLASS::Clone() const \
{ \
return new CLASS(*this); \
}
MUP_POSTFIX_IMLP(OprtNano, "n", (float_type)1e-9, "n - unit multiplicator 1e-9")
MUP_POSTFIX_IMLP(OprtMicro, "u", (float_type)1e-6, "u - unit multiplicator 1e-6")
MUP_POSTFIX_IMLP(OprtMilli, "m", (float_type)1e-3, "m - unit multiplicator 1e-3")
MUP_POSTFIX_IMLP(OprtKilo, "k", (float_type)1e3, "k - unit multiplicator 1e3")
MUP_POSTFIX_IMLP(OprtMega, "M", (float_type)1e6, "M - unit multiplicator 1e6")
MUP_POSTFIX_IMLP(OprtGiga, "G", (float_type)1e9, "G - unit multiplicator 1e9")
#undef MUP_POSTFIX_IMLP
//------------------------------------------------------------------------------
std::unique_ptr<PackageUnit> PackageUnit::s_pInstance;
//------------------------------------------------------------------------------
IPackage* PackageUnit::Instance()
{
if (s_pInstance.get()==nullptr)
{
s_pInstance.reset(new PackageUnit);
}
return s_pInstance.get();
}
//------------------------------------------------------------------------------
void PackageUnit::AddToParser(ParserXBase *pParser)
{
pParser->DefinePostfixOprt(new OprtNano(this));
pParser->DefinePostfixOprt(new OprtMicro(this));
pParser->DefinePostfixOprt(new OprtMilli(this));
pParser->DefinePostfixOprt(new OprtKilo(this));
pParser->DefinePostfixOprt(new OprtMega(this));
pParser->DefinePostfixOprt(new OprtGiga(this));
}
//------------------------------------------------------------------------------
string_type PackageUnit::GetDesc() const
{
return _T("Postfix operators for basic unit conversions.");
}
//------------------------------------------------------------------------------
string_type PackageUnit::GetPrefix() const
{
return _T("");
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,80 @@
#ifndef MU_PACKAGE_UNIT_H
#define MU_PACKAGE_UNIT_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <memory>
#include "mpIPackage.h"
#include "mpIOprt.h"
MUP_NAMESPACE_START
#define MUP_POSTFIX_DEF(CLASS) \
class CLASS : public IOprtPostfix \
{ \
public: \
CLASS(IPackage* pPackage=nullptr); \
virtual void Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int a_iArgc); \
virtual const char_type* GetDesc() const; \
virtual IToken* Clone() const; \
};
MUP_POSTFIX_DEF(OprtNano)
MUP_POSTFIX_DEF(OprtMicro)
MUP_POSTFIX_DEF(OprtMilli)
MUP_POSTFIX_DEF(OprtKilo)
MUP_POSTFIX_DEF(OprtMega)
MUP_POSTFIX_DEF(OprtGiga)
#undef MUP_POSTFIX_DEF
//------------------------------------------------------------------------------
/** \brief Package for installing unit postfix operators into muParserX. */
class PackageUnit : public IPackage
{
friend class std::unique_ptr<PackageUnit>;
public:
static IPackage* Instance();
virtual void AddToParser(ParserXBase *pParser);
virtual string_type GetDesc() const;
virtual string_type GetPrefix() const;
private:
static std::unique_ptr<PackageUnit> s_pInstance;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,91 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpParser.h"
//--- Standard includes ----------------------------------------------------
#include <cmath>
#include <algorithm>
#include <numeric>
//--- Parser framework -----------------------------------------------------
#include "mpPackageUnit.h"
#include "mpPackageStr.h"
#include "mpPackageCmplx.h"
#include "mpPackageNonCmplx.h"
#include "mpPackageCommon.h"
#include "mpPackageMatrix.h"
using namespace std;
/** \brief Namespace for mathematical applications. */
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
/** \brief Default constructor.
Call ParserXBase class constructor and initiate function, operator
and constant initialization.
*/
ParserX::ParserX(unsigned ePackages)
:ParserXBase()
{
DefineNameChars(_T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"));
DefineOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_µ{}"));
DefineInfixOprtChars(_T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ()/+-*^?<>=#!$%&|~'_"));
if (ePackages & pckUNIT)
AddPackage(PackageUnit::Instance());
if (ePackages & pckSTRING)
AddPackage(PackageStr::Instance());
if (ePackages & pckCOMPLEX)
AddPackage(PackageCmplx::Instance());
if (ePackages & pckNON_COMPLEX)
AddPackage(PackageNonCmplx::Instance());
if (ePackages & pckCOMMON)
AddPackage(PackageCommon::Instance());
if (ePackages & pckMATRIX)
AddPackage(PackageMatrix::Instance());
}
//------------------------------------------------------------------------------
void ParserX::ResetErrorMessageProvider(ParserMessageProviderBase *pProvider)
{
ParserErrorMsg::Reset(pProvider);
}
} // namespace mu

View File

@ -0,0 +1,62 @@
#ifndef MUP_PARSERX_H
#define MUP_PARSERX_H
/** \file
\brief Definition of the parser class
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
//--- Parser framework -----------------------------------------------------
#include "mpDefines.h"
#include "mpParserBase.h"
MUP_NAMESPACE_START
/** \brief The parser implementation.
\sa ParserXBase
This is the class that implements the parser. It installs all functions
and operatore and defines the constants.
*/
class ParserX : public ParserXBase
{
public:
ParserX(unsigned ePackages = pckALL_COMPLEX);
static void ResetErrorMessageProvider(ParserMessageProviderBase *pProvider);
};
} // namespace mu
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
#ifndef MUP_PARSERBASE_H
#define MUP_PARSERBASE_H
/** \file
\brief Definition of the muParserX engine.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include <cmath>
#include <string>
#include <iostream>
#include <map>
#include <memory>
#include "mpIOprt.h"
#include "mpIValReader.h"
#include "mpIPackage.h"
#include "mpStack.h"
#include "mpTokenReader.h"
#include "mpError.h"
#include "mpValue.h"
#include "mpVariable.h"
#include "mpTypes.h"
#include "mpRPN.h"
#include "mpValueCache.h"
MUP_NAMESPACE_START
/** \brief Implementation of the parser engine.
\author Ingo Berg
This is the muParser core. It provides the parsing logic and manages
the callback functions, operators, variables and constants. Do not
instantiate this class directly. Create an instance of mup::ParserX instead.
*/
class ParserXBase
{
friend class TokenReader;
private:
typedef const IValue& (ParserXBase::*parse_function_type)() const;
static const char_type *c_DefaultOprt[];
static bool s_bDumpStack;
static bool s_bDumpRPN;
public:
static string_type GetVersion();
static void EnableDebugDump(bool bDumpCmd, bool bDumpRPN);
ParserXBase();
ParserXBase( const ParserXBase &a_Parser );
ParserXBase& operator=(const ParserXBase &a_Parser);
virtual ~ParserXBase();
const IValue& Eval() const;
void SetExpr(const string_type &a_sExpr);
void AddValueReader(IValueReader *a_pReader);
void AddPackage(IPackage *p);
void DefineConst(const string_type &ident, const Value &val);
void DefineVar(const string_type &ident, const Variable &var);
void DefineFun(const ptr_cal_type &fun);
void DefineOprt(const TokenPtr<IOprtBin> &oprt);
void DefinePostfixOprt(const TokenPtr<IOprtPostfix> &oprt);
void DefineInfixOprt(const TokenPtr<IOprtInfix> &oprt);
bool IsVarDefined(const string_type &ident) const;
bool IsConstDefined(const string_type &ident) const;
bool IsFunDefined(const string_type &ident) const;
bool IsOprtDefined(const string_type &ident) const;
bool IsPostfixOprtDefined(const string_type &ident) const;
bool IsInfixOprtDefined(const string_type &ident) const;
void RemoveVar(const string_type &ident) ;
void RemoveConst(const string_type &ident);
void RemoveFun(const string_type &ident);
void RemoveOprt(const string_type &ident);
void RemovePostfixOprt(const string_type &ident);
void RemoveInfixOprt(const string_type &ident);
// Clear user defined variables, constants or functions
void ClearVar();
void ClearFun();
void ClearConst();
void ClearInfixOprt();
void ClearPostfixOprt();
void ClearOprt();
void DumpRPN() const;
const var_maptype& GetExprVar() const;
const var_maptype& GetVar() const;
const val_maptype& GetConst() const;
const fun_maptype& GetFunDef() const;
const string_type& GetExpr() const;
const char_type ** GetOprtDef() const;
void DefineNameChars(const char_type *a_szCharset);
void DefineOprtChars(const char_type *a_szCharset);
void DefineInfixOprtChars(const char_type *a_szCharset);
void EnableAutoCreateVar(bool bStat);
void EnableOptimizer(bool bStat);
bool IsAutoCreateVarEnabled() const;
const char_type* ValidNameChars() const;
const char_type* ValidOprtChars() const;
const char_type* ValidInfixOprtChars() const;
void Error(EErrorCodes a_iErrc,
int a_iPos = -1,
const IToken *a_pTok = 0) const;
// Allow clients to check syntacticaly correctnes of name against character set.
void CheckName(const string_type &a_sName, const string_type &a_CharSet) const;
protected:
fun_maptype m_FunDef; ///< Function definitions
oprt_pfx_maptype m_PostOprtDef; ///< Postfix operator callbacks
oprt_ifx_maptype m_InfixOprtDef; ///< Infix operator callbacks.
oprt_bin_maptype m_OprtDef; ///< Binary operator callbacks
val_maptype m_valDef; ///< Definition of parser constants
var_maptype m_varDef; ///< user defind variables.
private:
void ReInit() const;
void ClearExpr();
void CreateRPN() const;
void StackDump(const Stack<ptr_tok_type> &a_stOprt) const;
// Used by by DefineVar and DefineConst methods
// for better checking of var/const/oprt/fun existence.
void CheckForEntityExistence(const string_type & ident, EErrorCodes error_code);
void Assign(const ParserXBase &a_Parser);
void InitTokenReader();
void ApplyFunc(Stack<ptr_tok_type> &a_stOpt, int a_iArgCount) const;
void ApplyIfElse(Stack<ptr_tok_type> &a_stOpt) const;
void ApplyRemainingOprt(Stack<ptr_tok_type> &a_stOpt) const;
const IValue& ParseFromString() const;
const IValue& ParseFromRPN() const;
/** \brief Pointer to the parser function.
Eval() calls the function whose address is stored there.
*/
mutable parse_function_type m_pParserEngine;
/** \brief Managed pointer to the token reader object. */
std::unique_ptr<TokenReader> m_pTokenReader;
val_vec_type m_valDynVarShadow; ///< Value objects referenced by variables created at parser runtime
string_type m_sNameChars; ///< Charset for names
string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens
string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
mutable int m_nPos;
/** \brief Index of the final result in the stack array.
The parser supports expressions using with commas for seperating
multiple expression. Each comma will increase this number.
(i.e. "a=10,b=15,c=a*b")
*/
mutable int m_nFinalResultIdx;
/** \brief A flag indicating querying of expression variables is underway.
If this flag is set the parser is momentarily querying the expression
variables. In these cases undefined variable errors must be ignored cause
the whole point of querying the expression variables is for finding out
which variables mut be defined.
*/
mutable bool m_bIsQueryingExprVar;
mutable bool m_bAutoCreateVar; ///< If this flag is set unknown variables will be defined automatically
mutable RPN m_rpn; ///< reverse polish notation
mutable val_vec_type m_vStackBuffer;
mutable ValueCache m_cache; ///< A cache for recycling value items instead of deleting them
};
} // namespace mu
#endif

View File

@ -0,0 +1,181 @@
#include "mpParserMessageProvider.h"
#include <cassert>
#include "mpError.h"
MUP_NAMESPACE_START
//-------------------------------------------------------------------------------------------------
//
// class ParserMessageProviderBase - Base class for message providers
//
//-------------------------------------------------------------------------------------------------
ParserMessageProviderBase::ParserMessageProviderBase()
:m_vErrMsg(0)
{}
//-----------------------------------------------------------------------------------------------
ParserMessageProviderBase::~ParserMessageProviderBase()
{}
//-----------------------------------------------------------------------------------------------
void ParserMessageProviderBase::Init()
{
InitErrorMessages();
for (int i=0; i<ecCOUNT; ++i)
{
if (!m_vErrMsg[i].length())
throw std::runtime_error("Incomplete translation (at least one error code missing)");
}
}
//---------------------------------------------------------------------------------------------
string_type ParserMessageProviderBase::GetErrorMsg(EErrorCodes eError) const
{
int nError = (int)eError;
return (nError<(int)m_vErrMsg.size()) ? m_vErrMsg[nError] : string_type();
}
//-----------------------------------------------------------------------------------------------
//
// class ParserMessageProviderEnglish - English Parser Messages (default)
//
//-----------------------------------------------------------------------------------------------
ParserMessageProviderEnglish::ParserMessageProviderEnglish()
:ParserMessageProviderBase()
{}
//-----------------------------------------------------------------------------------------------
void ParserMessageProviderEnglish::InitErrorMessages()
{
m_vErrMsg.resize(ecCOUNT);
m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Undefined token \"$IDENT$\" found at position $POS$.");
m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error.");
m_vErrMsg[ecUNKNOWN_ESCAPE_SEQUENCE] = _T("Unknown escape sequence.");
m_vErrMsg[ecINVALID_NAME] = _T("Invalid function, variable or constant name.");
m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");
m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");
m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$IDENT$\" found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of expression found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unexpected comma found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$IDENT$\" found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$IDENT$\" found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$IDENT$\" found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$IDENT$\" found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");
m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("The \"$IDENT$\" operator must be preceded by a closing bracket.");
m_vErrMsg[ecUNEXPECTED_NEWLINE] = _T("Unexprected newline.");
m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis.");
m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("If-then-else operator is missing an else clause.");
m_vErrMsg[ecMISPLACED_COLON] = _T("Misplaced colon at position $POS$.");
m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters passed to function \"$IDENT$\".");
m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters passed to function \"$IDENT$\".");
m_vErrMsg[ecDIV_BY_ZERO] = _T("Division by zero occurred.");
m_vErrMsg[ecDOMAIN_ERROR] = _T("The value passed as argument to function/operator \"$IDENT$\" is not part of its domain.");
m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict.");
m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");
m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("Binary operator identifier conflicts with a built in operator.");
m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");
m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");
m_vErrMsg[ecVAL_EXPECTED] = _T("Numerical function called with a non value type of argument.");
m_vErrMsg[ecTYPE_CONFLICT] = _T("Value \"$IDENT$\" is of type '$TYPE1$'. There is no implicit conversion to type '$TYPE2$'.");
m_vErrMsg[ecTYPE_CONFLICT_FUN] = _T("Argument $ARG$ of function/operator \"$IDENT$\" is of type '$TYPE1$' whereas type '$TYPE2$' was expected.");
m_vErrMsg[ecTYPE_CONFLICT_IDX] = _T("Index to \"$IDENT$\" must be a positive integer value. '$TYPE1$' is not an acceptable type.");
m_vErrMsg[ecGENERIC] = _T("Parser error.");
m_vErrMsg[ecINVALID_TYPE] = _T("Invalid argument type.");
m_vErrMsg[ecINVALID_TYPECAST] = _T("Value type conversion from type '$TYPE1$' to '$TYPE2$' is not supported!");
m_vErrMsg[ecARRAY_SIZE_MISMATCH] = _T("Array size mismatch.");
m_vErrMsg[ecNOT_AN_ARRAY] = _T("Using the index operator on the scalar variable \"$IDENT$\" is not allowed.");
m_vErrMsg[ecUNEXPECTED_SQR_BRACKET] = _T("Unexpected \"[]\".");
m_vErrMsg[ecUNEXPECTED_CURLY_BRACKET] = _T("Unexpected \"{}\".");
m_vErrMsg[ecINDEX_OUT_OF_BOUNDS] = _T("Index to variable \"$IDENT$\" is out of bounds.");
m_vErrMsg[ecINDEX_DIMENSION] = _T("Index operator dimension error.");
m_vErrMsg[ecMISSING_SQR_BRACKET] = _T("Missing \"]\".");
m_vErrMsg[ecMISSING_CURLY_BRACKET] = _T("Missing \"}\".");
m_vErrMsg[ecASSIGNEMENT_TO_VALUE] = _T("Assignment operator \"$IDENT$\" can't be used in this context.");
m_vErrMsg[ecEVAL] = _T("Can't evaluate function/operator \"$IDENT$\": $HINT$");
m_vErrMsg[ecINVALID_PARAMETER] = _T("Parameter $ARG$ of function \"$IDENT$\" is invalid.");
m_vErrMsg[ecINVALID_NUMBER_OF_PARAMETERS] = _T("Invalid number of function arguments.");
m_vErrMsg[ecOVERFLOW] = _T("Possible arithmetic overflow occurred in function/operator \"$IDENT$\".");
m_vErrMsg[ecMATRIX_DIMENSION_MISMATCH] = _T("Matrix dimension error.");
m_vErrMsg[ecVARIABLE_DEFINED] = _T("Variable \"$IDENT$\" is already defined.");
m_vErrMsg[ecCONSTANT_DEFINED] = _T("Constant \"$IDENT$\" is already defined.");
m_vErrMsg[ecFUNOPRT_DEFINED] = _T("Function/operator \"$IDENT$\" is already defined.");
}
#if defined(_UNICODE)
//-------------------------------------------------------------------------------------------------
//
// class ParserMessageProviderGerman - German translations of Parser Messages
//
//-------------------------------------------------------------------------------------------------
ParserMessageProviderGerman::ParserMessageProviderGerman()
:ParserMessageProviderBase()
{}
//-----------------------------------------------------------------------------------------------
void ParserMessageProviderGerman::InitErrorMessages()
{
m_vErrMsg.resize(ecCOUNT);
m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Unbekanntes Token \"$IDENT$\" an Position $POS$ gefunden.");
m_vErrMsg[ecINTERNAL_ERROR] = _T("Interner Fehler.");
m_vErrMsg[ecUNKNOWN_ESCAPE_SEQUENCE] = _T("Unbekannte Escape-Sequenz.");
m_vErrMsg[ecINVALID_NAME] = _T("Ungültiger Funktions-, Variablen- oder Konstantenbezeichner.");
m_vErrMsg[ecINVALID_FUN_PTR] = _T("Ungültiger Zeiger auf eine Callback-Funktion.");
m_vErrMsg[ecINVALID_VAR_PTR] = _T("Ungültiger Variablenzeiger.");
m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unerwarteter Operator \"$IDENT$\" an Position $POS$.");
m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unerwartetes Formelende an Position $POS$.");
m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unerwartetes Komma an Position $POS$.");
m_vErrMsg[ecUNEXPECTED_PARENS ] = _T("Unerwartete Klammer \"$IDENT$\" an Position $POS$ gefunden.");
m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unerwartete Funktion \"$IDENT$\" an Position $POS$ gefunden.");
m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unerwarteter Wert \"$IDENT$\" an Position $POS$ gefunden.");
m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unerwartete Variable \"$IDENT$\" an Position $POS$ gefunden.");
m_vErrMsg[ecUNEXPECTED_STR] = _T("Unerwarteter Text an Position $POS$ gefunden.");
m_vErrMsg[ecUNEXPECTED_CONDITIONAL] = _T("Der Operator \"$IDENT$\" muss stets auf eine schließenden Klammer folgen.");
m_vErrMsg[ecUNEXPECTED_NEWLINE] = _T("Unerwarteter Zeilenumbruch.");
m_vErrMsg[ecMISSING_PARENS] = _T("Fehlende Klammer.");
m_vErrMsg[ecMISSING_ELSE_CLAUSE] = _T("\"If-then-else\" Operator ohne \"else\" Zweig verwendet.");
m_vErrMsg[ecMISPLACED_COLON] = _T("Komma an unerwarteter Position $POS$ gefunden.");
m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Der Funktion \"$IDENT$\" wurden zu viele Argumente übergeben.");
m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Der Funktion \"$IDENT$\" wurden nicht genug Argumente übergeben.");
m_vErrMsg[ecDIV_BY_ZERO] = _T("Division durch Null.");
m_vErrMsg[ecDOMAIN_ERROR] = _T("Der Parameter der Funktion \"$IDENT$\" hat einen Wert, der nicht Teil des Definitionsbereiches der Funktion ist.");
m_vErrMsg[ecNAME_CONFLICT] = _T("Namenskonflikt");
m_vErrMsg[ecOPT_PRI] = _T("Ungültige Operatorpriorität (muss größer oder gleich Null sein).");
m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("Die Überladung für diesen Binäroperator steht im Widerspruch zu intern vorhanden operatoren.");
m_vErrMsg[ecUNTERMINATED_STRING] = _T("Die Zeichenkette an Position $POS$ wird nicht beendet.");
m_vErrMsg[ecSTRING_EXPECTED] = _T("Es wurde eine Zeichenkette als Funktionseingabewert erwartet.");
m_vErrMsg[ecVAL_EXPECTED] = _T("Numerische Funktionen können nicht mit nichtnumerischen Parametern aufgerufen werden.");
m_vErrMsg[ecTYPE_CONFLICT] = _T("Der Wert \"$IDENT$\" ist vom Typ '$TYPE1$' und es gibt keine passende Typkonversion in den erwarteten Typ '$TYPE2$'.");
m_vErrMsg[ecTYPE_CONFLICT_FUN] = _T("Das Argument $ARG$ der Funktion oder des Operators \"$IDENT$\" ist vom Typ '$TYPE1$', erwartet wurde Typ '$TYPE2$'.");
m_vErrMsg[ecTYPE_CONFLICT_IDX] = _T("Der Index der Variable \"$IDENT$\" muss ein positiver Ganzzahlwert sein. Der übergebene Indexwert ist vom Typ '$TYPE1$'.");
m_vErrMsg[ecGENERIC] = _T("Allgemeiner Parser Fehler.");
m_vErrMsg[ecINVALID_TYPE] = _T("Ungültiger Funktionsargumenttyp.");
m_vErrMsg[ecINVALID_TYPECAST] = _T("Umwandlungen vom Typ '$TYPE1$' in den Typ '$TYPE2$' werden nicht unterstützt!");
m_vErrMsg[ecARRAY_SIZE_MISMATCH] = _T("Feldgrößen stimmen nicht überein.");
m_vErrMsg[ecNOT_AN_ARRAY] = _T("Der Indexoperator kann nicht auf die Skalarvariable \"$IDENT$\" angewandt werden.");
m_vErrMsg[ecUNEXPECTED_SQR_BRACKET] = _T("Eckige Klammern sind an dieser Position nicht erlaubt.");
m_vErrMsg[ecUNEXPECTED_CURLY_BRACKET] = _T("Geschweifte Klammern sind an dieser Position nicht erlaubt.");
m_vErrMsg[ecINDEX_OUT_OF_BOUNDS] = _T("Indexüberschreitung bei Variablenzugriff auf \"$IDENT$\".");
m_vErrMsg[ecINDEX_DIMENSION] = _T("Die Operation kann nicht auf Felder angewandt werden, deren Größe unterschiedlich ist.");
m_vErrMsg[ecMISSING_SQR_BRACKET] = _T("Fehlendes \"]\".");
m_vErrMsg[ecMISSING_CURLY_BRACKET] = _T("Fehlendes \"}\".");
m_vErrMsg[ecASSIGNEMENT_TO_VALUE] = _T("Der Zuweisungsoperator \"$IDENT$\" kann in diesem Zusammenhang nicht verwendet werden.");
m_vErrMsg[ecEVAL] = _T("Die Funktion bzw. der Operator \"$IDENT$\" kann nicht berechnet werden: $HINT$");
m_vErrMsg[ecINVALID_PARAMETER] = _T("Der Parameter $ARG$ der Funktion \"$IDENT$\" is ungültig.");
m_vErrMsg[ecINVALID_NUMBER_OF_PARAMETERS] = _T("Unzulässige Zahl an Funktionsparametern.");
m_vErrMsg[ecOVERFLOW] = _T("Ein arithmetische Überlauf wurde in Funktion/Operator \"$IDENT$\" entdeckt.");
m_vErrMsg[ecMATRIX_DIMENSION_MISMATCH] = _T("Matrixdimensionen stimmen nicht überein, Operation \"$IDENT$\" kann nicht ausgeführt werden.");
m_vErrMsg[ecVARIABLE_DEFINED] = _T("Die Variable \"$IDENT$\" is bereits definiert.");
m_vErrMsg[ecCONSTANT_DEFINED] = _T("Die Konstante \"$IDENT$\" is bereits definiert.");
m_vErrMsg[ecFUNOPRT_DEFINED] = _T("Ein Element mit der Bezeichnung \"$IDENT$\" ist bereits definiert.");
}
#endif // _UNICODE
MUP_NAMESPACE_END

View File

@ -0,0 +1,61 @@
#ifndef MP_PARSER_MESSAGE_PROVIDER_H
#define MP_PARSER_MESSAGE_PROVIDER_H
#include <vector>
#include <memory>
#include "mpDefines.h"
#include "mpTypes.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
/** \brief Base class for Parser Message providing classes. */
class ParserMessageProviderBase
{
friend class std::unique_ptr<ParserMessageProviderBase>;
public:
ParserMessageProviderBase();
virtual ~ParserMessageProviderBase();
void Init();
string_type GetErrorMsg(EErrorCodes errc) const;
private:
// Disable CC and assignment operator for this class and derivatives
ParserMessageProviderBase(const ParserMessageProviderBase &ref);
ParserMessageProviderBase& operator=(const ParserMessageProviderBase &ref);
protected:
std::vector<string_type> m_vErrMsg;
virtual void InitErrorMessages() = 0;
};
//-----------------------------------------------------------------------------------------------
/** \brief English versions of parser messages. */
class ParserMessageProviderEnglish : public ParserMessageProviderBase
{
public:
ParserMessageProviderEnglish();
protected:
virtual void InitErrorMessages();
};
//-----------------------------------------------------------------------------------------------
/** \brief German versions of parser messages. */
class ParserMessageProviderGerman : public ParserMessageProviderBase
{
public:
ParserMessageProviderGerman();
protected:
virtual void InitErrorMessages();
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,186 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <iomanip>
#include "mpRPN.h"
#include "mpIToken.h"
#include "mpICallback.h"
#include "mpError.h"
#include "mpStack.h"
#include "mpIfThenElse.h"
#include "mpScriptTokens.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
RPN::RPN()
:m_vRPN()
, m_nStackPos(-1)
, m_nLine(0)
, m_nMaxStackPos(0)
, m_bEnableOptimizer(false)
{}
//---------------------------------------------------------------------------
RPN::~RPN()
{}
//---------------------------------------------------------------------------
void RPN::Add(ptr_tok_type tok)
{
m_vRPN.push_back(tok);
if (tok->AsIValue() != nullptr)
{
m_nStackPos++;
}
else if (tok->AsICallback())
{
ICallback *pFun = tok->AsICallback();
MUP_VERIFY(pFun != nullptr);
m_nStackPos -= pFun->GetArgsPresent() - 1;
}
MUP_VERIFY(m_nStackPos >= 0);
m_nMaxStackPos = std::max(m_nStackPos, m_nMaxStackPos);
}
//---------------------------------------------------------------------------
void RPN::AddNewline(ptr_tok_type tok, int n)
{
static_cast<TokenNewline*>(tok.Get())->SetStackOffset(n);
m_vRPN.push_back(tok);
m_nStackPos -= n;
m_nLine++;
}
//---------------------------------------------------------------------------
void RPN::Pop(int num)
{
if (m_vRPN.size() == 0)
return;
for (int i = 0; i < num; ++i)
{
ptr_tok_type tok = m_vRPN.back();
if (tok->AsIValue() != 0)
m_nStackPos--;
m_vRPN.pop_back();
}
}
//---------------------------------------------------------------------------
void RPN::Reset()
{
m_vRPN.clear();
m_nStackPos = -1;
m_nMaxStackPos = 0;
m_nLine = 0;
}
//---------------------------------------------------------------------------
/** \brief
At the moment this will only ass the jump distances to the if-else clauses
found in the expression.
*/
void RPN::Finalize()
{
// Determine the if-then-else jump offsets
Stack<int> stIf, stElse;
int idx;
for (int i = 0; i < static_cast<int>(m_vRPN.size()); ++i)
{
switch (m_vRPN[i]->GetCode())
{
case cmIF:
stIf.push(i);
break;
case cmELSE:
stElse.push(i);
idx = stIf.pop();
static_cast<TokenIfThenElse*>(m_vRPN[idx].Get())->SetOffset(i - idx);
break;
case cmENDIF:
idx = stElse.pop();
static_cast<TokenIfThenElse*>(m_vRPN[idx].Get())->SetOffset(i - idx);
break;
default:
continue;
}
}
}
//---------------------------------------------------------------------------
void RPN::EnableOptimizer(bool bStat)
{
m_bEnableOptimizer = bStat;
}
//---------------------------------------------------------------------------
std::size_t RPN::GetSize() const
{
return m_vRPN.size();
}
//---------------------------------------------------------------------------
const token_vec_type& RPN::GetData() const
{
return m_vRPN;
}
//---------------------------------------------------------------------------
int RPN::GetRequiredStackSize() const
{
return m_nMaxStackPos + 1;
}
//---------------------------------------------------------------------------
void RPN::AsciiDump() const
{
console() << "Number of tokens: " << m_vRPN.size() << "\n";
console() << "MaxStackPos: " << m_nMaxStackPos << "\n";
for (std::size_t i = 0; i < m_vRPN.size(); ++i)
{
ptr_tok_type pTok = m_vRPN[i];
console() << std::setw(2) << i << " : "
<< std::setw(2) << pTok->GetExprPos() << " : "
<< pTok->AsciiDump() << std::endl;
}
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,76 @@
#ifndef MUP_RPN_H
#define MUP_RPN_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpFwdDecl.h"
#include "mpTypes.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
/** \brief A class representing the reverse polnish notation of the expression.
*/
class RPN
{
public:
RPN();
~RPN();
void Add(ptr_tok_type tok);
void AddNewline(ptr_tok_type tok, int n);
void Pop(int num);
void Reset();
void Finalize();
void AsciiDump() const;
const token_vec_type& GetData() const;
std::size_t GetSize() const;
int GetRequiredStackSize() const;
void EnableOptimizer(bool bStat);
private:
token_vec_type m_vRPN;
int m_nStackPos;
int m_nLine;
int m_nMaxStackPos;
bool m_bEnableOptimizer;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,74 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "mpScriptTokens.h"
#include "mpTypes.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
TokenNewline::TokenNewline()
:IToken(cmSCRIPT_NEWLINE)
,m_nOffset(0)
{}
//---------------------------------------------------------------------------
IToken* TokenNewline::Clone() const
{
return new TokenNewline(*this);
}
//---------------------------------------------------------------------------
void TokenNewline::SetStackOffset(int nOffset)
{
m_nOffset = nOffset;
}
//---------------------------------------------------------------------------
int TokenNewline::GetStackOffset() const
{
return m_nOffset;
}
//---------------------------------------------------------------------------
string_type TokenNewline::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; offset=") << m_nOffset;
ss << _T("]");
return ss.str();
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,68 @@
#ifndef MUP_SCRIPT_TOKENS_H
#define MUP_SCRIPT_TOKENS_H
/** \file
\brief Definition of basic types used by muParserX
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpIToken.h"
MUP_NAMESPACE_START
//---------------------------------------------------------------------------
/** \brief A class for encapsulation a newline token. */
class TokenNewline : public IToken
{
public:
TokenNewline();
//---------------------------------------------
// IToken interface
//---------------------------------------------
virtual IToken* Clone() const;
virtual string_type AsciiDump() const;
int GetStackOffset() const;
void SetStackOffset(int nOffset);
private:
int m_nOffset;
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,154 @@
#ifndef MUP_STACK_H
#define MUP_STACK_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <cassert>
#include <string>
#include <vector>
#include "mpError.h"
MUP_NAMESPACE_START
/** \brief Parser stack implementation.
Stack implementation based on a std::stack. The behaviour of pop() had been
slightly changed in order to get an error code if the stack is empty.
The stack is used within the Parser both as a value stack and as an operator stack.
\author (C) 2010 Ingo Berg
*/
template <typename TVal, typename TCont = std::vector<TVal> >
class Stack
{
private:
/** \brief Type of the underlying container. */
typedef TCont cont_type;
cont_type m_Cont;
public:
typedef TVal value_type;
//---------------------------------------------------------------------------
Stack()
:m_Cont()
{}
//---------------------------------------------------------------------------
virtual ~Stack()
{
m_Cont.clear();
}
//---------------------------------------------------------------------------
void clear()
{
m_Cont.clear();
}
//---------------------------------------------------------------------------
/** \brief Pop a value from the stack.
Unlike the standard implementation this function will return the value that
is going to be taken from the stack.
\throw ParserException in case the stack is empty.
\sa pop(int &a_iErrc)
*/
value_type pop()
{
if (empty())
throw ParserError(_T("stack is empty."));
value_type el = top();
m_Cont.pop_back();
return el;
}
//---------------------------------------------------------------------------
void pop(unsigned a_iNum)
{
for (unsigned i=0; i<a_iNum; ++i)
m_Cont.pop_back();
}
//---------------------------------------------------------------------------
/** \brief Push an object into the stack.
\param a_Val object to push into the stack.
\throw nothrow
*/
void push(const value_type& a_Val)
{
m_Cont.push_back(a_Val);
}
//---------------------------------------------------------------------------
/** \brief Return the number of stored elements. */
unsigned size() const
{
return (unsigned)m_Cont.size();
}
//---------------------------------------------------------------------------
/** \brief Returns true if stack is empty false otherwise. */
bool empty() const
{
return m_Cont.empty();
}
//---------------------------------------------------------------------------
/** \brief Return reference to the top object in the stack.
The top object is the one pushed most recently.
*/
value_type& top()
{
return m_Cont.back();
}
//---------------------------------------------------------------------------
value_type* get_data()
{
return &m_Cont[0];
}
//---------------------------------------------------------------------------
const value_type* get_data() const
{
return &m_Cont[0];
}
};
} // namespace mu
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MU_PARSER_TEST_H
#define MU_PARSER_TEST_H
#include <string>
#include <numeric> // for accumulate
#include "mpParser.h"
#include "mpOprtBinCommon.h"
MUP_NAMESPACE_START
/** \brief Test cases for unit testing the parser framework.
*/
class ParserTester // final
{
private:
static int c_iCount;
int TestParserValue();
int TestErrorCodes();
int TestStringFun();
int TestVector();
int TestBinOp();
int TestPostfix();
int TestInfix();
int TestEqn();
int TestMultiArg();
int TestUndefVar();
int TestIfElse();
int TestMatrix();
int TestComplex();
int TestScript();
int TestValReader();
int TestIssueReports();
void Assessment(int a_iNumErr) const;
void Abort() const;
public:
typedef int (ParserTester::*testfun_type)();
ParserTester();
/** \brief Destructor (trivial). */
~ParserTester() {};
/** \brief Copy constructor is deactivated. */
ParserTester(const ParserTester &a_Obj)
:m_vTestFun()
,m_stream(a_Obj.m_stream)
{};
void Run();
private:
std::vector<testfun_type> m_vTestFun;
#if defined(_UNICODE)
std::wostream *m_stream;
#else
std::ostream *m_stream;
#endif
void AddTest(testfun_type a_pFun);
// Test Double Parser
int EqnTest(const string_type &a_str, Value a_val, bool a_fPass, int nExprVar = -1);
int ThrowTest(const string_type &a_str, int a_nErrc, int a_nPos = -1, string_type a_sIdent = string_type());
}; // ParserTester
} // namespace mu
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
/** \file
\brief Definition of the token reader used to break the expression string up
into tokens.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_TOKEN_READER_H
#define MUP_TOKEN_READER_H
//--- Standard includes ----------------------------------------------------
#include <cstdio>
#include <cstring>
#include <map>
#include <stack>
#include <string>
#include <list>
//--- muParserX framework --------------------------------------------------
#include "mpIToken.h"
#include "mpError.h"
#include "mpStack.h"
#include "mpFwdDecl.h"
MUP_NAMESPACE_START
/** \brief Token reader for the ParserXBase class. */
class TokenReader
{
friend class ParserXBase;
public:
typedef std::vector<ptr_tok_type> token_buf_type;
private:
TokenReader(const TokenReader &a_Reader);
TokenReader& operator=(const TokenReader &a_Reader);
void Assign(const TokenReader &a_Reader);
void DeleteValReader();
void SetParent(ParserXBase *a_pParent);
int ExtractToken(const char_type *a_szCharSet, string_type &a_sTok, int a_iPos) const;
void SkipCommentsAndWhitespaces();
bool IsBuiltIn(ptr_tok_type &t);
bool IsEOF(ptr_tok_type &t);
bool IsNewline(ptr_tok_type &a_Tok);
bool IsNewLine(ptr_tok_type &t);
bool IsInfixOpTok(ptr_tok_type &t);
bool IsFunTok(ptr_tok_type &t);
bool IsPostOpTok(ptr_tok_type &t);
bool IsOprt(ptr_tok_type &t);
bool IsValTok(ptr_tok_type &t);
bool IsVarOrConstTok(ptr_tok_type &t);
bool IsUndefVarTok(ptr_tok_type &t);
bool IsComment();
const ptr_tok_type& Store(const ptr_tok_type &t, int pos);
ParserXBase *m_pParser; ///< Pointer to the parser bound to this token reader
string_type m_sExpr; ///< The expression beeing currently parsed
int m_nPos; ///< Current parsing position in the expression
int m_nNumBra; ///< Number of open parenthesis
int m_nNumIndex; ///< Number of open index paranethesis
int m_nNumCurly; ///< Number of open curly brackets
int m_nNumIfElse; ///< Coubter for if-then-else levels
int m_nSynFlags; ///< Flags to controll the syntax flow
token_buf_type m_vTokens;
ECmdCode m_eLastTokCode;
mutable fun_maptype *m_pFunDef;
mutable oprt_bin_maptype *m_pOprtDef;
mutable oprt_ifx_maptype *m_pInfixOprtDef;
mutable oprt_pfx_maptype *m_pPostOprtDef;
mutable val_maptype *m_pConstDef;
val_vec_type *m_pDynVarShadowValues; ///< Value items created for holding values of variables created at parser runtime
var_maptype *m_pVarDef; ///< The only non const pointer to parser internals
readervec_type m_vValueReader; ///< Value token identification function
var_maptype m_UsedVar;
float_type m_fZero; ///< Dummy value of zero, referenced by undefined variables
public:
TokenReader(ParserXBase *a_pParent);
~TokenReader();
TokenReader* Clone(ParserXBase *a_pParent) const;
void AddValueReader(IValueReader *a_pReader);
void AddSynFlags(int flag);
int GetPos() const;
const string_type& GetExpr() const;
const var_maptype& GetUsedVar() const;
const token_buf_type& GetTokens() const;
void SetExpr(const string_type &a_sExpr);
void ReInit();
ptr_tok_type ReadNextToken();
}; // class TokenReader
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,406 @@
/** \file
\brief Definition of basic types used by muParserX
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_TYPES_H
#define MUP_TYPES_H
//--- Standard include ------------------------------------------------------
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <complex>
//--- muParserX framework ---------------------------------------------------
#include "suSortPred.h" // We need the string utils sorting predicates
#include "mpDefines.h"
#include "mpMatrix.h"
#include "mpCompat.h"
MUP_NAMESPACE_START
// Forward declarations
class IValueReader;
class IOprtBin;
class IOprtPostfix;
class IOprtInfix;
class IFunction;
class IToken;
class ICallback;
class IValue;
class ParserXBase;
class Value;
class Variable;
class TokenReader;
// smart pointer types
template<typename T>
class TokenPtr;
/** \brief Type of a managed pointer storing parser tokens. */
typedef TokenPtr<IToken> ptr_tok_type;
/** \brief Type of a managed pointer storing callback tokens. */
typedef TokenPtr<ICallback> ptr_cal_type;
/** \brief Type of a managed pointer storing value tokens. */
typedef TokenPtr<IValue> ptr_val_type;
/** \brief Type of a managed pointer storing binary operator tokens. */
typedef TokenPtr<IOprtBin> ptr_binop_type;
/** \brief Type for a vector of tokens. */
typedef std::vector<ptr_tok_type> token_vec_type;
/** \brief Type for a vector of value items. */
typedef std::vector<ptr_val_type> val_vec_type;
// parser type definitions
/** \brief Parser datatype for floating point value. */
typedef MUP_FLOAT_TYPE float_type;
/** \brief Parser datatype for integer valuse. */
typedef MUP_INT_TYPE int_type;
/** \brief The basic type used for representing complex numbers. */
typedef std::complex<float_type> cmplx_type;
/** \brief Parser boolean datatype.
This must be bool! The only reason for this typedef is that I need the name bool_type
for a preprocessor macro definition to avoid inconsistent naming of the macro parameters.
*/
typedef bool bool_type;
/** \brief The parsers underlying matrix type. */
typedef Matrix<Value> matrix_type;
/** \brief Parser datatype for strings. */
typedef MUP_STRING_TYPE string_type;
/** \brief Character type of the parser. */
typedef string_type::value_type char_type;
typedef std::basic_stringstream<char_type, std::char_traits<char_type>, std::allocator<char_type> > stringstream_type;
/** \brief Type of a vector holding pointers to value reader objects. */
typedef std::vector<IValueReader*> readervec_type;
/** \brief type for the parser variable storage. */
typedef std::map<string_type, ptr_tok_type> var_maptype;
/** \brief type of a container used to store parser values. */
typedef std::map<string_type, ptr_tok_type> val_maptype;
/** \brief Type of a container that binds Callback object pointer
to operator identifiers. */
typedef std::map<string_type, ptr_tok_type> fun_maptype;
/** \brief Type of a container that binds Callback object pointer
to operator identifiers.
*/
typedef std::map<string_type, ptr_tok_type, su::pred::SortByLength<string_type> > oprt_bin_maptype;
/** \brief Type of a map for storing postfix operators by their name. */
typedef std::map<string_type, ptr_tok_type> oprt_pfx_maptype;
/** \brief Type of a map for storing infix operators by their name. */
typedef std::map<string_type, ptr_tok_type> oprt_ifx_maptype;
//------------------------------------------------------------------------------
/** \brief Bytecode values.
\attention The order of the operator entries must match the order in
ParserXBase::c_DefaultOprt!
*/
enum ECmdCode
{
// The following are codes for built in binary operators
// apart from built in operators the user has the opportunity to
// add user defined operators.
cmBO = 0, ///< Operator item: opening bracket
cmBC = 1, ///< Operator item: closing bracket
cmIO = 2, ///< Operator item: index operator opening
cmIC = 3, ///< Operator item: index operator closing
cmCBO = 4, ///< Operator item: curly bracket (opening)
cmCBC = 5, ///< Operator item: curly bracket (closing)
cmARG_SEP = 6, ///< Operator item: comma
cmIF = 7, ///< Ternary if then else operator
cmELSE = 8, ///< Ternary if then else operator
cmENDIF = 9, ///< Ternary if then else operator
cmJMP = 10, ///< Reserved for future use
cmVAL = 11, ///< value item
cmFUNC = 12, ///< Code for a function item
cmOPRT_BIN = 13, ///< Binary operator
cmOPRT_INFIX = 14, ///< Infix operator
cmOPRT_POSTFIX = 15, ///< Postfix operator
cmEOE = 16, ///< End of expression
// The following codes are reserved in case i will ever turn this
// into a scripting language
cmSCRIPT_NEWLINE = 17, ///< Newline
cmSCRIPT_COMMENT = 18,
cmSCRIPT_WHILE = 19, ///< Reserved for future use
cmSCRIPT_GOTO = 20, ///< Reserved for future use
cmSCRIPT_LABEL = 21, ///< Reserved for future use
cmSCRIPT_FOR = 22, ///< Reserved for future use
cmSCRIPT_IF = 23, ///< Reserved for future use
cmSCRIPT_ELSE = 24, ///< Reserved for future use
cmSCRIPT_ELSEIF = 25, ///< Reserved for future use
cmSCRIPT_ENDIF = 26, ///< Reserved for future use
cmSCRIPT_FUNCTION = 27, ///< Reserved for future use
// misc codes
cmUNKNOWN = 28, ///< uninitialized item
cmCOUNT ///< Dummy entry for counting the enum values
}; // ECmdCode
//------------------------------------------------------------------------------
/** \brief Strings assigned to the enum codes of ECmdCode.
Used for debugging purposes only.
*/
extern const char_type *g_sCmdCode[];
//------------------------------------------------------------------------------
enum EPackages
{
pckCOMMON = 1 << 0,
pckUNIT = 1 << 1,
pckCOMPLEX = 1 << 2,
pckNON_COMPLEX = 1 << 3,
pckSTRING = 1 << 4,
pckMATRIX = 1 << 5,
pckALL_COMPLEX = pckCOMMON | pckCOMPLEX | pckSTRING | pckUNIT | pckMATRIX,
pckALL_NON_COMPLEX = pckCOMMON | pckNON_COMPLEX | pckSTRING | pckUNIT | pckMATRIX
};
//------------------------------------------------------------------------------
/** \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
{
noBO = 1 << 0, ///< to avoid i.e. "cos(7)("
noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"
noIO = 1 << 2, ///< No opening bracket "["
noIC = 1 << 3, ///< No closing bracket "]"
noCBO = 1 << 4, ///< No opening curly bracket
noCBC = 1 << 5, ///< No opening closing bracket
noVAL = 1 << 6, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
noVAR = 1 << 7, ///< to avoid i.e. "sin a" or "sin(8)a"
noCOMMA = 1 << 8, ///< to avoid i.e. ",," or "+," ...
noFUN = 1 << 9, ///< to avoid i.e. "sqrt cos" or "(1)sin"
noOPT = 1 << 10, ///< to avoid i.e. "(+)"
noPFX = 1 << 11, ///< to avoid i.e. "(5!!)" "sin!"
noIFX = 1 << 12, ///< to avoid i.e. "++4" "!!4"
noEND = 1 << 13, ///< to avoid unexpected end of expression
noIF = 1 << 14,
noELSE = 1 << 15,
noNEWLINE = 1 << 16, ///< to avoid i.e. "a+\nb" or "sin(\na)"
sfSTART_OF_LINE = noOPT | noBC | noPFX | noCOMMA | noIO | noIC | noIF | noELSE,
sfALLOW_NONE = ~0 ///< All of he above flags set
};
//------------------------------------------------------------------------------
/** \brief Binary operator associativity values. */
enum EOprtAsct
{
oaNONE = 0,
oaLEFT = 1,
oaRIGHT = 2
};
//------------------------------------------------------------------------------
/** \brief Parser operator precedence values.
These are predefined values for the operator precedence.
*/
enum EOprtPrecedence
{
// assignment operators
prASSIGN = -1,
// if-then-else
prIF_THEN_ELSE = 0,
// binary operators
prLOGIC_OR = 1,
// prLOGIC_XOR = 2,
prLOGIC_AND = 3,
prBIT_OR = 4,
prBIT_XOR = 5,
prBIT_AND = 6,
prRELATIONAL1 = 7, ///< For "==", "!="
prRELATIONAL2 = 8, ///< Relational operators "<", "<=", ">", ">="
prSHIFT = 9, ///< Shift operators "<<", ">>"
prCOLON = 10, ///< Colon operator
prADD_SUB = 11, ///< addition
prMUL_DIV = 12, ///< multiplication/division
prPOW = 13, ///< power operator priority (highest)
// infix operators
prINFIX = 12, ///< Signs have a higher priority than ADD_SUB, but lower than power operator
prPOSTFIX = 12 ///< Postfix operator priority (currently unused)
};
/** \brief Error codes.
This is the complete list of all error codes used by muparserx
*/
enum EErrorCodes
{
// Expression syntax errors
ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found
ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.
ecUNEXPECTED_EOF = 2, ///< Unexpected end of expression. (Example: "2+sin(")
ecUNEXPECTED_COMMA = 3, ///< An unexpected comma has been found. (Example: "1,23")
ecUNEXPECTED_VAL = 4, ///< An unexpected value token has been found
ecUNEXPECTED_VAR = 5, ///< An unexpected variable token has been found
ecUNEXPECTED_PARENS = 6, ///< Unexpected Parenthesis, opening or closing
ecUNEXPECTED_STR = 7, ///< A string has been found at an inapropriate position
ecUNEXPECTED_CONDITIONAL = 8,
ecUNEXPECTED_NEWLINE = 9,
ecSTRING_EXPECTED = 10, ///< A string function has been called with a different type of argument
ecVAL_EXPECTED = 11, ///< A numerical function has been called with a non value type of argument
ecMISSING_PARENS = 12, ///< Missing parens. (Example: "3*sin(3")
ecMISSING_ELSE_CLAUSE = 13,
ecMISPLACED_COLON = 14,
ecUNEXPECTED_FUN = 15, ///< Unexpected function found. (Example: "sin(8)cos(9)")
ecUNTERMINATED_STRING = 16, ///< unterminated string constant. (Example: "3*valueof("hello)")
ecTOO_MANY_PARAMS = 17, ///< Too many function parameters
ecTOO_FEW_PARAMS = 18, ///< Too few function parameters. (Example: "ite(1<2,2)")
ecTYPE_CONFLICT = 19, ///< Generic type conflict
ecTYPE_CONFLICT_FUN = 20, ///< Function argument type conflict.
ecTYPE_CONFLICT_IDX = 21, ///< Function argument type conflict.
ecINVALID_TYPE = 22,
ecINVALID_TYPECAST = 23, ///< Invalid Value token cast.
ecARRAY_SIZE_MISMATCH = 24, ///< Array size mismatch during a vector operation
ecNOT_AN_ARRAY = 25, ///< Using the index operator on a scalar variable
ecUNEXPECTED_SQR_BRACKET = 26, ///< Invalid use of the index operator
ecUNEXPECTED_CURLY_BRACKET = 27, ///< Invalid use of the index operator
ecINVALID_NAME = 28, ///< Invalid function, variable or constant name.
ecBUILTIN_OVERLOAD = 29, ///< Trying to overload builtin operator
ecINVALID_FUN_PTR = 30, ///< Invalid callback function pointer
ecINVALID_VAR_PTR = 31, ///< Invalid variable pointer
ecINVALID_PARAMETER = 32, ///< Invalid function parameter
ecINVALID_NUMBER_OF_PARAMETERS = 33,
ecNAME_CONFLICT = 34, ///< Name conflict
ecOPT_PRI = 35, ///< Invalid operator priority
ecASSIGNEMENT_TO_VALUE = 36, ///< Assignment to operator (3=4 instead of a=4)
//
ecDOMAIN_ERROR = 37, ///< Trying to use func/oprtr with out-of-domain input args
ecDIV_BY_ZERO = 38, ///< Division by zero (currently unused)
ecGENERIC = 39, ///< Generic error
ecINDEX_OUT_OF_BOUNDS = 40, ///< Array index is out of bounds
ecINDEX_DIMENSION = 41,
ecMISSING_SQR_BRACKET = 42, ///< The index operator was not closed properly (i.e. "v[3")
ecMISSING_CURLY_BRACKET = 43,
ecEVAL = 44, ///< Error while evaluating function / operator
ecOVERFLOW = 45, ///< Overflow (possibly) occurred
// Matrix errors
ecMATRIX_DIMENSION_MISMATCH = 46,
// string related errors
ecUNKNOWN_ESCAPE_SEQUENCE = 47,
// already-defined item errors
ecVARIABLE_DEFINED = 48, ///< Variable is already defined
ecCONSTANT_DEFINED = 49, ///< Constant is already defined
ecFUNOPRT_DEFINED = 50, ///< Function/operator is already defined
// internal errors
ecINTERNAL_ERROR = 51, ///< Internal error of any kind.
// The last two are special entries
ecCOUNT, ///< This is no error code, It just stores just the total number of error codes
ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages
};
#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 // _UNICODE
} // namespace mu
#endif

View File

@ -0,0 +1,347 @@
/** \file
\brief Implementation of classes that interpret values in a string.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpValReader.h"
#include "mpError.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
//
// Reader for floating point values
//
//------------------------------------------------------------------------------
DblValReader::DblValReader()
:IValueReader()
{}
//------------------------------------------------------------------------------
DblValReader::~DblValReader()
{}
//------------------------------------------------------------------------------
bool DblValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_Val)
{
stringstream_type stream(a_szExpr + a_iPos);
float_type fVal(0);
std::streamoff iEnd(0);
stream >> fVal;
if (stream.fail())
return false;
if (stream.eof())
{
// This part sucks but tellg will return -1 if eof is set,
// so i need a special treatment for the case that the number
// just read here is the last part of the string
for (; a_szExpr[a_iPos] != 0; ++a_iPos);
}
else
{
iEnd = stream.tellg(); // Position after reading
assert(iEnd > 0);
a_iPos += (int)iEnd;
}
// Finally i have to check if the next sign is the "i" for a imaginary unit
// if so this is an imaginary value
if (a_szExpr[a_iPos] == 'i')
{
a_Val = cmplx_type(0.0, fVal);
a_iPos++;
}
else
{
a_Val = cmplx_type(fVal, 0.0);
}
return true;
}
//------------------------------------------------------------------------------
IValueReader* DblValReader::Clone(TokenReader *pTokenReader) const
{
IValueReader *pReader = new DblValReader(*this);
pReader->SetParent(pTokenReader);
return pReader;
}
//------------------------------------------------------------------------------
//
// Reader for boolean values
//
//------------------------------------------------------------------------------
BoolValReader::BoolValReader()
:IValueReader()
{}
//------------------------------------------------------------------------------
BoolValReader::~BoolValReader()
{}
//------------------------------------------------------------------------------
bool BoolValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_Val)
{
string_type sExpr(a_szExpr + a_iPos);
if (sExpr.find(_T("true")) == 0)
{
a_Val = true;
a_iPos += 4;
return true;
}
else if (sExpr.find(_T("false")) == 0)
{
a_Val = false;
a_iPos += 5;
return true;
}
return false;
}
//------------------------------------------------------------------------------
IValueReader* BoolValReader::Clone(TokenReader *pTokenReader) const
{
IValueReader *pReader = new BoolValReader(*this);
pReader->SetParent(pTokenReader);
return pReader;
}
//------------------------------------------------------------------------------
//
// Reader for hex values
//
//------------------------------------------------------------------------------
HexValReader::HexValReader()
:IValueReader()
{}
//------------------------------------------------------------------------------
/** \brief Try to read a hex value from a given position in the expression.
\param a_szExpr The Expression
\param [in/out] a_iPos The current position in the expression
\param [out] a_val The value that was read
Hex values must start with a "0x" characters. The position a_iPos is advanded in case
a hex value was found.
*/
bool HexValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_val)
{
std::size_t len = std::char_traits<char_type>::length(a_szExpr);
if (a_iPos >= (int)len || a_szExpr[a_iPos + 1] != 'x' || a_szExpr[a_iPos + 1] == 0 || a_szExpr[a_iPos] != '0')
return 0;
unsigned iVal(0);
stringstream_type::pos_type nPos(0);
stringstream_type ss(a_szExpr + a_iPos + 2);
ss >> std::hex >> iVal;
if (ss.fail())
return false;
if (ss.eof())
{
// This part sucks but tellg will return -1 if eof is set,
// so i need a special treatment for those cases.
for (; a_szExpr[a_iPos] != 0; ++a_iPos);
}
else
{
nPos = ss.tellg();
assert(nPos > 0);
a_iPos += (int)(2 + nPos);
}
a_val = (float_type)iVal;
return true;
}
//------------------------------------------------------------------------------
IValueReader* HexValReader::Clone(TokenReader *pTokenReader) const
{
IValueReader *pReader = new HexValReader(*this);
pReader->SetParent(pTokenReader);
return pReader;
}
//------------------------------------------------------------------------------
//
// Reader for binary values
//
//------------------------------------------------------------------------------
BinValReader::BinValReader()
:IValueReader()
{}
//------------------------------------------------------------------------------
BinValReader::~BinValReader()
{}
//------------------------------------------------------------------------------
bool BinValReader::IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_Val)
{
const char_type *szExpr = a_szExpr + a_iPos;
if (szExpr[0] != '0' || (szExpr[1] != 'b' && szExpr[1] != 'B'))
return false;
// <ibg 2014-05-26/> Number of bits hardcoded to 32, i can't
// store 64 bit integers in double values without
// loss. There is no point in accepting them.
unsigned iVal = 0, iBits = 32 /*sizeof(iVal)*8*/, i;
for (i = 0; (szExpr[i + 2] == '0' || szExpr[i + 2] == '1') && i <= iBits; ++i)
{
iVal |= (unsigned)(szExpr[i + 2] == '1') << ((iBits - 1) - i);
}
if (i == 0)
return false;
if (i > iBits)
{
throw ParserError(_T("Binary to integer conversion error (overflow)."));
}
a_Val = (float_type)((int)(iVal >> (iBits - i)));
a_iPos += i + 2;
return true;
}
//------------------------------------------------------------------------------
IValueReader* BinValReader::Clone(TokenReader *pTokenReader) const
{
IValueReader *pReader = new BinValReader(*this);
pReader->SetParent(pTokenReader);
return pReader;
}
//------------------------------------------------------------------------------
//
// Reader for string values
//
//------------------------------------------------------------------------------
StrValReader::StrValReader()
:IValueReader()
{}
//------------------------------------------------------------------------------
StrValReader::~StrValReader()
{}
//------------------------------------------------------------------------------
string_type StrValReader::Unescape(const char_type *szExpr, int &nPos)
{
string_type out;
bool bEscape = false;
for (char_type c = szExpr[nPos]; c != 0; c = szExpr[++nPos])
{
switch (c)
{
case '\\':
if (!bEscape)
{
bEscape = true;
break;
}
[[gnu::fallthrough]];
case '"':
if (!bEscape)
{
++nPos;
return out;
}
[[gnu::fallthrough]];
default:
if (bEscape)
{
switch (c)
{
case 'n': out += '\n'; break;
case 'r': out += '\r'; break;
case 't': out += '\t'; break;
case '"': out += '\"'; break;
case '\\': out += '\\'; break;
default:
throw ParserError(ErrorContext(ecUNKNOWN_ESCAPE_SEQUENCE, nPos));
}
bEscape = false;
}
else
{
out += c;
}
}
}
throw ParserError(ErrorContext(ecUNTERMINATED_STRING, nPos));
}
//------------------------------------------------------------------------------
bool StrValReader::IsValue(const char_type *a_pszExpr, int &a_iPos, Value &a_Val)
{
const char_type *szExpr = a_pszExpr + a_iPos;
if (szExpr[0] != '"')
return false;
a_Val = Unescape(a_pszExpr, ++a_iPos);
return true;
}
//------------------------------------------------------------------------------
IValueReader* StrValReader::Clone(TokenReader *pTokenReader) const
{
IValueReader *pReader = new StrValReader(*this);
pReader->SetParent(pTokenReader);
return pReader;
}
} // namespace mu

View File

@ -0,0 +1,138 @@
/** \file
\brief Definition of classes that interpret values in a string.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MU_PARSER_IMPL_READER_H
#define MU_PARSER_IMPL_READER_H
#include "mpIValReader.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
//
// Reader for floating point values
//
//------------------------------------------------------------------------------
/** \brief A class for reading floating point values from an expression string.
\ingroup valreader
*/
class DblValReader : public IValueReader
{
public:
DblValReader();
virtual ~DblValReader();
virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal) override;
virtual IValueReader* Clone(TokenReader *pTokenReader) const override;
};
//------------------------------------------------------------------------------
//
// Reader for boolean values
//
//------------------------------------------------------------------------------
/** \brief A class for reading boolean values from an expression string.
\ingroup valreader
*/
class BoolValReader : public IValueReader
{
public:
BoolValReader();
virtual ~BoolValReader();
virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal) override;
virtual IValueReader* Clone(TokenReader *pTokenReader) const override;
};
//------------------------------------------------------------------------------
//
// Reader for hex values
//
//------------------------------------------------------------------------------
/** \brief A class for reading hex values from an expression string.
\ingroup valreader
*/
class HexValReader : public IValueReader
{
public:
HexValReader();
virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal) override;
virtual IValueReader* Clone(TokenReader *pTokenReader) const override;
};
//------------------------------------------------------------------------------
//
// Reader for binary values
//
//------------------------------------------------------------------------------
/** \brief A class for reading binary values from an expression string.
\ingroup valreader
*/
class BinValReader : public IValueReader
{
public:
BinValReader();
virtual ~BinValReader();
virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal) override;
virtual IValueReader* Clone(TokenReader *pTokenReader) const override;
};
//------------------------------------------------------------------------------
//
// Reader for string values
//
//------------------------------------------------------------------------------
/** \brief A class for reading strings from an expression string.
\ingroup valreader
*/
class StrValReader : public IValueReader
{
public:
StrValReader();
virtual ~StrValReader();
virtual bool IsValue(const char_type *a_szExpr, int &a_iPos, Value &a_fVal) override;
virtual IValueReader* Clone(TokenReader *pTokenReader) const override;
private:
string_type Unescape(const char_type *szExpr, int &len);
};
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,810 @@
/*
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpValue.h"
#include "mpError.h"
#include "mpValueCache.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Construct an empty value object of a given type.
\param cType The type of the value to construct (default='v').
*/
Value::Value(char_type cType)
:IValue(cmVAL)
, m_val(0, 0)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_cType(cType)
, m_iFlags(flNONE)
, m_pCache(nullptr)
{
// strings and arrays must allocate their memory
switch (cType)
{
case 's': m_psVal = new string_type(); break;
case 'm': m_pvVal = new matrix_type(0, Value(0.0)); break;
}
}
//---------------------------------------------------------------------------
Value::Value(int_type a_iVal)
:IValue(cmVAL)
, m_val((float_type)a_iVal, 0)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_cType('i')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(bool_type a_bVal)
:IValue(cmVAL)
, m_val((float_type)a_bVal, 0)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_cType('b')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(string_type a_sVal)
:IValue(cmVAL)
, m_val()
, m_psVal(new string_type(a_sVal))
, m_pvVal(nullptr)
, m_cType('s')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(int_type array_size, float_type v)
:IValue(cmVAL)
, m_val()
, m_psVal(nullptr)
, m_pvVal(new matrix_type(array_size, Value(v)))
, m_cType('m')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
/** \brief Create a m x n matrix
*/
Value::Value(int_type m, int_type n, float_type v)
:IValue(cmVAL)
, m_val()
, m_psVal(nullptr)
, m_pvVal(new matrix_type(m, n, Value(v)))
, m_cType('m')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(const char_type* a_szVal)
:IValue(cmVAL)
, m_val()
, m_psVal(new string_type(a_szVal))
, m_pvVal(nullptr)
, m_cType('s')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(const cmplx_type& v)
:IValue(cmVAL)
, m_val(v)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_cType('c')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{
// modified as suggested here: https://github.com/beltoforion/muparserx/issues/98
m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c';
}
//---------------------------------------------------------------------------
Value::Value(float_type val)
:IValue(cmVAL)
, m_val(val, 0)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_cType((val == (int_type)val) ? 'i' : 'f')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(const matrix_type& val)
:IValue(cmVAL)
, m_val()
, m_psVal(nullptr)
, m_pvVal(new matrix_type(val))
, m_cType('m')
, m_iFlags(flNONE)
, m_pCache(nullptr)
{}
//---------------------------------------------------------------------------
Value::Value(const Value& a_Val)
:IValue(cmVAL)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_pCache(nullptr)
{
Assign(a_Val);
}
//---------------------------------------------------------------------------
Value::Value(const IValue& a_Val)
:IValue(cmVAL)
, m_psVal(nullptr)
, m_pvVal(nullptr)
, m_pCache(nullptr)
{
Reset();
switch (a_Val.GetType())
{
case 'i':
case 'f':
case 'b': m_val = cmplx_type(a_Val.GetFloat(), 0);
break;
case 'c': m_val = cmplx_type(a_Val.GetFloat(), a_Val.GetImag());
break;
case 's': if (!m_psVal)
m_psVal = new string_type(a_Val.GetString());
else
*m_psVal = a_Val.GetString();
break;
case 'm': if (!m_pvVal)
m_pvVal = new matrix_type(a_Val.GetArray());
else
*m_pvVal = a_Val.GetArray();
break;
case 'v': break;
default: MUP_FAIL(INVALID_TYPE_CODE);
}
m_cType = a_Val.GetType();
}
//---------------------------------------------------------------------------
Value& Value::operator=(const Value& a_Val)
{
Assign(a_Val);
return *this;
}
//---------------------------------------------------------------------------
/** \brief Return the matrix element at row col.
Row and col are the indices of the matrix. If this element does not
represent a matrix row and col must be 0 otherwise an index out of bound error
is thrown.
*/
IValue& Value::At(const IValue& row, const IValue& col)
{
if (!row.IsInteger() || !col.IsInteger())
{
ErrorContext errc(ecTYPE_CONFLICT_IDX, GetExprPos());
errc.Type1 = (!row.IsInteger()) ? row.GetType() : col.GetType();
errc.Type2 = 'i';
throw ParserError(errc);
}
int_type nRow = row.GetInteger(),
nCol = col.GetInteger();
return At(nRow, nCol);
}
//---------------------------------------------------------------------------
IValue& Value::At(int nRow, int nCol)
{
if (IsMatrix())
{
if (nRow >= m_pvVal->GetRows() || nCol >= m_pvVal->GetCols() || nRow < 0 || nCol < 0)
throw ParserError(ErrorContext(ecINDEX_OUT_OF_BOUNDS, -1, GetIdent()));
return m_pvVal->At(nRow, nCol);
}
else if (nRow == 0 && nCol == 0)
{
return *this;
}
else
throw ParserError(ErrorContext(ecINDEX_OUT_OF_BOUNDS));
}
//---------------------------------------------------------------------------
Value::~Value()
{
delete m_psVal;
delete m_pvVal;
}
//---------------------------------------------------------------------------
IToken* Value::Clone() const
{
return new Value(*this);
}
//---------------------------------------------------------------------------
Value* Value::AsValue()
{
return this;
}
//---------------------------------------------------------------------------
/** \brief Copy constructor. */
void Value::Assign(const Value& ref)
{
if (this == &ref)
return;
m_val = ref.m_val;
m_cType = ref.m_cType;
m_iFlags = ref.m_iFlags;
// allocate room for a string
if (ref.m_psVal)
{
if (!m_psVal)
m_psVal = new string_type(*ref.m_psVal);
else
*m_psVal = *ref.m_psVal;
}
else
{
delete m_psVal;
m_psVal = nullptr;
}
// allocate room for a vector
if (ref.m_pvVal)
{
if (m_pvVal == nullptr)
m_pvVal = new matrix_type(*ref.m_pvVal);
else
*m_pvVal = *ref.m_pvVal;
}
else
{
delete m_pvVal;
m_pvVal = nullptr;
}
// Do NOT access ref beyound this point! If you do, "unboxing" of
// a 1 x 1 matrix using:
//
// this->Assign(m_pvVal->At(0,0));
//
// will blow up in your face since ref will become invalid at them very
// moment you delete m_pvVal!
}
//---------------------------------------------------------------------------
void Value::Reset()
{
m_val = cmplx_type(0, 0);
delete m_psVal;
m_psVal = nullptr;
delete m_pvVal;
m_pvVal = nullptr;
m_cType = 'f';
m_iFlags = flNONE;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(bool val)
{
m_val = cmplx_type((float_type)val, 0);
delete m_psVal;
m_psVal = nullptr;
delete m_pvVal;
m_pvVal = nullptr;
m_cType = 'b';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(int_type a_iVal)
{
m_val = cmplx_type(a_iVal, 0);
delete m_psVal;
m_psVal = nullptr;
delete m_pvVal;
m_pvVal = nullptr;
m_cType = 'i';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(float_type val)
{
m_val = cmplx_type(val, 0);
delete m_psVal;
m_psVal = nullptr;
delete m_pvVal;
m_pvVal = nullptr;
m_cType = (val == (int_type)val) ? 'i' : 'f';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(string_type a_sVal)
{
m_val = cmplx_type();
if (!m_psVal)
m_psVal = new string_type(a_sVal);
else
*m_psVal = a_sVal;
delete m_pvVal;
m_pvVal = nullptr;
m_cType = 's';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(const char_type* a_szVal)
{
m_val = cmplx_type();
if (!m_psVal)
m_psVal = new string_type(a_szVal);
else
*m_psVal = a_szVal;
delete m_pvVal;
m_pvVal = nullptr;
m_cType = 's';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(const matrix_type& a_vVal)
{
m_val = cmplx_type(0, 0);
delete m_psVal;
m_psVal = nullptr;
if (m_pvVal == nullptr)
m_pvVal = new matrix_type(a_vVal);
else
*m_pvVal = a_vVal;
m_cType = 'm';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator=(const cmplx_type& val)
{
m_val = val;
delete m_psVal;
m_psVal = nullptr;
delete m_pvVal;
m_pvVal = nullptr;
// modified as suggested here: https://github.com/beltoforion/muparserx/issues/98
m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c';
m_iFlags = flNONE;
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator+=(const IValue& val)
{
if (IsScalar() && val.IsScalar())
{
// Scalar/Scalar addition
m_val += val.GetComplex();
// modified as suggested here: https://github.com/beltoforion/muparserx/issues/98
m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c';
}
else if (IsMatrix() && val.IsMatrix())
{
// Matrix/Matrix addition
assert(m_pvVal);
*m_pvVal += val.GetArray();
}
else if (IsString() && val.IsString())
{
// string/string addition
assert(m_psVal);
*m_psVal += val.GetString();
}
else
{
// Type conflict
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, _T("+"), GetType(), val.GetType(), 2));
}
return *this;
}
//---------------------------------------------------------------------------
IValue& Value::operator-=(const IValue& val)
{
if (IsScalar() && val.IsScalar())
{
// Scalar/Scalar addition
m_val -= val.GetComplex();
// modified as suggested here: https://github.com/beltoforion/muparserx/issues/98
m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c';
}
else if (IsMatrix() && val.IsMatrix())
{
// Matrix/Matrix addition
assert(m_pvVal);
*m_pvVal -= val.GetArray();
}
else
{
// There is a typeconflict:
throw ParserError(ErrorContext(ecTYPE_CONFLICT_FUN, -1, _T("-"), GetType(), val.GetType(), 2));
}
return *this;
}
//---------------------------------------------------------------------------
/** \brief Assign a value with multiplication
\param val The value to multiply to this
When multiplying to values with each value representing a matrix type
the result is checked whether it is a 1 x 1 matrix. If so the value is
"unboxed" and stored directly in this value object. It is no longer
treated as a matrix internally.
*/
IValue& Value::operator*=(const IValue& val)
{
if (IsScalar() && val.IsScalar())
{
// Scalar/Scalar multiplication
m_val *= val.GetComplex();
// modified as suggested here: https://github.com/beltoforion/muparserx/issues/98
m_cType = (m_val.imag() == 0) ? ((std::floor(m_val.real()) == m_val.real()) ? 'i' : 'f') : 'c';
}
else if (IsMatrix() && val.IsMatrix())
{
// Matrix/Matrix addition
assert(m_pvVal);
*m_pvVal *= val.GetArray();
// The result may actually be a scalar value, i.e. the scalar product of
// two vectors.
if (m_pvVal->GetCols() == 1 && m_pvVal->GetRows() == 1)
{
Assign(m_pvVal->At(0, 0));
}
}
else if (IsMatrix() && val.IsScalar())
{
*m_pvVal *= val;
}
else if (IsScalar() && val.IsMatrix())
{
// transform this into a matrix and multiply with rhs
Value prod = val * (*this);
Assign(prod);
}
else
{
// Type conflict
ErrorContext errc(ecTYPE_CONFLICT_FUN, -1, _T("*"));
errc.Type1 = GetType();
errc.Type2 = 'm'; //val.GetType();
errc.Arg = 2;
throw ParserError(errc);
}
return *this;
}
//---------------------------------------------------------------------------
/** \brief Returns a character representing the type of this value instance.
\return m_cType Either one of 'c' for comlex, 'i' for integer,
'f' for floating point, 'b' for boolean, 's' for string or
'm' for matrix values.
*/
char_type Value::GetType() const
{
return m_cType;
}
//---------------------------------------------------------------------------
/** \brief Return the value as an integer.
This function should only be called if you really need an integer value and
want to make sure your either get one or throw an exception if the value
can not be implicitely converted into an integer.
*/
int_type Value::GetInteger() const
{
float_type v = m_val.real();
if (m_cType != 'i')
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT;
err.Type1 = m_cType;
err.Type2 = 'i';
if (GetIdent().length())
{
err.Ident = GetIdent();
}
else
{
stringstream_type ss;
ss << *this;
err.Ident = ss.str();
}
throw ParserError(err);
}
return (int_type)v;
}
//---------------------------------------------------------------------------
float_type Value::GetFloat() const
{
return m_val.real();
}
//---------------------------------------------------------------------------
/** \brief Get the imaginary part of the value.
\throw ParserError in case this value represents a string or a matrix
*/
float_type Value::GetImag() const
{
if (!IsScalar())
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT;
err.Type1 = m_cType;
err.Type2 = 'c';
if (GetIdent().length())
{
err.Ident = GetIdent();
}
else
{
stringstream_type ss;
ss << *this;
err.Ident = ss.str();
}
throw ParserError(err);
}
return m_val.imag();
}
//---------------------------------------------------------------------------
/** \brief Returns this value as a complex number.
\throw nothrow
If the value instance does not represent a complex value the returned value
is undefined. No exception is triggered. If you are unsure about the type
use IsComplex() or GetType() to verify the type.
*/
const cmplx_type& Value::GetComplex() const
{
return m_val;
}
//---------------------------------------------------------------------------
const string_type& Value::GetString() const
{
CheckType('s');
assert(m_psVal != nullptr);
return *m_psVal;
}
//---------------------------------------------------------------------------
bool Value::GetBool() const
{
CheckType('b');
return m_val.real() == 1;
}
//---------------------------------------------------------------------------
const matrix_type& Value::GetArray() const
{
CheckType('m');
assert(m_pvVal != nullptr);
return *m_pvVal;
}
//---------------------------------------------------------------------------
int Value::GetRows() const
{
return (GetType() != 'm') ? 1 : GetArray().GetRows();
}
//---------------------------------------------------------------------------
int Value::GetCols() const
{
return (GetType() != 'm') ? 1 : GetArray().GetCols();
}
//---------------------------------------------------------------------------
void Value::CheckType(char_type a_cType) const
{
if (m_cType != a_cType)
{
ErrorContext err;
err.Errc = ecTYPE_CONFLICT;
err.Type1 = m_cType;
err.Type2 = a_cType;
if (GetIdent().length())
{
err.Ident = GetIdent();
}
else
{
stringstream_type ss;
ss << *this;
err.Ident = ss.str();
}
throw ParserError(err);
}
}
//---------------------------------------------------------------------------
bool Value::IsVariable() const
{
return false;
}
//---------------------------------------------------------------------------
string_type Value::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[GetCode()];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; type=\"") << GetType() << _T("\"");
ss << _T("; val=");
switch (m_cType)
{
case 'i': ss << (int_type)m_val.real(); break;
case 'f': ss << m_val.real(); break;
case 'm': ss << _T("(matrix)"); break;
case 's':
assert(m_psVal != nullptr);
ss << _T("\"") << m_psVal << _T("\""); break;
}
ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("vol");
ss << _T("]");
return ss.str();
}
//-----------------------------------------------------------------------------------------------
void Value::Release()
{
if (m_pCache)
m_pCache->ReleaseToCache(this);
else
delete this;
}
//-----------------------------------------------------------------------------------------------
void Value::BindToCache(ValueCache* pCache)
{
m_pCache = pCache;
}
//-----------------------------------------------------------------------------------------------
Value::operator cmplx_type ()
{
return GetComplex();
}
//-----------------------------------------------------------------------------------------------
Value::operator int_type()
{
return GetInteger();
}
//-----------------------------------------------------------------------------------------------
Value::operator string_type()
{
return GetString();
}
//-----------------------------------------------------------------------------------------------
Value::operator float_type()
{
return GetFloat();
}
//-----------------------------------------------------------------------------------------------
Value::operator bool()
{
return GetBool();
}
} // namespace mu

View File

@ -0,0 +1,140 @@
/** \file
\brief Definition of basic types used by muParserX
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MUP_VALUE_H
#define MUP_VALUE_H
//--- Standard includes ------------------------------------------------------------
#include <complex>
#include <list>
//--- Parser framework -------------------------------------------------------------
#include "mpIValue.h"
#include "mpTypes.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief Value class of muParserX
This class represents a value to be used with muParserX. It's a Variant like
class able to store a variety of types.
*/
class Value : public IValue
{
public:
explicit Value(char_type cType = 'v');
Value(int_type val);
Value(bool_type val);
Value(float_type val);
Value(string_type val);
Value(const char_type *val);
Value(const cmplx_type &v);
Value(const matrix_type &val);
// Array and Matrix constructors
Value(int_type m, float_type v);
Value(int_type m, int_type n, float_type v);
Value(const Value &a_Val );
Value(const IValue &a_Val);
Value& operator=(const Value &a_Val);
virtual ~Value();
virtual IValue& At(int nRow, int nCol = 0) override;
virtual IValue& At(const IValue &row, const IValue &col) override;
virtual IValue& operator=(int_type a_iVal) override;
virtual IValue& operator=(float_type a_fVal) override;
virtual IValue& operator=(string_type a_sVal) override;
virtual IValue& operator=(bool val) override;
virtual IValue& operator=(const matrix_type &a_vVal) override;
virtual IValue& operator=(const cmplx_type &val) override;
virtual IValue& operator=(const char_type *a_szVal);
virtual IValue& operator+=(const IValue &val) override;
virtual IValue& operator-=(const IValue &val) override;
virtual IValue& operator*=(const IValue &val) override;
virtual char_type GetType() const override;
virtual int_type GetInteger() const override;
virtual float_type GetFloat() const override;
virtual float_type GetImag() const override;
virtual bool GetBool() const override;
virtual const cmplx_type& GetComplex() const override;
virtual const string_type& GetString() const override;
virtual const matrix_type& GetArray() const override;
virtual int GetRows() const override;
virtual int GetCols() const override;
virtual bool IsVariable() const override;
virtual IToken* Clone() const override;
virtual Value* AsValue() override;
virtual string_type AsciiDump() const override;
void BindToCache(ValueCache *pCache);
// Conversion operators
operator cmplx_type();
operator int_type();
operator string_type();
operator float_type();
operator bool();
private:
cmplx_type m_val; ///< Member variable for storing the value of complex, float, int and boolean values
string_type *m_psVal; ///< Variable for storing a string value
matrix_type *m_pvVal; ///< A Vector for storing array variable content
char_type m_cType; ///< A byte indicating the type os the represented value
EFlags m_iFlags; ///< Additional flags
ValueCache *m_pCache; ///< Pointer to the Value Cache
void CheckType(char_type a_cType) const;
void Assign(const Value &a_Val);
void Reset();
virtual void Release() override;
}; // class Value
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,105 @@
/** \file
\brief Definition of a class for caching unused value items and recycling them.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpValueCache.h"
#include "mpValue.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
ValueCache::ValueCache(int size)
:m_nIdx(-1)
,m_vCache(size, (mup::Value*)0) // hint to myself: don't use nullptr gcc will go postal...
{}
//------------------------------------------------------------------------------
ValueCache::~ValueCache()
{
ReleaseAll();
}
//------------------------------------------------------------------------------
void ValueCache::ReleaseAll()
{
for (std::size_t i=0; i<m_vCache.size(); ++i)
{
delete m_vCache[i];
m_vCache[i] = nullptr;
}
m_nIdx = -1;
}
//------------------------------------------------------------------------------
void ValueCache::ReleaseToCache(Value *pValue)
{
// std::cout << "dbg: " << ct << " ptr: " << this << " void ValueCache::ReleaseToCache(Value *pValue) \n";
if (pValue==nullptr)
return;
assert(pValue->GetRef()==0);
// Add the value to the cache if the cache has room for it
// otherwise release the value item instantly
if ( m_nIdx < ((int)m_vCache.size()-1) )
{
m_nIdx++;
m_vCache[m_nIdx] = pValue;
}
else
delete pValue;
}
//------------------------------------------------------------------------------
Value* ValueCache::CreateFromCache()
{
Value *pValue = nullptr;
if (m_nIdx>=0)
{
pValue = m_vCache[m_nIdx];
m_vCache[m_nIdx] = nullptr;
m_nIdx--;
}
else
{
pValue = new Value();
pValue->BindToCache(this);
}
return pValue;
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,73 @@
#ifndef MUP_VALUE_CACHE_H
#define MUP_VALUE_CACHE_H
/** \file
\brief Implementation of a cache for recycling unused value items.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include <vector>
#include "mpFwdDecl.h"
MUP_NAMESPACE_START
/** \brief The ValueCache class provides a simple mechanism to recycle
unused value items.
This class serves as a factory for value items. It allows skipping
unnecessary and slow new/delete calls by storing unused value
objects in an internal buffer for later reuse. By eliminating new/delete
calls the parser is sped up approximately by factor 3-4.
*/
class ValueCache
{
public:
ValueCache(int size=10);
~ValueCache();
void ReleaseAll();
void ReleaseToCache(Value *pValue);
Value* CreateFromCache();
private:
ValueCache(const ValueCache &ref);
ValueCache& operator=(const ValueCache &ref);
int m_nIdx;
std::vector<Value*> m_vCache;
};
MUP_NAMESPACE_END
#endif // include guard

View File

@ -0,0 +1,395 @@
/** \file
\brief Implementation of the muParserX variable class.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#include "mpVariable.h"
#include "mpError.h"
#include "mpValue.h"
MUP_NAMESPACE_START
//-----------------------------------------------------------------------------------------------
/** \brief Create a variable and bind a value to it.
\param pVal Pointer of the value to bind to this variable.
It is possible to create an empty variable object by setting pVal to nullptr.
Such variable objects must be bound later in order to be of any use. The parser
does NOT assume ownership over the pointer!
*/
Variable::Variable(IValue *pVal)
:IValue(cmVAL)
,m_pVal(pVal)
{
AddFlags(IToken::flVOLATILE);
}
//-----------------------------------------------------------------------------------------------
Variable::Variable(const Variable &obj)
:IValue(cmVAL)
{
Assign(obj);
AddFlags(IToken::flVOLATILE);
}
//-----------------------------------------------------------------------------------------------
Variable& Variable::operator=(const Variable &obj)
{
Assign(obj);
return *this;
}
//-----------------------------------------------------------------------------------------------
/** \brief Assign a value to the variable.
\param ref Reference to the value to be assigned
*/
IValue& Variable::operator=(const Value &ref)
{
assert(m_pVal);
*m_pVal = ref;
return *this;
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator=(int_type val)
{
assert(m_pVal);
return m_pVal->operator=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator=(float_type val)
{
assert(m_pVal);
return m_pVal->operator=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator=(string_type val)
{
assert(m_pVal);
return m_pVal->operator=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator=(bool_type val)
{
assert(m_pVal);
return m_pVal->operator=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator=(const matrix_type &val)
{
assert(m_pVal);
return m_pVal->operator=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator=(const cmplx_type &val)
{
assert(m_pVal);
return m_pVal->operator=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator+=(const IValue &val)
{
assert(m_pVal);
return m_pVal->operator+=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator-=(const IValue &val)
{
assert(m_pVal);
return m_pVal->operator-=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::operator*=(const IValue &val)
{
assert(m_pVal);
return m_pVal->operator*=(val);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::At(int nRow, int nCol)
{
return m_pVal->At(nRow, nCol);
}
//-----------------------------------------------------------------------------------------------
IValue& Variable::At(const IValue &row, const IValue &col)
{
try
{
return m_pVal->At(row, col);
}
catch(ParserError &exc)
{
// add the identifier to the error context
exc.GetContext().Ident = GetIdent();
throw exc;
}
}
//-----------------------------------------------------------------------------------------------
Variable::~Variable()
{}
//-----------------------------------------------------------------------------------------------
void Variable::Assign(const Variable &ref)
{
if (this==&ref)
return;
m_pVal = ref.m_pVal;
}
//-----------------------------------------------------------------------------------------------
/** \brief Returns a character representing the type of the variable.
\throw nothrow
*/
char_type Variable::GetType() const
{
return (m_pVal) ? m_pVal->GetType() : 'v';
}
//-----------------------------------------------------------------------------------------------
/** \brief Returns the Value pointer bound to this variable.
\throw nothrow
*/
IValue* Variable::GetPtr() const
{
return m_pVal;
}
//-----------------------------------------------------------------------------------------------
int_type Variable::GetInteger() const
{
try
{
return m_pVal->GetInteger();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
float_type Variable::GetFloat() const
{
try
{
return m_pVal->GetFloat();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
float_type Variable::GetImag() const
{
try
{
return m_pVal->GetImag();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
const cmplx_type& Variable::GetComplex() const
{
try
{
return m_pVal->GetComplex();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
const string_type& Variable::GetString() const
{
try
{
return m_pVal->GetString();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
bool Variable::GetBool() const
{
try
{
return m_pVal->GetBool();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
const matrix_type& Variable::GetArray() const
{
try
{
return m_pVal->GetArray();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
int Variable::GetRows() const
{
try
{
return m_pVal->GetRows();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
int Variable::GetCols() const
{
try
{
return m_pVal->GetCols();
}
catch (ParserError &exc)
{
exc.GetContext().Ident = GetIdent();
throw;
}
}
//-----------------------------------------------------------------------------------------------
void Variable::SetFloat(float_type a_fVal)
{
assert(m_pVal);
*m_pVal = a_fVal;
}
//-----------------------------------------------------------------------------------------------
void Variable::SetString(const string_type &a_sVal)
{
assert(m_pVal);
*m_pVal = a_sVal;
}
//-----------------------------------------------------------------------------------------------
void Variable::SetBool(bool a_bVal)
{
assert(m_pVal);
*m_pVal = a_bVal;
}
//-----------------------------------------------------------------------------------------------
void Variable::Bind(IValue *pValue)
{
m_pVal = pValue;
}
//---------------------------------------------------------------------------
bool Variable::IsVariable() const
{
return true;
}
//-----------------------------------------------------------------------------------------------
IToken* Variable::Clone() const
{
return new Variable(*this);
}
//-----------------------------------------------------------------------------------------------
Value* Variable::AsValue()
{
return nullptr;
}
//-----------------------------------------------------------------------------------------------
string_type Variable::AsciiDump() const
{
stringstream_type ss;
ss << g_sCmdCode[ GetCode() ];
ss << _T(" [addr=0x") << std::hex << this << std::dec;
ss << _T("; pos=") << GetExprPos();
ss << _T("; id=\"") << GetIdent() << _T("\"");
ss << _T("; type=\"") << GetType() << _T("\"");
ss << _T("; val=");
switch(GetType())
{
case 'i': ss << (int_type)GetFloat(); break;
case 'f': ss << GetFloat(); break;
case 'm': ss << _T("(array)"); break;
case 's': ss << _T("\"") << GetString() << _T("\""); break;
}
ss << ((IsFlagSet(IToken::flVOLATILE)) ? _T("; ") : _T("; not ")) << _T("vol");
ss << _T("]");
return ss.str();
}
MUP_NAMESPACE_END

View File

@ -0,0 +1,113 @@
/** \file
\brief Definition of the muParserX variable class.
<pre>
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</pre>
*/
#ifndef MP_VARIABLE_H
#define MP_VARIABLE_H
#include "mpIValue.h"
#include "mpTypes.h"
MUP_NAMESPACE_START
//------------------------------------------------------------------------------
/** \brief The variable class represents a parser variable.
This class stores a pointer to a value object and refers all
operations to this value object.
*/
class Variable : public IValue
{
public:
Variable(IValue *pVal);
Variable(const Variable &a_Var);
Variable& operator=(const Variable &a_Var);
virtual IValue& At(int nRow, int nCol);
virtual IValue& At(const IValue &nRows, const IValue &nCols);
virtual IValue& operator=(const Value &val);
virtual IValue& operator=(const matrix_type &val);
virtual IValue& operator=(const cmplx_type &val);
virtual IValue& operator=(int_type val);
virtual IValue& operator=(float_type val);
virtual IValue& operator=(string_type val);
virtual IValue& operator=(bool_type val);
virtual IValue& operator+=(const IValue &ref);
virtual IValue& operator-=(const IValue &ref);
virtual IValue& operator*=(const IValue &val);
virtual ~Variable();
virtual char_type GetType() const;
virtual int_type GetInteger() const;
virtual float_type GetFloat() const;
virtual float_type GetImag() const;
virtual bool GetBool() const;
virtual const cmplx_type& GetComplex() const;
virtual const string_type& GetString() const;
virtual const matrix_type& GetArray() const;
virtual int GetRows() const;
virtual int GetCols() const;
virtual bool IsVariable() const;
virtual IToken* Clone() const;
virtual Value* AsValue();
void SetFloat(float_type a_fVal);
void SetString(const string_type &a_sVal);
void SetBool(bool a_bVal);
void Bind(IValue *pValue);
IValue* GetPtr() const;
string_type AsciiDump() const;
private:
IValue *m_pVal; ///< Pointer to the value object bound to this variable
void Assign(const Variable &a_Var);
void CheckType(char_type a_cType) const;
}; // class Variable
MUP_NAMESPACE_END
#endif

View File

@ -0,0 +1,63 @@
#ifndef SU_PRED_H
#define SU_PRED_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** \brief Namespace containing utility functions and classes for string processing. */
namespace su
{
namespace pred
{
/** \brief Sort two strings based on their length.
*/
template<class TString>
struct SortByLength
{
bool operator()(const TString& a_sLeft, const TString& a_sRight) const
{
if (a_sLeft.length() == a_sRight.length())
{
return a_sLeft < a_sRight;
}
else
{
return a_sLeft.length() < a_sRight.length();
}
}
};
} // namespace pred
} // end of namespace
#endif

View File

@ -0,0 +1,180 @@
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2013 Ingo Berg
All rights reserved.
muParserX - A C++ math parser library with array and string support
Copyright (c) 2013, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SU_STRING_TOKENS_H
#define SU_STRING_TOKENS_H
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
namespace su
{
struct TokenNotFound : public std::runtime_error
{
TokenNotFound() : std::runtime_error("Token not found") {};
};
//---------------------------------------------------------------------------
//
// Deklaration: StringTokens
//
// Zweck: Klasse zum Zerlegen eines durch beliebige Trennungszeichen
// (Tokens) geteilten Strings. Die Teilstrings werden in einem
// vector abgelegt und können über ihren Index, oder eine
// Suchfunktion angesprochen werden.
//
// Einschränkungen: Die Klasse ist als Template geschrieben. Der Template
// Parameter entspricht dem Typ des Ausgangsstringes.
//
//---------------------------------------------------------------------------
template<typename TData>
/* final */ class StringTokens
{
public:
typedef TData string_type;
typedef typename TData::value_type char_type;
private:
typedef std::vector<string_type> storage_type;
public:
//--- Konstruktor -----------------------------------------------------------
StringTokens(const string_type &a_sInput, const string_type &a_sDelim = " ")
:m_delimiter(a_sDelim)
,m_tokens()
{
Tokenize(a_sInput, a_sDelim);
}
//--- Default Konstruktor ---------------------------------------------------
StringTokens()
:m_delimiter(string_type(" "))
,m_tokens()
{}
//--- Destruktor ------------------------------------------------------------
~StringTokens()
{}
//---------------------------------------------------------------------------
void Tokenize(const string_type &a_sInput, const string_type &a_sDelim = " ")
{
string_type buf(a_sInput);
int j = 0;
for (int i=0; i<(int)buf.length(); ++i)
{
if ( a_sDelim.find(buf[i])!=buf.npos )
{
if (i!=j)
m_tokens.push_back( TData(buf.substr(j, i-j).c_str()) );
j = i+1;
}
}
if ( j < (int)(buf.length()) )
m_tokens.push_back( string_type(buf.substr(j).c_str()) );
}
//---------------------------------------------------------------------------
typename const storage_type& Get() const
{
return m_tokens;
}
//---------------------------------------------------------------------------
unsigned int Count() const
{
return static_cast<unsigned int>(m_tokens.size());
}
//---------------------------------------------------------------------------
// Zweck: Rückgabe des Tokens, das an idx'ter Stelle gefunden wurde.
// wird ein Index angegeben, der nicht der Tokenanzahl
// entspricht, so wird eine Exception ausgelöst.
const TData& operator[](unsigned int idx) const
{
try
{
return m_tokens.at(idx);
}
catch(std::out_of_range&)
{
throw TokenNotFound();
}
}
//---------------------------------------------------------------------------
TData& operator[](unsigned idx)
{
try
{
return m_tokens.at(idx);
}
catch(std::out_of_range&)
{
throw TokenNotFound();
}
}
//---------------------------------------------------------------------------
int IndexOf(const TData &str) const
{
storage_type::const_iterator item,
b = m_tokens.begin(),
e = m_tokens.end();
item = std::find(b, e, str);
return (item == e) ? -1 : item-b;
}
private:
StringTokens(const StringTokens &a_Tokens);
StringTokens &operator=(const StringTokens &a_Tokens);
string_type m_delimiter;
storage_type m_tokens;
};
} // end of namespace
#endif

View File

@ -0,0 +1,64 @@
#ifndef _UT_GENERIC_H
#define _UT_GENERIC_H
/*
__________ ____ ___
_____ __ _\______ \_____ _______ ______ __________\ \/ /
/ \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ /
| Y Y \ | / | / __ \| | \/\___ \\ ___/| | \/ \
|__|_| /____/|____| (____ /__| /____ >\___ >__| /___/\ \
\/ \/ \/ \/ \_/
Copyright (C) 2016, Ingo Berg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace utils
{
template<typename T>
class scoped_setter
{
public:
scoped_setter(T &ref, T new_val)
:m_ref(ref)
,m_buf(ref)
{
ref = new_val;
}
~scoped_setter()
{
m_ref = m_buf;
}
private:
T &m_ref;
T m_buf;
// Disable CC and assignment operator
scoped_setter(const scoped_setter &ref);
scoped_setter& operator=(const scoped_setter &ref);
};
}
#endif

View File

@ -4,6 +4,7 @@
#include "ui_tdrdialog.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QDebug>
#include "ui_tdrexplanationwidget.h"
using namespace Math;
using namespace std;

View File

@ -3,6 +3,7 @@
#include "medianfilter.h"
#include "tdr.h"
#include "dft.h"
#include "expression.h"
#include "Traces/trace.h"
TraceMath::TraceMath()
@ -21,6 +22,8 @@ TraceMath *TraceMath::createMath(TraceMath::Type type)
return new Math::TDR();
case Type::DFT:
return new Math::DFT();
case Type::Expression:
return new Math::Expression();
default:
return nullptr;
}
@ -42,6 +45,10 @@ TraceMath::TypeInfo TraceMath::getInfo(TraceMath::Type type)
ret.name = "DFT";
ret.explanationWidget = Math::DFT::createExplanationWidget();
break;
case Type::Expression:
ret.name = "Custom Expression";
ret.explanationWidget = Math::Expression::createExplanationWidget();
break;
default:
break;
}
@ -126,7 +133,7 @@ void TraceMath::inputTypeChanged(TraceMath::DataType type)
disconnect(input, &TraceMath::outputSamplesChanged, this, &TraceMath::inputSamplesChanged);
updateStepResponse(false);
} else {
connect(input, &TraceMath::outputSamplesChanged, this, &TraceMath::inputSamplesChanged);
connect(input, &TraceMath::outputSamplesChanged, this, &TraceMath::inputSamplesChanged, Qt::UniqueConnection);
inputSamplesChanged(0, input->data.size());
}
emit outputTypeChanged(dataType);

View File

@ -73,6 +73,7 @@ public:
MedianFilter,
TDR,
DFT,
Expression,
// Add new math operations here, do not explicitly assign values and keep the Last entry at the last position
Last,
};

View File

@ -52,6 +52,8 @@ void Trace::addData(const Trace::Data& d) {
auto lower = lower_bound(data.begin(), data.end(), d, [](const Data &lhs, const Data &rhs) -> bool {
return lhs.x < rhs.x;
});
// calculate index now because inserting a sample into data might lead to reallocation -> arithmetic on lower not valid anymore
auto index = lower - data.begin();
if(lower == data.end()) {
// highest frequency yet, add to vector
data.push_back(d);
@ -74,13 +76,12 @@ void Trace::addData(const Trace::Data& d) {
}
break;
}
} else {
// insert at this position
data.insert(lower, d);
}
success();
emit outputSamplesChanged(lower - data.begin(), lower - data.begin() + 1);
emit outputSamplesChanged(index, index + 1);
}
void Trace::addData(const Trace::Data &d, const Protocol::SweepSettings &s)

View File

@ -592,12 +592,17 @@ void VNA::SettingsChanged(std::function<void (Device::TransmissionResult)> cb)
{
settings.suppressPeaks = Preferences::getInstance().Acquisition.suppressPeaks ? 1 : 0;
if(window->getDevice()) {
window->getDevice()->Configure(settings, cb);
}
window->getDevice()->Configure(settings, [=](Device::TransmissionResult res){
// device received command, reset traces now
average.reset(settings.points);
traceModel.clearVNAData();
UpdateAverageCount();
UpdateCalWidget();
if(cb) {
cb(res);
}
});
}
emit traceModel.SpanChanged(settings.f_start, settings.f_stop);
}

View File

@ -129,11 +129,11 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
connect(ui->AcquisitionUseHarmonic, &QCheckBox::toggled, [=](bool enabled) {
if(enabled) {
InformationBox::ShowMessage("Harmonic Mixing", "When harmonic mixing is enabled, the frequency range of the VNA is extended up to 18GHz "
InformationBox::ShowMessage("Harmonic Mixing", "When harmonic mixing is enabled, the frequency range of the VNA is (theoretically) extended up to 18GHz "
"by using higher harmonics of the source signal as well as the 1.LO. The fundamental frequency is still present "
"in the output signal and might disturb the measurement if the DUT is not linear. Performance above 6GHz is not "
"specified and generally not very good. However, this mode might be useful, if the signal of interest is just above "
"6GHz. Performance below 6GHz is not affected by this setting");
"specified and generally not very good. However, this mode might be useful if the signal of interest is just above "
"6GHz (typically useful values up to 7-8GHz). Performance below 6GHz is not affected by this setting");
}
});
}