Inja 3.4.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 <string_view>
6#include <utility>
7
8#include "function_storage.hpp"
9#include "utils.hpp"
10
11namespace inja {
12
13class NodeVisitor;
14class BlockNode;
15class TextNode;
16class ExpressionNode;
17class LiteralNode;
18class DataNode;
19class FunctionNode;
20class ExpressionListNode;
21class StatementNode;
22class ForStatementNode;
23class ForArrayStatementNode;
24class ForObjectStatementNode;
25class IfStatementNode;
26class IncludeStatementNode;
27class ExtendsStatementNode;
28class BlockStatementNode;
29class SetStatementNode;
30
32public:
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
56class AstNode {
57public:
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
66class BlockNode : public AstNode {
67public:
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
77class TextNode : public AstNode {
78public:
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
88class ExpressionNode : public AstNode {
89public:
90 explicit ExpressionNode(size_t pos): AstNode(pos) {}
91
92 void accept(NodeVisitor& v) const {
93 v.visit(*this);
94 }
95};
96
98public:
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
108class DataNode : public ExpressionNode {
109public:
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
132 using Op = FunctionStorage::Operation;
133
134public:
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
252public:
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
263class StatementNode : public AstNode {
264public:
265 StatementNode(size_t pos): AstNode(pos) {}
266
267 virtual void accept(NodeVisitor& v) const = 0;
268};
269
271public:
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
282public:
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
293public:
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
306public:
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
324public:
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
335public:
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
346public:
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
359public:
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