From 9614c9d85085724e67c77bbeef40404faf96b558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Fri, 18 Dec 2020 18:52:38 +0100 Subject: [PATCH] Custom math expressions + bugfix harmonic mixing --- Software/PC_Application/Application.pro | 89 + Software/PC_Application/Device/device.cpp | 1 + .../PC_Application/Traces/Math/expression.cpp | 120 ++ .../PC_Application/Traces/Math/expression.h | 38 + .../Traces/Math/expressiondialog.ui | 97 + .../Math/expressionexplanationwidget.ui | 44 + .../Traces/Math/parser/mpCompat.h | 51 + .../Traces/Math/parser/mpDefines.h | 106 + .../Traces/Math/parser/mpError.cpp | 260 +++ .../Traces/Math/parser/mpError.h | 140 ++ .../Traces/Math/parser/mpFuncCmplx.cpp | 635 ++++++ .../Traces/Math/parser/mpFuncCmplx.h | 262 +++ .../Traces/Math/parser/mpFuncCommon.cpp | 272 +++ .../Traces/Math/parser/mpFuncCommon.h | 111 + .../Traces/Math/parser/mpFuncMatrix.cpp | 249 +++ .../Traces/Math/parser/mpFuncMatrix.h | 103 + .../Traces/Math/parser/mpFuncNonCmplx.cpp | 126 ++ .../Traces/Math/parser/mpFuncNonCmplx.h | 104 + .../Traces/Math/parser/mpFuncStr.cpp | 180 ++ .../Traces/Math/parser/mpFuncStr.h | 92 + .../Traces/Math/parser/mpFwdDecl.h | 55 + .../Traces/Math/parser/mpICallback.cpp | 141 ++ .../Traces/Math/parser/mpICallback.h | 88 + .../Traces/Math/parser/mpIOprt.cpp | 170 ++ .../Traces/Math/parser/mpIOprt.h | 117 ++ .../Traces/Math/parser/mpIPackage.cpp | 51 + .../Traces/Math/parser/mpIPackage.h | 62 + .../Traces/Math/parser/mpIPrecedence.h | 61 + .../Traces/Math/parser/mpIToken.cpp | 325 +++ .../Traces/Math/parser/mpIToken.h | 235 +++ .../Traces/Math/parser/mpIValReader.cpp | 72 + .../Traces/Math/parser/mpIValReader.h | 101 + .../Traces/Math/parser/mpIValue.cpp | 449 ++++ .../Traces/Math/parser/mpIValue.h | 187 ++ .../Traces/Math/parser/mpIfThenElse.cpp | 100 + .../Traces/Math/parser/mpIfThenElse.h | 80 + .../Traces/Math/parser/mpMatrix.h | 448 ++++ .../Traces/Math/parser/mpMatrixError.h | 50 + .../Traces/Math/parser/mpOprtBinAssign.cpp | 249 +++ .../Traces/Math/parser/mpOprtBinAssign.h | 126 ++ .../Traces/Math/parser/mpOprtBinCommon.cpp | 589 ++++++ .../Traces/Math/parser/mpOprtBinCommon.h | 247 +++ .../Traces/Math/parser/mpOprtCmplx.cpp | 321 +++ .../Traces/Math/parser/mpOprtCmplx.h | 130 ++ .../Traces/Math/parser/mpOprtIndex.cpp | 117 ++ .../Traces/Math/parser/mpOprtIndex.h | 65 + .../Traces/Math/parser/mpOprtMatrix.cpp | 182 ++ .../Traces/Math/parser/mpOprtMatrix.h | 80 + .../Traces/Math/parser/mpOprtNonCmplx.cpp | 423 ++++ .../Traces/Math/parser/mpOprtNonCmplx.h | 145 ++ .../Math/parser/mpOprtPostfixCommon.cpp | 112 + .../Traces/Math/parser/mpOprtPostfixCommon.h | 51 + .../Traces/Math/parser/mpPackageCmplx.cpp | 102 + .../Traces/Math/parser/mpPackageCmplx.h | 62 + .../Traces/Math/parser/mpPackageCommon.cpp | 141 ++ .../Traces/Math/parser/mpPackageCommon.h | 64 + .../Traces/Math/parser/mpPackageMatrix.cpp | 82 + .../Traces/Math/parser/mpPackageMatrix.h | 62 + .../Traces/Math/parser/mpPackageNonCmplx.cpp | 108 + .../Traces/Math/parser/mpPackageNonCmplx.h | 63 + .../Traces/Math/parser/mpPackageStr.cpp | 81 + .../Traces/Math/parser/mpPackageStr.h | 63 + .../Traces/Math/parser/mpPackageUnit.cpp | 119 ++ .../Traces/Math/parser/mpPackageUnit.h | 80 + .../Traces/Math/parser/mpParser.cpp | 91 + .../Traces/Math/parser/mpParser.h | 62 + .../Traces/Math/parser/mpParserBase.cpp | 1294 ++++++++++++ .../Traces/Math/parser/mpParserBase.h | 225 ++ .../Math/parser/mpParserMessageProvider.cpp | 181 ++ .../Math/parser/mpParserMessageProvider.h | 61 + .../Traces/Math/parser/mpRPN.cpp | 186 ++ .../PC_Application/Traces/Math/parser/mpRPN.h | 76 + .../Traces/Math/parser/mpScriptTokens.cpp | 74 + .../Traces/Math/parser/mpScriptTokens.h | 68 + .../Traces/Math/parser/mpStack.h | 154 ++ .../Traces/Math/parser/mpTest.cpp | 1838 +++++++++++++++++ .../Traces/Math/parser/mpTest.h | 104 + .../Traces/Math/parser/mpTokenReader.cpp | 1026 +++++++++ .../Traces/Math/parser/mpTokenReader.h | 137 ++ .../Traces/Math/parser/mpTypes.h | 406 ++++ .../Traces/Math/parser/mpValReader.cpp | 347 ++++ .../Traces/Math/parser/mpValReader.h | 138 ++ .../Traces/Math/parser/mpValue.cpp | 810 ++++++++ .../Traces/Math/parser/mpValue.h | 140 ++ .../Traces/Math/parser/mpValueCache.cpp | 105 + .../Traces/Math/parser/mpValueCache.h | 73 + .../Traces/Math/parser/mpVariable.cpp | 395 ++++ .../Traces/Math/parser/mpVariable.h | 113 + .../Traces/Math/parser/suSortPred.h | 63 + .../Traces/Math/parser/suStringTokens.h | 180 ++ .../Traces/Math/parser/utGeneric.h | 64 + Software/PC_Application/Traces/Math/tdr.cpp | 1 + .../PC_Application/Traces/Math/tracemath.cpp | 9 +- .../PC_Application/Traces/Math/tracemath.h | 1 + Software/PC_Application/Traces/trace.cpp | 5 +- Software/PC_Application/VNA/vna.cpp | 15 +- Software/PC_Application/preferences.cpp | 6 +- 97 files changed, 18173 insertions(+), 11 deletions(-) create mode 100644 Software/PC_Application/Traces/Math/expression.cpp create mode 100644 Software/PC_Application/Traces/Math/expression.h create mode 100644 Software/PC_Application/Traces/Math/expressiondialog.ui create mode 100644 Software/PC_Application/Traces/Math/expressionexplanationwidget.ui create mode 100644 Software/PC_Application/Traces/Math/parser/mpCompat.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpDefines.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpError.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpError.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncCmplx.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncCmplx.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncCommon.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncCommon.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncMatrix.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncMatrix.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncStr.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpFuncStr.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpFwdDecl.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpICallback.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpICallback.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIOprt.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpIOprt.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIPackage.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpIPackage.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIPrecedence.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIToken.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpIToken.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIValReader.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpIValReader.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIValue.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpIValue.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpIfThenElse.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpIfThenElse.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpMatrix.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpMatrixError.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtCmplx.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtCmplx.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtIndex.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtIndex.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtMatrix.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtMatrix.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.h create mode 100755 Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.cpp create mode 100755 Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageCmplx.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageCmplx.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageCommon.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageCommon.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageMatrix.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageMatrix.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageStr.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageStr.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageUnit.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpPackageUnit.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpParser.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpParser.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpParserBase.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpParserBase.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpParserMessageProvider.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpParserMessageProvider.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpRPN.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpRPN.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpScriptTokens.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpScriptTokens.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpStack.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpTest.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpTest.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpTokenReader.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpTokenReader.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpTypes.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpValReader.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpValReader.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpValue.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpValue.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpValueCache.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpValueCache.h create mode 100644 Software/PC_Application/Traces/Math/parser/mpVariable.cpp create mode 100644 Software/PC_Application/Traces/Math/parser/mpVariable.h create mode 100644 Software/PC_Application/Traces/Math/parser/suSortPred.h create mode 100644 Software/PC_Application/Traces/Math/parser/suStringTokens.h create mode 100644 Software/PC_Application/Traces/Math/parser/utGeneric.h diff --git a/Software/PC_Application/Application.pro b/Software/PC_Application/Application.pro index f88eae3..91e78d3 100644 --- a/Software/PC_Application/Application.pro +++ b/Software/PC_Application/Application.pro @@ -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 \ diff --git a/Software/PC_Application/Device/device.cpp b/Software/PC_Application/Device/device.cpp index 2d68298..b2fd6b9 100644 --- a/Software/PC_Application/Device/device.cpp +++ b/Software/PC_Application/Device/device.cpp @@ -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; diff --git a/Software/PC_Application/Traces/Math/expression.cpp b/Software/PC_Application/Traces/Math/expression.cpp new file mode 100644 index 0000000..23cd15a --- /dev/null +++ b/Software/PC_Application/Traces/Math/expression.cpp @@ -0,0 +1,120 @@ +#include "expression.h" +#include +#include "ui_expressiondialog.h" +#include +#include +#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;itimeToDistance(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()); + } +} diff --git a/Software/PC_Application/Traces/Math/expression.h b/Software/PC_Application/Traces/Math/expression.h new file mode 100644 index 0000000..bf5b02d --- /dev/null +++ b/Software/PC_Application/Traces/Math/expression.h @@ -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 diff --git a/Software/PC_Application/Traces/Math/expressiondialog.ui b/Software/PC_Application/Traces/Math/expressiondialog.ui new file mode 100644 index 0000000..5380d30 --- /dev/null +++ b/Software/PC_Application/Traces/Math/expressiondialog.ui @@ -0,0 +1,97 @@ + + + ExpressionDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 637 + 313 + + + + Custom Expression + + + true + + + + + + + + Expression: + + + + + + + + + + + + 0 + + + + + + + <html><head/><body><p>Available variables:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">x: the S parameter as a (complex) voltage vector. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">f: measurement frequency in Hz</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">w: angular measurement frequency (w = 2πf)</li></ul><p>Examples:<br/>Add 10db to the trace (10db = exp10(10/20) = sqrt(10)):</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">x * sqrt(10)</li></ul><p>Clip trace at 0db (0db = exp10(0/20) = 1) while preserving phase:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">abs(x) &lt; 1 ? x : exp(i*arg(x))</li></ul></body></html> + + + + + + + + + + + <html><head/><body><p>Available variables:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">x: the impulse response as a (complex) vector. </li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">t: time in seconds</li><li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">d: distance in meters</li></ul></body></html> + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + ExpressionDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + diff --git a/Software/PC_Application/Traces/Math/expressionexplanationwidget.ui b/Software/PC_Application/Traces/Math/expressionexplanationwidget.ui new file mode 100644 index 0000000..0852bec --- /dev/null +++ b/Software/PC_Application/Traces/Math/expressionexplanationwidget.ui @@ -0,0 +1,44 @@ + + + ExpressionExplanationWidget + + + + 0 + 0 + 417 + 421 + + + + Form + + + + + + <html><head/><body><p><span style=" font-weight:600;">Custom Expression</span></p><p>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.</p><p><br/></p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 20 + 251 + + + + + + + + + diff --git a/Software/PC_Application/Traces/Math/parser/mpCompat.h b/Software/PC_Application/Traces/Math/parser/mpCompat.h new file mode 100644 index 0000000..4767005 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpCompat.h @@ -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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpDefines.h b/Software/PC_Application/Traces/Math/parser/mpDefines.h new file mode 100644 index 0000000..d27c9f3 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpDefines.h @@ -0,0 +1,106 @@ +/** \file + \brief A file containing macros used by muParserX + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_DEFINES_H +#define MUP_DEFINES_H + +#include + + +#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(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(POINTER); +#endif + +#endif + + diff --git a/Software/PC_Application/Traces/Math/parser/mpError.cpp b/Software/PC_Application/Traces/Math/parser/mpError.cpp new file mode 100644 index 0000000..3809ce3 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpError.cpp @@ -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 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpError.h b/Software/PC_Application/Traces/Math/parser/mpError.h new file mode 100644 index 0000000..4090515 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpError.h @@ -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 +#include +#include +#include +#include +#include + +#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 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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncCmplx.cpp b/Software/PC_Application/Traces/Math/parser/mpFuncCmplx.cpp new file mode 100644 index 0000000..9f97b23 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncCmplx.cpp @@ -0,0 +1,635 @@ +/** \file + \brief Definition of functions for complex valued operations. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "mpFuncCmplx.h" + +//--- Standard includes ---------------------------------------------------- +#include +#include +#include +#include + +//--- 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 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncCmplx.h b/Software/PC_Application/Traces/Math/parser/mpFuncCmplx.h new file mode 100644 index 0000000..9436cce --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncCmplx.h @@ -0,0 +1,262 @@ +/** \file + \brief Definition of functions for complex valued operations. + +
+			   __________                                 ____  ___
+	_____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+  |  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_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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncCommon.cpp b/Software/PC_Application/Traces/Math/parser/mpFuncCommon.cpp new file mode 100644 index 0000000..71797ad --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncCommon.cpp @@ -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 +#include +#include + +#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; iGetType()) + { + 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; iGetType()) + { + 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; iGetType()) + { + 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncCommon.h b/Software/PC_Application/Traces/Math/parser/mpFuncCommon.h new file mode 100644 index 0000000..33064f8 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncCommon.h @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncMatrix.cpp b/Software/PC_Application/Traces/Math/parser/mpFuncMatrix.cpp new file mode 100644 index 0000000..995e680 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncMatrix.cpp @@ -0,0 +1,249 @@ +/** \file + \brief Definition of functions for complex valued operations. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+    /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+    |  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.
+    
+ */ +#include "mpFuncMatrix.h" + +//--- Standard includes ---------------------------------------------------- +#include +#include +#include +#include + +//--- 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncMatrix.h b/Software/PC_Application/Traces/Math/parser/mpFuncMatrix.h new file mode 100644 index 0000000..a4aa676 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncMatrix.h @@ -0,0 +1,103 @@ +/** \file + \brief Definition of functions for complex valued operations. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.cpp b/Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.cpp new file mode 100644 index 0000000..4ea6b7d --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.cpp @@ -0,0 +1,126 @@ +/** \file + \brief Implementation of basic functions used by muParserX. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "mpFuncNonCmplx.h" + +//--- Standard includes ---------------------------------------------------- +#include +#include +#include + +//--- 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.h b/Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.h new file mode 100644 index 0000000..0053d3f --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncNonCmplx.h @@ -0,0 +1,104 @@ +/** \file + \brief Implementation of basic functions used by muParserX. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncStr.cpp b/Software/PC_Application/Traces/Math/parser/mpFuncStr.cpp new file mode 100644 index 0000000..093d016 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncStr.cpp @@ -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 +#include +#include +#include +#include + +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFuncStr.h b/Software/PC_Application/Traces/Math/parser/mpFuncStr.h new file mode 100644 index 0000000..a322c17 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFuncStr.h @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpFwdDecl.h b/Software/PC_Application/Traces/Math/parser/mpFwdDecl.h new file mode 100644 index 0000000..e128a0d --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpFwdDecl.h @@ -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 + class TokenPtr; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpICallback.cpp b/Software/PC_Application/Traces/Math/parser/mpICallback.cpp new file mode 100644 index 0000000..1523f75 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpICallback.cpp @@ -0,0 +1,141 @@ +/** \file + \brief Implementation of the interface for parser callback objects. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "mpICallback.h" +#include + +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpICallback.h b/Software/PC_Application/Traces/Math/parser/mpICallback.h new file mode 100644 index 0000000..62267fc --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpICallback.h @@ -0,0 +1,88 @@ +/** \file + \brief Definition of the interface for parser callback objects. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpIOprt.cpp b/Software/PC_Application/Traces/Math/parser/mpIOprt.cpp new file mode 100644 index 0000000..5ccf807 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIOprt.cpp @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIOprt.h b/Software/PC_Application/Traces/Math/parser/mpIOprt.h new file mode 100644 index 0000000..01d7938 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIOprt.h @@ -0,0 +1,117 @@ +/** \file mpIOprt.h + \brief Definition of base classes needed for parser operator definitions. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpIPackage.cpp b/Software/PC_Application/Traces/Math/parser/mpIPackage.cpp new file mode 100644 index 0000000..f534584 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIPackage.cpp @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIPackage.h b/Software/PC_Application/Traces/Math/parser/mpIPackage.h new file mode 100644 index 0000000..0b665ec --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIPackage.h @@ -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 +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIPrecedence.h b/Software/PC_Application/Traces/Math/parser/mpIPrecedence.h new file mode 100644 index 0000000..8a5a207 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIPrecedence.h @@ -0,0 +1,61 @@ +/** \file mpIPrecedence.h + \brief Definition of base classes needed for parser operator definitions. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpIToken.cpp b/Software/PC_Application/Traces/Math/parser/mpIToken.cpp new file mode 100644 index 0000000..4f26181 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIToken.cpp @@ -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 +#include +#include +#include +#include + +#include "mpIPrecedence.h" + +MUP_NAMESPACE_START + +#ifdef MUP_LEAKAGE_REPORT + std::list 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::const_iterator item = IToken::s_Tokens.begin(); + std::vector 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::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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIToken.h b/Software/PC_Application/Traces/Math/parser/mpIToken.h new file mode 100644 index 0000000..0dd8509 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIToken.h @@ -0,0 +1,235 @@ +/* +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_ITOKEN_H +#define MUP_ITOKEN_H + +#include +#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; + friend class TokenPtr; + friend class TokenPtr; + friend class TokenPtr; + friend class TokenPtr; + friend class TokenPtr; + friend class TokenPtr; + friend class TokenPtr; + friend class TokenPtr; + + 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 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 + 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(m_pTok); + } + + //--------------------------------------------------------------------------- + T& operator*() const + { + assert(m_pTok); + return *(static_cast(m_pTok)); + } + + //--------------------------------------------------------------------------- + token_type Get() const + { + return static_cast(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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIValReader.cpp b/Software/PC_Application/Traces/Math/parser/mpIValReader.cpp new file mode 100644 index 0000000..ab6c629 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIValReader.cpp @@ -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 + + +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(); + } +} diff --git a/Software/PC_Application/Traces/Math/parser/mpIValReader.h b/Software/PC_Application/Traces/Math/parser/mpIValReader.h new file mode 100644 index 0000000..e8810eb --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIValReader.h @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIValue.cpp b/Software/PC_Application/Traces/Math/parser/mpIValue.cpp new file mode 100644 index 0000000..878b3d0 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIValue.cpp @@ -0,0 +1,449 @@ +/** \file + \brief Implementation of the virtual base class used for all parser values. + +
+                __________                                 ____  ___
+     _____  __ _\______   \_____ _______  ______ __________\   \/  /
+    /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+    |  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 "mpIValue.h" + +//--- Standard includes ------------------------------------------------------ +#include +#include +#include +#include + +//--- 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::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(this)->At(i) != const_cast(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(this)->At(i) != const_cast(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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIValue.h b/Software/PC_Application/Traces/Math/parser/mpIValue.h new file mode 100644 index 0000000..4eb269e --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIValue.h @@ -0,0 +1,187 @@ +/** \file + \brief Definition of the virtual base class used for all parser values. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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: +
    +
  • 0 - scalar
  • +
  • 1 - vector
  • +
  • 2 - matrix
  • +
+ */ + 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 + + diff --git a/Software/PC_Application/Traces/Math/parser/mpIfThenElse.cpp b/Software/PC_Application/Traces/Math/parser/mpIfThenElse.cpp new file mode 100644 index 0000000..3d5a76f --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIfThenElse.cpp @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpIfThenElse.h b/Software/PC_Application/Traces/Math/parser/mpIfThenElse.h new file mode 100644 index 0000000..f8ed789 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpIfThenElse.h @@ -0,0 +1,80 @@ +/** \file + \brief Definition of basic types used by muParserX + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 diff --git a/Software/PC_Application/Traces/Math/parser/mpMatrix.h b/Software/PC_Application/Traces/Math/parser/mpMatrix.h new file mode 100644 index 0000000..924c956 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpMatrix.h @@ -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 +#include +#include +#include +#include +#include +#include "mpMatrixError.h" + +MUP_NAMESPACE_START + +//----------------------------------------------------------------------------------------------- +template +class Matrix +{ + template + friend Matrix operator+(const Matrix& lhs, const Matrix& rhs); + + template + 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 &v) + :m_nRows(v.size()) + , m_nCols(1) + , m_eStorageScheme(mssROWS_FIRST) + , m_vData(v) + {} + + //--------------------------------------------------------------------------------------------- + /* Constructs a Matrix object representing a vector + */ + template + Matrix(T(&v)[TSize]) + :m_nRows(TSize) + , m_nCols(1) + , m_eStorageScheme(mssROWS_FIRST) + , m_vData(v, v + TSize) + {} + + //--------------------------------------------------------------------------------------------- + template + 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 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& 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 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 +Matrix operator*(const Matrix& lhs, const T& rhs) +{ + return Matrix(lhs) *= rhs; +} + +//--------------------------------------------------------------------------------------------- +template +Matrix operator*(const Matrix& lhs, const Matrix& rhs) +{ + return Matrix(lhs) *= rhs; +} + +//--------------------------------------------------------------------------------------------- +template +Matrix operator+(const Matrix& lhs, const Matrix& rhs) +{ + return Matrix(lhs) += rhs; +} + +//--------------------------------------------------------------------------------------------- +template +Matrix operator-(const Matrix& lhs, const Matrix& rhs) +{ + return Matrix(lhs) -= rhs; +} + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpMatrixError.h b/Software/PC_Application/Traces/Math/parser/mpMatrixError.h new file mode 100644 index 0000000..8af23ad --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpMatrixError.h @@ -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 +#include + +MUP_NAMESPACE_START + + class MatrixError : public std::runtime_error + { + public: + explicit MatrixError(const std::string &sMsg) + :std::runtime_error(sMsg) + {} + }; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.cpp new file mode 100644 index 0000000..18fed10 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.cpp @@ -0,0 +1,249 @@ +/** \file + \brief This file contains the implementation of binary assignment + operators used in muParser. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "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(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(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(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(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(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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.h b/Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.h new file mode 100644 index 0000000..781f711 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtBinAssign.h @@ -0,0 +1,126 @@ +/** \file + \brief This file contains the definition of binary assignment + operators used in muParser. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_OPRT_BIN_ASSIGN_H +#define MUP_OPRT_BIN_ASSIGN_H + +//--- Standard includes ---------------------------------------------------------- +#include + +//--- 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.cpp new file mode 100644 index 0000000..c1d6e22 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.cpp @@ -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 +#include + + +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::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::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); +} + +} diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.h b/Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.h new file mode 100644 index 0000000..da23ce6 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtBinCommon.h @@ -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 +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtCmplx.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtCmplx.cpp new file mode 100644 index 0000000..dfc6da5 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtCmplx.cpp @@ -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 +#include + +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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtCmplx.h b/Software/PC_Application/Traces/Math/parser/mpOprtCmplx.h new file mode 100644 index 0000000..756ef9f --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtCmplx.h @@ -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 +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtIndex.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtIndex.cpp new file mode 100644 index 0000000..5670063 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtIndex.cpp @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtIndex.h b/Software/PC_Application/Traces/Math/parser/mpOprtIndex.h new file mode 100644 index 0000000..de4e0c8 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtIndex.h @@ -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 +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtMatrix.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtMatrix.cpp new file mode 100644 index 0000000..b06ed6f --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtMatrix.cpp @@ -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; iGetFloat() + i; + + *ret = arr; + } + + //----------------------------------------------------------- + const char_type* OprtColon::GetDesc() const + { + return _T(": - Colon operator"); + } + + //----------------------------------------------------------- + IToken* OprtColon::Clone() const + { + return new OprtColon(*this); + } +MUP_NAMESPACE_END diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtMatrix.h b/Software/PC_Application/Traces/Math/parser/mpOprtMatrix.h new file mode 100644 index 0000000..f2ea98d --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtMatrix.h @@ -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 +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.cpp new file mode 100644 index 0000000..d58ef63 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.cpp @@ -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; iGetRows(); ++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; iGetRows(); ++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; iIsNonComplexScalar()) + 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; iIsNonComplexScalar()) + 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; iGetType()=='m' && arg2->IsNonComplexScalar()) + { + // Skalar * Vector + matrix_type out(a_pArg[0]->GetArray()); + for (int i=0; iGetFloat(); + + *ret = out; + } + else if (arg2->GetType()=='m' && arg1->IsNonComplexScalar()) + { + // Vector * Skalar + matrix_type out(arg2->GetArray()); + for (int i=0; iGetFloat(); + + *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); + } +} diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.h b/Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.h new file mode 100644 index 0000000..795fdc4 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtNonCmplx.h @@ -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 +#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 diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.cpp b/Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.cpp new file mode 100755 index 0000000..f8ba01e --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.cpp @@ -0,0 +1,112 @@ +#include +#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; + + // 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::is_iec559 && + (result>std::numeric_limits::max() || result < 1.0) ) + #ifdef _MSC_VER + #pragma warning(pop) + #endif /* _MSC_VER */ + { + throw ParserError(ErrorContext(ecOVERFLOW, GetExprPos(), GetIdent())); + } + // + } + + *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); + } + +} diff --git a/Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.h b/Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.h new file mode 100755 index 0000000..1eaa419 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpOprtPostfixCommon.h @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageCmplx.cpp b/Software/PC_Application/Traces/Math/parser/mpPackageCmplx.cpp new file mode 100644 index 0000000..29435c4 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageCmplx.cpp @@ -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::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 diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageCmplx.h b/Software/PC_Application/Traces/Math/parser/mpPackageCmplx.h new file mode 100644 index 0000000..9b9c620 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageCmplx.h @@ -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 +#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; + +public: + + static IPackage* Instance(); + virtual void AddToParser(ParserXBase *pParser); + virtual string_type GetDesc() const; + virtual string_type GetPrefix() const; + +private: + + static std::unique_ptr s_pInstance; +}; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageCommon.cpp b/Software/PC_Application/Traces/Math/parser/mpPackageCommon.cpp new file mode 100644 index 0000000..30fec3c --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageCommon.cpp @@ -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::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); +// commented: "%" is a reserved sign for either the +// modulo operator or comment lines. +// pParser->DefinePostfixOprt(new OprtPercentage); +// +} + +//------------------------------------------------------------------------------ +string_type PackageCommon::GetDesc() const +{ + return _T(""); +} + +//------------------------------------------------------------------------------ +string_type PackageCommon::GetPrefix() const +{ + return _T(""); +} + +MUP_NAMESPACE_END diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageCommon.h b/Software/PC_Application/Traces/Math/parser/mpPackageCommon.h new file mode 100644 index 0000000..5eb8b42 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageCommon.h @@ -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 +#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; + +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 s_pInstance; +}; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageMatrix.cpp b/Software/PC_Application/Traces/Math/parser/mpPackageMatrix.cpp new file mode 100644 index 0000000..26dc20b --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageMatrix.cpp @@ -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::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 diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageMatrix.h b/Software/PC_Application/Traces/Math/parser/mpPackageMatrix.h new file mode 100644 index 0000000..94f043c --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageMatrix.h @@ -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 +#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; + +public: + + static IPackage* Instance(); + virtual void AddToParser(ParserXBase *pParser); + virtual string_type GetDesc() const; + virtual string_type GetPrefix() const; + +private: + + static std::unique_ptr s_pInstance; +}; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.cpp b/Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.cpp new file mode 100644 index 0000000..fca5624 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.cpp @@ -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::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 diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.h b/Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.h new file mode 100644 index 0000000..4e3ef01 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageNonCmplx.h @@ -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 +#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; + +public: + + static IPackage* Instance(); + + virtual void AddToParser(ParserXBase *pParser); + virtual string_type GetDesc() const; + virtual string_type GetPrefix() const; + +private: + + static std::unique_ptr s_pInstance; +}; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageStr.cpp b/Software/PC_Application/Traces/Math/parser/mpPackageStr.cpp new file mode 100644 index 0000000..2fc00a0 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageStr.cpp @@ -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::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 diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageStr.h b/Software/PC_Application/Traces/Math/parser/mpPackageStr.h new file mode 100644 index 0000000..972d08f --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageStr.h @@ -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 + +#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; + +public: + + static IPackage* Instance(); + virtual void AddToParser(ParserXBase *pParser); + virtual string_type GetDesc() const; + virtual string_type GetPrefix() const; + +private: + + static std::unique_ptr s_pInstance; +}; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageUnit.cpp b/Software/PC_Application/Traces/Math/parser/mpPackageUnit.cpp new file mode 100644 index 0000000..7420e75 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageUnit.cpp @@ -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::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 diff --git a/Software/PC_Application/Traces/Math/parser/mpPackageUnit.h b/Software/PC_Application/Traces/Math/parser/mpPackageUnit.h new file mode 100644 index 0000000..7cb75d5 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpPackageUnit.h @@ -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 +#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; + +public: + + static IPackage* Instance(); + virtual void AddToParser(ParserXBase *pParser); + virtual string_type GetDesc() const; + virtual string_type GetPrefix() const; + +private: + + static std::unique_ptr s_pInstance; +}; + +MUP_NAMESPACE_END + +#endif diff --git a/Software/PC_Application/Traces/Math/parser/mpParser.cpp b/Software/PC_Application/Traces/Math/parser/mpParser.cpp new file mode 100644 index 0000000..59ea64d --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpParser.cpp @@ -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 +#include +#include + +//--- 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpParser.h b/Software/PC_Application/Traces/Math/parser/mpParser.h new file mode 100644 index 0000000..6eaa08d --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpParser.h @@ -0,0 +1,62 @@ +#ifndef MUP_PARSERX_H +#define MUP_PARSERX_H + +/** \file + \brief Definition of the parser class + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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.
+
+*/ + +//--- 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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpParserBase.cpp b/Software/PC_Application/Traces/Math/parser/mpParserBase.cpp new file mode 100644 index 0000000..1d45107 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpParserBase.cpp @@ -0,0 +1,1294 @@ +/** \file + \brief Implementation of the muParserX engine. + +
+			   __________                                 ____  ___
+	 _____  __ _\______   \_____ _______  ______ __________\   \/  /
+	/     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+	|  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 "mpParserBase.h" + +#include +#include +#include +#include + +#include "utGeneric.h" +#include "mpDefines.h" +#include "mpIfThenElse.h" +#include "mpScriptTokens.h" + +using namespace std; + +MUP_NAMESPACE_START + +//------------------------------------------------------------------------------ +const char_type* g_sCmdCode[] = { + _T("BRCK. OPEN "), + _T("BRCK. CLOSE "), + _T("IDX OPEN "), + _T("IDX CLOSE "), + _T("CURLY BRCK. OPEN "), + _T("CURLY BRCK. CLOSE"), + _T("ARG_SEP "), + _T("IF "), + _T("ELSE "), + _T("ENDIF "), + _T("JMP "), + _T("VAL "), + _T("FUNC "), + _T("OPRT_BIN "), + _T("OPRT_IFX "), + _T("OPRT_PFX "), + _T("END "), + _T("SCR_ENDL "), + _T("SCR_CMT "), + _T("SCR_WHILE "), + _T("SCR_GOTO "), + _T("SCR_LABEL "), + _T("SCR_FOR "), + _T("SCR_IF "), + _T("SCR_ELSE "), + _T("SCR_ELIF "), + _T("SCR_ENDIF "), + _T("SCR_FUNC "), + _T("UNKNOWN "), + nullptr }; + +//------------------------------------------------------------------------------ +bool ParserXBase::s_bDumpStack = false; +bool ParserXBase::s_bDumpRPN = false; + +//------------------------------------------------------------------------------ +/** \brief Identifiers for built in binary operators. + + When defining custom binary operators with AddOprt(...) make sure not to choose + names conflicting with these definitions. + */ +const char_type* ParserXBase::c_DefaultOprt[] = { + _T("("), + _T(")"), + _T("["), + _T("]"), + _T("{"), + _T("}"), + _T(","), + _T("?"), + _T(":"), + 0 }; + +//------------------------------------------------------------------------------ +/** \brief Default constructor. */ +ParserXBase::ParserXBase() + :m_FunDef() + , m_PostOprtDef() + , m_InfixOprtDef() + , m_OprtDef() + , m_valDef() + , m_varDef() + , m_pParserEngine(&ParserXBase::ParseFromString) + , m_pTokenReader() + , m_valDynVarShadow() + , m_sNameChars() + , m_sOprtChars() + , m_sInfixOprtChars() + , m_bIsQueryingExprVar(false) + , m_bAutoCreateVar(false) + , m_rpn() + , m_vStackBuffer() +{ + InitTokenReader(); +} + +//--------------------------------------------------------------------------- +/** \brief Copy constructor. + \param a_Parser Reference to the other parser object + + Implemented by calling Assign(a_Parser) + */ +ParserXBase::ParserXBase(const ParserXBase& a_Parser) + :m_FunDef() + , m_PostOprtDef() + , m_InfixOprtDef() + , m_OprtDef() + , m_valDef() + , m_varDef() + , m_pParserEngine(&ParserXBase::ParseFromString) + , m_pTokenReader() + , m_valDynVarShadow() + , m_sNameChars() + , m_sOprtChars() + , m_sInfixOprtChars() + , m_bAutoCreateVar() + , m_rpn() + , m_vStackBuffer() +{ + m_pTokenReader.reset(new TokenReader(this)); + Assign(a_Parser); +} + +//--------------------------------------------------------------------------- +/** \brief Destructor. + \throw nothrow + */ +ParserXBase::~ParserXBase() +{ + // It is important to release the stack buffer before + // releasing the value cache. Since it may contain + // Values referencing the cache. + m_vStackBuffer.clear(); + m_cache.ReleaseAll(); +} + +//--------------------------------------------------------------------------- +/** \brief Assignement operator. + \param a_Parser Object to copy to this. + \return *this + \throw nothrow + + Implemented by calling Assign(a_Parser). Self assignement is suppressed. + */ +ParserXBase& ParserXBase::operator=(const ParserXBase& a_Parser) +{ + Assign(a_Parser); + return *this; +} + +//--------------------------------------------------------------------------- +/** \brief Copy state of a parser object to this. + \param a_Parser the source object. + + Clears Variables and Functions of this parser. + Copies the states of all internal variables. + Resets parse function to string parse mode. + */ +void ParserXBase::Assign(const ParserXBase& ref) +{ + if (&ref == this) + return; + + // Don't copy bytecode instead cause the parser to create new bytecode + // by resetting the parse function. + ReInit(); + + m_pTokenReader.reset(ref.m_pTokenReader->Clone(this)); + + m_OprtDef = ref.m_OprtDef; + m_FunDef = ref.m_FunDef; + m_PostOprtDef = ref.m_PostOprtDef; + m_InfixOprtDef = ref.m_InfixOprtDef; + m_valDef = ref.m_valDef; + m_valDynVarShadow = ref.m_valDynVarShadow; + m_varDef = ref.m_varDef; // Copy user defined variables + + // Copy charsets + m_sNameChars = ref.m_sNameChars; + m_sOprtChars = ref.m_sOprtChars; + m_sInfixOprtChars = ref.m_sInfixOprtChars; + + m_bAutoCreateVar = ref.m_bAutoCreateVar; + + // Things that should not be copied: + // - m_vStackBuffer + // - m_cache + // - m_rpn +} + +//--------------------------------------------------------------------------- +/** \brief Evaluate the expression. + \pre A formula must be set. + \pre Variables must have been set (if needed) + \sa SetExpr + \return The evaluation result + \throw ParseException if no Formula is set or in case of any other error related to the formula. + + A note on const correctness: + I consider it important that Calc is a const function. + Due to caching operations Calc changes only the state of internal variables with one exception + m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making + Calc non const GetExprVar is non const because it explicitely calls Eval() forcing this update. + */ +const IValue& ParserXBase::Eval() const +{ + return (this->*m_pParserEngine)(); +} + +//--------------------------------------------------------------------------- +/** \brief Return the strings of all Operator identifiers. + \return Returns a pointer to the c_DefaultOprt array of const char *. + \throw nothrow + + GetOprt is a const function returning a pinter to an array of const char pointers. + */ +const char_type** ParserXBase::GetOprtDef() const +{ + return (const char_type**)(&c_DefaultOprt[0]); +} + +//--------------------------------------------------------------------------- +/** \brief Define the set of valid characters to be used in names of + functions, variables, constants. + */ +void ParserXBase::DefineNameChars(const char_type* a_szCharset) +{ + m_sNameChars = a_szCharset; +} + +//--------------------------------------------------------------------------- +/** \brief Define the set of valid characters to be used in names of + binary operators and postfix operators. + \param a_szCharset A string containing all characters that can be used + in operator identifiers. + */ +void ParserXBase::DefineOprtChars(const char_type* a_szCharset) +{ + m_sOprtChars = a_szCharset; +} + +//--------------------------------------------------------------------------- +/** \brief Define the set of valid characters to be used in names of + infix operators. + \param a_szCharset A string containing all characters that can be used + in infix operator identifiers. + */ +void ParserXBase::DefineInfixOprtChars(const char_type* a_szCharset) +{ + m_sInfixOprtChars = a_szCharset; +} + +//--------------------------------------------------------------------------- +/** \brief Virtual function that defines the characters allowed in name identifiers. + \sa #ValidOprtChars, #ValidPrefixOprtChars + */ +const char_type* ParserXBase::ValidNameChars() const +{ + MUP_VERIFY(m_sNameChars.size()); + return m_sNameChars.c_str(); +} + +//--------------------------------------------------------------------------- +/** \brief Virtual function that defines the characters allowed in operator definitions. + \sa #ValidNameChars, #ValidPrefixOprtChars + */ +const char_type* ParserXBase::ValidOprtChars() const +{ + MUP_VERIFY(m_sOprtChars.size()); + return m_sOprtChars.c_str(); +} + +//--------------------------------------------------------------------------- +/** \brief Virtual function that defines the characters allowed in infix operator definitions. + \sa #ValidNameChars, #ValidOprtChars + */ +const char_type* ParserXBase::ValidInfixOprtChars() const +{ + MUP_VERIFY(m_sInfixOprtChars.size()); + return m_sInfixOprtChars.c_str(); +} + +//--------------------------------------------------------------------------- +/** \brief Initialize the token reader. + \post m_pTokenReader.Get()!=0 + \throw nothrow + + Create new token reader object and submit pointers to function, operator, + constant and variable definitions. + */ +void ParserXBase::InitTokenReader() +{ + m_pTokenReader.reset(new TokenReader(this)); +} + +//--------------------------------------------------------------------------- +/** \brief Reset parser to string parsing mode and clear internal buffers. + \throw nothrow + + Resets the token reader. + */ +void ParserXBase::ReInit() const +{ + m_pParserEngine = &ParserXBase::ParseFromString; + m_pTokenReader->ReInit(); + m_rpn.Reset(); + m_vStackBuffer.clear(); + m_nPos = 0; +} + +//--------------------------------------------------------------------------- +/** \brief Adds a new package to the parser. + + The parser becomes the owner of the package pointer and is responsible for + its deletion. + */ +void ParserXBase::AddPackage(IPackage* p) +{ + p->AddToParser(this); +} + +//--------------------------------------------------------------------------- +/** \brief Add a value reader object to muParserX. + \param a_pReader Pointer to the value reader object. + */ +void ParserXBase::AddValueReader(IValueReader* a_pReader) +{ + m_pTokenReader->AddValueReader(a_pReader); +} + +//--------------------------------------------------------------------------- +/** \brief Check if a given name contains invalid characters. + \param a_strName The name to check + \param a_szCharSet The characterset + \throw ParserException if the name contains invalid charakters. + */ +void ParserXBase::CheckName(const string_type& a_strName, + const string_type& a_szCharSet) const +{ + if (!a_strName.length() || + (a_strName.find_first_not_of(a_szCharSet) != string_type::npos) || + (a_strName[0] >= (char_type)'0' && a_strName[0] <= (char_type)'9')) + { + Error(ecINVALID_NAME); + } +} + +//--------------------------------------------------------------------------- +/** \brief Set the mathematical expression. + \param a_sExpr String with the expression + \throw ParserException in case of syntax errors. + + Triggers first time calculation thus the creation of the bytecode and + scanning of used variables. + */ +void ParserXBase::SetExpr(const string_type& a_sExpr) +{ + m_pTokenReader->SetExpr(a_sExpr); + ReInit(); +} + +//--------------------------------------------------------------------------- +/** \brief Add a user defined variable. + \param a_sName The variable name + \param a_Var The variable to be added to muParserX + */ +void ParserXBase::DefineVar(const string_type& ident, const Variable& var) +{ + CheckName(ident, ValidNameChars()); + + CheckForEntityExistence(ident, ecVARIABLE_DEFINED); + + m_varDef[ident] = ptr_tok_type(var.Clone()); +} + +void ParserXBase::CheckForEntityExistence(const string_type& ident, EErrorCodes error_code) +{ + if (IsVarDefined(ident) || + IsConstDefined(ident) || + IsFunDefined(ident) || + IsOprtDefined(ident) || + IsPostfixOprtDefined(ident) || + IsInfixOprtDefined(ident)) + throw ParserError(ErrorContext(error_code, 0, ident)); +} + +//--------------------------------------------------------------------------- +/** \brief Define a parser Constant. + \param a_sName The name of the constant + \param a_Val Const reference to the constants value + + Parser constants are handed over by const reference as opposed to variables + which are handed over by reference. Consequently the parser can not change + their value. + */ +void ParserXBase::DefineConst(const string_type& ident, const Value& val) +{ + CheckName(ident, ValidNameChars()); + + CheckForEntityExistence(ident, ecCONSTANT_DEFINED); + + m_valDef[ident] = ptr_tok_type(val.Clone()); +} + +//--------------------------------------------------------------------------- +/** \brief Add a callback object to the parser. + \param a_pFunc Pointer to the intance of a parser callback object + representing the function. + \sa GetFunDef, functions + + The parser takes ownership over the callback object. + */ +void ParserXBase::DefineFun(const ptr_cal_type& fun) +{ + if (IsFunDefined(fun->GetIdent())) + throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, fun->GetIdent())); + + fun->SetParent(this); + m_FunDef[fun->GetIdent()] = ptr_tok_type(fun->Clone()); +} + +//--------------------------------------------------------------------------- +/** \brief Define a binary operator. + \param a_pCallback Pointer to the callback object + */ +void ParserXBase::DefineOprt(const TokenPtr& oprt) +{ + if (IsOprtDefined(oprt->GetIdent())) + throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); + + oprt->SetParent(this); + m_OprtDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); +} + +//--------------------------------------------------------------------------- +/** \brief Add a user defined operator. + \post Will reset the Parser to string parsing mode. + \param a_pOprt Pointer to a unary postfix operator object. The parser will + become the new owner of this object hence will destroy it. + */ +void ParserXBase::DefinePostfixOprt(const TokenPtr& oprt) +{ + if (IsPostfixOprtDefined(oprt->GetIdent())) + throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); + + // Operator is not added yet, add it. + oprt->SetParent(this); + m_PostOprtDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); +} + +//--------------------------------------------------------------------------- +/** \brief Add a user defined operator. + \param a_pOprt Pointer to a unary postfix operator object. The parser will + become the new owner of this object hence will destroy it. +*/ +void ParserXBase::DefineInfixOprt(const TokenPtr& oprt) +{ + if (IsInfixOprtDefined(oprt->GetIdent())) + throw ParserError(ErrorContext(ecFUNOPRT_DEFINED, 0, oprt->GetIdent())); + + // Function is not added yet, add it. + oprt->SetParent(this); + m_InfixOprtDef[oprt->GetIdent()] = ptr_tok_type(oprt->Clone()); +} + +//--------------------------------------------------------------------------- +void ParserXBase::RemoveVar(const string_type& ident) +{ + m_varDef.erase(ident); + ReInit(); +} + +//--------------------------------------------------------------------------- +void ParserXBase::RemoveConst(const string_type& ident) +{ + m_valDef.erase(ident); + ReInit(); +} + +//--------------------------------------------------------------------------- +void ParserXBase::RemoveFun(const string_type& ident) +{ + m_FunDef.erase(ident); + ReInit(); +} + +//--------------------------------------------------------------------------- +void ParserXBase::RemoveOprt(const string_type& ident) +{ + m_OprtDef.erase(ident); + ReInit(); +} + +//--------------------------------------------------------------------------- +void ParserXBase::RemovePostfixOprt(const string_type& ident) +{ + m_PostOprtDef.erase(ident); + ReInit(); +} + +//--------------------------------------------------------------------------- +void ParserXBase::RemoveInfixOprt(const string_type& ident) +{ + m_InfixOprtDef.erase(ident); + ReInit(); +} + +//--------------------------------------------------------------------------- +bool ParserXBase::IsVarDefined(const string_type& ident) const +{ + return m_varDef.find(ident) != m_varDef.end(); +} + +//--------------------------------------------------------------------------- +bool ParserXBase::IsConstDefined(const string_type& ident) const +{ + return m_valDef.find(ident) != m_valDef.end(); +} + +//--------------------------------------------------------------------------- +bool ParserXBase::IsFunDefined(const string_type& ident) const +{ + return m_FunDef.find(ident) != m_FunDef.end(); +} + +//--------------------------------------------------------------------------- +bool ParserXBase::IsOprtDefined(const string_type& ident) const +{ + return m_OprtDef.find(ident) != m_OprtDef.end(); +} + +//--------------------------------------------------------------------------- +bool ParserXBase::IsPostfixOprtDefined(const string_type& ident) const +{ + return m_PostOprtDef.find(ident) != m_PostOprtDef.end(); +} + +//--------------------------------------------------------------------------- +bool ParserXBase::IsInfixOprtDefined(const string_type& ident) const +{ + return m_InfixOprtDef.find(ident) != m_InfixOprtDef.end(); +} + +//--------------------------------------------------------------------------- +/** \brief Return a map containing the used variables only. */ +const var_maptype& ParserXBase::GetExprVar() const +{ + utils::scoped_setter guard(m_bIsQueryingExprVar, true); + + // Create RPN, but do not compute the result or switch to RPN + // parsing mode. The expression may contain yet to be defined variables. + CreateRPN(); + return m_pTokenReader->GetUsedVar(); +} + +//--------------------------------------------------------------------------- +/** \brief Return a map containing the used variables only. */ +const var_maptype& ParserXBase::GetVar() const +{ + return m_varDef; +} + +//--------------------------------------------------------------------------- +/** \brief Return a map containing all parser constants. */ +const val_maptype& ParserXBase::GetConst() const +{ + return m_valDef; +} + +//--------------------------------------------------------------------------- +/** \brief Return prototypes of all parser functions. + \return #m_FunDef + \sa FunProt, functions + \throw nothrow + + The return type is a map of the public type #funmap_type containing the prototype + definitions for all numerical parser functions. String functions are not part of + this map. The Prototype definition is encapsulated in objects of the class FunProt + one per parser function each associated with function names via a map construct. + */ +const fun_maptype& ParserXBase::GetFunDef() const +{ + return m_FunDef; +} + +//--------------------------------------------------------------------------- +/** \brief Retrieve the mathematical expression. */ +const string_type& ParserXBase::GetExpr() const +{ + return m_pTokenReader->GetExpr(); +} + +//--------------------------------------------------------------------------- +/** \brief Get the version number of muParserX. + \return A string containing the version number of muParserX. + */ +string_type ParserXBase::GetVersion() +{ + return MUP_PARSER_VERSION; +} + +//--------------------------------------------------------------------------- +void ParserXBase::ApplyRemainingOprt(Stack& stOpt) const + +{ + while (stOpt.size() && + stOpt.top()->GetCode() != cmBO && + stOpt.top()->GetCode() != cmIO && + stOpt.top()->GetCode() != cmCBO && + stOpt.top()->GetCode() != cmIF) + { + ptr_tok_type& op = stOpt.top(); + switch (op->GetCode()) + { + case cmOPRT_INFIX: + case cmOPRT_BIN: ApplyFunc(stOpt, 2); break; + case cmELSE: ApplyIfElse(stOpt); break; + default: Error(ecINTERNAL_ERROR); + } // switch operator token type + } // While operator stack not empty +} + +//--------------------------------------------------------------------------- +/** \brief Simulates the call of a parser function with its corresponding arguments. + \param a_stOpt The operator stack + \param a_stVal The value stack + \param a_iArgCount The number of function arguments + */ +void ParserXBase::ApplyFunc(Stack& a_stOpt, + int a_iArgCount) const +{ + if (a_stOpt.empty()) + return; + + ptr_tok_type tok = a_stOpt.pop(); + ICallback* pFun = tok->AsICallback(); + + int iArgCount = (pFun->GetArgc() >= 0) ? pFun->GetArgc() : a_iArgCount; + pFun->SetNumArgsPresent(iArgCount); + + m_nPos -= (iArgCount - 1); + m_rpn.Add(tok); +} + +//--------------------------------------------------------------------------- +/** \brief Simulates the effect of the execution of an if-then-else block. +*/ +void ParserXBase::ApplyIfElse(Stack& a_stOpt) const +{ + while (a_stOpt.size() && a_stOpt.top()->GetCode() == cmELSE) + { + MUP_VERIFY(a_stOpt.size() > 0); + MUP_VERIFY(m_nPos >= 3); + MUP_VERIFY(a_stOpt.top()->GetCode() == cmELSE); + + ptr_tok_type opElse = a_stOpt.pop(); + ptr_tok_type opIf = a_stOpt.pop(); + MUP_VERIFY(opElse->GetCode() == cmELSE) + + if (opIf->GetCode() != cmIF) + { + ErrorContext err; + err.Expr = m_pTokenReader->GetExpr(); + err.Errc = ecMISPLACED_COLON; + err.Pos = m_pTokenReader->GetPos(); + throw ParserError(err); + } + + // If then else hat 3 argumente und erzeugt einen rückgabewert (3-1=2) + m_nPos -= 2; + m_rpn.Add(ptr_tok_type(new TokenIfThenElse(cmENDIF))); + } +} + +//--------------------------------------------------------------------------- +void ParserXBase::DumpRPN() const +{ + m_rpn.AsciiDump(); +} + +//--------------------------------------------------------------------------- +void ParserXBase::CreateRPN() const +{ + if (!m_pTokenReader->GetExpr().length()) + Error(ecUNEXPECTED_EOF, 0); + + // The Stacks take the ownership over the tokens + Stack stOpt; + Stack stArgCount; + Stack stIdxCount; + ptr_tok_type pTok, pTokPrev; + Value val; + + ReInit(); + + for (;;) + { + pTokPrev = pTok; + pTok = m_pTokenReader->ReadNextToken(); + +#if defined(MUP_DUMP_TOKENS) + console() << pTok->AsciiDump() << endl; +#endif + + ECmdCode eCmd = pTok->GetCode(); + switch (eCmd) + { + case cmVAL: + m_nPos++; + m_rpn.Add(pTok); + break; + + case cmCBC: + case cmIC: + { + ECmdCode eStarter = (ECmdCode)(eCmd - 1); + MUP_VERIFY(eStarter == cmCBO || eStarter == cmIO); + + // The argument count for parameterless functions is zero + // by default an opening bracket sets parameter count to 1 + // in preparation of arguments to come. If the last token + // was an opening bracket we know better... + if (pTokPrev.Get() != nullptr && pTokPrev->GetCode() == eStarter) + --stArgCount.top(); + + ApplyRemainingOprt(stOpt); + + // if opt is "]" and opta is "[" the bracket content has been evaluated. + // Now check whether there is an index operator on the stack. + if (stOpt.size() && stOpt.top()->GetCode() == eStarter) + { + // + // Find out how many dimensions were used in the index operator. + // + int iArgc = stArgCount.pop(); + stOpt.pop(); // Take opening bracket from stack + + ICallback* pOprtIndex = pTok->AsICallback(); + MUP_VERIFY(pOprtIndex != nullptr); + + pOprtIndex->SetNumArgsPresent(iArgc); + m_rpn.Add(pOprtIndex); + + // If this is an index operator there must be something else in the register (the variable to index) + MUP_VERIFY(eCmd != cmIC || m_nPos >= (int)iArgc + 1); + + // Reduce the index into the value registers accordingly + m_nPos -= iArgc; + + if (eCmd == cmCBC) + { + ++m_nPos; + } + } // if opening index bracket is on top of operator stack + } + break; + + case cmBC: + { + // The argument count for parameterless functions is zero + // by default an opening bracket sets parameter count to 1 + // in preparation of arguments to come. If the last token + // was an opening bracket we know better... + if (pTokPrev.Get() != nullptr && pTokPrev->GetCode() == cmBO) + --stArgCount.top(); + + ApplyRemainingOprt(stOpt); + + // if opt is ")" and opta is "(" the bracket content has been evaluated. + // Now its time to check if there is either a function or a sign pending. + // - Neither the opening nor the closing bracket will be pushed back to + // the operator stack + // - Check if a function is standing in front of the opening bracket, + // if so evaluate it afterwards to apply an infix operator. + if (stOpt.size() && stOpt.top()->GetCode() == cmBO) + { + // + // Here is the stuff to evaluate a function token + // + int iArgc = stArgCount.pop(); + + stOpt.pop(); // Take opening bracket from stack + if (stOpt.empty()) + break; + + if ((stOpt.top()->GetCode() != cmFUNC) && (stOpt.top()->GetCode() != cmOPRT_INFIX)) + break; + + ICallback* pFun = stOpt.top()->AsICallback(); + + if (pFun->GetArgc() != -1 && iArgc > pFun->GetArgc()) + Error(ecTOO_MANY_PARAMS, pTok->GetExprPos(), pFun); + + if (iArgc < pFun->GetArgc()) + Error(ecTOO_FEW_PARAMS, pTok->GetExprPos(), pFun); + + // Apply function, if present + if (stOpt.size() && + stOpt.top()->GetCode() != cmOPRT_INFIX && + stOpt.top()->GetCode() != cmOPRT_BIN) + { + ApplyFunc(stOpt, iArgc); + } + } + } + break; + + case cmELSE: + ApplyRemainingOprt(stOpt); + m_rpn.Add(pTok); + stOpt.push(pTok); + break; + + case cmSCRIPT_NEWLINE: + ApplyRemainingOprt(stOpt); + m_rpn.AddNewline(pTok, m_nPos); + stOpt.clear(); + m_nPos = 0; + break; + + case cmARG_SEP: + if (stArgCount.empty()) + Error(ecUNEXPECTED_COMMA, m_pTokenReader->GetPos() - 1); + + ++stArgCount.top(); + + ApplyRemainingOprt(stOpt); + break; + + case cmEOE: + ApplyRemainingOprt(stOpt); + m_rpn.Finalize(); + break; + + case cmIF: + case cmOPRT_BIN: + { + while (stOpt.size() && + stOpt.top()->GetCode() != cmBO && + stOpt.top()->GetCode() != cmIO && + stOpt.top()->GetCode() != cmCBO && + stOpt.top()->GetCode() != cmELSE && + stOpt.top()->GetCode() != cmIF) + { + IToken* pOprt1 = stOpt.top().Get(); + IToken* pOprt2 = pTok.Get(); + MUP_VERIFY(pOprt1 != nullptr && pOprt2 != nullptr); + MUP_VERIFY(pOprt1->AsIPrecedence() && pOprt2->AsIPrecedence()); + + int nPrec1 = pOprt1->AsIPrecedence()->GetPri(), + nPrec2 = pOprt2->AsIPrecedence()->GetPri(); + + if (pOprt1->GetCode() == pOprt2->GetCode()) + { + // Deal with operator associativity + EOprtAsct eOprtAsct = pOprt1->AsIPrecedence()->GetAssociativity(); + if ((eOprtAsct == oaRIGHT && (nPrec1 <= nPrec2)) || + (eOprtAsct == oaLEFT && (nPrec1 < nPrec2))) + { + break; + } + } + else if (nPrec1 < nPrec2) + { + break; + } + + // apply the operator now + // (binary operators are identic to functions with two arguments) + ApplyFunc(stOpt, 2); + } // while ( ... ) + + if (pTok->GetCode() == cmIF) + m_rpn.Add(pTok); + + stOpt.push(pTok); + } + break; + + // + // Postfix Operators + // + case cmOPRT_POSTFIX: + MUP_VERIFY(m_nPos); + m_rpn.Add(pTok); + break; + + case cmCBO: + case cmIO: + case cmBO: + stOpt.push(pTok); + stArgCount.push(1); + break; + + // + // Functions + // + case cmOPRT_INFIX: + case cmFUNC: + { + ICallback* pFunc = pTok->AsICallback(); + MUP_VERIFY(pFunc != nullptr); + stOpt.push(pTok); + } + break; + + default: + Error(ecINTERNAL_ERROR); + } // switch Code + + if (ParserXBase::s_bDumpStack) + { + StackDump(stOpt); + } + + if (pTok->GetCode() == cmEOE) + break; + } // for (all tokens) + + if (ParserXBase::s_bDumpRPN) + { + m_rpn.AsciiDump(); + } + + if (m_nPos > 1) + { + Error(ecUNEXPECTED_COMMA, -1); + } +} + +//--------------------------------------------------------------------------- +/** \brief One of the two main parse functions. + \sa ParseCmdCode(), ParseValue() + + Parse expression from input string. Perform syntax checking and create bytecode. + After parsing the string and creating the bytecode the function pointer + #m_pParseFormula will be changed to the second parse routine the uses bytecode instead of string parsing. + */ +const IValue& ParserXBase::ParseFromString() const +{ + CreateRPN(); + + // Umsachalten auf RPN + m_vStackBuffer.assign(m_rpn.GetRequiredStackSize(), ptr_val_type()); + for (std::size_t i = 0; i < m_vStackBuffer.size(); ++i) + { + Value* pValue = new Value; + pValue->BindToCache(&m_cache); + m_vStackBuffer[i].Reset(pValue); + } + + m_pParserEngine = &ParserXBase::ParseFromRPN; + + return (this->*m_pParserEngine)(); +} + +//--------------------------------------------------------------------------- +const IValue& ParserXBase::ParseFromRPN() const +{ + ptr_val_type* pStack = &m_vStackBuffer[0]; + if (m_rpn.GetSize() == 0) + { + // Passiert bei leeren strings oder solchen, die nur Leerzeichen enthalten + ErrorContext err; + err.Expr = m_pTokenReader->GetExpr(); + err.Errc = ecUNEXPECTED_EOF; + err.Pos = 0; + throw ParserError(err); + } + + const ptr_tok_type* pRPN = &(m_rpn.GetData()[0]); + + int sidx = -1; + std::size_t lenRPN = m_rpn.GetSize(); + for (std::size_t i = 0; i < lenRPN; ++i) + { + IToken* pTok = pRPN[i].Get(); + ECmdCode eCode = pTok->GetCode(); + + switch (eCode) + { + case cmSCRIPT_NEWLINE: + sidx = -1; + continue; + + case cmVAL: + { + IValue* pVal = static_cast(pTok); + + sidx++; + MUP_VERIFY(sidx < (int)m_vStackBuffer.size()); + if (pVal->IsVariable()) + { + pStack[sidx].Reset(pVal); + } + else + { + ptr_val_type& val = pStack[sidx]; + if (val->IsVariable()) + val.Reset(m_cache.CreateFromCache()); + + *val = *(static_cast(pTok)); + } + } + continue; + + case cmIC: + { + ICallback* pIdxOprt = static_cast(pTok); + int nArgs = pIdxOprt->GetArgsPresent(); + sidx -= nArgs - 1; + MUP_VERIFY(sidx >= 0); + + ptr_val_type& idx = pStack[sidx]; // Pointer to the first index + ptr_val_type& val = pStack[--sidx]; // Pointer to the variable or value beeing indexed + pIdxOprt->Eval(val, &idx, nArgs); + } + continue; + + case cmCBC: + case cmOPRT_POSTFIX: + case cmFUNC: + case cmOPRT_BIN: + case cmOPRT_INFIX: + { + ICallback* pFun = static_cast(pTok); + int nArgs = pFun->GetArgsPresent(); + sidx -= nArgs - 1; + + // most likely cause: Comma in if-then-else sum(false?1,0,0:3) + if (sidx < 0) + { + ErrorContext err; + err.Expr = m_pTokenReader->GetExpr(); + err.Errc = ecUNEXPECTED_COMMA; + err.Pos = m_pTokenReader->GetPos(); + throw ParserError(err); + } + + ptr_val_type& val = pStack[sidx]; + try + { + if (val->IsVariable()) + { + ptr_val_type buf(m_cache.CreateFromCache()); + pFun->Eval(buf, &val, nArgs); + val = buf; + } + else + { + pFun->Eval(val, &val, nArgs); + } + } + catch (ParserError& exc) + { + // Not too happy about that: + // Multiarg functions may throw specific error codes when evaluating. + // These codes would be converted to ecEVAL here. I omit the conversion + // for certain handpicked errors. (The reason this catch block exists is + // that not all exceptions contain proper metadata when thrown out of + // a function.) + if (exc.GetCode() == ecTOO_FEW_PARAMS || + exc.GetCode() == ecDOMAIN_ERROR || + exc.GetCode() == ecOVERFLOW || + exc.GetCode() == ecINVALID_NUMBER_OF_PARAMETERS || + exc.GetCode() == ecASSIGNEMENT_TO_VALUE) + { + exc.GetContext().Pos = pFun->GetExprPos(); + throw; + } + // + else + { + ErrorContext err; + err.Expr = m_pTokenReader->GetExpr(); + err.Ident = pFun->GetIdent(); + err.Errc = ecEVAL; + err.Pos = pFun->GetExprPos(); + err.Hint = exc.GetMsg(); + throw ParserError(err); + } + } + catch (MatrixError& /*exc*/) + { + ErrorContext err; + err.Expr = m_pTokenReader->GetExpr(); + err.Ident = pFun->GetIdent(); + err.Errc = ecMATRIX_DIMENSION_MISMATCH; + err.Pos = pFun->GetExprPos(); + throw ParserError(err); + } + } + continue; + + case cmIF: + MUP_VERIFY(sidx >= 0); + if (pStack[sidx--]->GetBool() == false) + i += static_cast(pTok)->GetOffset(); + continue; + + case cmELSE: + case cmJMP: + i += static_cast(pTok)->GetOffset(); + continue; + + case cmENDIF: + continue; + + default: + Error(ecINTERNAL_ERROR); + } // switch token + } // for all RPN tokens + + return *pStack[0]; +} + +//--------------------------------------------------------------------------- +void ParserXBase::Error(EErrorCodes a_iErrc, int a_iPos, const IToken* a_pTok) const +{ + ErrorContext err; + err.Errc = a_iErrc; + err.Pos = a_iPos; + err.Expr = m_pTokenReader->GetExpr(); + err.Ident = (a_pTok) ? a_pTok->GetIdent() : _T(""); + throw ParserError(err); +} + +//------------------------------------------------------------------------------ +/** \brief Clear all user defined variables. + \throw nothrow + + Resets the parser to string parsing mode by calling #ReInit. + */ +void ParserXBase::ClearVar() +{ + m_varDef.clear(); + m_valDynVarShadow.clear(); + ReInit(); +} + +//------------------------------------------------------------------------------ +/** \brief Clear the expression. + \throw nothrow + + Clear the expression and existing bytecode. + */ +void ParserXBase::ClearExpr() +{ + m_pTokenReader->SetExpr(_T("")); + ReInit(); +} + +//------------------------------------------------------------------------------ +/** \brief Clear all function definitions. + \throw nothrow + */ +void ParserXBase::ClearFun() +{ + m_FunDef.clear(); + ReInit(); +} + +//------------------------------------------------------------------------------ +/** \brief Clear all user defined constants. + \throw nothrow + + Both numeric and string constants will be removed from the internal storage. + */ +void ParserXBase::ClearConst() +{ + m_valDef.clear(); + ReInit(); +} + +//------------------------------------------------------------------------------ +/** \brief Clear all user defined postfix operators. + \throw nothrow + */ +void ParserXBase::ClearPostfixOprt() +{ + m_PostOprtDef.clear(); + ReInit(); +} + +//------------------------------------------------------------------------------ +/** \brief Clear all user defined binary operators. + \throw nothrow + */ +void ParserXBase::ClearOprt() +{ + m_OprtDef.clear(); + ReInit(); +} + +//------------------------------------------------------------------------------ +/** \brief Clear the user defined Prefix operators. + \throw nothrow + */ +void ParserXBase::ClearInfixOprt() +{ + m_InfixOprtDef.clear(); + ReInit(); +} + +//------------------------------------------------------------------------------ +void ParserXBase::EnableAutoCreateVar(bool bStat) +{ + m_bAutoCreateVar = bStat; +} + +//------------------------------------------------------------------------------ +void ParserXBase::EnableOptimizer(bool bStat) +{ + m_rpn.EnableOptimizer(bStat); +} + +//--------------------------------------------------------------------------- +/** \brief Enable the dumping of bytecode amd stack content on the console. + \param bDumpCmd Flag to enable dumping of the current bytecode to the console. + \param bDumpStack Flag to enable dumping of the stack content is written to the console. + + This function is for debug purposes only! + */ +void ParserXBase::EnableDebugDump(bool bDumpRPN, bool bDumpStack) +{ + ParserXBase::s_bDumpRPN = bDumpRPN; + ParserXBase::s_bDumpStack = bDumpStack; +} + +//------------------------------------------------------------------------------ +bool ParserXBase::IsAutoCreateVarEnabled() const +{ + return m_bAutoCreateVar; +} + +//------------------------------------------------------------------------------ +/** \brief Dump stack content. + + This function is used for debugging only. + */ +void ParserXBase::StackDump(const Stack& a_stOprt) const +{ + using std::cout; + Stack stOprt(a_stOprt); + + string_type sInfo = _T("StackDump> "); + console() << sInfo; + + if (stOprt.empty()) + console() << _T("\n") << sInfo << _T("Operator stack is empty.\n"); + else + console() << _T("\n") << sInfo << _T("Operator stack:\n"); + + while (!stOprt.empty()) + { + ptr_tok_type tok = stOprt.pop(); + console() << sInfo << _T(" ") << g_sCmdCode[tok->GetCode()] << _T(" \"") << tok->GetIdent() << _T("\" \n"); + } + + console() << endl; +} +} // namespace mu diff --git a/Software/PC_Application/Traces/Math/parser/mpParserBase.h b/Software/PC_Application/Traces/Math/parser/mpParserBase.h new file mode 100644 index 0000000..d5f6a5c --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpParserBase.h @@ -0,0 +1,225 @@ +#ifndef MUP_PARSERBASE_H +#define MUP_PARSERBASE_H + +/** \file + \brief Definition of the muParserX engine. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 +#include +#include +#include +#include + +#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 &oprt); + void DefinePostfixOprt(const TokenPtr &oprt); + void DefineInfixOprt(const TokenPtr &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 &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 &a_stOpt, int a_iArgCount) const; + void ApplyIfElse(Stack &a_stOpt) const; + void ApplyRemainingOprt(Stack &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 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 + diff --git a/Software/PC_Application/Traces/Math/parser/mpParserMessageProvider.cpp b/Software/PC_Application/Traces/Math/parser/mpParserMessageProvider.cpp new file mode 100644 index 0000000..dbd4427 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpParserMessageProvider.cpp @@ -0,0 +1,181 @@ +#include "mpParserMessageProvider.h" +#include +#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 +#include + +#include "mpDefines.h" +#include "mpTypes.h" + + +MUP_NAMESPACE_START + + //----------------------------------------------------------------------------------------------- + /** \brief Base class for Parser Message providing classes. */ + class ParserMessageProviderBase + { + friend class std::unique_ptr; + + 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 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpRPN.cpp b/Software/PC_Application/Traces/Math/parser/mpRPN.cpp new file mode 100644 index 0000000..1a0031b --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpRPN.cpp @@ -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 +#include + +#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(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 stIf, stElse; + int idx; + for (int i = 0; i < static_cast(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(m_vRPN[idx].Get())->SetOffset(i - idx); + break; + + case cmENDIF: + idx = stElse.pop(); + static_cast(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 diff --git a/Software/PC_Application/Traces/Math/parser/mpRPN.h b/Software/PC_Application/Traces/Math/parser/mpRPN.h new file mode 100644 index 0000000..cde8dc5 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpRPN.h @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpScriptTokens.cpp b/Software/PC_Application/Traces/Math/parser/mpScriptTokens.cpp new file mode 100644 index 0000000..d044032 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpScriptTokens.cpp @@ -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 diff --git a/Software/PC_Application/Traces/Math/parser/mpScriptTokens.h b/Software/PC_Application/Traces/Math/parser/mpScriptTokens.h new file mode 100644 index 0000000..40f4663 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpScriptTokens.h @@ -0,0 +1,68 @@ +#ifndef MUP_SCRIPT_TOKENS_H +#define MUP_SCRIPT_TOKENS_H + +/** \file + \brief Definition of basic types used by muParserX + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "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 diff --git a/Software/PC_Application/Traces/Math/parser/mpStack.h b/Software/PC_Application/Traces/Math/parser/mpStack.h new file mode 100644 index 0000000..1a765fc --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpStack.h @@ -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 +#include +#include + +#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 > + 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 + __________ ____ ___ + _____ __ _\______ \_____ _______ ______ __________\ \/ / + / \| | \ ___/\__ \\_ __ \/ ___// __ \_ __ \ / + | 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 "mpTest.h" +#include "mpValue.h" + +#include +#include +#include +#include +#include +#include + +#define MUP_CONST_PI 3.141592653589793238462643 +#define MUP_CONST_E 2.718281828459045235360287 + +using namespace std; + +MUP_NAMESPACE_START + +//----------------------------------------------------------------------------------------------- +// +// class OprtStrAdd +// +//----------------------------------------------------------------------------------------------- + +class DbgSillyAdd : public IOprtBin +{ +public: + + DbgSillyAdd() + :IOprtBin(_T("++"), (int)prADD_SUB, oaLEFT) + {} + + //----------------------------------------------------------------------------------------------- + void 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(); + *ret = a + b; + } + + //----------------------------------------------------------------------------------------------- + const char_type* GetDesc() const + { + return _T("internally used operator without special meaning for unit testing"); + } + + //----------------------------------------------------------------------------------------------- + IToken* Clone() const + { + return new DbgSillyAdd(*this); + } +}; + +//------------------------------------------------------------------------------ +class FunTest0 : public ICallback +{ +public: + FunTest0() : ICallback(cmFUNC, _T("test0"), 0) + {} + + virtual void Eval(ptr_val_type &ret, const ptr_val_type * /*a_pArg*/, int /*a_iArgc*/) + { + *ret = 0.0; + } + + virtual const char_type* GetDesc() const + { + return _T(""); + } + + virtual IToken* Clone() const + { + return new FunTest0(*this); + } +}; // class FunTest0 + +//--------------------------------------------------------------------------- +int ParserTester::c_iCount = 0; + +//--------------------------------------------------------------------------- +ParserTester::ParserTester() + :m_vTestFun() + , m_stream(&console()) +{ + AddTest(&ParserTester::TestParserValue); + AddTest(&ParserTester::TestUndefVar); + AddTest(&ParserTester::TestErrorCodes); + AddTest(&ParserTester::TestEqn); + AddTest(&ParserTester::TestIfElse); + AddTest(&ParserTester::TestStringFun); + AddTest(&ParserTester::TestMatrix); + AddTest(&ParserTester::TestComplex); + AddTest(&ParserTester::TestVector); + AddTest(&ParserTester::TestBinOp); + AddTest(&ParserTester::TestPostfix); + AddTest(&ParserTester::TestInfix); + AddTest(&ParserTester::TestMultiArg); + AddTest(&ParserTester::TestScript); + AddTest(&ParserTester::TestValReader); + AddTest(&ParserTester::TestIssueReports); + + ParserTester::c_iCount = 0; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestIssueReports() +{ + int iNumErr = 0; + *m_stream << _T("testing github issue reports..."); + + // Github: Issue 55 + iNumErr += ThrowTest(_T("{0,{0}}*{0,{0}}*{,{0}}*{0,{0}0,{0}}*{0,{0}}*{,{0}}*{0}*{000}"), ecUNEXPECTED_COMMA); + + // Github: Issue 56 + iNumErr += ThrowTest(_T("0M[,1][0/1M[0M]M]"), ecUNEXPECTED_COMMA); + + // Github Issue 57: + iNumErr += ThrowTest(_T("{?{{{{:44"), ecUNEXPECTED_CONDITIONAL); + + // Github Issue 60 + iNumErr += ThrowTest(_T("0<01?1=:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1<:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1>:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1-:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1+:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1*:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1/:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1&:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1<<:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("0<01?1>>:1"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("{ ? 0 : 7m}-{7, -00007m}-{7M}"), ecUNEXPECTED_CONDITIONAL); + iNumErr += ThrowTest(_T("{ { { ? 2 }, 7:2 }*7m }"), ecUNEXPECTED_CONDITIONAL); + + // Not too happy about the undefined code, but better than a crash of an assertion at runtime + iNumErr += ThrowTest(_T("{0<0?0,0:0<0}"), ecUNEXPECTED_COMMA); + + // Github Issue 63 + iNumErr += ThrowTest(_T("0<0-0--eye()"), ecINVALID_NUMBER_OF_PARAMETERS); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestUndefVar() +{ + int iNumErr = 0; + *m_stream << _T("testing implicit definition of undefined variables..."); + + // Test 1: No variables defined, test detection of undefined variables + { + ParserX p; + p.SetExpr(_T("a+b+c+d")); + const mup::var_maptype &expr_var = p.GetExprVar(); + const mup::var_maptype &var = p.GetVar(); + + // The expression contains 4 undefined variables + if (expr_var.size() != 4) + iNumErr++; + + // There are no variables defined + if (var.size() != 0) + iNumErr++; + } + + // Test 2: Variables were defined explicitely, test detection of variables + { + ParserX p; + + // Now define the variables and perform the check again + Value vVarVal[] = { 1.0, 2.0, 3.0, 4.0 }; + p.DefineVar(_T("a"), Variable(&vVarVal[0])); + p.DefineVar(_T("b"), Variable(&vVarVal[1])); + p.DefineVar(_T("c"), Variable(&vVarVal[2])); + p.DefineVar(_T("d"), Variable(&vVarVal[3])); + + p.SetExpr(_T("a+b+c+d")); + const mup::var_maptype &expr_var = p.GetExprVar(); + const mup::var_maptype &var = p.GetVar(); + + // The expression contains 4 undefined variables + if (expr_var.size() != 4) + iNumErr++; + + // There are no variables defined + if (var.size() != 4) + iNumErr++; + } + + // Test 3: Variables were defined implicitels, test detection of undefined variables + { + ParserX p; + + // Now define the variables and perform the check again + p.EnableAutoCreateVar(true); + + p.SetExpr(_T("a+b+c+d")); + const mup::var_maptype &expr_var = p.GetExprVar(); + const mup::var_maptype &var = p.GetVar(); + + // The expression contains 4 undefined variables + if (expr_var.size() != 4) + iNumErr++; + + // There are no variables defined + if (var.size() != 4) + iNumErr++; + } + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestMatrix() +{ + int iNumErr = 0; + *m_stream << _T("testing matrix calculations..."); + + Value unity(3, 3, 0); + unity.At(0, 0) = 1.0; + unity.At(1, 1) = 1.0; + unity.At(2, 2) = 1.0; + + Value va(3, 0); + va.At(0) = 1.0; + va.At(1) = 2.0; + va.At(2) = 3.0; + + //Value m2(3, 3, 0); + //m2.At(0, 0) = 1; m2.At(0, 1) = 2; m2.At(0, 2) = 3; + //m2.At(1, 0) = 4; m2.At(1, 1) = 5; m2.At(1, 2) = 6; + //m2.At(2, 0) = 7; m2.At(2, 1) = 8; m2.At(2, 2) = 9; + + Value m1_plus_m2(3, 3, 0); + m1_plus_m2.At(0, 0) = 2.0; m1_plus_m2.At(0, 1) = 2.0; m1_plus_m2.At(0, 2) = 3.0; + m1_plus_m2.At(1, 0) = 4.0; m1_plus_m2.At(1, 1) = 6.0; m1_plus_m2.At(1, 2) = 6.0; + m1_plus_m2.At(2, 0) = 7.0; m1_plus_m2.At(2, 1) = 8.0; m1_plus_m2.At(2, 2) = 10.0; + + Value m2_minus_m1(3, 3, 0); + m2_minus_m1.At(0, 0) = 0.0; m2_minus_m1.At(0, 1) = 2.0; m2_minus_m1.At(0, 2) = 3.0; + m2_minus_m1.At(1, 0) = 4.0; m2_minus_m1.At(1, 1) = 4.0; m2_minus_m1.At(1, 2) = 6.0; + m2_minus_m1.At(2, 0) = 7.0; m2_minus_m1.At(2, 1) = 8.0; m2_minus_m1.At(2, 2) = 8.0; + + Value m2_times_10(3, 3, 0); + m2_times_10.At(0, 0) = 10.0; m2_times_10.At(0, 1) = 20.0; m2_times_10.At(0, 2) = 30.0; + m2_times_10.At(1, 0) = 40.0; m2_times_10.At(1, 1) = 50.0; m2_times_10.At(1, 2) = 60.0; + m2_times_10.At(2, 0) = 70.0; m2_times_10.At(2, 1) = 80.0; m2_times_10.At(2, 2) = 90.0; + + Value va_times_vb_transp(3, 3, 0); + va_times_vb_transp.At(0, 0) = 4.0; va_times_vb_transp.At(0, 1) = 3.0; va_times_vb_transp.At(0, 2) = 2.0; + va_times_vb_transp.At(1, 0) = 8.0; va_times_vb_transp.At(1, 1) = 6.0; va_times_vb_transp.At(1, 2) = 4.0; + va_times_vb_transp.At(2, 0) = 12.0; va_times_vb_transp.At(2, 1) = 9.0; va_times_vb_transp.At(2, 2) = 6.0; + + Value size_3x6(1, 2, 0); + size_3x6.At(0, 0) = 3.0; + size_3x6.At(0, 1) = 6.0; + + Value size_3x3(1, 2, 0); + size_3x3.At(0, 0) = 3.0; + size_3x3.At(0, 1) = 3.0; + + Value size_3x1(1, 2, 0); + size_3x1.At(0, 0) = 3.0; + size_3x1.At(0, 1) = 1.0; + + Value size_1x3(1, 2, 0); + size_1x3.At(0, 0) = 1.0; + size_1x3.At(0, 1) = 3.0; + + // Check matrix dimension mismatch error + iNumErr += ThrowTest(_T("\"hallo\"+m1"), ecEVAL); + iNumErr += ThrowTest(_T("m1+\"hallo\""), ecEVAL); + iNumErr += ThrowTest(_T("va+m1"), ecMATRIX_DIMENSION_MISMATCH); + iNumErr += ThrowTest(_T("m1+va"), ecMATRIX_DIMENSION_MISMATCH); + iNumErr += ThrowTest(_T("va-m1"), ecMATRIX_DIMENSION_MISMATCH); + iNumErr += ThrowTest(_T("m1-va"), ecMATRIX_DIMENSION_MISMATCH); + iNumErr += ThrowTest(_T("va*m1"), ecMATRIX_DIMENSION_MISMATCH); + iNumErr += ThrowTest(_T("va+eye(2)"), ecMATRIX_DIMENSION_MISMATCH); + + // Issue 63: + iNumErr += ThrowTest(_T("0-0-eye()"), ecINVALID_NUMBER_OF_PARAMETERS); + + iNumErr += ThrowTest(_T("m1[1]"), ecINDEX_DIMENSION); + iNumErr += ThrowTest(_T("m1[1,2,3]"), ecINDEX_DIMENSION); + iNumErr += ThrowTest(_T("va[1,2]"), ecINDEX_OUT_OF_BOUNDS); // va has 1 column, 3 rows -> the coulumn index is referencing the third column + iNumErr += ThrowTest(_T("a+m1"), ecEVAL); + iNumErr += ThrowTest(_T("m1+a"), ecEVAL); + iNumErr += ThrowTest(_T("a-m1"), ecEVAL); + iNumErr += ThrowTest(_T("m1-a"), ecEVAL); + iNumErr += ThrowTest(_T("va[,1]"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("va[{1]"), ecMISSING_CURLY_BRACKET); + iNumErr += ThrowTest(_T("{,1}"), ecUNEXPECTED_COMMA); + + // sample expressions + iNumErr += EqnTest(_T("m1"), unity, true); + iNumErr += EqnTest(_T("m1*m1"), unity, true); + iNumErr += EqnTest(_T("m1+m2"), m1_plus_m2, true); + iNumErr += EqnTest(_T("m2-m1"), m2_minus_m1, true); + iNumErr += EqnTest(_T("10*m2"), m2_times_10, true); + iNumErr += EqnTest(_T("m2*10"), m2_times_10, true); + iNumErr += EqnTest(_T("5*m2*b"), m2_times_10, true); + iNumErr += EqnTest(_T("b*m2*5"), m2_times_10, true); + iNumErr += EqnTest(_T("m1*va"), va, true); + + // ones + Value ones_3(3, 1.0); + Value ones_3x3(3, 3, 1.0); + iNumErr += ThrowTest(_T("ones(1,2,3)"), ecINVALID_NUMBER_OF_PARAMETERS); + iNumErr += ThrowTest(_T("ones()"), ecINVALID_NUMBER_OF_PARAMETERS); + iNumErr += EqnTest(_T("ones(1,1)"), 1.0, true); + iNumErr += EqnTest(_T("ones(1)"), 1.0, true); + iNumErr += EqnTest(_T("ones(3,3)"), ones_3x3, true); + iNumErr += EqnTest(_T("ones(3,1)"), ones_3, true); + iNumErr += EqnTest(_T("ones(3)"), ones_3, true); + + iNumErr += EqnTest(_T("size(ones(3,3))"), size_3x3, true); // check return value dimension + iNumErr += EqnTest(_T("size(ones(1,3))"), size_1x3, true); // check return value dimension + iNumErr += EqnTest(_T("size(ones(3,1))"), size_3x1, true); // check return value dimension + iNumErr += EqnTest(_T("size(ones(3))"), size_3x3, true); // check return value dimension + + // zeros + iNumErr += ThrowTest(_T("zeros()"), ecINVALID_NUMBER_OF_PARAMETERS); + iNumErr += EqnTest(_T("size(zeros(3,3))"), size_3x3, true); // check return value dimension + iNumErr += EqnTest(_T("size(zeros(1,3))"), size_1x3, true); // check return value dimension + iNumErr += EqnTest(_T("size(zeros(3,1))"), size_3x1, true); // check return value dimension + iNumErr += EqnTest(_T("size(zeros(3))"), size_3x3, true); // check return value dimension + + // eye + iNumErr += ThrowTest(_T("eye()"), ecINVALID_NUMBER_OF_PARAMETERS); + iNumErr += EqnTest(_T("size(eye(3,3))"), size_3x3, true); // check return value dimension + iNumErr += EqnTest(_T("size(eye(1,3))"), size_1x3, true); // check return value dimension + iNumErr += EqnTest(_T("size(eye(3,1))"), size_3x1, true); // check return value dimension + iNumErr += EqnTest(_T("size(eye(3))"), size_3x3, true); // check return value dimension + + iNumErr += EqnTest(_T("size(eye(3,6))"), size_3x6, true); // check return value dimension + + // transposition + iNumErr += EqnTest(_T("va'*vb"), 16.0, true); + iNumErr += EqnTest(_T("2*va'*vb"), 32.0, true); + iNumErr += EqnTest(_T("va*vb'"), va_times_vb_transp, true); + + // index operator + // erster index: Zeilenindex, zweiter index: Spaltenindex + iNumErr += EqnTest(_T("va[0]"), 1.0, true); + iNumErr += EqnTest(_T("va[1]"), 2.0, true); + iNumErr += EqnTest(_T("va[2]"), 3.0, true); + // Use two dimensional index operator on a vector + iNumErr += EqnTest(_T("va[0,0]"), 1.0, true); + iNumErr += EqnTest(_T("va[1,0]"), 2.0, true); + iNumErr += EqnTest(_T("va[2,0]"), 3.0, true); + + // Now test the same with a transposed vector: + iNumErr += EqnTest(_T("va'[0]"), 1.0, true); + iNumErr += EqnTest(_T("va'[1]"), 2.0, true); + iNumErr += EqnTest(_T("va'[2]"), 3.0, true); + // Use two dimensional index operator on a vector + iNumErr += EqnTest(_T("va'[0,0]"), 1.0, true); + iNumErr += EqnTest(_T("va'[0,1]"), 2.0, true); + iNumErr += EqnTest(_T("va'[0,2]"), 3.0, true); + iNumErr += EqnTest(_T("(va')[0,2]"), 3.0, true); // <- Index operator after closing bracket is ok + + // vector creation + iNumErr += EqnTest(_T("{1,2,3}'"), va, true); + iNumErr += EqnTest(_T("{a,2,3}'"), va, true); // that was an actual bug: variable a was overwritten + + // assignment to element: + iNumErr += ThrowTest(_T("va'[0]=123"), ecASSIGNEMENT_TO_VALUE); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestComplex() +{ + int iNumErr = 0; + *m_stream << _T("testing complex calculations..."); + + // complex numbers + // ca=1+i, cb=2+3i, cc=3+4i + iNumErr += EqnTest(_T("ca==1+i"), true, true); + iNumErr += EqnTest(_T("ca==ca"), true, true); + iNumErr += EqnTest(_T("ca!=1+i"), false, true); + iNumErr += EqnTest(_T("ca!=ca"), false, true); + iNumErr += EqnTest(_T("ca!=cb"), true, true); + iNumErr += EqnTest(_T("ca!=va"), true, true); + iNumErr += EqnTest(_T("ca==va"), false, true); + + // When comparing complex number Matlab/Octave compare only the real part + // I'll do the same... + iNumErr += EqnTest(_T("ca<10+i"), true, true); + iNumErr += EqnTest(_T("ca>10+i"), false, true); + iNumErr += EqnTest(_T("ca<=10+i"), true, true); + iNumErr += EqnTest(_T("ca>=10+i"), false, true); + iNumErr += EqnTest(_T("ca<=1"), true, true); + iNumErr += EqnTest(_T("ca>=1"), true, true); + + // complex numbers + iNumErr += EqnTest(_T("i*i"), -1.0, true, 0); + iNumErr += EqnTest(_T("1i"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("norm(3+4i)"), 25.0, true, 0); + iNumErr += EqnTest(_T("norm(4i+3)"), 25.0, true, 0); + iNumErr += EqnTest(_T("norm(3i+4)"), 25.0, true, 0); + iNumErr += EqnTest(_T("real(4.1i+3.1)"), (float_type)3.1, true, 0); + iNumErr += EqnTest(_T("imag(3.1i+4.1)"), (float_type)3.1, true, 0); + iNumErr += EqnTest(_T("real(3.1)"), (float_type)3.1, true, 0); + iNumErr += EqnTest(_T("imag(2.1i)"), (float_type)2.1, true, 0); + iNumErr += EqnTest(_T("-(4i+5)"), cmplx_type(-5, -4), true, 0); + iNumErr += EqnTest(_T("sqrt(-1)"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("(-1)^0.5"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("(-3)^(4/3)"), std::pow(cmplx_type(-3, 0), + cmplx_type(4.0 / 3, 0)), true, 0); + + // Issue 41: Complex pow of small numbers zeros out the imaginary part + // https://code.google.com/p/muparserx/issues/detail?id=41 + iNumErr += EqnTest(_T("(1e-15 + 1e-15*i) ^ 2"), std::pow(cmplx_type(1e-15, 1e-15), 2), true, 0); + + iNumErr += EqnTest(_T("sqrt(i*i)"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("sqrt(f)"), cmplx_type(0, 1), true, 1); + iNumErr += EqnTest(_T("sqrt(2-3)"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("sqrt(a-b)"), cmplx_type(0, 1), true, 2); + iNumErr += EqnTest(_T("sqrt((2-3))"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("sqrt((a-b))"), cmplx_type(0, 1), true, 2); + iNumErr += EqnTest(_T("sqrt(-(1))"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("sqrt((-1))"), cmplx_type(0, 1), true, 0); + iNumErr += EqnTest(_T("sqrt(-(-1))"), cmplx_type(1, 0), true, 0); + iNumErr += EqnTest(_T("sqrt(1)"), cmplx_type(1, 0), true, 0); + iNumErr += EqnTest(_T("a=1+2i"), cmplx_type(1, 2), true, 1); + iNumErr += EqnTest(_T("-(1+2i)"), cmplx_type(-1, -2), true, 0); + iNumErr += EqnTest(_T("-(-1-2i)"), cmplx_type(1, 2), true, 0); + iNumErr += EqnTest(_T("a*i"), cmplx_type(0, 1), true, 1); + iNumErr += EqnTest(_T("-(a+b*i)"), cmplx_type(-1, -2), true, 2); + iNumErr += EqnTest(_T("-(-a-b*i)"), cmplx_type(1, 2), true, 2); + iNumErr += EqnTest(_T("(2+4i)*(8-6i)"), cmplx_type(40, 20), true, 0); + + // Issue 17: Wrong result on complex power. + iNumErr += EqnTest(_T("(-0.27 + 0.66*i)^2"), cmplx_type(-0.3627, -0.3564), true, 0); + iNumErr += EqnTest(_T("(-1+5i)^2"), cmplx_type(-24, -10), true, 0); + + iNumErr += EqnTest(_T("c=(a=1+2i)"), cmplx_type(1, 2), true, 2); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestParserValue() +{ + int iNumErr = 0; + *m_stream << _T("testing parser value types..."); + + // Define values and variables for each type + Value bVal = true; + Value fVal = (float_type)3.14; + Value sVal = string_type(_T("hello world")); + Value sVal1 = _T("hello world"); // Test assignment from const char* to string + Value cVal = cmplx_type(1, 1); + Value aVal(2, 0); + aVal.At(0) = (float_type)2.0; + aVal.At(1) = (float_type)3.0; + + // Create a 3x3 matrix + Value matrix(3, 0); + matrix.At(0) = Value(3, 0); + matrix.At(1) = Value(3, 0); + matrix.At(2) = Value(3, 0); + + Variable bVar(&bVal), + fVar(&fVal), + sVar(&sVal), + sVar1(&sVal1), + cVar(&cVal), + aVar(&aVal); + + // Check the value types + try + { + // Test if matrix values do work + if (!matrix.IsMatrix() || matrix.GetRows() != 3) + iNumErr++; + + std::size_t sz = matrix.GetRows(); + for (std::size_t i = 0; i < sz; ++i) + { + std::size_t dim_row = matrix.At(static_cast(i)).GetRows(); + if (dim_row != 3) + { + iNumErr++; + console() << _T("\n Array dimension mismatch in matrix row ") << i + << _T(" (expected=3; dim=") << dim_row << _T(")"); + } + } + + // test type checking of values + if (!fVal.IsScalar() || fVal.IsMatrix() || fVal.GetType() != 'f') iNumErr++; + if (!cVal.IsScalar() || cVal.IsMatrix() || cVal.GetType() != 'c') iNumErr++; + if (aVal.IsScalar() || !aVal.IsMatrix() || aVal.GetType() != 'm') iNumErr++; + if (sVal.IsScalar() || sVal.IsMatrix() || sVal.GetType() != 's') iNumErr++; + if (sVal1.IsScalar() || sVal1.IsMatrix() || sVal1.GetType() != 's') iNumErr++; + if (bVal.IsScalar() || bVal.IsMatrix() || bVal.GetType() != 'b') iNumErr++; + + // test type checking of variables + if (!fVar.IsScalar() || fVar.IsMatrix() || fVar.GetType() != 'f') iNumErr++; + if (!cVar.IsScalar() || cVar.IsMatrix() || cVar.GetType() != 'c') iNumErr++; + if (aVar.IsScalar() || !aVar.IsMatrix() || aVar.GetType() != 'm') iNumErr++; + if (sVar.IsScalar() || sVar.IsMatrix() || sVar.GetType() != 's') iNumErr++; + if (sVar1.IsScalar() || sVar1.IsMatrix() || sVar1.GetType() != 's') iNumErr++; + if (bVar.IsScalar() || bVar.IsMatrix() || bVar.GetType() != 'b') iNumErr++; + + // Issue 33: https://code.google.com/p/muparserx/issues/detail?id=33 + // Remark: Type information was not properly set when invoking +=, -= operators + { + Value x = 1.0; + Value y = cmplx_type(0, 1); + x += y; + if (x.GetImag() != 1 || x.GetFloat() != 1 || x.GetType() != 'c') + { + *m_stream << _T("\nValue::operator+=(...) failed."); + iNumErr++; + } + + x = 1.0; + y = cmplx_type(0, 1); + x -= y; + if (x.GetImag() != -1 || x.GetFloat() != 1 || x.GetType() != 'c') + { + *m_stream << _T("\nValue::operator-=(...) failed."); + iNumErr++; + } + } + } + catch (...) + { + iNumErr++; + } + + bool bError; + +#define VALUE_THROWCHECK(VAR, FAIL, MEMBER) \ + bError = (FAIL); \ + try \ + { \ + VAR.MEMBER(); \ + } \ + catch (...) \ + { \ + bError ^= true; \ + } \ + iNumErr += (bError) ? 1 : 0; \ + c_iCount++; + + // Check if the getter functions really throw an exception + // when used with an incorrect value type + // Case 1: test float values + VALUE_THROWCHECK(fVal, false, GetFloat) + VALUE_THROWCHECK(fVal, false, GetImag) + VALUE_THROWCHECK(fVal, true, GetBool) + VALUE_THROWCHECK(fVal, true, GetString) + VALUE_THROWCHECK(fVal, true, GetArray) + // for variables + VALUE_THROWCHECK(fVar, false, GetFloat) + VALUE_THROWCHECK(fVar, false, GetImag) + VALUE_THROWCHECK(fVar, true, GetBool) + VALUE_THROWCHECK(fVar, true, GetString) + VALUE_THROWCHECK(fVar, true, GetArray) + + // Case 2: test bool values + VALUE_THROWCHECK(bVal, false, GetFloat) + VALUE_THROWCHECK(bVal, true, GetImag) + VALUE_THROWCHECK(bVal, false, GetBool) + VALUE_THROWCHECK(bVal, true, GetString) + VALUE_THROWCHECK(bVal, true, GetArray) + // for variables + VALUE_THROWCHECK(bVar, false, GetFloat) + VALUE_THROWCHECK(bVar, true, GetImag) + VALUE_THROWCHECK(bVar, false, GetBool) + VALUE_THROWCHECK(bVar, true, GetString) + VALUE_THROWCHECK(bVar, true, GetArray) + + // Case 3: test string values + // VALUE_THROWCHECK(sVal, true, GetFloat) + VALUE_THROWCHECK(sVal, true, GetImag) + VALUE_THROWCHECK(sVal, true, GetBool) + VALUE_THROWCHECK(sVal, false, GetString) + VALUE_THROWCHECK(sVal, true, GetArray) + // for variables + // VALUE_THROWCHECK(sVar, true, GetFloat) + VALUE_THROWCHECK(sVar, true, GetImag) + VALUE_THROWCHECK(sVar, true, GetBool) + VALUE_THROWCHECK(sVar, false, GetString) + VALUE_THROWCHECK(sVar, true, GetArray) + + // Case 4: test array values + // VALUE_THROWCHECK(aVal, true, GetFloat) + VALUE_THROWCHECK(aVal, true, GetImag) + VALUE_THROWCHECK(aVal, true, GetBool) + VALUE_THROWCHECK(aVal, true, GetString) + VALUE_THROWCHECK(aVal, false, GetArray) + // for variables + // VALUE_THROWCHECK(aVar, true, GetFloat) + VALUE_THROWCHECK(aVar, true, GetImag) + VALUE_THROWCHECK(aVar, true, GetBool) + VALUE_THROWCHECK(aVar, true, GetString) + VALUE_THROWCHECK(aVar, false, GetArray) + + // Case 5: test complex values + // VALUE_THROWCHECK(cVal, false, GetFloat) + VALUE_THROWCHECK(cVal, false, GetImag) + VALUE_THROWCHECK(cVal, true, GetBool) + VALUE_THROWCHECK(cVal, true, GetString) + VALUE_THROWCHECK(cVal, true, GetArray) + // for variables + // VALUE_THROWCHECK(cVar, false, GetFloat) + VALUE_THROWCHECK(cVar, false, GetImag) + VALUE_THROWCHECK(cVar, true, GetBool) + VALUE_THROWCHECK(cVar, true, GetString) + VALUE_THROWCHECK(cVar, true, GetArray) +#undef VALUE_THROWCHECK + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestErrorCodes() +{ + int iNumErr = 0; + *m_stream << _T("testing error codes..."); + + iNumErr += ThrowTest(_T("a,b"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("(a,b)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("((a,b))"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("2*1,2"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sin(1,2)"), ecTOO_MANY_PARAMS); + + // Invalid expression + // Issue 20: http://code.google.com/p/muparserx/issues/detail?id=20 + iNumErr += ThrowTest(_T(" "), ecUNEXPECTED_EOF); + + iNumErr += ThrowTest(_T("sin(nonexistent_var)"), ecUNASSIGNABLE_TOKEN, 4, _T("nonexistent_var")); + + // Invalid function argument types + iNumErr += ThrowTest(_T("sin(\"test\")"), ecEVAL, 0); + iNumErr += ThrowTest(_T("max(1, \"test\")"), ecEVAL, 0); + iNumErr += ThrowTest(_T("max(1,sin(8), \"t\")"), ecEVAL, 0); + iNumErr += ThrowTest(_T("str2dbl(sin(3.14))"), ecEVAL, 0); + + // Invalid unary operator argument types + iNumErr += ThrowTest(_T("\"test\"n"), ecEVAL, 6); // (nano can only be applied to floats) + iNumErr += ThrowTest(_T("(1+3i)/(8*9i)+\"hallo\""), ecEVAL); + iNumErr += ThrowTest(_T("(1+3i)/(8*9i)-\"hallo\""), ecEVAL); + iNumErr += ThrowTest(_T("(1+3i)/(8*9i)*\"hallo\""), ecEVAL); + iNumErr += ThrowTest(_T("(1+3i)/(8*9i)/\"hallo\""), ecEVAL); + iNumErr += ThrowTest(_T("10+va"), ecEVAL, 2); + + // Type conflicts in binary operators + iNumErr += ThrowTest(_T("\"test\" // 8"), ecEVAL, 7); + iNumErr += ThrowTest(_T("8//\"test\""), ecEVAL, 1); + iNumErr += ThrowTest(_T("5//8"), ecEVAL, 1); + iNumErr += ThrowTest(_T("\"t\"//sin(8)"), ecEVAL, 3); + iNumErr += ThrowTest(_T("sin(8)//\"t\""), ecEVAL, 6); + + // Unexpected end of expression + iNumErr += ThrowTest(_T("3+"), ecUNEXPECTED_EOF); + iNumErr += ThrowTest(_T("8*"), ecUNEXPECTED_EOF); + iNumErr += ThrowTest(_T("3+("), ecUNEXPECTED_EOF); + iNumErr += ThrowTest(_T("3+sin"), ecUNEXPECTED_EOF); + iNumErr += ThrowTest(_T("(2+"), ecUNEXPECTED_EOF); + + iNumErr += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("3)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("(3))"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("()"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("(2+)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("sin(cos)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("sin(())"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("sin()"), ecTOO_FEW_PARAMS); + iNumErr += ThrowTest(_T("sin)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("pi)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("a)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("2(-m)"), ecUNEXPECTED_PARENS); + iNumErr += ThrowTest(_T("2(m)"), ecUNEXPECTED_PARENS); + + iNumErr += ThrowTest(_T("(1+2"), ecMISSING_PARENS); + iNumErr += ThrowTest(_T("((3)"), ecMISSING_PARENS); + + // The behaviour in the next function depends on whether + // implicit variable creation is allowed or not. (momentarily its active) + iNumErr += ThrowTest(_T("5z)"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("5t6"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("5 t 6"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("ksdfj"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("-m"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("m4"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("sin(m)"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("m m"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("m(8)"), ecUNASSIGNABLE_TOKEN); + iNumErr += ThrowTest(_T("4 + m"), ecUNASSIGNABLE_TOKEN); + + // unexpected operator + iNumErr += ThrowTest(_T("5+*3)"), ecUNEXPECTED_OPERATOR); + + // unexpected comma (used without a function) + iNumErr += ThrowTest(_T(",3"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sin(,sin(8))"), ecUNEXPECTED_COMMA); + + // unexpected variable + iNumErr += ThrowTest(_T("a _xxx_ b"), ecUNASSIGNABLE_TOKEN, 2); // if a variable factory is installed ecUNEXPECTED_VAR + + iNumErr += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN); + iNumErr += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL); + iNumErr += ThrowTest(_T("sin(3)+"), ecUNEXPECTED_EOF); + + // value recognition + iNumErr += ThrowTest(_T("0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex value + iNumErr += ThrowTest(_T("1+0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex value + iNumErr += ThrowTest(_T("a+0x"), ecUNASSIGNABLE_TOKEN); // incomplete hex value + + // index operator + iNumErr += ThrowTest(_T("3n[1]"), ecINDEX_OUT_OF_BOUNDS); // Indexing a scalar is ok, but this index is out of bounds (0 would be ok) + iNumErr += ThrowTest(_T("min(3,]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("sin(]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("va[]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("3+]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("sin[a)"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("1+[8]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("1[8]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("[1]"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("]1"), ecUNEXPECTED_SQR_BRACKET); + iNumErr += ThrowTest(_T("va[[3]]"), ecUNEXPECTED_SQR_BRACKET); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestStringFun() +{ + int iNumErr = 0; + *m_stream << _T("testing string functions..."); + + // escape sequences + iNumErr += EqnTest(_T("\"\\\"quoted_string\\\"\""), _T("\"quoted_string\""), true); // "\"quoted_string\"" -> "quoted_string" + iNumErr += EqnTest(_T("\"\\\"\\\"\""), _T("\"\""), true); // "\"\"" -> "" + iNumErr += EqnTest(_T("\"\\\\\""), _T("\\"), true); // "\\" -> \ (single backslash) + + // String functions + iNumErr += EqnTest(_T("strlen(\"12345\")"), 5.0, true); + iNumErr += EqnTest(_T("strlen(toupper(\"abcde\"))"), 5.0, true); + iNumErr += EqnTest(_T("sin(0)+(float)strlen(\"12345\")"), (float_type)5.0, true); + iNumErr += EqnTest(_T("10*(float)strlen(toupper(\"12345\"))"), (float_type)50.0, true); + iNumErr += EqnTest(_T("\"hello \"//\"world\""), string_type(_T("hello world")), true); + iNumErr += EqnTest(_T("toupper(\"hello \")//\"world\""), string_type(_T("HELLO world")), true); + iNumErr += EqnTest(_T("\"hello \"//toupper(\"world\")//\" !!!\""), string_type(_T("hello WORLD !!!")), true); + + Assessment(iNumErr); + + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestPostfix() +{ + int iNumErr = 0; + *m_stream << _T("testing postfix operators..."); + + // application + iNumErr += EqnTest(_T("1n"), (float_type)1e-9, true); + iNumErr += EqnTest(_T("8n"), (float_type)8e-9, true); + iNumErr += EqnTest(_T("8n"), (float_type)123.0, false); + iNumErr += EqnTest(_T("3m+5"), (float_type)5.003, true); + iNumErr += EqnTest(_T("1000m"), (float_type)1.0, true); + iNumErr += EqnTest(_T("1000 m"), (float_type)1.0, true); + iNumErr += EqnTest(_T("(a)m"), (float_type)1e-3, true); + iNumErr += EqnTest(_T("-(a)m"), (float_type)-1e-3, true); + iNumErr += EqnTest(_T("-2m"), (float_type)-2e-3, true); + iNumErr += EqnTest(_T("a++b"), 3.0, true); + iNumErr += EqnTest(_T("a ++ b"), 3.0, true); + iNumErr += EqnTest(_T("1++2"), 3.0, true); + iNumErr += EqnTest(_T("1 ++ 2"), 3.0, true); + iNumErr += EqnTest(_T("2+(a*1000)m"), (float_type)3.0, true); + // some incorrect results + iNumErr += EqnTest(_T("1000m"), (float_type)0.1, false); + iNumErr += EqnTest(_T("(a)m"), (float_type)2.0, false); + // factorial operator + iNumErr += EqnTest(_T("5!"), 120.0, true); + iNumErr += EqnTest(_T("-5!"), -120.0, true); + iNumErr += ThrowTest(_T("(-5)!"), ecDOMAIN_ERROR); + + // Special tests for systems not supporting IEEE 754 + if (!std::numeric_limits::is_iec559) + { + iNumErr += ThrowTest(_T("123456!"), ecOVERFLOW); + } + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestInfix() +{ + int iNumErr = 0; + *m_stream << _T("testing infix operators..."); + + float_type a = 1; + float_type b = 2; + + iNumErr += EqnTest(_T("-1"), (float_type)-1.0, true); + iNumErr += EqnTest(_T("-(-1)"), (float_type)1.0, true); + iNumErr += EqnTest(_T("-(-1)*2"), (float_type)2.0, true); + iNumErr += EqnTest(_T("-(-2)*sqrt(4)"), (float_type)4.0, true); + iNumErr += EqnTest(_T("-a"), -a, true); + iNumErr += EqnTest(_T("-(a)"), -(a), true); + iNumErr += EqnTest(_T("-(-a)"), -(-a), true); + iNumErr += EqnTest(_T("-(-a)*2"), -(-a) * 2, true); + iNumErr += EqnTest(_T("-(8)"), (float_type)-8.0, true); + iNumErr += EqnTest(_T("-8"), (float_type)-8.0, true); + iNumErr += EqnTest(_T("-(2+1)"), (float_type)-3.0, true); + //iNumErr += EqnTest("-(f1of1(1+2*3)+1*2)", -9.0, true); + //iNumErr += EqnTest("-(-f1of1(1+2*3)+1*2)", 5.0, true); + iNumErr += EqnTest(_T("-sin(8)"), (float_type)-0.989358, true); + iNumErr += EqnTest(_T("-sin(8)"), (float_type)0.989358, false); + iNumErr += EqnTest(_T("3-(-a)"), (float_type)4.0, true); + iNumErr += EqnTest(_T("3--a"), (float_type)4.0, true); + iNumErr += EqnTest(_T("2++4"), (float_type)6.0, true); + iNumErr += EqnTest(_T("--1"), (float_type)1.0, true); + + // sign precedence + // Issue 14: https://code.google.com/p/muparserx/issues/detail?id=14 + iNumErr += EqnTest(_T("-3^2"), -9.0, true); + iNumErr += EqnTest(_T("-b^2^3-b^8"), -std::pow(b, std::pow(2.0, 3.0)) - std::pow(b, 8), true); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestMultiArg() +{ + int iNumErr = 0; + *m_stream << _T("testing multiarg functions..."); + + // Multiarg functions being called without any parameters + iNumErr += ThrowTest(_T("min()"), ecTOO_FEW_PARAMS); + iNumErr += ThrowTest(_T("max()"), ecTOO_FEW_PARAMS); + iNumErr += ThrowTest(_T("sum()"), ecTOO_FEW_PARAMS); + + // application + iNumErr += EqnTest(_T("max(1,8,9,(int)6)"), (float_type)9.0, true); + iNumErr += EqnTest(_T("max((int)6, 1+2, 4, -9)"), (float_type)6.0, true); + iNumErr += EqnTest(_T("min((int)6, 1+2, 4, -9)"), (float_type)-9.0, true); + + // + iNumErr += EqnTest(_T("a=test0()"), (float_type)0, true); + iNumErr += EqnTest(_T("b=a+test0()"), (float_type)1, true); + + // added as response to this bugreport: + // http://code.google.com/p/muparserx/issues/detail?id=1 + // cause of the error: Function tokens were not cloned in the tokenreader when beeing found. + // a pointer to the one and only function onject was returned instead + // consequently the argument counter was overwritten by the second function call + // causing an assertion later on. + iNumErr += EqnTest(_T("sum(1,2)/sum(3,4)"), (float_type)0.428571, true); + iNumErr += EqnTest(_T("3/sum(3,4,5)"), (float_type)0.25, true); + iNumErr += EqnTest(_T("sum(3)/sum(3,4,5)"), (float_type)0.25, true); + iNumErr += EqnTest(_T("sum(3)+sum(3,4,5)"), (float_type)15, true); + iNumErr += EqnTest(_T("sum(1,2)/sum(3,4,5)"), (float_type)0.25, true); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestVector() +{ + int iNumErr = 0; + *m_stream << _T("testing vector operations..."); + + // Vector operations + iNumErr += ThrowTest(_T("10+2*va"), ecEVAL); // fail: number + vector + iNumErr += ThrowTest(_T("10+va*2"), ecEVAL); // fail: number + vector + iNumErr += ThrowTest(_T("va+vc"), ecMATRIX_DIMENSION_MISMATCH); // fail: vectors of different size + iNumErr += ThrowTest(_T("va-vc"), ecMATRIX_DIMENSION_MISMATCH); // fail: vectors of different size + iNumErr += ThrowTest(_T("va*vc"), ecMATRIX_DIMENSION_MISMATCH); // fail: vectors of different size + iNumErr += ThrowTest(_T("va*vb"), ecMATRIX_DIMENSION_MISMATCH); // fail: matrix dimension mismatch + iNumErr += ThrowTest(_T("va*va"), ecMATRIX_DIMENSION_MISMATCH); // fail: matrix dimension mismatch + iNumErr += ThrowTest(_T("(va*vb)*b"), ecMATRIX_DIMENSION_MISMATCH); // fail: matrix dimension mismatch + iNumErr += ThrowTest(_T("va[1.23]"), ecTYPE_CONFLICT_IDX, 7); // fail: float value used as index + iNumErr += ThrowTest(_T("va[sin(8)]"), ecTYPE_CONFLICT_IDX, 9); // fail: float value used as index + iNumErr += ThrowTest(_T("va[-1]"), ecINDEX_OUT_OF_BOUNDS); // fail: negative value used as an index + iNumErr += ThrowTest(_T("va[c]"), ecINDEX_OUT_OF_BOUNDS); + iNumErr += ThrowTest(_T("va[(3)]"), ecINDEX_OUT_OF_BOUNDS); + iNumErr += ThrowTest(_T("a[1]"), ecINDEX_OUT_OF_BOUNDS); // indexing a scalar is ok, but this index is out of bounds (0 would be ok...) + iNumErr += ThrowTest(_T("va[1"), ecMISSING_SQR_BRACKET); + iNumErr += ThrowTest(_T("va[1]]"), ecUNEXPECTED_SQR_BRACKET); + + //iNumErr += ThrowTest(_T("va==9"), ecEVAL); + //iNumErr += ThrowTest(_T("va==a"), ecEVAL); + //iNumErr += ThrowTest(_T("a==va"), ecEVAL); + //iNumErr += ThrowTest(_T("9==va"), ecEVAL); + + Value v(3, 0); + v.At(0) = (float_type)5.0; + v.At(1) = (float_type)5.0; + v.At(2) = (float_type)5.0; + iNumErr += EqnTest(_T("va+vb"), v, true); + + v.At(0) = (float_type)5.0; + v.At(1) = (float_type)5.0; + v.At(2) = (float_type)6.0; + iNumErr += EqnTest(_T("va+vb"), v, false); + + v.At(0) = (float_type)-1.0; + v.At(1) = (float_type)-2.0; + v.At(2) = (float_type)-3.0; + iNumErr += EqnTest(_T("-va"), v, true); + + iNumErr += EqnTest(_T("sizeof(va+vb)"), 3.0, true); + iNumErr += EqnTest(_T("sizeof(va-vb)"), 3.0, true); + + iNumErr += EqnTest(_T("va==vb"), false, true); + iNumErr += EqnTest(_T("va!=vb"), true, true); + //iNumErr += EqnTest(_T("vavb"), true, true); + //iNumErr += EqnTest(_T("va<=vb"), false, true); + //iNumErr += EqnTest(_T("va>=vb"), true, true); + + iNumErr += EqnTest(_T("vb[va[0]]"), 3.0, true); + iNumErr += EqnTest(_T("m1[0,0]+m1[1,1]+m1[2,2]"), 3.0, true); + iNumErr += EqnTest(_T("vb[m1[0,0]]"), 3.0, true); + + iNumErr += EqnTest(_T("m1[0,0]=2"), 2.0, true); + iNumErr += EqnTest(_T("m1[1,1]=2"), 2.0, true); + iNumErr += EqnTest(_T("m1[2,2]=2"), 2.0, true); + iNumErr += EqnTest(_T("va[0]=12.3"), (float_type)12.3, true); + iNumErr += EqnTest(_T("va[1]=12.3"), (float_type)12.3, true); + iNumErr += EqnTest(_T("va[2]=12.3"), (float_type)12.3, true); + + iNumErr += EqnTest(_T("va[0]"), 1.0, true); + iNumErr += EqnTest(_T("va[1]"), 2.0, true); + iNumErr += EqnTest(_T("va[2]"), 3.0, true); + iNumErr += EqnTest(_T("(va[2])"), 3.0, true); + iNumErr += EqnTest(_T("va[a]"), 2.0, true); + iNumErr += EqnTest(_T("(va[a])"), 2.0, true); + iNumErr += EqnTest(_T("va[b]"), 3.0, true); + iNumErr += EqnTest(_T("va[(2)]"), 3.0, true); + iNumErr += EqnTest(_T("va[-(-2)]"), 3.0, true); + iNumErr += EqnTest(_T("(va[(2)])"), 3.0, true); + iNumErr += EqnTest(_T("(va[-(-2)])"), 3.0, true); + iNumErr += EqnTest(_T("va[1+1]"), 3.0, true); + iNumErr += EqnTest(_T("va[(int)sin(8)+1]"), 2.0, true); + + iNumErr += EqnTest(_T("va[2]+4"), 7.0, true); + iNumErr += EqnTest(_T("4+va[2]"), 7.0, true); + iNumErr += EqnTest(_T("va[2]*4"), 12.0, true); + iNumErr += EqnTest(_T("4*va[2]"), 12.0, true); + iNumErr += EqnTest(_T("va[2]+a"), 4.0, true); + iNumErr += EqnTest(_T("a+va[2]"), 4.0, true); + iNumErr += EqnTest(_T("va[2]*b"), 6.0, true); + iNumErr += EqnTest(_T("b*va[2]"), 6.0, true); + + // Issue 68 (and related issues): + iNumErr += EqnTest(_T("(abs(-3)+2)>=min(6,5)"), true, true); + iNumErr += EqnTest(_T("(abs(-3))>abs(2)"), true, true); + iNumErr += EqnTest(_T("min(1,2,-3)>-4"), true, true); + iNumErr += EqnTest(_T("(abs(-3))>-2"), true, true); + iNumErr += EqnTest(_T("abs(-3)>abs(2)"), true, true); + + // Issue 42: + // https://code.google.com/p/muparserx/issues/detail?id=42 + v.At(0) = (float_type)1.0; + v.At(1) = (float_type)0.0; + v.At(2) = (float_type)0.0; + iNumErr += EqnTest(_T("{1,0,0}'"), v, true); + iNumErr += EqnTest(_T("{(1),0,0}'"), v, true); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestBinOp() +{ + int iNumErr = 0; + *m_stream << _T("testing binary operators..."); + float_type a = 1; + + // standard aperators + iNumErr += EqnTest(_T("1+7"), (float_type)8.0, true); + iNumErr += EqnTest(_T("10-1"), (float_type)9.0, true); + iNumErr += EqnTest(_T("3*4"), (float_type)12.0, true); + iNumErr += EqnTest(_T("10/2"), (float_type)5.0, true); + // operator associativity + iNumErr += EqnTest(_T("2^2^3"), (float_type)256.0, true); + iNumErr += EqnTest(_T("3+4*2/(1-5)^2^3"), (float_type)3.0001220703125, true); + iNumErr += EqnTest(_T("1/2/3"), (float_type)1.0 / (float_type)6.0, true); + + // operator precedencs + iNumErr += EqnTest(_T("1+2-3*4/5^6"), (float_type)2.99923, true); + iNumErr += EqnTest(_T("a+b-c*4/5^6"), (float_type)2.99923, true); + iNumErr += EqnTest(_T("1^2/3*4-5+6"), (float_type)2.3333, true); + iNumErr += EqnTest(_T("a^b/c*4-5+6"), (float_type)2.3333, true); + iNumErr += EqnTest(_T("1+2*3"), (float_type)7.0, true); + iNumErr += EqnTest(_T("a+b*c"), (float_type)7.0, true); + iNumErr += EqnTest(_T("(1+2)*3"), (float_type)9.0, true); + iNumErr += EqnTest(_T("(a+b)*c"), (float_type)9.0, true); + iNumErr += EqnTest(_T("(1+2)*(-3)"), (float_type)-9.0, true); + iNumErr += EqnTest(_T("(a+b)*(-c)"), (float_type)-9.0, true); + iNumErr += EqnTest(_T("2/4"), (float_type)0.5, true); + iNumErr += EqnTest(_T("4&4"), 4.0, true); + iNumErr += EqnTest(_T("2+2&(a+b+c)"), 4.0, true); + iNumErr += EqnTest(_T("3&3"), 3.0, true); + iNumErr += EqnTest(_T("c&3"), 3.0, true); + iNumErr += EqnTest(_T("(c)&3"), 3.0, true); + iNumErr += EqnTest(_T("(a+b)&3"), 3.0, true); + iNumErr += EqnTest(_T("(a+b+c)&6"), 6.0, true); + iNumErr += EqnTest(_T("(1+2+3)&6"), 6.0, true); + iNumErr += EqnTest(_T("3&c"), 3.0, true); + iNumErr += EqnTest(_T("(a<<1)+2"), 4.0, true); + iNumErr += EqnTest(_T("(a<<2)+2"), 6.0, true); + iNumErr += EqnTest(_T("(a<<3)+2"), 10.0, true); + iNumErr += EqnTest(_T("(a<<4)+2"), 18.0, true); + iNumErr += EqnTest(_T("(a<<5)+2"), 34.0, true); + iNumErr += EqnTest(_T("1<<31"), (float_type)2147483648, true); + iNumErr += EqnTest(_T("-1<<31"), (float_type)-2147483648.0, true); + iNumErr += EqnTest(_T("1<<45"), (float_type)35184372088832.0, true); + iNumErr += EqnTest(_T("-1<<45"), (float_type)-35184372088832.0, true); + iNumErr += EqnTest(_T("8<<-2"), 2.0, true); + iNumErr += EqnTest(_T("8<<-4"), 0.0, true); + // Issue 25: http://code.google.com/p/muparserx/issues/detail?id=25 + iNumErr += ThrowTest(_T("55<<2222222"), ecOVERFLOW); + // Issue 16: http://code.google.com/p/muparserx/issues/detail?id=16 + iNumErr += EqnTest(_T("true == true && false"), true == true && false, true); + iNumErr += EqnTest(_T("false == true && false"), false == true && false, true); + iNumErr += EqnTest(_T("a==1.0 && a==1.0"), a == 1.0 && a == 1.0, true); + + // bool operators for comparing values + iNumErr += EqnTest(_T("aa"), true, true); + iNumErr += EqnTest(_T("a>a"), false, true); + iNumErr += EqnTest(_T("aa"), false, true); + iNumErr += EqnTest(_T("a<=a"), true, true); + iNumErr += EqnTest(_T("a<=b"), true, true); + iNumErr += EqnTest(_T("b<=a"), false, true); + iNumErr += EqnTest(_T("a>=a"), true, true); + iNumErr += EqnTest(_T("b>=a"), true, true); + iNumErr += EqnTest(_T("a>=b"), false, true); + // The following equations were raising type conflict errors once + // since the result of sqrt(1) is 1 which is an integer as fas as muParserX + // is concerned: + iNumErr += EqnTest(_T("sqrt(a)sin(8)"), true, true); + iNumErr += EqnTest(_T("sqrt(a)>=sin(8)"), true, true); + iNumErr += EqnTest(_T("sqrt(a)==sin(8)"), false, true); + iNumErr += EqnTest(_T("sqrt(a)!=sin(8)"), true, true); + iNumErr += EqnTest(_T("sqrt(a)+1.01"), (float_type)2.01, true); + iNumErr += EqnTest(_T("sqrt(a)-1.01"), (float_type)-0.01, true); + + // interaction with sign operator + iNumErr += EqnTest(_T("3-(-a)"), 4.0, true); + iNumErr += EqnTest(_T("3--a"), 4.0, true); + + // Problems with small bogus real/imag values introduced due to limited floating point accuracy + iNumErr += EqnTest(_T("(-2)^3"), -8.0, true); // may introduce incorrect imaginary value (When computed with the log/exp formula: -8 + 2.93e-15i) + iNumErr += EqnTest(_T("imag((-2)^3)==0"), true, true); // may introduce incorrect imaginary value (When computed with the log/exp formula: -8 + 2.93e-15i) + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestIfElse() +{ + int iNumErr = 0; + *m_stream << _T("testing if-else conditional..."); + + float_type a = 1; + + // test case copied from muparser (https://oss-fuzz.com/testcase-detail/4777121158529024) + iNumErr += ThrowTest(_T("3!=min(false?2>2,2>5,1:6)"), ecUNEXPECTED_COMMA); + + // test case copied from muparser (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22922#c1) + iNumErr += ThrowTest(_T("1?2:0?(7:1)"), ecMISPLACED_COLON); + + // test case copied from muparser (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23410) + // with variations + iNumErr += ThrowTest(_T(R"(false ? 4 : "", ? 4 : "", ? 4 : "")"), ecUNEXPECTED_COMMA); + iNumErr += EqnTest(_T(R"(false ? "four" : 4)"), 4, true); + iNumErr += EqnTest(_T(R"(true ? "four" : 4)"), "four", true); + iNumErr += EqnTest(_T(R"(true ? "foo" : "bar")"), "foo", true); + + // test case and variations copied from muparser https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22938 + iNumErr += ThrowTest(_T("sum(false?1,0,0:3)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sum(false?(1,0,0):3)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sum(2>3?2,4,2:4)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sum(2>3?2,4,sin(2):4)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sum(2>3?sin(a),4,2:4)"), ecUNEXPECTED_COMMA); + iNumErr += ThrowTest(_T("sum(2>3?sin(2),4,2:4)"), ecUNEXPECTED_COMMA); + + // Test error detection + iNumErr += ThrowTest(_T(": 2"), ecMISPLACED_COLON); + iNumErr += ThrowTest(_T("? 1 : 2"), ecUNEXPECTED_CONDITIONAL); + iNumErr += ThrowTest(_T("(ab) ? true : false) ? 1 : 2"), 2.0, true); + iNumErr += EqnTest(_T("((a>b) ? true : false) ? 1 : sum((a>b) ? 1 : 2)"), 2.0, true); + iNumErr += EqnTest(_T("((a>b) ? false : true) ? 1 : sum((a>b) ? 1 : 2)"), 1.0, true); + iNumErr += EqnTest(_T("(true) ? 10 : 11"), 10.0, true); + iNumErr += EqnTest(_T("(true) ? a+b : c+d"), 3.0, true); + iNumErr += EqnTest(_T("(true) ? false : true"), false, true); + iNumErr += EqnTest(_T("(false) ? 10 : 11"), 11.0, true); + iNumErr += EqnTest(_T("(false) ? a+b : c+d"), 1.0, true); + iNumErr += EqnTest(_T("(false) ? false : true"), true, true); + iNumErr += EqnTest(_T("(ab) ? 10 : 11"), 11.0, true); + iNumErr += EqnTest(_T("(ab) ? c : d"), -2.0, true); + iNumErr += EqnTest(_T("(a>b) ? true : false"), false, true); + + // With multiarg functions + iNumErr += EqnTest(_T("sum((a>b) ? 1 : 2)"), 2.0, true); + iNumErr += EqnTest(_T("sum((a>b) ? 1 : 2, 100)"), 102.0, true); + iNumErr += EqnTest(_T("sum((true) ? 1 : 2)"), 1.0, true); + iNumErr += EqnTest(_T("sum((true) ? 1 : 2, 100)"), 101.0, true); + iNumErr += EqnTest(_T("sum(3, (a>b) ? 3 : 10)"), 13.0, true); + iNumErr += EqnTest(_T("sum(3, (ab) ? 3 : 10)*10"), 130.0, true); + iNumErr += EqnTest(_T("sum(3, (ab) ? 3 : 10)"), 130.0, true); + iNumErr += EqnTest(_T("10*sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab) ? sum(3, (ab)&&(a2)&&(1<2) ? 128 : 255"), 255.0, true); + iNumErr += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128.0, true); + iNumErr += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255.0, true); + iNumErr += EqnTest(_T("((ab)&&(ac) ? 1 : 2) : 3"), 2., true); + iNumErr += EqnTest(_T("(a>b) ? ((bb) ? ((b>c) ? 1 : 2) : 3"), 3., true); + + // nested conditionals without brackets + iNumErr += EqnTest(_T("(ac) ? 1 : 2 : 3"), 2., true); + iNumErr += EqnTest(_T("(a>b) ? (bb) ? (b>c) ? 1 : 2 : 3"), 3., true); + + // Neue Tests + iNumErr += EqnTest(_T("(ab)&&(a2)&&(1<2) ? 128 : 255"), 255., true); + iNumErr += EqnTest(_T("((1<2)&&(1<2)) ? 128 : 255"), 128., true); + iNumErr += EqnTest(_T("((1>2)&&(1<2)) ? 128 : 255"), 255., true); + iNumErr += EqnTest(_T("((ab)&&(a0 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 255., true); + iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 :(1>0 ? 32 : 64)"), 255., true); + iNumErr += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 128., true); + iNumErr += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 :(1>2 ? 32 : 64)"), 128., true); + iNumErr += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 64"), 32., true); + iNumErr += EqnTest(_T("1>2 ? 1>0 ? 128 : 255 : 1>2 ? 32 : 64"), 64., true); + iNumErr += EqnTest(_T("1>0 ? 50 : 1>0 ? 128 : 255"), 50., true); + iNumErr += EqnTest(_T("1>0 ? 50 : (1>0 ? 128 : 255)"), 50., true); + iNumErr += EqnTest(_T("1>0 ? 1>0 ? 128 : 255 : 50"), 128., true); + iNumErr += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 : 1>2 ? 64 : 16"), 32., true); + iNumErr += EqnTest(_T("1>2 ? 1>2 ? 128 : 255 : 1>0 ? 32 :(1>2 ? 64 : 16)"), 32., true); + iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : 1>0 ? 32 :1>2 ? 64 : 16"), 255., true); + iNumErr += EqnTest(_T("1>0 ? 1>2 ? 128 : 255 : (1>0 ? 32 :1>2 ? 64 : 16)"), 255., true); + iNumErr += EqnTest(_T("true ? false ? 128 : 255 : true ? 32 : 64"), 255., true); + + // assignment operators + iNumErr += EqnTest(_T("a= false ? 128 : 255"), 255., true); + iNumErr += EqnTest(_T("a=((a>b)&&(a + + // long formula (Reference: Matlab) + iNumErr += EqnTest( + "(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e" + ")+a)))*2.77)", -2.16995656, true); + */ + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestScript() +{ + int iNumErr = 0; + *m_stream << _T("testing script features..."); + + // Test error detection + iNumErr += ThrowTest(_T("sin(\n"), ecUNEXPECTED_NEWLINE); + iNumErr += ThrowTest(_T("1+\n"), ecUNEXPECTED_NEWLINE); + iNumErr += ThrowTest(_T("a*\n"), ecUNEXPECTED_NEWLINE); + iNumErr += ThrowTest(_T("va[\n"), ecUNEXPECTED_NEWLINE); + iNumErr += ThrowTest(_T("(true) ? \n"), ecUNEXPECTED_NEWLINE); + iNumErr += ThrowTest(_T("(true) ? 10:\n"), ecUNEXPECTED_NEWLINE); + + // Expressions spanning multiple lines + iNumErr += EqnTest(_T("a=1\n") + _T("b=2\n") + _T("c=3\n") + _T("a+b+c"), 6., true); + + // Ending an expression with a newline + iNumErr += EqnTest(_T("3\n"), 3., true); + iNumErr += EqnTest(_T("1+2\n"), 3., true); + iNumErr += EqnTest(_T("\n1+2\n"), 3., true); + iNumErr += EqnTest(_T("\n1+2\n\na+b"), 3., true); + + // Testing comments + /* 20130107 Not yet... + iNumErr += EqnTest(_T("a=10 % this is a comment\n") + _T("b=23 % this is another comment\n") + _T("a+b"), 33, true); + */ + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +int ParserTester::TestValReader() +{ + int iNumErr = 0; + *m_stream << _T("testing value reader..."); + + // Hex value reader + iNumErr += EqnTest(_T("0x1"), 1., true); + iNumErr += EqnTest(_T("0x1+0x2"), 3., true); + iNumErr += EqnTest(_T("0xff"), 255., true); + + // Reading of binary values + iNumErr += EqnTest(_T("0b1"), 1., true); + iNumErr += EqnTest(_T("0b01"), 1., true); + iNumErr += EqnTest(_T("0b11"), 3., true); + iNumErr += EqnTest(_T("0b011"), 3., true); + iNumErr += EqnTest(_T("0b11111111"), 255., true); + iNumErr += EqnTest(_T("b*0b011"), 6.0, true); + iNumErr += EqnTest(_T("0b1111111111111111111111111111111"), 2147483647., true); + iNumErr += EqnTest(_T("0b10000000000000000000000000000000"), -2147483647. - 1, true); + iNumErr += EqnTest(_T("0b11111111111111111111111111111111"), -1., true); + iNumErr += ThrowTest(_T("0b100000000000000000000000000000000"), ecUNDEFINED); + + // string value reader + iNumErr += EqnTest(_T("\"hallo\""), _T("hallo"), true); + + // boolean value reader + iNumErr += EqnTest(_T("true"), true, true); + iNumErr += EqnTest(_T("false"), false, true); + + // boolean value reader + iNumErr += EqnTest(_T("true"), true, true); + iNumErr += EqnTest(_T("false"), false, true); + + // mixed + iNumErr += EqnTest(_T("0b011+0xef"), 242., true); + + Assessment(iNumErr); + return iNumErr; +} + +//--------------------------------------------------------------------------- +void ParserTester::AddTest(testfun_type a_pFun) +{ + m_vTestFun.push_back(a_pFun); +} + +//--------------------------------------------------------------------------- +void ParserTester::Run() +{ + int iStat = 0; + try + { + for (int i = 0; i < (int)m_vTestFun.size(); ++i) + iStat += (this->*m_vTestFun[i])(); + } + catch (ParserError &e) + { + *m_stream << e.GetMsg() << endl; + *m_stream << e.GetToken() << endl; + Abort(); + } + catch (std::exception &e) + { + *m_stream << e.what() << endl; + Abort(); + } + catch (...) + { + *m_stream << _T("Internal error"); + Abort(); + } + + if (iStat == 0) + { + *m_stream << _T("Test passed (") << ParserTester::c_iCount << _T(" expressions)") << endl; + } + else + { + *m_stream << _T("Test failed with ") << iStat + << _T(" errors (") << ParserTester::c_iCount + << _T(" expressions)") << endl; + } + ParserTester::c_iCount = 0; + +#ifdef MUP_LEAKAGE_REPORT + // All tokens must have been destroyed by now, verify this + IToken::LeakageReport(); +#endif +} + +//--------------------------------------------------------------------------- +int ParserTester::ThrowTest(const string_type &a_sExpr, int a_nErrc, int a_nPos, string_type a_sIdent) +{ + ParserTester::c_iCount++; + + try + { + ParserX p; + + // Add variables + Value vVarVal[] = { 1., 2., 3., -2. }; + p.DefineVar(_T("a"), Variable(&vVarVal[0])); + p.DefineVar(_T("b"), Variable(&vVarVal[1])); + p.DefineVar(_T("c"), Variable(&vVarVal[2])); + p.DefineVar(_T("d"), Variable(&vVarVal[3])); + + // array variables + Value aVal1(3, 0); + aVal1.At(0) = (float_type)1.0; + aVal1.At(1) = (float_type)2.0; + aVal1.At(2) = (float_type)3.0; + + Value aVal2(3, 0); + aVal2.At(0) = (float_type)4.0; + aVal2.At(1) = (float_type)3.0; + aVal2.At(2) = (float_type)2.0; + + Value aVal3(4, 0); + aVal3.At(0) = (float_type)4.0; + aVal3.At(1) = (float_type)3.0; + aVal3.At(2) = (float_type)2.0; + aVal3.At(3) = (float_type)5.0; + + Value aVal4(4, 0); + aVal4.At(0) = (float_type)4.0; + aVal4.At(1) = false; + aVal4.At(2) = _T("hallo"); + + // Matrix variables + Value m1(3, 3, 0); + m1.At(0, 0) = 1.; + m1.At(1, 1) = 1.; + m1.At(2, 2) = 1.; + + Value m2(3, 3, 0); + m2.At(0, 0) = 1.; m2.At(0, 1) = 2.; m2.At(0, 2) = 3.; + m2.At(1, 0) = 4.; m2.At(1, 1) = 5.; m2.At(1, 2) = 6.; + m2.At(2, 0) = 7.; m2.At(2, 1) = 8.; m2.At(2, 2) = 9.; + + p.DefineVar(_T("m1"), Variable(&m1)); + p.DefineVar(_T("m2"), Variable(&m2)); + p.DefineVar(_T("va"), Variable(&aVal1)); + p.DefineVar(_T("vb"), Variable(&aVal2)); + p.DefineVar(_T("vc"), Variable(&aVal3)); + p.DefineVar(_T("vd"), Variable(&aVal4)); + + p.SetExpr(a_sExpr); + Value fRes = p.Eval(); + } + catch (ParserError &e) + { + // output the formula in case of an failed test + if (a_nErrc != e.GetCode()) + { + *m_stream << _T("\n ") + << _T("Expression: \"") << a_sExpr + << _T("\" Code:") << e.GetCode() + << _T(" Expected:") << a_nErrc; + } + + // Check whether the error is reported at the correct expression position + if (a_nPos != -1 && a_nPos != e.GetPos()) + { + *m_stream << _T("\n ") + << _T("Invalid error position: \"") << a_sExpr + << _T("\" Pos:") << e.GetPos() + << _T(" Expected:") << a_nPos; + } + + if (a_sIdent.length() && a_sIdent != e.GetContext().Ident) + { + *m_stream << _T("\n ") + << _T("Invalid identifier: \"") << a_sExpr + << _T("\" Ident:") << e.GetContext().Ident + << _T(" Expected:") << a_sIdent; + } + + return (a_nErrc == e.GetCode() && (a_nPos == -1 || a_nPos == e.GetPos())) ? 0 : 1; + } + + *m_stream << _T("\n ") + << _T("Expression failed: \"") + << a_sExpr + << _T("\" (no exception raised)."); + + return 1; +} + +//--------------------------------------------------------------------------- +int ParserTester::EqnTest(const string_type &a_str, Value a_val, bool a_fPass, int nExprVar) +{ + ParserTester::c_iCount++; + int iRet(1); + Value fVal[5]; + + try + { + // p1 is a pointer since I'm going to delete it in order to test if + // parsers after copy construction still refer to members of the deleted object. + // !! If this is the case this function will crash !! + std::unique_ptr p1(new ParserX()); + + // Add variables + Value vVarVal[] = { 1., 2., 3., -2., -1. }; + + // m1 ist die Einheitsmatrix + Value m1(3, 3, 0); + m1.At(0, 0) = 1.; + m1.At(1, 1) = 1.; + m1.At(2, 2) = 1.; + + // m2 ist die Einheitsmatrix + Value m2(3, 3, 0); + m2.At(0, 0) = 1.; m2.At(0, 1) = 2.; m2.At(0, 2) = 3.; + m2.At(1, 0) = 4.; m2.At(1, 1) = 5.; m2.At(1, 2) = 6.; + m2.At(2, 0) = 7.; m2.At(2, 1) = 8.; m2.At(2, 2) = 9.; + + p1->DefineOprt(new DbgSillyAdd); + p1->DefineFun(new FunTest0); + + p1->DefineVar(_T("a"), Variable(&vVarVal[0])); + p1->DefineVar(_T("b"), Variable(&vVarVal[1])); + p1->DefineVar(_T("c"), Variable(&vVarVal[2])); + p1->DefineVar(_T("d"), Variable(&vVarVal[3])); + p1->DefineVar(_T("f"), Variable(&vVarVal[4])); + p1->DefineVar(_T("m1"), Variable(&m1)); + p1->DefineVar(_T("m2"), Variable(&m2)); + + // Add constants + p1->DefineConst(_T("const"), 1.); + p1->DefineConst(_T("const1"), 2.); + p1->DefineConst(_T("const2"), 3.); + + // some vector variables + Value aVal1(3, 0); + aVal1.At(0) = (float_type)1.0; + aVal1.At(1) = (float_type)2.0; + aVal1.At(2) = (float_type)3.0; + + Value aVal2(3, 0); + aVal2.At(0) = (float_type)4.0; + aVal2.At(1) = (float_type)3.0; + aVal2.At(2) = (float_type)2.0; + p1->DefineVar(_T("va"), Variable(&aVal1)); + p1->DefineVar(_T("vb"), Variable(&aVal2)); + + // complex variables + Value cVal[3]; + cVal[0] = mup::cmplx_type(1, 1); + cVal[1] = mup::cmplx_type(2, 3); + cVal[2] = mup::cmplx_type(3, 4); + p1->DefineVar(_T("ca"), Variable(&cVal[0])); + p1->DefineVar(_T("cb"), Variable(&cVal[1])); + p1->DefineVar(_T("cc"), Variable(&cVal[2])); + + p1->SetExpr(a_str); + + fVal[0] = p1->Eval(); + + // Test copy and assignement operators + std::vector vParser; + vParser.push_back(*p1); // Push p1 into the vector + ParserX p2 = vParser[0]; // take parser from vector + + // destroy the originals from p2 + vParser.clear(); // delete the vector + p1.reset(0); // delete the original + + fVal[1] = p2.Eval(); // If copy constructions does not work + // we may see a crash here + + // Test assignement operator + // additionally disable Optimizer this time + ParserX p3; + p3 = p2; + fVal[2] = p3.Eval(); // If assignment does not work + // we may see a crash here + + // Calculating a second time will parse from rpn rather than from + // string. The result must be the same... + fVal[3] = p3.Eval(); + + // Calculate yet another time. There is the possibility of + // changing variables as a side effect of expression + // evaluation. So there are really bugs that could make this fail... + fVal[4] = p3.Eval(); + + // Check i number of used variables is correct + if (nExprVar != -1) + { + std::size_t n2 = p2.GetExprVar().size(); + std::size_t n3 = p3.GetExprVar().size(); + + if (n2 + n3 != 2 * n2 || int(n2) != nExprVar) + { + *m_stream << _T(" Number of expression variables is incorrect. (expected: ") + << nExprVar << _T("; detected: ") << n2 << _T(")"); + } + } + + // Check the three results + // 1.) computed results must have identic type + char_type cType = fVal[0].GetType(); + bool bStat = cType == fVal[1].GetType() && + cType == fVal[2].GetType() && + cType == fVal[3].GetType() && + cType == fVal[4].GetType(); + if (!bStat) + { + *m_stream << _T("\n ") << a_str << _T(" : inconsistent result type (") + << fVal[0].GetType() << _T(", ") + << fVal[1].GetType() << _T(", ") + << fVal[2].GetType() << _T(", ") + << fVal[3].GetType() << _T(", ") + << fVal[4].GetType() << _T(")"); + return 1; + } + + if ((cType == 'c' || a_val.GetType() == 'c') && cType != a_val.GetType()) + { + *m_stream << _T("\n ") << a_str << _T(" : Complex value sliced!"); + return 1; + } + + // Compare the results + switch (cType) + { + case 'i': + case 'b': + case 's': bStat = (a_val == fVal[0] && + a_val == fVal[1] && + a_val == fVal[2] && + a_val == fVal[3] && + a_val == fVal[4]); + break; + + // We need more attention for comaring float values due to floating point + // inaccuracies. + case 'f': + { + bStat = true; + int num = sizeof(fVal) / sizeof(Value); + for (int i = 0; i < num; ++i) + bStat &= (fabs(a_val.GetFloat() - fVal[i].GetFloat()) <= fabs(fVal[i].GetFloat()*0.0001)); + } + break; + + case 'c': + { + bStat = true; + int num = sizeof(fVal) / sizeof(Value); + for (int i = 0; i < num; ++i) + { + bStat &= (fabs(a_val.GetFloat() - fVal[i].GetFloat()) <= std::max((float_type)1e-15, fabs(fVal[i].GetFloat() * (float_type)0.0000001))); + bStat &= (fabs(a_val.GetImag() - fVal[i].GetImag()) <= std::max((float_type)1e-15, fabs(fVal[i].GetImag() * (float_type)0.0000001))); + } + } + break; + + case 'm': + { + bStat = true; + int num = sizeof(fVal) / sizeof(Value); + + for (int i = 0; i < num; ++i) + { + struct CheckArray + { + CheckArray() + {} + + bool Check(IValue &v1, IValue &v2) + { + if (v1.GetType() != v2.GetType()) + return false; + + if (v1.GetRows() != v2.GetRows()) + return false; + + if (v1.IsMatrix()) + { + for (int i = 0; i < v1.GetRows(); ++i) + { + for (int j = 0; j < v1.GetCols(); ++j) + { + if (!Check(v1.At(i, j), v2.At(i, j))) + return false; + } + } + + return true; + } + else + { + return (fabs(v1.GetFloat() - v2.GetFloat()) <= std::max((float_type)1e-15, fabs(v1.GetFloat() * (float_type)0.0000001))); + } + } + } checker; + + bStat = checker.Check(a_val, fVal[i]); + if (!bStat) + break; + } + } + break; + + default: + throw std::runtime_error("Parser return value has an unexpected typecode."); + } + + iRet = (bStat == a_fPass) ? 0 : 1; + } + catch (ParserError &e) + { + *m_stream << _T("\n ") << a_str << _T(" : ") << e.GetMsg(); + return 1; + } + catch (std::exception &e) + { + *m_stream << _T("\n ") << a_str << _T(" : ") << e.what() << _T("\n"); + return 1; + } + catch (...) + { + *m_stream << _T("\n \"") << a_str << _T("\" : ") << _T("Unexpected Eception"); + return 1; + } + + if (iRet) + { + *m_stream << _T("\n ") << a_str << _T(" : ") << _T("(at least one incorrect result ") + << fVal[0] << _T(", ") + << fVal[1] << _T(", ") + << fVal[2] << _T(", ") + << fVal[3] << _T(", ") + << fVal[4] << _T("; expected=") << a_val << _T(")"); + } + + return iRet; +} + +//--------------------------------------------------------------------------- +/** \brief Internal error in test class Test is going to be aborted. */ +void ParserTester::Abort() const +{ + *m_stream << _T("\nTest failed (internal error in test class)") << endl; + while (!getchar()); + exit(-1); +} + +//--------------------------------------------------------------------------- +void ParserTester::Assessment(int a_iNumErr) const +{ + if (a_iNumErr == 0) + *m_stream << _T("passed") << endl; + else + *m_stream << _T("\n failed with ") << a_iNumErr << _T(" errors") << endl; +} +MUP_NAMESPACE_END diff --git a/Software/PC_Application/Traces/Math/parser/mpTest.h b/Software/PC_Application/Traces/Math/parser/mpTest.h new file mode 100644 index 0000000..1a18506 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpTest.h @@ -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 +#include // 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 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 + + diff --git a/Software/PC_Application/Traces/Math/parser/mpTokenReader.cpp b/Software/PC_Application/Traces/Math/parser/mpTokenReader.cpp new file mode 100644 index 0000000..7737adc --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpTokenReader.cpp @@ -0,0 +1,1026 @@ +/** \file + \brief Implementation of the token reader used to break the expression string up + into tokens. + +
+				__________                                 ____  ___
+	 _____  __ _\______   \_____ _______  ______ __________\   \/  /
+	/     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+	|  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 "mpTokenReader.h" + +#include + +#include "mpParserBase.h" +#include "mpIValReader.h" +#include "mpIfThenElse.h" +#include "mpScriptTokens.h" +#include "mpOprtIndex.h" +#include "mpOprtMatrix.h" + +MUP_NAMESPACE_START + +//--------------------------------------------------------------------------- +/** \brief Copy constructor. + \sa Assign + \throw nothrow + */ + TokenReader::TokenReader(const TokenReader &a_Reader) +{ + Assign(a_Reader); +} + +//--------------------------------------------------------------------------- +/** \brief Assignement operator. + \param a_Reader Object to copy to this token reader. + \throw nothrow + + Self assignement will be suppressed otherwise #Assign is called. + */ +TokenReader& TokenReader::operator=(const TokenReader &a_Reader) +{ + if (&a_Reader != this) + Assign(a_Reader); + + return *this; +} + +//--------------------------------------------------------------------------- +/** \brief Assign state of a token reader to this token reader. + \param a_Reader Object from which the state should be copied. + \throw nothrow + */ +void TokenReader::Assign(const TokenReader &obj) +{ + m_pParser = obj.m_pParser; + m_sExpr = obj.m_sExpr; + m_nPos = obj.m_nPos; + m_nNumBra = obj.m_nNumBra; + m_nNumIndex = obj.m_nNumIndex; + m_nNumCurly = obj.m_nNumCurly; + m_nNumIfElse = obj.m_nNumIfElse; + m_nSynFlags = obj.m_nSynFlags; + m_UsedVar = obj.m_UsedVar; + m_pVarDef = obj.m_pVarDef; + m_pPostOprtDef = obj.m_pPostOprtDef; + m_pInfixOprtDef = obj.m_pInfixOprtDef; + m_pOprtDef = obj.m_pOprtDef; + m_pFunDef = obj.m_pFunDef; + m_pConstDef = obj.m_pConstDef; + m_pDynVarShadowValues = obj.m_pDynVarShadowValues; + m_vTokens = obj.m_vTokens; + + // Reader klassen klonen + DeleteValReader(); + std::size_t i, iSize = obj.m_vValueReader.size(); + for (i = 0; i < iSize; ++i) + { + m_vValueReader.push_back(obj.m_vValueReader[i]->Clone(this)); + } +} + +//--------------------------------------------------------------------------- +/** \brief Constructor. + + Create a Token reader and bind it to a parser object. + + \pre [assert] a_pParser may not be nullptr + \post #m_pParser==a_pParser + \param a_pParent Parent parser object of the token reader. + */ +TokenReader::TokenReader(ParserXBase *a_pParent) + :m_pParser(a_pParent) + , m_sExpr() + , m_nPos(0) + , m_nNumBra(0) + , m_nNumIndex(0) + , m_nNumCurly(0) + , m_nNumIfElse(0) + , m_nSynFlags(0) + , m_vTokens() + , m_eLastTokCode(cmUNKNOWN) + , m_pFunDef(nullptr) + , m_pOprtDef(nullptr) + , m_pInfixOprtDef(nullptr) + , m_pPostOprtDef(nullptr) + , m_pConstDef(nullptr) + , m_pDynVarShadowValues(nullptr) + , m_pVarDef(nullptr) + , m_vValueReader() + , m_UsedVar() + , m_fZero(0) +{ + assert(m_pParser); + SetParent(m_pParser); +} + +//--------------------------------------------------------------------------- +/** \brief Destructor (trivial). + + \throw nothrow + */ +TokenReader::~TokenReader() +{ + DeleteValReader(); +} + +//--------------------------------------------------------------------------- +void TokenReader::DeleteValReader() +{ + int iSize = (int)m_vValueReader.size(); + for (int i = 0; i < iSize; ++i) + delete m_vValueReader[i]; + + m_vValueReader.clear(); +} + +//--------------------------------------------------------------------------- +/** \brief Create instance of a ParserTokenReader identical with this + and return its pointer. + + This is a factory method the calling function must take care of the object destruction. + + \return A new ParserTokenReader object. + \throw nothrow + */ +TokenReader* TokenReader::Clone(ParserXBase *a_pParent) const +{ + std::unique_ptr ptr(new TokenReader(*this)); + ptr->SetParent(a_pParent); + return ptr.release(); +} + +//--------------------------------------------------------------------------- +void TokenReader::AddValueReader(IValueReader *a_pReader) +{ + a_pReader->SetParent(this); + m_vValueReader.push_back(a_pReader); +} + +//--------------------------------------------------------------------------- +void TokenReader::AddSynFlags(int flag) +{ + m_nSynFlags |= flag; +} + +//--------------------------------------------------------------------------- +const TokenReader::token_buf_type& TokenReader::GetTokens() const +{ + return m_vTokens; +} + +//--------------------------------------------------------------------------- +/** \brief Return the current position of the token reader in the formula string. + + \return #m_nPos + \throw nothrow + */ +int TokenReader::GetPos() const +{ + return m_nPos; +} + +//--------------------------------------------------------------------------- +/** \brief Return a reference to the formula. + + \return #m_sExpr + \throw nothrow + */ +const string_type& TokenReader::GetExpr() const +{ + return m_sExpr; +} + +//--------------------------------------------------------------------------- +/** \brief Return a map containing the used variables only. */ +const var_maptype& TokenReader::GetUsedVar() const +{ + return m_UsedVar; +} + +//--------------------------------------------------------------------------- +/** \brief Initialize the token Reader. + + Sets the expression position index to zero and set Syntax flags to + default for initial parsing. + */ +void TokenReader::SetExpr(const string_type &a_sExpr) +{ + if (a_sExpr.empty()) + throw ParserError(_T("Expression is empty!"), ecUNEXPECTED_EOF); + + if (a_sExpr.find_first_not_of(' ') == std::string::npos) + throw ParserError(_T("Expression is empty!"), ecUNEXPECTED_EOF); + + if (std::all_of(a_sExpr.begin(), a_sExpr.end(), [](char_type c) { return !std::isgraph(c); })) + throw ParserError(_T("Non printable characters in expression found!")); + + // Check maximum allowed expression length. An arbitrary value small enough so i can debug expressions sent to me + if (a_sExpr.length() >= 10000) + throw ParserError(_T("Expression longer than 10000 characters!")); + + m_sExpr = a_sExpr; + ReInit(); +} + +//--------------------------------------------------------------------------- +/** \brief Reset the token reader to the start of the formula. + \post #m_nPos==0, #m_nSynFlags = noOPT | noBC | noPOSTOP | noSTR + \throw nothrow + \sa ESynCodes + + The syntax flags will be reset to a value appropriate for the + start of a formula. + */ +void TokenReader::ReInit() +{ + m_nPos = 0; + m_nNumBra = 0; + m_nNumIndex = 0; + m_nNumCurly = 0; + m_nNumIfElse = 0; + m_nSynFlags = noOPT | noBC | noCBC | noPFX | noCOMMA | noIO | noIC | noIF | noELSE; + m_UsedVar.clear(); + m_eLastTokCode = cmUNKNOWN; + m_vTokens.clear(); +} + +//--------------------------------------------------------------------------- +const ptr_tok_type& TokenReader::Store(const ptr_tok_type &t, int token_pos) +{ + m_eLastTokCode = t->GetCode(); + t->SetExprPos(token_pos); + m_vTokens.push_back(t); + return t; +} + +//--------------------------------------------------------------------------- +void TokenReader::SkipCommentsAndWhitespaces() +{ + bool bSkip = true; + while (m_nPos < static_cast(m_sExpr.length()) && bSkip) + { + switch (m_sExpr[m_nPos]) + { + // skip comments + case '#': + { + std::size_t i = m_sExpr.find_first_of('\n', m_nPos + 1); + m_nPos = static_cast((i != string_type::npos) ? i : m_sExpr.length()); + } + break; + + // skip whitespaces + case ' ': + ++m_nPos; + break; + + default: + bSkip = false; + } // switch + } // while comment or whitespace +} + +//--------------------------------------------------------------------------- +/** \brief Read the next token from the string. */ +ptr_tok_type TokenReader::ReadNextToken() +{ + assert(m_pParser); + + SkipCommentsAndWhitespaces(); + + int token_pos = m_nPos; + ptr_tok_type pTok; + + // Check for end of expression + if (IsEOF(pTok)) + return Store(pTok, token_pos); + + if (IsNewline(pTok)) + return Store(pTok, token_pos); + + if (!(m_nSynFlags & noOPT) && IsOprt(pTok)) + return Store(pTok, token_pos); // Check for user defined binary operator + + if (!(m_nSynFlags & noIFX) && IsInfixOpTok(pTok)) + return Store(pTok, token_pos); // Check for unary operators + + if (IsValTok(pTok)) + return Store(pTok, token_pos); // Check for values / constant tokens + + if (IsBuiltIn(pTok)) + return Store(pTok, token_pos); // Check built in operators / tokens + + if (IsVarOrConstTok(pTok)) + return Store(pTok, token_pos); // Check for variable tokens + + if (IsFunTok(pTok)) + return Store(pTok, token_pos); + + if (!(m_nSynFlags & noPFX) && IsPostOpTok(pTok)) + return Store(pTok, token_pos); // Check for unary operators + + // 2.) We have found no token, maybe there is a token that we don't expect here. + // Again call the Identifier functions but this time only those we don't expect + // to find. + if ((m_nSynFlags & noOPT) && IsOprt(pTok)) + return Store(pTok, token_pos); // Check for user defined binary operator + + if ((m_nSynFlags & noIFX) && IsInfixOpTok(pTok)) + return Store(pTok, token_pos); // Check for unary operators + + if ((m_nSynFlags & noPFX) && IsPostOpTok(pTok)) + return Store(pTok, token_pos); // Check for unary operators + // + + // Now we are in trouble because there is something completely unknown.... + + // Check the string for an undefined variable token. This is done + // only if a flag is set indicating to ignore undefined variables. + // This is a way to conditionally avoid an error if undefined variables + // occur. The GetExprVar function must supress the error for undefined + // variables in order to collect all variable names including the + // undefined ones. + if ((m_pParser->m_bIsQueryingExprVar || m_pParser->m_bAutoCreateVar) && IsUndefVarTok(pTok)) + return Store(pTok, token_pos); + + // Check for unknown token + // + // !!! From this point on there is no exit without an exception possible... + // + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos); + + ErrorContext err; + err.Errc = ecUNASSIGNABLE_TOKEN; + err.Expr = m_sExpr; + err.Pos = m_nPos; + + if (iEnd != m_nPos) + err.Ident = sTok; + else + err.Ident = m_sExpr.substr(m_nPos); + + throw ParserError(err); +} + +//--------------------------------------------------------------------------- +void TokenReader::SetParent(ParserXBase *a_pParent) +{ + m_pParser = a_pParent; + m_pFunDef = &a_pParent->m_FunDef; + m_pOprtDef = &a_pParent->m_OprtDef; + m_pInfixOprtDef = &a_pParent->m_InfixOprtDef; + m_pPostOprtDef = &a_pParent->m_PostOprtDef; + m_pVarDef = &a_pParent->m_varDef; + m_pConstDef = &a_pParent->m_valDef; + m_pDynVarShadowValues = &a_pParent->m_valDynVarShadow; +} + +//--------------------------------------------------------------------------- +/** \brief Extract all characters that belong to a certain charset. + \param a_szCharSet [in] Const char array of the characters allowed in the token. + \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet. + \param a_iPos [in] Position in the string from where to start reading. + \return The Position of the first character not listed in a_szCharSet. + \throw nothrow + */ +int TokenReader::ExtractToken(const char_type *a_szCharSet, + string_type &a_sTok, + int a_iPos) const +{ + int iEnd = (int)m_sExpr.find_first_not_of(a_szCharSet, a_iPos); + + if (iEnd == (int)string_type::npos) + iEnd = (int)m_sExpr.length(); + + if (iEnd != a_iPos) + a_sTok.assign(m_sExpr.begin() + a_iPos, m_sExpr.begin() + iEnd); + + return iEnd; +} + +//--------------------------------------------------------------------------- +/** \brief Check if a built in operator or other token can be found. +*/ +bool TokenReader::IsBuiltIn(ptr_tok_type &a_Tok) +{ + const char_type **pOprtDef = m_pParser->GetOprtDef(), + *szFormula = m_sExpr.c_str(); + int i; + + try + { + // Compare token with function and operator strings + // check string for operator/function + for (i = 0; pOprtDef[i]; i++) + { + std::size_t len(std::char_traits::length(pOprtDef[i])); + if (string_type(pOprtDef[i]) == string_type(szFormula + m_nPos, szFormula + m_nPos + len)) + { + switch (i) + { + case cmARG_SEP: + if (m_nSynFlags & noCOMMA) + throw ecUNEXPECTED_COMMA; + + m_nSynFlags = noBC | noCBC | noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE; + a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i])); + break; + + case cmELSE: + if (m_nSynFlags & noELSE) + throw ecMISPLACED_COLON; + + m_nNumIfElse--; + if (m_nNumIfElse < 0) + throw ecMISPLACED_COLON; + + m_nSynFlags = noBC | noCBC | noIO | noIC | noPFX | noEND | noNEWLINE | noCOMMA | noOPT | noIF | noELSE; + a_Tok = ptr_tok_type(new TokenIfThenElse(cmELSE)); + break; + + case cmIF: + if (m_nSynFlags & noIF) + throw ecUNEXPECTED_CONDITIONAL; + + m_nNumIfElse++; + m_nSynFlags = noBC | noCBC | noIO | noPFX | noIC | noEND | noNEWLINE | noCOMMA | noOPT | noIF | noELSE; + a_Tok = ptr_tok_type(new TokenIfThenElse(cmIF)); + break; + + case cmBO: + if (m_nSynFlags & noBO) + throw ecUNEXPECTED_PARENS; + + if (m_eLastTokCode == cmFUNC) + { + m_nSynFlags = noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE | noCBC; + } + else + { + m_nSynFlags = noBC | noOPT | noEND | noNEWLINE | noCOMMA | noPFX | noIC | noIO | noIF | noELSE | noCBC; + } + + m_nNumBra++; + a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i])); + break; + + case cmBC: + if (m_nSynFlags & noBC) + throw ecUNEXPECTED_PARENS; + + m_nSynFlags = noBO | noVAR | noVAL | noFUN | noIFX | noCBO; + m_nNumBra--; + + if (m_nNumBra < 0) + throw ecUNEXPECTED_PARENS; + + a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i])); + break; + + case cmIO: + if (m_nSynFlags & noIO) + throw ecUNEXPECTED_SQR_BRACKET; + + m_nSynFlags = noIC | noIO | noOPT | noPFX | noBC | noNEWLINE | noCBC | noCOMMA; + m_nNumIndex++; + a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i])); + break; + + case cmIC: + if (m_nSynFlags & noIC) + throw ecUNEXPECTED_SQR_BRACKET; + + m_nSynFlags = noBO | noIFX | noCBO; + m_nNumIndex--; + + if (m_nNumIndex < 0) + throw ecUNEXPECTED_SQR_BRACKET; + + a_Tok = ptr_tok_type(new OprtIndex()); + break; + + case cmCBO: + if (m_nSynFlags & noVAL) + throw ecUNEXPECTED_CURLY_BRACKET; + + m_nSynFlags = noCBC | noIC | noIO | noOPT | noPFX | noBC | noNEWLINE | noCOMMA | noIF; + m_nNumCurly++; + a_Tok = ptr_tok_type(new GenericToken((ECmdCode)i, pOprtDef[i])); + break; + + case cmCBC: + if (m_nSynFlags & noIC) + throw ecUNEXPECTED_CURLY_BRACKET; + + m_nSynFlags = noBO | noCBO | noIFX; + m_nNumCurly--; + + if (m_nNumCurly < 0) + throw ecUNEXPECTED_CURLY_BRACKET; + + a_Tok = ptr_tok_type(new OprtCreateArray()); + break; + + default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing... + throw ecINTERNAL_ERROR; + } // switch operator id + + m_nPos += (int)len; + return true; + } // if operator string found + } // end of for all operator strings + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Expr = m_sExpr; + err.Ident = pOprtDef[i]; + err.Pos = m_nPos; + throw ParserError(err); + } + + return false; +} + +//--------------------------------------------------------------------------- +/** \brief Check for End of expression +*/ +bool TokenReader::IsNewline(ptr_tok_type &a_Tok) +{ + // nicht nach: bionop, infixop, argumentseparator, + // erlaubt nach: Werten, variablen, schließenden klammern, schliessendem index + bool bRet(false); + try + { + if (m_sExpr[m_nPos] == '\n') + { + // Check if all brackets were closed + if (m_nSynFlags & noNEWLINE) + throw ecUNEXPECTED_NEWLINE; + + if (m_nNumBra > 0) + throw ecMISSING_PARENS; + + if (m_nNumIndex > 0) + throw ecMISSING_SQR_BRACKET; + + if (m_nNumCurly > 0) + throw ecMISSING_CURLY_BRACKET; + + if (m_nNumIfElse > 0) + throw(ecMISSING_ELSE_CLAUSE); + + m_nPos++; + m_nSynFlags = sfSTART_OF_LINE; + a_Tok = ptr_tok_type(new TokenNewline()); + bRet = true; + } + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Ident = _T(""); + err.Expr = m_sExpr; + err.Pos = m_nPos; + throw ParserError(err); + } + + return bRet; +} + +//--------------------------------------------------------------------------- +/** \brief Check for End of expression +*/ +bool TokenReader::IsEOF(ptr_tok_type &a_Tok) +{ + bool bRet(false); + try + { + if (m_sExpr.length() && m_nPos >= (int)m_sExpr.length()) + { + if (m_nSynFlags & noEND) + throw ecUNEXPECTED_EOF; + + if (m_nNumBra > 0) + throw ecMISSING_PARENS; + + if (m_nNumCurly > 0) + throw ecMISSING_CURLY_BRACKET; + + if (m_nNumIndex > 0) + throw ecMISSING_SQR_BRACKET; + + if (m_nNumIfElse > 0) + throw ecMISSING_ELSE_CLAUSE; + + m_nSynFlags = 0; + a_Tok = ptr_tok_type(new GenericToken(cmEOE)); + bRet = true; + } + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Ident = _T(""); + err.Expr = m_sExpr; + err.Pos = m_nPos; + throw ParserError(err); + } + + return bRet; +} + +//--------------------------------------------------------------------------- +/** \brief Check if a string position contains a unary infix operator. + \return true if a function token has been found false otherwise. + */ +bool TokenReader::IsInfixOpTok(ptr_tok_type &a_Tok) +{ + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_nPos); + + if (iEnd == m_nPos) + return false; + + try + { + // iteraterate over all infix operator strings + oprt_ifx_maptype::const_iterator item = m_pInfixOprtDef->begin(); + for (item = m_pInfixOprtDef->begin(); item != m_pInfixOprtDef->end(); ++item) + { + if (sTok.find(item->first) != 0) + continue; + + a_Tok = ptr_tok_type(item->second->Clone()); + m_nPos += (int)item->first.length(); + + if (m_nSynFlags & noIFX) + throw ecUNEXPECTED_OPERATOR; + + m_nSynFlags = noPFX | noIFX | noOPT | noBC | noIC | noIO | noEND | noCOMMA | noNEWLINE | noIF | noELSE; + return true; + } + + return false; + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Pos = m_nPos; + err.Ident = a_Tok->GetIdent(); + err.Expr = m_sExpr; + throw ParserError(err); + } +} + +//--------------------------------------------------------------------------- +/** \brief Check expression for function tokens. */ +bool TokenReader::IsFunTok(ptr_tok_type &a_Tok) +{ + if (m_pFunDef->size() == 0) + return false; + + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos); + if (iEnd == m_nPos) + return false; + + try + { + fun_maptype::iterator item = m_pFunDef->find(sTok); + if (item == m_pFunDef->end()) + return false; + + m_nPos = (int)iEnd; + a_Tok = ptr_tok_type(item->second->Clone()); + a_Tok->Compile(_T("xxx")); + + if (m_nSynFlags & noFUN) + throw ecUNEXPECTED_FUN; + + m_nSynFlags = sfALLOW_NONE ^ noBO; + return true; + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Pos = m_nPos - (int)a_Tok->GetIdent().length(); + err.Ident = a_Tok->GetIdent(); + err.Expr = m_sExpr; + throw ParserError(err); + } +} + +//--------------------------------------------------------------------------- +/** \brief Check if a string position contains a unary post value operator. */ +bool TokenReader::IsPostOpTok(ptr_tok_type &a_Tok) +{ + if (m_nSynFlags & noPFX) + { + // Only look for postfix operators if they are allowed at the given position. + // This will prevent conflicts with variable names such as: + // "sin(n)" where n is the postfix for "nano" + return false; + // + } + + // Tricky problem with equations like "3m+5": + // m is a postfix operator, + is a valid sign for postfix operators and + // for binary operators parser detects "m+" as operator string and + // finds no matching postfix operator. + // + // This is a special case so this routine slightly differs from the other + // token readers. + + // Test if there could be a postfix operator + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_nPos); + if (iEnd == m_nPos) + return false; + + try + { + // iteraterate over all postfix operator strings + oprt_pfx_maptype::const_iterator item; + for (item = m_pPostOprtDef->begin(); item != m_pPostOprtDef->end(); ++item) + { + if (sTok.find(item->first) != 0) + continue; + + a_Tok = ptr_tok_type(item->second->Clone()); + m_nPos += (int)item->first.length(); + + if (m_nSynFlags & noPFX) + throw ecUNEXPECTED_OPERATOR; + + m_nSynFlags = noVAL | noVAR | noFUN | noBO | noPFX /*| noIO*/ | noIF; + return true; + } + + return false; + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Pos = m_nPos - (int)a_Tok->GetIdent().length(); + err.Ident = a_Tok->GetIdent(); + err.Expr = m_sExpr; + throw ParserError(err); + } +} + +//--------------------------------------------------------------------------- +/** \brief Check if a string position contains a binary operator. */ +bool TokenReader::IsOprt(ptr_tok_type &a_Tok) +{ + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_nPos); + if (iEnd == m_nPos) + return false; + + oprt_bin_maptype::reverse_iterator item; + try + { + // Note: + // All tokens in oprt_bin_maptype are have been sorted by their length + // Long operators must come first! Otherwise short names (like: "add") that + // are part of long token names (like: "add123") will be found instead + // of the long ones. + // Length sorting is done with ascending length so we use a reverse iterator here. + for (item = m_pOprtDef->rbegin(); item != m_pOprtDef->rend(); ++item) + { + if (sTok.find(item->first) != 0) + continue; + + // operator found, check if we expect one... + if (m_nSynFlags & noOPT) + { + // An operator was found but is not expected to occur at + // this position of the formula, maybe it is an infix + // operator, not a binary operator. Both operator types + // can use the same characters in their identifiers. + if (IsInfixOpTok(a_Tok)) + return true; + + // nope, it's no infix operator and we dont expect + // an operator + throw ecUNEXPECTED_OPERATOR; + } + else + { + a_Tok = ptr_tok_type(item->second->Clone()); + + m_nPos += (int)a_Tok->GetIdent().length(); + m_nSynFlags = noBC | noIO | noIC | noOPT | noCOMMA | noEND | noNEWLINE | noPFX | noIF | noELSE; + return true; + } + } + + return false; + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Pos = m_nPos; // - (int)item->first.length(); + err.Ident = item->first; + err.Expr = m_sExpr; + throw ParserError(err); + } +} + +//--------------------------------------------------------------------------- +/** \brief Check whether the token at a given position is a value token. + + Value tokens are either values or constants. + + \param a_Tok [out] If a value token is found it will be placed here. + \return true if a value token has been found. + */ +bool TokenReader::IsValTok(ptr_tok_type &a_Tok) +{ + if (m_vValueReader.size() == 0) + return false; + + stringstream_type stream(m_sExpr.c_str() + m_nPos); + string_type sTok; + + try + { + // call the value recognition functions provided by the user + // Call user defined value recognition functions + int iSize = (int)m_vValueReader.size(); + Value val; + for (int i = 0; i < iSize; ++i) + { + int iStart = m_nPos; + if (m_vValueReader[i]->IsValue(m_sExpr.c_str(), m_nPos, val)) + { + sTok.assign(m_sExpr.c_str(), iStart, m_nPos); + if (m_nSynFlags & noVAL) + throw ecUNEXPECTED_VAL; + + m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX | noIO; + a_Tok = ptr_tok_type(val.Clone()); + a_Tok->SetIdent(string_type(sTok.begin(), sTok.begin() + (m_nPos - iStart))); + return true; + } + } + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Pos = m_nPos; + err.Ident = sTok; + err.Expr = m_sExpr; + err.Pos = m_nPos - (int)sTok.length(); + throw ParserError(err); + } + + return false; +} + +//--------------------------------------------------------------------------- +/** \brief Check wheter a token at a given position is a variable token. + \param a_Tok [out] If a variable token has been found it will be placed here. + \return true if a variable token has been found. + */ +bool TokenReader::IsVarOrConstTok(ptr_tok_type &a_Tok) +{ + if (!m_pVarDef->size() && !m_pConstDef->size() && !m_pFunDef->size()) + return false; + + string_type sTok; + int iEnd; + try + { + iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos); + if (iEnd == m_nPos || (sTok.size() > 0 && sTok[0] >= _T('0') && sTok[0] <= _T('9'))) + return false; + + // Check for variables + var_maptype::const_iterator item = m_pVarDef->find(sTok); + if (item != m_pVarDef->end()) + { + if (m_nSynFlags & noVAR) + throw ecUNEXPECTED_VAR; + + m_nPos = iEnd; + m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX; + a_Tok = ptr_tok_type(item->second->Clone()); + a_Tok->SetIdent(sTok); + m_UsedVar[item->first] = item->second; // Add variable to used-var-list + return true; + } + + // Check for constants + item = m_pConstDef->find(sTok); + if (item != m_pConstDef->end()) + { + if (m_nSynFlags & noVAL) + throw ecUNEXPECTED_VAL; + + m_nPos = iEnd; + m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX | noIO; + a_Tok = ptr_tok_type(item->second->Clone()); + a_Tok->SetIdent(sTok); + return true; + } + } + catch (EErrorCodes e) + { + ErrorContext err; + err.Errc = e; + err.Pos = m_nPos; + err.Ident = sTok; + err.Expr = m_sExpr; + throw ParserError(err); + } + + return false; +} + +//--------------------------------------------------------------------------- +bool TokenReader::IsComment() +{ + return false; +} + +//--------------------------------------------------------------------------- +/** \brief Check wheter a token at a given position is an undefined variable. + \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here. + \return true if a variable token has been found. + \throw nothrow + */ +bool TokenReader::IsUndefVarTok(ptr_tok_type &a_Tok) +{ + string_type sTok; + int iEnd = ExtractToken(m_pParser->ValidNameChars(), sTok, m_nPos); + if (iEnd == m_nPos || (sTok.size() > 0 && sTok[0] >= _T('0') && sTok[0] <= _T('9'))) + return false; + + if (m_nSynFlags & noVAR) + { + ErrorContext err; + err.Errc = ecUNEXPECTED_VAR; + err.Ident = sTok; + err.Expr = m_sExpr; + err.Pos = m_nPos; + throw ParserError(err); + } + + // Create a variable token + if (m_pParser->m_bAutoCreateVar) + { + ptr_val_type val(new Value); // Create new value token + m_pDynVarShadowValues->push_back(val); // push to the vector of shadow values + a_Tok = ptr_tok_type(new Variable(val.Get())); // bind variable to the new value item + (*m_pVarDef)[sTok] = a_Tok; // add new variable to the variable list + } + else + a_Tok = ptr_tok_type(new Variable(nullptr)); // bind variable to empty variable + + a_Tok->SetIdent(sTok); + m_UsedVar[sTok] = a_Tok; // add new variable to used-var-list + + m_nPos = iEnd; + m_nSynFlags = noVAL | noVAR | noFUN | noBO | noIFX; + return true; +} +} // namespace mu diff --git a/Software/PC_Application/Traces/Math/parser/mpTokenReader.h b/Software/PC_Application/Traces/Math/parser/mpTokenReader.h new file mode 100644 index 0000000..ba303f1 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpTokenReader.h @@ -0,0 +1,137 @@ +/** \file + \brief Definition of the token reader used to break the expression string up + into tokens. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_TOKEN_READER_H +#define MUP_TOKEN_READER_H + +//--- Standard includes ---------------------------------------------------- +#include +#include +#include +#include +#include +#include + +//--- 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 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 + + diff --git a/Software/PC_Application/Traces/Math/parser/mpTypes.h b/Software/PC_Application/Traces/Math/parser/mpTypes.h new file mode 100644 index 0000000..0d7764e --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpTypes.h @@ -0,0 +1,406 @@ +/** \file + \brief Definition of basic types used by muParserX + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+  |  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_TYPES_H +#define MUP_TYPES_H + +//--- Standard include ------------------------------------------------------ +#include +#include +#include +#include +#include +#include + +//--- 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 +class TokenPtr; + +/** \brief Type of a managed pointer storing parser tokens. */ +typedef TokenPtr ptr_tok_type; + +/** \brief Type of a managed pointer storing callback tokens. */ +typedef TokenPtr ptr_cal_type; + +/** \brief Type of a managed pointer storing value tokens. */ +typedef TokenPtr ptr_val_type; + +/** \brief Type of a managed pointer storing binary operator tokens. */ +typedef TokenPtr ptr_binop_type; + +/** \brief Type for a vector of tokens. */ +typedef std::vector token_vec_type; + +/** \brief Type for a vector of value items. */ +typedef std::vector 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 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 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, std::allocator > stringstream_type; + +/** \brief Type of a vector holding pointers to value reader objects. */ +typedef std::vector readervec_type; + +/** \brief type for the parser variable storage. */ +typedef std::map var_maptype; + +/** \brief type of a container used to store parser values. */ +typedef std::map val_maptype; + +/** \brief Type of a container that binds Callback object pointer + to operator identifiers. */ +typedef std::map fun_maptype; + +/** \brief Type of a container that binds Callback object pointer + to operator identifiers. +*/ +typedef std::map > oprt_bin_maptype; + +/** \brief Type of a map for storing postfix operators by their name. */ +typedef std::map oprt_pfx_maptype; + +/** \brief Type of a map for storing infix operators by their name. */ +typedef std::map 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpValReader.cpp b/Software/PC_Application/Traces/Math/parser/mpValReader.cpp new file mode 100644 index 0000000..8add7b0 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpValReader.cpp @@ -0,0 +1,347 @@ +/** \file + \brief Implementation of classes that interpret values in a string. + +
+                 __________                                 ____  ___
+      _____  __ _\______   \_____ _______  ______ __________\   \/  /
+     /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+    |  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 "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::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; + + // 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 diff --git a/Software/PC_Application/Traces/Math/parser/mpValReader.h b/Software/PC_Application/Traces/Math/parser/mpValReader.h new file mode 100644 index 0000000..f1e8cbf --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpValReader.h @@ -0,0 +1,138 @@ +/** \file + \brief Definition of classes that interpret values in a string. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 diff --git a/Software/PC_Application/Traces/Math/parser/mpValue.cpp b/Software/PC_Application/Traces/Math/parser/mpValue.cpp new file mode 100644 index 0000000..60b36bb --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpValue.cpp @@ -0,0 +1,810 @@ +/* +
+			 __________                                 ____  ___
+  _____  __ _\______   \_____ _______  ______ __________\   \/  /
+ /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
+|  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 "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 diff --git a/Software/PC_Application/Traces/Math/parser/mpValue.h b/Software/PC_Application/Traces/Math/parser/mpValue.h new file mode 100644 index 0000000..81b1cd1 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpValue.h @@ -0,0 +1,140 @@ +/** \file + \brief Definition of basic types used by muParserX + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_VALUE_H +#define MUP_VALUE_H + +//--- Standard includes ------------------------------------------------------------ +#include +#include + +//--- 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 + + diff --git a/Software/PC_Application/Traces/Math/parser/mpValueCache.cpp b/Software/PC_Application/Traces/Math/parser/mpValueCache.cpp new file mode 100644 index 0000000..b8cfd63 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpValueCache.cpp @@ -0,0 +1,105 @@ +/** \file + \brief Definition of a class for caching unused value items and recycling them. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "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; iGetRef()==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 diff --git a/Software/PC_Application/Traces/Math/parser/mpValueCache.h b/Software/PC_Application/Traces/Math/parser/mpValueCache.h new file mode 100644 index 0000000..85a4e53 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpValueCache.h @@ -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. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 + +#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 m_vCache; + }; + +MUP_NAMESPACE_END + +#endif // include guard diff --git a/Software/PC_Application/Traces/Math/parser/mpVariable.cpp b/Software/PC_Application/Traces/Math/parser/mpVariable.cpp new file mode 100644 index 0000000..a0c56c0 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpVariable.cpp @@ -0,0 +1,395 @@ +/** \file + \brief Implementation of the muParserX variable class. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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 "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 diff --git a/Software/PC_Application/Traces/Math/parser/mpVariable.h b/Software/PC_Application/Traces/Math/parser/mpVariable.h new file mode 100644 index 0000000..612ab57 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/mpVariable.h @@ -0,0 +1,113 @@ +/** \file + \brief Definition of the muParserX variable class. + +
+               __________                                 ____  ___
+    _____  __ _\______   \_____ _______  ______ __________\   \/  /
+   /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     / 
+  |  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_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 + + diff --git a/Software/PC_Application/Traces/Math/parser/suSortPred.h b/Software/PC_Application/Traces/Math/parser/suSortPred.h new file mode 100644 index 0000000..8e9df96 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/suSortPred.h @@ -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 + 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 diff --git a/Software/PC_Application/Traces/Math/parser/suStringTokens.h b/Software/PC_Application/Traces/Math/parser/suStringTokens.h new file mode 100644 index 0000000..ce74207 --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/suStringTokens.h @@ -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 +#include +#include +#include + + +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 +/* final */ class StringTokens +{ +public: + typedef TData string_type; + typedef typename TData::value_type char_type; + +private: + typedef std::vector 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(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 diff --git a/Software/PC_Application/Traces/Math/parser/utGeneric.h b/Software/PC_Application/Traces/Math/parser/utGeneric.h new file mode 100644 index 0000000..88d471a --- /dev/null +++ b/Software/PC_Application/Traces/Math/parser/utGeneric.h @@ -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 + 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 diff --git a/Software/PC_Application/Traces/Math/tdr.cpp b/Software/PC_Application/Traces/Math/tdr.cpp index ec60792..bc9288d 100644 --- a/Software/PC_Application/Traces/Math/tdr.cpp +++ b/Software/PC_Application/Traces/Math/tdr.cpp @@ -4,6 +4,7 @@ #include "ui_tdrdialog.h" #include #include +#include #include "ui_tdrexplanationwidget.h" using namespace Math; using namespace std; diff --git a/Software/PC_Application/Traces/Math/tracemath.cpp b/Software/PC_Application/Traces/Math/tracemath.cpp index 696d3ed..fce714a 100644 --- a/Software/PC_Application/Traces/Math/tracemath.cpp +++ b/Software/PC_Application/Traces/Math/tracemath.cpp @@ -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); diff --git a/Software/PC_Application/Traces/Math/tracemath.h b/Software/PC_Application/Traces/Math/tracemath.h index b05ddb3..ff29cbb 100644 --- a/Software/PC_Application/Traces/Math/tracemath.h +++ b/Software/PC_Application/Traces/Math/tracemath.h @@ -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, }; diff --git a/Software/PC_Application/Traces/trace.cpp b/Software/PC_Application/Traces/trace.cpp index 049bf0c..9f388de 100644 --- a/Software/PC_Application/Traces/trace.cpp +++ b/Software/PC_Application/Traces/trace.cpp @@ -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) diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 5eb2de2..146d2d5 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -592,12 +592,17 @@ void VNA::SettingsChanged(std::function 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); + } + }); } - average.reset(settings.points); - traceModel.clearVNAData(); - UpdateAverageCount(); - UpdateCalWidget(); emit traceModel.SpanChanged(settings.f_start, settings.f_stop); } diff --git a/Software/PC_Application/preferences.cpp b/Software/PC_Application/preferences.cpp index 10dff39..6136c6a 100644 --- a/Software/PC_Application/preferences.cpp +++ b/Software/PC_Application/preferences.cpp @@ -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"); } }); }