diff --git a/filters/private/expr/Expression.cpp b/filters/private/expr/Expression.cpp new file mode 100644 index 0000000000..ef03b4cbe1 --- /dev/null +++ b/filters/private/expr/Expression.cpp @@ -0,0 +1,227 @@ +#include "Expression.hpp" +#include "Parser.hpp" + +namespace pdal +{ +namespace expr +{ + +Node::Node(NodeType type) : m_type(type) +{} + +Node::~Node() +{} + +NodeType Node::type() const +{ return m_type; } + + +UnNode::UnNode(NodeType type, NodePtr sub) : + Node(type), m_sub(std::move(sub)) +{} + +std::string UnNode::print() const +{ + return "!(" + m_sub->print() + ")"; +} + +BinNode::BinNode(NodeType type, NodePtr left, NodePtr right) : + Node(type), m_left(std::move(left)), m_right(std::move(right)) +{} + +std::string BinNode::print() const +{ + std::string s; + + switch (type()) + { + case NodeType::Add: + s = "+"; + break; + case NodeType::Subtract: + s = "-"; + break; + case NodeType::Multiply: + s = "*"; + break; + case NodeType::Divide: + s = "/"; + break; + default: + break; + } + + return "(" + m_left->print() + " " + s + " " + m_right->print() + ")"; +} + +/** +virtual void prepare(PointLayoutPtr l) +{ +m_left->prepare(l); +m_right->prepare(l); +} + +virtual double eval(PointRef& p) const +{ +double l = m_left->eval(p); +double r = m_right->eval(p); +switch (type()) +{ +case NodeType::Add: +return l + r; +case NodeType::Subtract: +return l - r; +case NodeType::Multiply: +return l * r; +case NodeType::Divide: +return l / r; +default: +return 0; +} +} +**/ + +BoolNode::BoolNode(NodeType type, NodePtr left, NodePtr right) : + Node(type), m_left(std::move(left)), m_right(std::move(right)) +{} + +std::string BoolNode::print() const +{ + std::string s; + switch (type()) + { + case NodeType::And: + s = "&&"; + break; + case NodeType::Or: + s = "||"; + break; + case NodeType::Equal: + s = "=="; + break; + case NodeType::NotEqual: + s = "!="; + break; + case NodeType::Greater: + s = ">"; + break; + case NodeType::GreaterEqual: + s = ">="; + break; + case NodeType::Less: + s = "<"; + break; + case NodeType::LessEqual: + s = "<="; + break; + default: + break; + } + + return "(" + m_left->print() + " " + s + " " + m_right->print() + ")"; +} + + /** + virtual void prepare(PointLayoutPtr l) + { + m_left->prepare(l); + m_right->prepare(l); + } + **/ + + /** + virtual double eval(PointRef& p) const + { + switch (type()) + { + case NodeType::And: + return m_left->eval(p) && m_right->eval(p); + case NodeType::Or: + return m_left->eval(p) || m_right->eval(p); + default: + return 0; + } + } + **/ + +ValNode::ValNode(double d) : Node(NodeType::Value), m_val(d) +{} + +std::string ValNode::print() const +{ + return std::to_string(m_val); +} + + /** + virtual void prepare(PointLayoutPtr l) + {} + + virtual double eval(PointRef&) const + { return m_val; } + **/ + +double ValNode::value() const +{ return m_val; } + +VarNode::VarNode(const std::string& s) : Node(NodeType::Identifier), m_name(s) +// , m_id(Dimension::Id::Unknown) +{} + +std::string VarNode::print() const +{ return m_name; } + + /** + virtual void prepare(PointLayoutPtr l) + { + m_id = l->findDim(m_name); + if (m_id == Dimension::Id::Unknown) + std::cerr << "Unknown dimension '" << m_name << "' in assigment."; + } + + virtual double eval(PointRef& p) const + { return p.getFieldAs(m_id); } + **/ + +Expression::Expression() +{} + +Expression::~Expression() +{} + +void Expression::clear() +{ + std::stack empty; + m_nodes.swap(empty); + m_error.clear(); +} + +bool Expression::parse(const std::string& s) +{ + clear(); + Parser p(*this); + bool ok = p.parse(s); + if (!ok) + m_error = p.error(); + return ok; +} + +std::string Expression::error() const +{ return m_error; } + +void Expression::print() const +{ std::cout << m_nodes.top()->print() << "\n"; } + +NodePtr Expression::popNode() +{ + NodePtr n(std::move(m_nodes.top())); + m_nodes.pop(); + return n; +} + +void Expression::pushNode(NodePtr node) +{ + m_nodes.push(std::move(node)); +} + +} // namespace expr +} // namespace pdal diff --git a/filters/private/expr/Expression.hpp b/filters/private/expr/Expression.hpp new file mode 100644 index 0000000000..5d0584f86d --- /dev/null +++ b/filters/private/expr/Expression.hpp @@ -0,0 +1,206 @@ +#pragma once + +#include +#include +#include + +namespace pdal +{ +namespace expr +{ + +enum class NodeType +{ + And, + Or, + Add, + Subtract, + Multiply, + Divide, + Not, + Equal, + NotEqual, + Greater, + GreaterEqual, + Less, + LessEqual, + Negative, + Value, + Identifier, + None +}; + +class Node +{ +protected: + Node(NodeType type); + +public: + virtual ~Node(); + NodeType type() const; + + virtual std::string print() const = 0; + /** + virtual void prepare(PointLayoutPtr l) = 0; + virtual double eval(PointRef& p) const = 0; + **/ + +private: + NodeType m_type; + +protected: + size_t m_pos; + size_t m_level; +}; +using NodePtr = std::unique_ptr; + +class UnNode : public Node +{ +public: + UnNode(NodeType type, NodePtr sub); + + virtual std::string print() const; + +private: + NodePtr m_sub; +}; + +class BinNode : public Node +{ +public: + BinNode(NodeType type, NodePtr left, NodePtr right); + + virtual std::string print() const; + + /** + virtual void prepare(PointLayoutPtr l) + { + m_left->prepare(l); + m_right->prepare(l); + } + + virtual double eval(PointRef& p) const + { + double l = m_left->eval(p); + double r = m_right->eval(p); + switch (type()) + { + case NodeType::Add: + return l + r; + case NodeType::Subtract: + return l - r; + case NodeType::Multiply: + return l * r; + case NodeType::Divide: + return l / r; + default: + return 0; + } + } + **/ + +private: + NodePtr m_left; + NodePtr m_right; +}; + +class BoolNode : public Node +{ +public: + BoolNode(NodeType type, NodePtr left, NodePtr right); + + virtual std::string print() const; + + /** + virtual void prepare(PointLayoutPtr l) + { + m_left->prepare(l); + m_right->prepare(l); + } + **/ + + /** + virtual double eval(PointRef& p) const + { + switch (type()) + { + case NodeType::And: + return m_left->eval(p) && m_right->eval(p); + case NodeType::Or: + return m_left->eval(p) || m_right->eval(p); + default: + return 0; + } + } + **/ + +private: + NodePtr m_left; + NodePtr m_right; +}; + +class ValNode : public Node +{ +public: + ValNode(double d); + + virtual std::string print() const; + + /** + virtual void prepare(PointLayoutPtr l) + {} + + virtual double eval(PointRef&) const + { return m_val; } + **/ + + double value() const; + +private: + double m_val; +}; + +class VarNode : public Node +{ +public: + VarNode(const std::string& s); + + virtual std::string print() const; + + /** + virtual void prepare(PointLayoutPtr l) + { + m_id = l->findDim(m_name); + if (m_id == Dimension::Id::Unknown) + std::cerr << "Unknown dimension '" << m_name << "' in assigment."; + } + + virtual double eval(PointRef& p) const + { return p.getFieldAs(m_id); } + **/ + +private: + std::string m_name; +// Dimension::Id m_id; +}; + +class Expression +{ +public: + Expression(); + ~Expression(); + + void clear(); + bool parse(const std::string& s); + std::string error() const; + void print() const; + NodePtr popNode(); + void pushNode(NodePtr node); + +private: + std::string m_error; + std::stack m_nodes; +}; + +} // namespace expr +} // namespace pdal diff --git a/filters/private/expr/Parser.cpp b/filters/private/expr/Parser.cpp index 5e102d1a75..5a0f352a7e 100644 --- a/filters/private/expr/Parser.cpp +++ b/filters/private/expr/Parser.cpp @@ -7,8 +7,7 @@ namespace expr bool Parser::parse(const std::string& s) { - std::stack nodes; - nodes.swap(m_nodes); + m_expression.clear(); m_lexer.reset(s); m_error.clear(); @@ -26,12 +25,6 @@ bool Parser::parse(const std::string& s) return ok; } - -void Parser::dump() -{ - std::cout << m_nodes.top()->print() << "\n"; -} - /** void Parser::prepare(PointLayoutPtr l) { @@ -102,18 +95,18 @@ bool Parser::orexpr() return false; } - NodePtr right = popNode(); - NodePtr left = popNode(); + NodePtr right = m_expression.popNode(); + NodePtr left = m_expression.popNode(); ValNode *leftVal = dynamic_cast(left.get()); ValNode *rightVal = dynamic_cast(right.get()); if (leftVal && rightVal) { double v = leftVal->value() || rightVal->value(); - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new BoolNode(NodeType::Or, + m_expression.pushNode(NodePtr(new BoolNode(NodeType::Or, std::move(left), std::move(right)))); } return true; @@ -135,18 +128,18 @@ bool Parser::andexpr() return false; } - NodePtr right = popNode(); - NodePtr left = popNode(); + NodePtr right = m_expression.popNode(); + NodePtr left = m_expression.popNode(); ValNode *leftVal = dynamic_cast(left.get()); ValNode *rightVal = dynamic_cast(right.get()); if (leftVal && rightVal) { double v = leftVal->value() && rightVal->value(); - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new BoolNode(NodeType::And, + m_expression.pushNode(NodePtr(new BoolNode(NodeType::And, std::move(left), std::move(right)))); } return true; @@ -185,8 +178,8 @@ bool Parser::compareexpr() return false; } - NodePtr right = popNode(); - NodePtr left = popNode(); + NodePtr right = m_expression.popNode(); + NodePtr left = m_expression.popNode(); ValNode *leftVal = dynamic_cast(left.get()); ValNode *rightVal = dynamic_cast(right.get()); if (leftVal && rightVal) @@ -204,10 +197,10 @@ bool Parser::compareexpr() v = (leftVal->value() < rightVal->value()); else if (type == NodeType::LessEqual) v = (leftVal->value() <= rightVal->value()); - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new BoolNode(type, + m_expression.pushNode(NodePtr(new BoolNode(type, std::move(left), std::move(right)))); } return true; @@ -236,8 +229,8 @@ bool Parser::addexpr() return false; } - NodePtr right(popNode()); - NodePtr left(popNode()); + NodePtr right = m_expression.popNode(); + NodePtr left = m_expression.popNode(); ValNode *leftVal = dynamic_cast(left.get()); ValNode *rightVal = dynamic_cast(right.get()); @@ -246,10 +239,10 @@ bool Parser::addexpr() double v = (type == NodeType::Add) ? leftVal->value() + rightVal->value() : leftVal->value() - rightVal->value(); - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new BinNode(type, + m_expression.pushNode(NodePtr(new BinNode(type, std::move(left), std::move(right)))); } return true; @@ -277,8 +270,8 @@ bool Parser::multexpr() return false; } - NodePtr right = popNode(); - NodePtr left = popNode(); + NodePtr right = m_expression.popNode(); + NodePtr left = m_expression.popNode(); ValNode *leftVal = dynamic_cast(left.get()); ValNode *rightVal = dynamic_cast(right.get()); @@ -296,10 +289,10 @@ bool Parser::multexpr() } v = leftVal->value() / rightVal->value(); } - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new BinNode(type, + m_expression.pushNode(NodePtr(new BinNode(type, std::move(left), std::move(right)))); } return true; @@ -316,15 +309,16 @@ bool Parser::notexpr() return false; } - NodePtr sub = popNode(); + NodePtr sub = m_expression.popNode(); ValNode *node = dynamic_cast(sub.get()); if (node) { double v = !node->value(); - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new UnNode(NodeType::Not, std::move(sub)))); + m_expression.pushNode( + NodePtr(new UnNode(NodeType::Not, std::move(sub)))); return true; } @@ -339,15 +333,16 @@ bool Parser::uminus() return false; } - NodePtr sub = popNode(); + NodePtr sub = m_expression.popNode(); ValNode *node = dynamic_cast(sub.get()); if (node) { double v = -(node->value()); - pushNode(NodePtr(new ValNode(v))); + m_expression.pushNode(NodePtr(new ValNode(v))); } else - pushNode(NodePtr(new UnNode(NodeType::Negative, std::move(sub)))); + m_expression.pushNode( + NodePtr(new UnNode(NodeType::Negative, std::move(sub)))); return true; } @@ -355,12 +350,12 @@ bool Parser::primary() { if (match(TokenType::Number)) { - pushNode(NodePtr(new ValNode(curToken().dval()))); + m_expression.pushNode(NodePtr(new ValNode(curToken().dval()))); return true; } else if (match(TokenType::Identifier)) { - pushNode(NodePtr(new VarNode(curToken().sval()))); + m_expression.pushNode(NodePtr(new VarNode(curToken().sval()))); return true; } diff --git a/filters/private/expr/Parser.hpp b/filters/private/expr/Parser.hpp index d93532b66c..d03978aa8c 100644 --- a/filters/private/expr/Parser.hpp +++ b/filters/private/expr/Parser.hpp @@ -6,286 +6,28 @@ #include #include "Lexer.hpp" +#include "Expression.hpp" namespace pdal { namespace expr { -enum class NodeType -{ - And, - Or, - Add, - Subtract, - Multiply, - Divide, - Not, - Equal, - NotEqual, - Greater, - GreaterEqual, - Less, - LessEqual, - Negative, - Value, - Identifier, - None -}; - -class Node -{ -protected: - Node(NodeType type) : m_type(type) - {} - -public: - virtual ~Node() - {} - NodeType type() const - { return m_type; } - - virtual std::string print() const = 0; - /** - virtual void prepare(PointLayoutPtr l) = 0; - virtual double eval(PointRef& p) const = 0; - **/ - -private: - NodeType m_type; - -protected: - size_t m_pos; - size_t m_level; -}; -using NodePtr = std::unique_ptr; - -class UnNode : public Node -{ -public: - UnNode(NodeType type, NodePtr sub) : Node(type), m_sub(std::move(sub)) - {} - - virtual std::string print() const - { - return "!(" + m_sub->print() + ")"; - } - -private: - NodePtr m_sub; -}; - -class BinNode : public Node -{ -public: - BinNode(NodeType type, NodePtr left, NodePtr right) : - Node(type), m_left(std::move(left)), m_right(std::move(right)) - {} - - virtual std::string print() const - { - std::string s; - - switch (type()) - { - case NodeType::Add: - s = "+"; - break; - case NodeType::Subtract: - s = "-"; - break; - case NodeType::Multiply: - s = "*"; - break; - case NodeType::Divide: - s = "/"; - break; - default: - break; - } - - return "(" + m_left->print() + " " + s + " " + m_right->print() + ")"; - } - - /** - virtual void prepare(PointLayoutPtr l) - { - m_left->prepare(l); - m_right->prepare(l); - } - - virtual double eval(PointRef& p) const - { - double l = m_left->eval(p); - double r = m_right->eval(p); - switch (type()) - { - case NodeType::Add: - return l + r; - case NodeType::Subtract: - return l - r; - case NodeType::Multiply: - return l * r; - case NodeType::Divide: - return l / r; - default: - return 0; - } - } - **/ - -private: - NodePtr m_left; - NodePtr m_right; -}; - -class BoolNode : public Node -{ -public: - BoolNode(NodeType type, NodePtr left, NodePtr right) : - Node(type), m_left(std::move(left)), m_right(std::move(right)) - {} - - virtual std::string print() const - { - std::string s; - switch (type()) - { - case NodeType::And: - s = "&&"; - break; - case NodeType::Or: - s = "||"; - break; - case NodeType::Equal: - s = "=="; - break; - case NodeType::NotEqual: - s = "!="; - break; - case NodeType::Greater: - s = ">"; - break; - case NodeType::GreaterEqual: - s = ">="; - break; - case NodeType::Less: - s = "<"; - break; - case NodeType::LessEqual: - s = "<="; - break; - default: - break; - } - - return "(" + m_left->print() + " " + s + " " + m_right->print() + ")"; - } - - /** - virtual void prepare(PointLayoutPtr l) - { - m_left->prepare(l); - m_right->prepare(l); - } - **/ - - /** - virtual double eval(PointRef& p) const - { - switch (type()) - { - case NodeType::And: - return m_left->eval(p) && m_right->eval(p); - case NodeType::Or: - return m_left->eval(p) || m_right->eval(p); - default: - return 0; - } - } - **/ - -private: - NodePtr m_left; - NodePtr m_right; -}; - -class ValNode : public Node -{ -public: - ValNode(double d) : Node(NodeType::Value), m_val(d) - {} - - virtual std::string print() const - { - return std::to_string(m_val); - } - - /** - virtual void prepare(PointLayoutPtr l) - {} - - virtual double eval(PointRef&) const - { return m_val; } - **/ - - double value() const - { return m_val; } - -private: - double m_val; -}; - -class VarNode : public Node +class Parser { public: - VarNode(const std::string& s) : Node(NodeType::Identifier), m_name(s) -// , m_id(Dimension::Id::Unknown) + Parser(Expression& expression) : m_expression(expression) {} - virtual std::string print() const - { return m_name; } - - /** - virtual void prepare(PointLayoutPtr l) - { - m_id = l->findDim(m_name); - if (m_id == Dimension::Id::Unknown) - std::cerr << "Unknown dimension '" << m_name << "' in assigment."; - } - - virtual double eval(PointRef& p) const - { return p.getFieldAs(m_id); } - **/ - -private: - std::string m_name; -// Dimension::Id m_id; -}; - -class Parser -{ -public: bool parse(const std::string& s); std::string error() const { return m_error; } - void dump(); /** void prepare(PointLayoutPtr l); double eval(PointRef& p) const; **/ private: - void pushNode(std::unique_ptr node) - { m_nodes.push(std::move(node)); } - - NodePtr popNode() - { - NodePtr n(std::move(m_nodes.top())); - m_nodes.pop(); - return n; - } - bool match(TokenType type); Token curToken() const; void setError(const std::string& err); @@ -301,9 +43,9 @@ class Parser bool primary(); bool parexpr(); + Expression& m_expression; Lexer m_lexer; Token m_curTok; - std::stack m_nodes; std::string m_error; };