2022-10-10 19:43:11 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 2022 Fredrik Öhrström (gpl-3.0-or-later)
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef FORMULA_IMPLEMENTATION
|
|
|
|
#define FORMULA_IMPLEMENTATION
|
|
|
|
|
|
|
|
#include"formula.h"
|
|
|
|
#include"meters.h"
|
|
|
|
|
|
|
|
#include<stack>
|
|
|
|
|
|
|
|
struct NumericFormula
|
|
|
|
{
|
2022-11-01 11:14:48 +00:00
|
|
|
NumericFormula(SIUnit u) : siunit_(u) { }
|
|
|
|
SIUnit &siunit() { return siunit_; }
|
2022-10-10 19:43:11 +00:00
|
|
|
virtual double calculate(Unit to) = 0;
|
|
|
|
virtual string str() = 0;
|
|
|
|
virtual string tree() = 0;
|
|
|
|
virtual ~NumericFormula() = 0;
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2022-11-01 11:14:48 +00:00
|
|
|
SIUnit siunit_;
|
2022-10-10 19:43:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct NumericFormulaConstant : public NumericFormula
|
|
|
|
{
|
|
|
|
NumericFormulaConstant(Unit u, double c) : NumericFormula(u), constant_(c) {}
|
|
|
|
double calculate(Unit to);
|
|
|
|
string str();
|
|
|
|
string tree();
|
|
|
|
~NumericFormulaConstant();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
double constant_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NumericFormulaField : public NumericFormula
|
|
|
|
{
|
|
|
|
NumericFormulaField(Unit u, Meter *m, FieldInfo *fi) : NumericFormula(u), meter_(m), field_info_(fi) {}
|
|
|
|
double calculate(Unit to);
|
|
|
|
string str();
|
|
|
|
string tree();
|
|
|
|
~NumericFormulaField();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
Meter *meter_;
|
|
|
|
FieldInfo *field_info_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NumericFormulaAddition : public NumericFormula
|
|
|
|
{
|
2022-11-01 11:14:48 +00:00
|
|
|
NumericFormulaAddition(SIUnit siu,
|
2022-10-10 19:43:11 +00:00
|
|
|
unique_ptr<NumericFormula> &a,
|
|
|
|
unique_ptr<NumericFormula> &b)
|
2022-11-01 11:14:48 +00:00
|
|
|
: NumericFormula(siu), left_(std::move(a)), right_(std::move(b)) {}
|
2022-10-10 19:43:11 +00:00
|
|
|
|
|
|
|
double calculate(Unit to);
|
|
|
|
string str();
|
|
|
|
string tree();
|
|
|
|
|
|
|
|
~NumericFormulaAddition();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
std::unique_ptr<NumericFormula> left_;
|
|
|
|
std::unique_ptr<NumericFormula> right_;
|
|
|
|
};
|
|
|
|
|
2022-11-01 11:14:48 +00:00
|
|
|
struct NumericFormulaMultiplication : public NumericFormula
|
|
|
|
{
|
|
|
|
NumericFormulaMultiplication(SIUnit siu,
|
|
|
|
unique_ptr<NumericFormula> &a,
|
|
|
|
unique_ptr<NumericFormula> &b)
|
|
|
|
: NumericFormula(siu), left_(std::move(a)), right_(std::move(b)) {}
|
|
|
|
|
|
|
|
double calculate(Unit to);
|
|
|
|
string str();
|
|
|
|
string tree();
|
|
|
|
|
|
|
|
~NumericFormulaMultiplication();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
std::unique_ptr<NumericFormula> left_;
|
|
|
|
std::unique_ptr<NumericFormula> right_;
|
|
|
|
};
|
|
|
|
|
2022-10-10 19:43:11 +00:00
|
|
|
enum class TokenType
|
|
|
|
{
|
|
|
|
SPACE,
|
|
|
|
LPAR,
|
|
|
|
RPAR,
|
|
|
|
NUMBER,
|
|
|
|
PLUS,
|
|
|
|
UNIT,
|
|
|
|
FIELD
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *toString(TokenType tt);
|
|
|
|
|
|
|
|
struct Token
|
|
|
|
{
|
|
|
|
Token(TokenType t, size_t s, size_t l) : type(t), start(s), len(l) {}
|
|
|
|
|
|
|
|
TokenType type;
|
|
|
|
size_t start;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
string str(const string &s);
|
|
|
|
string vals(const string &s);
|
|
|
|
double val(const string &s);
|
|
|
|
Unit unit(const string &s);
|
2022-11-01 11:14:48 +00:00
|
|
|
|
|
|
|
string withMarker(const string &s);
|
2022-10-10 19:43:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct FormulaImplementation : public Formula
|
|
|
|
{
|
|
|
|
bool parse(Meter *m, const string &f);
|
|
|
|
bool valid();
|
2022-11-01 11:14:48 +00:00
|
|
|
string errors();
|
2022-10-10 19:43:11 +00:00
|
|
|
double calculate(Unit to);
|
|
|
|
void clear();
|
|
|
|
string str();
|
|
|
|
string tree();
|
|
|
|
|
|
|
|
// Pushes a constant on the stack.
|
2022-11-01 11:14:48 +00:00
|
|
|
void doConstant(Unit u, double c);
|
|
|
|
// Pushes a field read on the stack.
|
|
|
|
void doField(Unit u, Meter *m, FieldInfo *fi);
|
2022-10-10 19:43:11 +00:00
|
|
|
// Pops the two top nodes of the stack and pushes an addition (using these members) on the stack.
|
2022-11-01 11:14:48 +00:00
|
|
|
// The target unit will be the first unit of the two operands.
|
|
|
|
void doAddition();
|
|
|
|
// Pops the two top nodes of the stack and pushes a multiplication (using these members) on the stack.
|
|
|
|
// The target unit will be multiplication of the SI Units.
|
|
|
|
void doMultiplication();
|
2022-10-10 19:43:11 +00:00
|
|
|
|
|
|
|
~FormulaImplementation();
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
bool tokenize();
|
|
|
|
bool go();
|
|
|
|
size_t findSpace(size_t i);
|
|
|
|
size_t findNumber(size_t i);
|
|
|
|
size_t findUnit(size_t i);
|
|
|
|
size_t findPlus(size_t i);
|
|
|
|
size_t findLPar(size_t i);
|
|
|
|
size_t findRPar(size_t i);
|
|
|
|
size_t findField(size_t i);
|
|
|
|
|
|
|
|
Token *LA(size_t i);
|
|
|
|
size_t parseOps(size_t i);
|
|
|
|
size_t parsePar(size_t i);
|
|
|
|
|
|
|
|
void handleConstant(Token *number, Token *unit);
|
2022-11-01 11:14:48 +00:00
|
|
|
void handleAddition(Token *add);
|
|
|
|
void handleMultiplication(Token *add);
|
2022-10-10 19:43:11 +00:00
|
|
|
void handleField(Token *field);
|
|
|
|
|
2022-11-01 11:14:48 +00:00
|
|
|
void pushOp(NumericFormula *nf);
|
|
|
|
std::unique_ptr<NumericFormula> popOp();
|
|
|
|
NumericFormula *topOp();
|
|
|
|
NumericFormula *top2Op();
|
|
|
|
|
2022-10-10 19:43:11 +00:00
|
|
|
bool valid_ = true;
|
2022-11-01 11:14:48 +00:00
|
|
|
std::vector<std::unique_ptr<NumericFormula>> op_stack_;
|
2022-10-10 19:43:11 +00:00
|
|
|
std::vector<Token> tokens_;
|
|
|
|
std::string formula_; // To be parsed.
|
|
|
|
Meter *meter_; // To be referenced when parsing.
|
2022-11-01 11:14:48 +00:00
|
|
|
|
|
|
|
// Any errors during parsing are store here.
|
|
|
|
std::vector<std::string> errors_;
|
2022-10-10 19:43:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|