Inja  3.4.0
A Template Engine for Modern C++
node.hpp
1 #ifndef INCLUDE_INJA_NODE_HPP_
2 #define INCLUDE_INJA_NODE_HPP_
3 
4 #include <string>
5 #include <string_view>
6 #include <utility>
7 
8 #include "function_storage.hpp"
9 #include "utils.hpp"
10 
11 namespace inja {
12 
13 class NodeVisitor;
14 class BlockNode;
15 class TextNode;
16 class ExpressionNode;
17 class LiteralNode;
18 class DataNode;
19 class FunctionNode;
20 class ExpressionListNode;
21 class StatementNode;
22 class ForStatementNode;
23 class ForArrayStatementNode;
24 class ForObjectStatementNode;
25 class IfStatementNode;
26 class IncludeStatementNode;
27 class ExtendsStatementNode;
28 class BlockStatementNode;
29 class SetStatementNode;
30 
31 class NodeVisitor {
32 public:
33  virtual ~NodeVisitor() = default;
34 
35  virtual void visit(const BlockNode& node) = 0;
36  virtual void visit(const TextNode& node) = 0;
37  virtual void visit(const ExpressionNode& node) = 0;
38  virtual void visit(const LiteralNode& node) = 0;
39  virtual void visit(const DataNode& node) = 0;
40  virtual void visit(const FunctionNode& node) = 0;
41  virtual void visit(const ExpressionListNode& node) = 0;
42  virtual void visit(const StatementNode& node) = 0;
43  virtual void visit(const ForStatementNode& node) = 0;
44  virtual void visit(const ForArrayStatementNode& node) = 0;
45  virtual void visit(const ForObjectStatementNode& node) = 0;
46  virtual void visit(const IfStatementNode& node) = 0;
47  virtual void visit(const IncludeStatementNode& node) = 0;
48  virtual void visit(const ExtendsStatementNode& node) = 0;
49  virtual void visit(const BlockStatementNode& node) = 0;
50  virtual void visit(const SetStatementNode& node) = 0;
51 };
52 
56 class AstNode {
57 public:
58  virtual void accept(NodeVisitor& v) const = 0;
59 
60  size_t pos;
61 
62  AstNode(size_t pos): pos(pos) {}
63  virtual ~AstNode() {}
64 };
65 
66 class BlockNode : public AstNode {
67 public:
68  std::vector<std::shared_ptr<AstNode>> nodes;
69 
70  explicit BlockNode(): AstNode(0) {}
71 
72  void accept(NodeVisitor& v) const {
73  v.visit(*this);
74  }
75 };
76 
77 class TextNode : public AstNode {
78 public:
79  const size_t length;
80 
81  explicit TextNode(size_t pos, size_t length): AstNode(pos), length(length) {}
82 
83  void accept(NodeVisitor& v) const {
84  v.visit(*this);
85  }
86 };
87 
88 class ExpressionNode : public AstNode {
89 public:
90  explicit ExpressionNode(size_t pos): AstNode(pos) {}
91 
92  void accept(NodeVisitor& v) const {
93  v.visit(*this);
94  }
95 };
96 
97 class LiteralNode : public ExpressionNode {
98 public:
99  const json value;
100 
101  explicit LiteralNode(std::string_view data_text, size_t pos): ExpressionNode(pos), value(json::parse(data_text)) {}
102 
103  void accept(NodeVisitor& v) const {
104  v.visit(*this);
105  }
106 };
107 
108 class DataNode : public ExpressionNode {
109 public:
110  const std::string name;
111  const json::json_pointer ptr;
112 
113  static std::string convert_dot_to_ptr(std::string_view ptr_name) {
114  std::string result;
115  do {
116  std::string_view part;
117  std::tie(part, ptr_name) = string_view::split(ptr_name, '.');
118  result.push_back('/');
119  result.append(part.begin(), part.end());
120  } while (!ptr_name.empty());
121  return result;
122  }
123 
124  explicit DataNode(std::string_view ptr_name, size_t pos): ExpressionNode(pos), name(ptr_name), ptr(json::json_pointer(convert_dot_to_ptr(ptr_name))) {}
125 
126  void accept(NodeVisitor& v) const {
127  v.visit(*this);
128  }
129 };
130 
131 class FunctionNode : public ExpressionNode {
132  using Op = FunctionStorage::Operation;
133 
134 public:
135  enum class Associativity {
136  Left,
137  Right,
138  };
139 
140  unsigned int precedence;
141  Associativity associativity;
142 
143  Op operation;
144 
145  std::string name;
146  int number_args; // Can also be negative -> -1 for unknown number
147  std::vector<std::shared_ptr<ExpressionNode>> arguments;
148  CallbackFunction callback;
149 
150  explicit FunctionNode(std::string_view name, size_t pos)
151  : ExpressionNode(pos), precedence(8), associativity(Associativity::Left), operation(Op::Callback), name(name), number_args(0) {}
152  explicit FunctionNode(Op operation, size_t pos): ExpressionNode(pos), operation(operation), number_args(1) {
153  switch (operation) {
154  case Op::Not: {
155  number_args = 1;
156  precedence = 4;
157  associativity = Associativity::Left;
158  } break;
159  case Op::And: {
160  number_args = 2;
161  precedence = 1;
162  associativity = Associativity::Left;
163  } break;
164  case Op::Or: {
165  number_args = 2;
166  precedence = 1;
167  associativity = Associativity::Left;
168  } break;
169  case Op::In: {
170  number_args = 2;
171  precedence = 2;
172  associativity = Associativity::Left;
173  } break;
174  case Op::Equal: {
175  number_args = 2;
176  precedence = 2;
177  associativity = Associativity::Left;
178  } break;
179  case Op::NotEqual: {
180  number_args = 2;
181  precedence = 2;
182  associativity = Associativity::Left;
183  } break;
184  case Op::Greater: {
185  number_args = 2;
186  precedence = 2;
187  associativity = Associativity::Left;
188  } break;
189  case Op::GreaterEqual: {
190  number_args = 2;
191  precedence = 2;
192  associativity = Associativity::Left;
193  } break;
194  case Op::Less: {
195  number_args = 2;
196  precedence = 2;
197  associativity = Associativity::Left;
198  } break;
199  case Op::LessEqual: {
200  number_args = 2;
201  precedence = 2;
202  associativity = Associativity::Left;
203  } break;
204  case Op::Add: {
205  number_args = 2;
206  precedence = 3;
207  associativity = Associativity::Left;
208  } break;
209  case Op::Subtract: {
210  number_args = 2;
211  precedence = 3;
212  associativity = Associativity::Left;
213  } break;
214  case Op::Multiplication: {
215  number_args = 2;
216  precedence = 4;
217  associativity = Associativity::Left;
218  } break;
219  case Op::Division: {
220  number_args = 2;
221  precedence = 4;
222  associativity = Associativity::Left;
223  } break;
224  case Op::Power: {
225  number_args = 2;
226  precedence = 5;
227  associativity = Associativity::Right;
228  } break;
229  case Op::Modulo: {
230  number_args = 2;
231  precedence = 4;
232  associativity = Associativity::Left;
233  } break;
234  case Op::AtId: {
235  number_args = 2;
236  precedence = 8;
237  associativity = Associativity::Left;
238  } break;
239  default: {
240  precedence = 1;
241  associativity = Associativity::Left;
242  }
243  }
244  }
245 
246  void accept(NodeVisitor& v) const {
247  v.visit(*this);
248  }
249 };
250 
251 class ExpressionListNode : public AstNode {
252 public:
253  std::shared_ptr<ExpressionNode> root;
254 
255  explicit ExpressionListNode(): AstNode(0) {}
256  explicit ExpressionListNode(size_t pos): AstNode(pos) {}
257 
258  void accept(NodeVisitor& v) const {
259  v.visit(*this);
260  }
261 };
262 
263 class StatementNode : public AstNode {
264 public:
265  StatementNode(size_t pos): AstNode(pos) {}
266 
267  virtual void accept(NodeVisitor& v) const = 0;
268 };
269 
271 public:
272  ExpressionListNode condition;
273  BlockNode body;
274  BlockNode* const parent;
275 
276  ForStatementNode(BlockNode* const parent, size_t pos): StatementNode(pos), parent(parent) {}
277 
278  virtual void accept(NodeVisitor& v) const = 0;
279 };
280 
282 public:
283  const std::string value;
284 
285  explicit ForArrayStatementNode(const std::string& value, BlockNode* const parent, size_t pos): ForStatementNode(parent, pos), value(value) {}
286 
287  void accept(NodeVisitor& v) const {
288  v.visit(*this);
289  }
290 };
291 
293 public:
294  const std::string key;
295  const std::string value;
296 
297  explicit ForObjectStatementNode(const std::string& key, const std::string& value, BlockNode* const parent, size_t pos)
298  : ForStatementNode(parent, pos), key(key), value(value) {}
299 
300  void accept(NodeVisitor& v) const {
301  v.visit(*this);
302  }
303 };
304 
306 public:
307  ExpressionListNode condition;
308  BlockNode true_statement;
309  BlockNode false_statement;
310  BlockNode* const parent;
311 
312  const bool is_nested;
313  bool has_false_statement {false};
314 
315  explicit IfStatementNode(BlockNode* const parent, size_t pos): StatementNode(pos), parent(parent), is_nested(false) {}
316  explicit IfStatementNode(bool is_nested, BlockNode* const parent, size_t pos): StatementNode(pos), parent(parent), is_nested(is_nested) {}
317 
318  void accept(NodeVisitor& v) const {
319  v.visit(*this);
320  }
321 };
322 
324 public:
325  const std::string file;
326 
327  explicit IncludeStatementNode(const std::string& file, size_t pos): StatementNode(pos), file(file) {}
328 
329  void accept(NodeVisitor& v) const {
330  v.visit(*this);
331  }
332 };
333 
335 public:
336  const std::string file;
337 
338  explicit ExtendsStatementNode(const std::string& file, size_t pos): StatementNode(pos), file(file) {}
339 
340  void accept(NodeVisitor& v) const {
341  v.visit(*this);
342  }
343 };
344 
346 public:
347  const std::string name;
348  BlockNode block;
349  BlockNode* const parent;
350 
351  explicit BlockStatementNode(BlockNode* const parent, const std::string& name, size_t pos): StatementNode(pos), name(name), parent(parent) {}
352 
353  void accept(NodeVisitor& v) const {
354  v.visit(*this);
355  }
356 };
357 
359 public:
360  const std::string key;
361  ExpressionListNode expression;
362 
363  explicit SetStatementNode(const std::string& key, size_t pos): StatementNode(pos), key(key) {}
364 
365  void accept(NodeVisitor& v) const {
366  v.visit(*this);
367  }
368 };
369 
370 } // namespace inja
371 
372 #endif // INCLUDE_INJA_NODE_HPP_
Base node class for the abstract syntax tree (AST).
Definition: node.hpp:56
Definition: node.hpp:66
Definition: node.hpp:345
Definition: node.hpp:108
Definition: node.hpp:251
Definition: node.hpp:88
Definition: node.hpp:334
Definition: node.hpp:281
Definition: node.hpp:292
Definition: node.hpp:270
Definition: node.hpp:131
Definition: node.hpp:305
Definition: node.hpp:323
Definition: node.hpp:97
Definition: node.hpp:31
Definition: node.hpp:358
Definition: node.hpp:263
Definition: node.hpp:77