plang.h
1 // Copyright 2013, Beeri 15. All rights reserved.
2 // Author: Roman Gershman (romange@gmail.com)
3 //
4 #ifndef _PLANG_H
5 #define _PLANG_H
6 
7 #include <functional>
8 #include <memory>
9 
10 #include "base/integral_types.h"
11 #include "strings/stringpiece.h"
12 
13 namespace google {
14 namespace protobuf {
15 class Message;
16 class EnumValueDescriptor;
17 } // namespace protobuf
18 } // namespace google
19 
20 namespace plang {
21 
22 namespace gpb = ::google::protobuf;
23 
25  StringPiece str;
26  int64 int_val;
27  uint64 uint_val;
28  bool bool_val;
29  double d_val;
30 
31  const gpb::EnumValueDescriptor* enum_val;
32 
33  ExprValueUnion() : str() {}
34 };
35 
36 class ExprValue {
37  double PromoteToDouble() const;
38 public:
39  ExprValueUnion val;
40 
41  // Copied from descriptor in order not to drag its depedency here.
42  enum CppType {
43  CPPTYPE_INT32 = 1,
44  CPPTYPE_INT64 = 2,
45  CPPTYPE_UINT32 = 3,
46  CPPTYPE_UINT64 = 4,
47  CPPTYPE_DOUBLE = 5,
48  CPPTYPE_FLOAT = 6,
49  CPPTYPE_BOOL = 7,
50  CPPTYPE_ENUM = 8,
51  CPPTYPE_STRING = 9,
52  CPPTYPE_MESSAGE = 10,
53 
54  MAX_CPPTYPE = 10,
55  };
56 
57  CppType type;
58 
59  explicit ExprValue(CppType t) : type(t) {}
60  ExprValue() : type(CPPTYPE_STRING) {}
61 
62  static ExprValue fromInt(int64 ival) {
63  ExprValue res{CPPTYPE_INT64};
64  res.val.int_val = ival;
65  return res;
66  }
67 
68  static ExprValue fromUInt(uint64 val) {
69  ExprValue res{CPPTYPE_INT64};
70  res.val.uint_val = val;
71  return res;
72  }
73 
74  explicit ExprValue(StringPiece str) : type(CPPTYPE_STRING) {
75  val.str = str;
76  }
77 
78  explicit ExprValue(const gpb::EnumValueDescriptor* eval) : type(CPPTYPE_ENUM) {
79  val.enum_val = eval;
80  }
81 
82  static ExprValue fromBool(bool b) {
83  ExprValue res{CPPTYPE_BOOL};
84  res.val.bool_val = b;
85  return res;
86  }
87 
88  static ExprValue fromDouble(double d) {
89  ExprValue res{CPPTYPE_DOUBLE};
90  res.val.d_val = d;
91  return res;
92  }
93 
94  bool Equal(const ExprValue& other) const;
95  bool Less(const ExprValue& other) const;
96  bool RLike(const ExprValue& other) const;
97 };
98 
99 class Expr {
100 public:
101  typedef std::function<bool(const ExprValue&)> ExprValueCb;
102 
103  // cb will be called for each value evaluated by Expr until it goes over all values returned by
104  // this expression or cb returns false.
105  // We need this weird interface because of the repeated fields.
106  virtual void eval(const gpb::Message& msg, ExprValueCb cb) const = 0;
107  virtual ~Expr() {};
108 };
109 
110 typedef std::vector<Expr*> ArgList;
111 
112 class NumericLiteral : public Expr {
113  union {
114  int64 signed_val;
115  uint64 uval;
116  double dval;
117  } val_;
118  enum class ValType { SINT64, UINT64, DOUBLE };
119  ValType val_type_;
120 public:
121  static NumericLiteral Signed(int64 v) {
122  NumericLiteral lit;
123  lit.val_.signed_val = v;
124  lit.val_type_ = ValType::SINT64;
125  return lit;
126  }
127 
128  static NumericLiteral Unsigned(uint64 v) {
129  NumericLiteral lit;
130  lit.val_.uval = v;
131  lit.val_type_ = ValType::UINT64;
132  return lit;
133  }
134 
135  static NumericLiteral Double(double v) {
136  NumericLiteral lit;
137  lit.val_.dval = v;
138  lit.val_type_ = ValType::DOUBLE;
139  return lit;
140  }
141 
142  virtual void eval(const gpb::Message& msg, ExprValueCb cb) const override {
143  switch (val_type_) {
144  case ValType::UINT64:
145  cb(ExprValue::fromUInt(val_.uval));
146  break;
147  case ValType::SINT64:
148  cb(ExprValue::fromInt(val_.signed_val));
149  break;
150  case ValType::DOUBLE:
151  cb(ExprValue::fromDouble(val_.dval));
152  }
153  }
154 };
155 
156 class StringTerm : public Expr {
157  std::string val_;
158  mutable std::string tmp_;
159 public:
160  enum Type { CONST, VARIABLE};
161 
162  StringTerm(const std::string& v, Type t) : val_(v), type_(t) {}
163 
164  virtual void eval(const gpb::Message& msg, ExprValueCb cb) const override;
165  const std::string& val() const { return val_; }
166 private:
167  Type type_;
168 };
169 
170 class BinOp : public Expr {
171  std::unique_ptr<Expr> left_;
172  std::unique_ptr<Expr> right_;
173 
174 public:
175  enum Type {EQ, AND, OR, LT, LE, NOT, RLIKE};
176  BinOp(Type t, Expr* l, Expr* r) : left_(l), right_(r), type_(t) {}
177 
178  virtual void eval(const gpb::Message& msg, ExprValueCb cb) const override;
179  const Expr& left() const { return *left_.get(); }
180  const Expr& right() const { return *right_.get(); }
181  Type type() const { return type_; }
182 private:
183  Type type_;
184 };
185 
186 class FunctionTerm : public Expr {
187  std::string name_;
188  ArgList args_;
189 public:
190  FunctionTerm(const std::string& name, ArgList&& lst);
191  ~FunctionTerm();
192 
193  virtual void eval(const gpb::Message& msg, ExprValueCb cb) const override;
194 };
195 
196 class IsDefFun : public Expr {
197  std::string name_;
198 public:
199  IsDefFun(const std::string& name) : name_(name) {};
200  virtual void eval(const gpb::Message& msg, ExprValueCb cb) const override;
201 };
202 
203 bool EvaluateBoolExpr(const Expr& e, const gpb::Message& msg);
204 
205 } // namespace plang
206 
207 #endif // _PLANG_H