1 #pragma once
2 
3 #include <stack>
4 #include <string>
5 #include <memory>
6 
7 #include <pdal/Dimension.hpp>
8 #include <pdal/PointLayout.hpp>
9 #include <pdal/PointRef.hpp>
10 #include <pdal/util/Utils.hpp>
11 
12 namespace pdal
13 {
14 namespace expr
15 {
16 
17 enum class NodeType
18 {
19     And,
20     Or,
21     Add,
22     Subtract,
23     Multiply,
24     Divide,
25     Not,
26     Equal,
27     NotEqual,
28     Greater,
29     GreaterEqual,
30     Less,
31     LessEqual,
32     Negative,
33     Value,
34     Identifier,
35     None
36 };
37 
38 struct Result
39 {
Resultpdal::expr::Result40     Result(double d)
41     { m_dval = d; m_bval = false; }
42 
Resultpdal::expr::Result43     Result(bool b)
44     { m_bval = b; m_dval = 0; }
45 
46     enum class Type
47     {
48         Bool,
49         Val
50     };
51 
52     double m_dval;
53     bool m_bval;
54     Type m_type;
55 };
56 
57 class Node
58 {
59 protected:
60     Node(NodeType type);
61 
62 public:
63     virtual ~Node();
64     NodeType type() const;
65 
66     virtual std::string print() const = 0;
67     virtual Utils::StatusWithReason prepare(PointLayoutPtr l) = 0;
68     virtual Result eval(PointRef& p) const = 0;
69     virtual bool isBool() const = 0;
isValue() const70     virtual bool isValue() const
71     { return !isBool(); }
72 
73 private:
74     NodeType m_type;
75 
76 protected:
77     size_t m_pos;
78     size_t m_level;
79 };
80 using NodePtr = std::unique_ptr<Node>;
81 
82 class LogicalNode : public Node
83 {
84 public:
LogicalNode(NodeType type)85     LogicalNode(NodeType type) : Node(type)
86     {}
87 
isBool() const88     virtual bool isBool() const
89     { return true; }
90 };
91 
92 class ValueNode : public Node
93 {
94 public:
ValueNode(NodeType type)95     ValueNode(NodeType type) : Node(type)
96     {}
97 
isBool() const98     virtual bool isBool() const
99     { return false; }
100 };
101 
102 class BinMathNode : public ValueNode
103 {
104 public:
105     BinMathNode(NodeType type, NodePtr left, NodePtr right);
106 
107     virtual std::string print() const;
108     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
109     virtual Result eval(PointRef& p) const;
110 
111 private:
112     NodePtr m_left;
113     NodePtr m_right;
114 };
115 
116 class UnMathNode : public ValueNode
117 {
118 public:
119     UnMathNode(NodeType type, NodePtr sub);
120 
121     virtual std::string print() const;
122     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
123     virtual Result eval(PointRef& p) const;
124 
125 private:
126     NodePtr m_sub;
127 };
128 
129 class NotNode : public LogicalNode
130 {
131 public:
132     NotNode(NodeType type, NodePtr sub);
133 
134     virtual std::string print() const;
135     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
136     virtual Result eval(PointRef& p) const;
137 
138 private:
139     NodePtr m_sub;
140 };
141 
142 class BoolNode : public LogicalNode
143 {
144 public:
145     BoolNode(NodeType type, NodePtr left, NodePtr right);
146 
147     virtual std::string print() const;
148     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
149     virtual Result eval(PointRef& p) const;
150 
151 private:
152     NodePtr m_left;
153     NodePtr m_right;
154 };
155 
156 class CompareNode : public LogicalNode
157 {
158 public:
159     CompareNode(NodeType type, NodePtr left, NodePtr right);
160 
161     virtual std::string print() const;
162     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
163     virtual Result eval(PointRef& p) const;
164 
165 private:
166     NodePtr m_left;
167     NodePtr m_right;
168 };
169 
170 class ConstValueNode : public ValueNode
171 {
172 public:
173     ConstValueNode(double d);
174 
175     virtual std::string print() const;
176     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
177     virtual Result eval(PointRef&) const;
178 
179     double value() const;
180 
181 private:
182     double m_val;
183 };
184 
185 class ConstLogicalNode : public LogicalNode
186 {
187 public:
188     ConstLogicalNode(bool b);
189 
190     virtual std::string print() const;
191     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
192     virtual Result eval(PointRef&) const;
193 
194     bool value() const;
195 
196 private:
197     bool m_val;
198 };
199 
200 class VarNode : public ValueNode
201 {
202 public:
203     VarNode(const std::string& s);
204 
205     virtual std::string print() const;
206     virtual Utils::StatusWithReason prepare(PointLayoutPtr l);
207     virtual Result eval(PointRef& p) const;
208     Dimension::Id eval() const;
209 
210 private:
211     std::string m_name;
212     Dimension::Id m_id;
213 };
214 
215 class Expression
216 {
217 public:
218     Expression();
219     virtual ~Expression();
220     Expression(const Expression& expr);
221     Expression(Expression&& expr) noexcept;
222     Expression& operator=(Expression&& expr);
223     Expression& operator=(const Expression& expr);
224 
225     void clear();
226     bool valid() const;
227     std::string error() const;
228     NodePtr popNode();
229     void pushNode(NodePtr node);
230     Node *topNode();
231     const Node *topNode() const;
232     virtual std::string print() const;
233     virtual Utils::StatusWithReason prepare(PointLayoutPtr layout) = 0;
234 
235 private:
236     std::string m_error;
237     std::stack<NodePtr> m_nodes;
238 
239     friend std::ostream& operator<<(std::ostream& out, const Expression& expr);
240 };
241 
242 } // namespace expr
243 } // namespace pdal
244