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