Skip to content

Commit

Permalink
expr: Implemented remaining functions
Browse files Browse the repository at this point in the history
  • Loading branch information
Petr Laštovička committed May 11, 2022
1 parent 3639e7e commit cae6f0b
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace cz::lastaapps::vimxel::expr {
// binary general
BinOpNode::BinOpNode(SNode left, SNode right)
: mLeft(left), mRight(right) {}
BinOpNode::BinOpNode(const vector<SNode>& args)
: mLeft(args[0]), mRight(args[1]) {}

// binary number only
shared_ptr<DoubleTerm> BinOpNumNode::castedLeft() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class BinOpNode : public OperatorNode {
const SNode mLeft, mRight;
public:
BinOpNode(SNode left, SNode right);
BinOpNode(const vector<SNode>& args);
};

struct BinOpNumNode : public BinOpNode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace cz::lastaapps::vimxel::expr {
// general n-ary operator
MultiOpNode::MultiOpNode(const vector<SNode>& children)
: mChildren(children) {}

vector<STerm> MultiOpNode::mapped() const {
vector<STerm> result;
auto mapper = [](const SNode& st) { return st->getValue(); };
Expand Down Expand Up @@ -47,7 +48,7 @@ vector<STerm> MultiOpNumOrAreaNode::checked() const {
// number or text
vector<STerm> MultiOpNumOrTextNode::checked() const {
const auto items = mapped();
for (const auto& term : mChildren) {
for (const auto& term : items) {
auto castedDouble = dynamic_pointer_cast<DoubleTerm>(term);
if (castedDouble != nullptr) continue;
auto castedText = dynamic_pointer_cast<TextTerm>(term);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef H_AGREGATE_NODE
#define H_AGREGATE_NODE
#ifndef H_TEXT_MANIP_NODE
#define H_TEXT_MANIP_NODE
#include <memory>
#include "node.hpp"
#include "terms.hpp"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#include "unOperatorNodes.hpp"
#include <stdexcept>

#include <stdexcept>

using namespace std;
namespace cz::lastaapps::vimxel::expr {

// unary general
UnOpNode::UnOpNode(SNode child)
: mChild(child ) {}
: mChild(child) {}
UnOpNode::UnOpNode(const vector<SNode>& args)
: mChild(args[0]) {}

// unary number operator
shared_ptr<DoubleTerm> UnOpNumNode::casted() const {
Expand All @@ -25,4 +27,4 @@ shared_ptr<TextTerm> UnOpTextNode::casted() const {
return casted;
}

}
} // namespace cz::lastaapps::vimxel::expr
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class UnOpNode : public OperatorNode {
const SNode mChild;
public:
UnOpNode(SNode child);
UnOpNode(const vector<SNode>& args);
};

struct UnOpNumNode : public UnOpNode {
Expand Down
104 changes: 96 additions & 8 deletions Semestralni_prace/src/cz/lastaapps/vimxel/expr/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ SNode Parser::evF() {
if (evFTerms(out)) return out;
if (evFConstants(out)) return out;
if (evFOperators(out)) return out;
if (evFBrackets(out)) return out;
if (evFFunctions(out)) return out;
throw invalid_argument("Expected number or nested expression");
}

Expand Down Expand Up @@ -94,20 +96,16 @@ bool Parser::evFConstants(SNode& out) {
mcase(TT::PI, {
nextToken();
out = make_shared<PiNode>();
})
mcase(TT::E, {
}) mcase(TT::E, {
nextToken();
out = make_shared<EulersNumberNode>();
})
mcase(TT::LIGHT_SPEED, {
}) mcase(TT::LIGHT_SPEED, {
nextToken();
out = make_shared<LightSpeedNode>();
})
mcase(TT::GOLDEN_RATION, {
}) mcase(TT::GOLDEN_RATION, {
nextToken();
out = make_shared<GoldenRationNode>();
})
default : return false;
}) default : return false;
}
return true;
}
Expand All @@ -125,5 +123,95 @@ bool Parser::evFOperators(SNode& out) {
return true;
}

bool Parser::evFBrackets(SNode& out) {
auto handleBracket = [&](const TT start, const TT end, const char c1, const char c2) {
if (mToken->type != start) return false;
nextToken();
if (mToken->type == end)
throw invalid_argument("Empty "s + c1 + c2 + " brackers");
out = evE();
if (mToken->type != end)
throw invalid_argument("Bracked "s + c1 + c2 + " not ended");
nextToken();
return true;
};

if (handleBracket(TT::BRACKET_LS, TT::BRACKER_RS, '(', ')')) return true;
if (handleBracket(TT::BRACKET_LM, TT::BRACKER_RM, '[', ']')) return true;
if (handleBracket(TT::BRACKET_LL, TT::BRACKER_RL, '{', '}')) return true;
return false;
}

bool Parser::evFFunctions(SNode& out) {
if (evFFunctionsCheck<TT::POW, 2, PowNode>(out)) return true;
if (evFFunctionsCheck<TT::SQRT, 1, SqrtNode>(out)) return true;
if (evFFunctionsCheck<TT::ABS, 1, AbsNode>(out)) return true;
if (evFFunctionsCheck<TT::EXP, 1, ExponentialNode>(out)) return true;
if (evFFunctionsCheck<TT::LN, 1, LnNode>(out)) return true;
if (evFFunctionsCheck<TT::LOG2, 1, Log2Node>(out)) return true;
if (evFFunctionsCheck<TT::LOG10, 1, Log10Node>(out)) return true;
if (evFFunctionsCheck<TT::LOG, 2, LogNode>(out)) return true;

if (evFFunctionsCheck<TT::ROUND, 1, RoundNode>(out)) return true;
if (evFFunctionsCheck<TT::CEIL, 1 ,CeilNode>(out)) return true;
if (evFFunctionsCheck<TT::FLOOR, 1, FloorNode>(out)) return true;
if (evFFunctionsCheck<TT::TRUNC, 1, TruncNode>(out)) return true;

if (evFFunctionsCheck<TT::SIN, 1, SinNode>(out)) return true;
if (evFFunctionsCheck<TT::COS, 1, CosNode>(out)) return true;
if (evFFunctionsCheck<TT::TAN, 1, TanNode>(out)) return true;
if (evFFunctionsCheck<TT::COT, 1, CotNode>(out)) return true;
if (evFFunctionsCheck<TT::ARCSIN, 1, ArcsinNode>(out)) return true;
if (evFFunctionsCheck<TT::ARCCOS, 1, ArccosNode>(out)) return true;
if (evFFunctionsCheck<TT::ARCTAN, 1, ArctanNode>(out)) return true;
if (evFFunctionsCheck<TT::ARCCOT, 1, ArccotNode>(out)) return true;

if (evFFunctionsCheck<TT::SUM, 0, SumNode>(out)) return true;
if (evFFunctionsCheck<TT::MAX, 0, MaxNode>(out)) return true;
if (evFFunctionsCheck<TT::MIN, 0, MinNode>(out)) return true;
if (evFFunctionsCheck<TT::AVG, 0, AvgNode>(out)) return true;

if (evFFunctionsCheck<TT::CONCAT, 0, ConcatNode>(out)) return true;
if (evFFunctionsCheck<TT::LOWER, 1, LowerNode>(out)) return true;
if (evFFunctionsCheck<TT::UPPER, 1, UpperNode>(out)) return true;

//if (evFFunctionsCheck<TT::>(out)) return true;
return false;
}
template <TT type, size_t size, typename Name>
bool Parser::evFFunctionsCheck(SNode& out) {
const auto pair = evFFunctionsOperands(type);
if (pair.first == false) return false;
if (size != 0 && size != pair.second.size())
throw invalid_argument("Wrong number of arguments");
out = make_shared<Name>(pair.second);
return true;
}

pair<bool, vector<SNode>> Parser::evFFunctionsOperands(const TT type) {
vector<SNode> nodes;
if (mToken->type != type) {
return make_pair(false, nodes);
}
nextToken();
if (mToken->type != TT::BRACKET_LS)
throw invalid_argument("Function without () brackets");
nextToken();
if (mToken->type != TT::BRACKER_RS) {
while (true) {
nodes.emplace_back(evE());
if (mToken->type == TT::BRACKER_RS)
break;
if (mToken->type == TT::COMMA) {
nextToken();
} else {
throw invalid_argument("Function parameters have to be separated by , or ;");
}
}
}
nextToken();
return make_pair(true, nodes);
}

#undef mcase
} // namespace cz::lastaapps::vimxel::expr
5 changes: 5 additions & 0 deletions Semestralni_prace/src/cz/lastaapps/vimxel/expr/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class Parser final {
bool evFTerms(SNode&);
bool evFConstants(SNode&);
bool evFOperators(SNode&);
bool evFBrackets(SNode&);
bool evFFunctions(SNode&);
template<TT type, size_t size, typename Name>
bool evFFunctionsCheck(SNode&);
pair<bool, vector<SNode>> evFFunctionsOperands(const TT type);
};
} // namespace cz::lastaapps::vimxel::exptr

Expand Down
8 changes: 7 additions & 1 deletion Semestralni_prace/src/cz/lastaapps/vimxel/expr/tokenizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,13 @@ bool Tokenizer::parseNumber(SToken& out) {
if (mPos != mString.end()) {
if (*mPos++ == '.') {
long double pow = 1;
while (mPos != mString.end() && isdigit(c = *mPos++)) {
while (true) {
if (mPos == mString.end())
break;
if (!isdigit(c = *mPos++)) {
--mPos;
break;
}
pow *= 10;
num += (c - '0') / pow;
}
Expand Down
16 changes: 14 additions & 2 deletions Semestralni_prace/src/cz/lastaapps/vimxel/table/table.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "table.hpp"

#include <cmath>

#include "../expr/parser.hpp"
#include "../expr/tokenizer.hpp"
#include "../log.hpp"
Expand Down Expand Up @@ -148,6 +149,11 @@ bool Table::tryParseNumber(const string& content, long double& out) {
char c;
auto mPos = noSpaces.begin();
long double num = 0;
bool isMinus = false;
if (*mPos == '-') {
isMinus = true;
++mPos;
}
while (true) {
if (mPos == noSpaces.end()) break;
if (!isdigit(c = *mPos++)) {
Expand All @@ -160,7 +166,13 @@ bool Table::tryParseNumber(const string& content, long double& out) {
if (mPos != noSpaces.end()) {
if (*mPos++ == '.') {
long double pow = 1;
while (mPos != noSpaces.end() && isdigit(c = *mPos++)) {
while (true) {
if (mPos == noSpaces.end())
break;
if (!isdigit(c = *mPos++)) {
--mPos;
break;
}
pow *= 10;
num += (c - '0') / pow;
}
Expand All @@ -169,7 +181,7 @@ bool Table::tryParseNumber(const string& content, long double& out) {
}
if (mPos != noSpaces.end())
return false;
out = num;
out = isMinus ? -1 * num : num;
return true;
}
void Table::destroyOldCell(const Coordinates& coord) {
Expand Down

0 comments on commit cae6f0b

Please sign in to comment.