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