2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
25#ifndef INCLUDE_INJA_INJA_HPP_
26#define INCLUDE_INJA_INJA_HPP_
28#include <nlohmann/json.hpp>
38#if (defined(__cpp_exceptions
) || defined(__EXCEPTIONS
) || defined(_CPPUNWIND)) && !defined(INJA_NOEXCEPTION)
40#define INJA_THROW(exception) throw exception
45#define INJA_THROW(exception)
47 std::ignore = exception
49#ifndef INJA_NOEXCEPTION
50#define INJA_NOEXCEPTION
55#ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
56#define INCLUDE_INJA_ENVIRONMENT_HPP_
66#ifndef INCLUDE_INJA_CONFIG_HPP_
67#define INCLUDE_INJA_CONFIG_HPP_
73#ifndef INCLUDE_INJA_TEMPLATE_HPP_
74#define INCLUDE_INJA_TEMPLATE_HPP_
82#ifndef INCLUDE_INJA_NODE_HPP_
83#define INCLUDE_INJA_NODE_HPP_
90#ifndef INCLUDE_INJA_FUNCTION_STORAGE_HPP_
91#define INCLUDE_INJA_FUNCTION_STORAGE_HPP_
100 using VoidCallbackFunction = std::function<
void(
Arguments& args)>;
103
104
158 explicit FunctionData(
const Operation& op,
const CallbackFunction& cb = CallbackFunction{})
206 void add_callback(std::string_view name,
int num_args,
const CallbackFunction& callback) {
211 auto it =
function_storage.find(std::make_pair(
static_cast<std::string>(name), num_args));
216 }
else if (num_args > 0) {
232#ifndef INCLUDE_INJA_UTILS_HPP_
233#define INCLUDE_INJA_UTILS_HPP_
238#include <string_view>
242#ifndef INCLUDE_INJA_EXCEPTIONS_HPP_
243#define INCLUDE_INJA_EXCEPTIONS_HPP_
261 explicit InjaError(
const std::string& type,
const std::string& message)
262 : std::runtime_error(
"[inja.exception." + type +
"] " + message)
269 : std::runtime_error(
"[inja.exception." + type +
"] (at " + std::to_string(location
.line) +
":" +
270 std::to_string(location
.column) +
") " + message)
311 inline std::string_view
slice(std::string_view view, size_t start, size_t end) {
312 start = std::min(start, view.size());
313 end = std::min(std::max(start, end), view.size());
314 return view.substr(start, end - start);
317 inline std::pair<std::string_view, std::string_view>
split(std::string_view view,
char Separator) {
318 size_t idx = view.find(Separator);
319 if (idx == std::string_view::npos) {
320 return std::make_pair(view, std::string_view());
322 return std::make_pair(
slice(view
, 0
, idx
),
slice(view
, idx + 1
, std::string_view::npos
));
325 inline bool starts_with(std::string_view view, std::string_view prefix) {
326 return (view.size() >= prefix.size() && view.compare(0, prefix.size(), prefix) == 0);
333 std::size_t last_newline = sliced.rfind(
"\n");
335 if (last_newline == std::string_view::npos) {
336 return {1, sliced.length() + 1};
340 size_t count_lines = 0;
341 size_t search_start = 0;
342 while (search_start <= sliced.size()) {
343 search_start = sliced.find(
"\n", search_start) + 1;
344 if (search_start == 0) {
350 return {count_lines + 1, sliced.length() - last_newline};
357 for (
auto pos = s.find(f);
358 pos != std::string::npos;
359 s.replace(pos, f.size(), t),
360 pos = s.find(f, pos + t.size()))
412
413
489 std::string_view part;
491 result.push_back(
'/');
492 result.append(part.begin(), part.end());
493 }
while (!ptr_name.empty());
497 explicit DataNode(std::string_view ptr_name, size_t pos)
797#ifndef INCLUDE_INJA_STATISTICS_HPP_
798#define INCLUDE_INJA_STATISTICS_HPP_
805
806
809 for (
auto& n : node
.nodes) {
884
885
905 using TemplateStorage = std::map<std::string,
Template>;
914
915
966
967
975
976
988#ifndef INCLUDE_INJA_PARSER_HPP_
989#define INCLUDE_INJA_PARSER_HPP_
1004#ifndef INCLUDE_INJA_LEXER_HPP_
1005#define INCLUDE_INJA_LEXER_HPP_
1013#ifndef INCLUDE_INJA_TOKEN_HPP_
1014#define INCLUDE_INJA_TOKEN_HPP_
1017#include <string_view>
1022
1023
1081 return static_cast<std::string>(
text);
1095
1096
1128 scan_body(std::string_view close,
Token::
Kind closeKind, std::string_view close_trim = std::string_view(),
bool trim =
false) {
1135 if (ch ==
' ' || ch ==
'\t' || ch ==
'\r') {
1166 if (std::isalpha(ch)) {
1267 if (!std::isalnum(ch) && ch !=
'.' && ch !=
'/' && ch !=
'_' && ch !=
'-') {
1282 if (!(std::isdigit(ch) || ch ==
'.' || ch ==
'e' || ch ==
'E' ||
1333 }
else if (ch ==
'\r') {
1343 std::string_view result = text;
1344 while (!result.empty()) {
1345 const char ch = result.back();
1346 if (ch ==
' ' || ch ==
'\t') {
1347 result.remove_suffix(1);
1348 }
else if (ch ==
'\n' || ch ==
'\r') {
1394 if (open_start == std::string_view::npos) {
1402 std::string_view open_str =
m_in.substr(
pos);
1403 bool must_lstrip =
false;
1496 if (end == std::string_view::npos) {
1537
1538
1581 inline void add_literal(Arguments& arguments,
const char* content_ptr) {
1584 arguments.emplace_back(std::make_shared<
LiteralNode>(data_text, data_text.data() - content_ptr));
1587 inline void add_operator(Arguments& arguments, OperatorStack& operator_stack) {
1588 auto function = operator_stack.top();
1589 operator_stack.pop();
1591 if (
static_cast<
int>(arguments.size()) < function->
number_args) {
1597 arguments.pop_back();
1599 arguments.emplace_back(function);
1607 std::string original_path =
static_cast<std::string>(path);
1608 std::string original_name = template_name;
1612 template_name = original_path + original_name;
1613 if (template_name.compare(0, 2,
"./") == 0) {
1614 template_name.erase(0, 2);
1620 file.open(template_name);
1622 std::string text((std::istreambuf_iterator<
char>(file)), std::istreambuf_iterator<
char>());
1660 size_t current_bracket_level{0};
1661 size_t current_brace_level{0};
1662 Arguments arguments;
1663 OperatorStack operator_stack;
1669 if (current_brace_level == 0 && current_bracket_level == 0) {
1671 add_literal(arguments, tmpl
.content.c_str());
1675 if (current_brace_level == 0 && current_bracket_level == 0) {
1677 add_literal(arguments, tmpl
.content.c_str());
1681 if (current_brace_level == 0 && current_bracket_level == 0) {
1684 current_bracket_level += 1;
1687 if (current_brace_level == 0 && current_bracket_level == 0) {
1690 current_brace_level += 1;
1693 if (current_bracket_level == 0) {
1697 current_bracket_level -= 1;
1698 if (current_brace_level == 0 && current_bracket_level == 0) {
1699 add_literal(arguments, tmpl
.content.c_str());
1703 if (current_brace_level == 0) {
1707 current_brace_level -= 1;
1708 if (current_brace_level == 0 && current_bracket_level == 0) {
1709 add_literal(arguments, tmpl
.content.c_str());
1718 if (current_brace_level == 0 && current_bracket_level == 0) {
1720 add_literal(arguments, tmpl
.content.c_str());
1725 goto parse_operator;
1752 arguments.emplace_back(func);
1756 arguments.emplace_back(
1836 while (!operator_stack.empty() && ((operator_stack.top()->
precedence > function_node->
precedence) ||
1839 add_operator(arguments, operator_stack);
1842 operator_stack.emplace(function_node);
1845 if (current_brace_level == 0 && current_bracket_level == 0) {
1850 if (current_brace_level == 0 && current_bracket_level == 0) {
1863 arguments.emplace_back(expr);
1873 while (!operator_stack.empty()) {
1874 add_operator(arguments, operator_stack);
1878 if (arguments.size() == 1) {
1879 expr = arguments[0];
1881 }
else if (arguments.size() > 1) {
1950 const std::string block_name =
static_cast<std::string>(
tok.text);
1952 auto block_statement_node =
1957 auto success = tmpl
.block_storage.emplace(block_name, block_statement_node);
1958 if (!success.second) {
1992 Token key_token = std::move(value_token);
1997 static_cast<std::string>(value_token
.text),
2057 std::string key =
static_cast<std::string>(
tok.text);
2064 if (tok.text !=
static_cast<
decltype(
tok.text)>(
"=")) {
2143 TemplateStorage& template_storage,
2152 auto result =
Template(static_cast<std::string>(input)
);
2158 std::string_view path = filename.substr(0, filename.find_last_of(
"/\\") + 1);
2167 file.open(filename);
2171 std::string text((std::istreambuf_iterator<
char>(file)), std::istreambuf_iterator<
char>());
2181#ifndef INCLUDE_INJA_RENDERER_HPP_
2182#define INCLUDE_INJA_RENDERER_HPP_
2203
2204
2229 static bool truthy(
const json* data) {
2230 if (data->is_boolean()) {
2231 return data->get<
bool>();
2232 }
else if (data->is_number()) {
2233 return (*data != 0);
2234 }
else if (data->is_null()) {
2237 return !data->empty();
2240 void print_data(
const std::shared_ptr<
json> value) {
2241 if (value->is_string()) {
2243 }
else if (value->is_number_unsigned()) {
2245 }
else if (value->is_number_integer()) {
2247 }
else if (value->is_null()) {
2254 if (!expression_list
.root) {
2279 return std::make_shared<
json>(*result);
2287 void make_result(
const json&& result) {
2288 auto result_ptr = std::make_shared<
json>(result);
2293 template <size_t N, size_t N_start = 0,
bool throw_not_found =
true>
2296 throw_renderer_error("function needs " + std::to_string(N_start + N) +
" variables, but has only found " +
2301 for (size_t i = N_start; i < N_start + N; i += 1) {
2311 std::array<
const json*, N> result;
2312 for (size_t i = 0; i < N; i += 1) {
2316 if (!result[N - i - 1]) {
2320 if (throw_not_found) {
2328 template <
bool throw_not_found =
true>
2342 for (size_t i = 0; i < N; i += 1) {
2346 if (!result[N - i - 1]) {
2350 if (throw_not_found) {
2359 for (
auto& n : node
.nodes) {
2389 const auto value = std::make_shared<
json>(function_data
.callback(empty_args));
2402 const auto args = get_arguments<1>(node);
2403 make_result(!truthy(args[0]));
2406 make_result(truthy(get_arguments<1, 0>(node)[0]) && truthy(get_arguments<1, 1>(node)[0]));
2409 make_result(truthy(get_arguments<1, 0>(node)[0]) || truthy(get_arguments<1, 1>(node)[0]));
2412 const auto args = get_arguments<2>(node);
2413 make_result(std::find(args[1]->begin(), args[1]->end(), *args[0]) != args[1]->end());
2416 const auto args = get_arguments<2>(node);
2417 make_result(*args[0] == *args[1]);
2420 const auto args = get_arguments<2>(node);
2421 make_result(*args[0] != *args[1]);
2424 const auto args = get_arguments<2>(node);
2425 make_result(*args[0] > *args[1]);
2428 const auto args = get_arguments<2>(node);
2429 make_result(*args[0] >= *args[1]);
2432 const auto args = get_arguments<2>(node);
2433 make_result(*args[0] < *args[1]);
2436 const auto args = get_arguments<2>(node);
2437 make_result(*args[0] <= *args[1]);
2440 const auto args = get_arguments<2>(node);
2441 if (args[0]->is_string() && args[1]->is_string()) {
2442 make_result(args[0]->get_ref<
const json::string_t&>() + args[1]->get_ref<
const json::string_t&>());
2443 }
else if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
2444 make_result(args[0]->get<
const json::number_integer_t>() + args[1]->get<
const json::number_integer_t>());
2446 make_result(args[0]->get<
const json::number_float_t>() + args[1]->get<
const json::number_float_t>());
2450 const auto args = get_arguments<2>(node);
2451 if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
2452 make_result(args[0]->get<
const json::number_integer_t>() - args[1]->get<
const json::number_integer_t>());
2454 make_result(args[0]->get<
const json::number_float_t>() - args[1]->get<
const json::number_float_t>());
2458 const auto args = get_arguments<2>(node);
2459 if (args[0]->is_number_integer() && args[1]->is_number_integer()) {
2460 make_result(args[0]->get<
const json::number_integer_t>() * args[1]->get<
const json::number_integer_t>());
2462 make_result(args[0]->get<
const json::number_float_t>() * args[1]->get<
const json::number_float_t>());
2466 const auto args = get_arguments<2>(node);
2467 if (args[1]->get<
const json::number_float_t>() == 0) {
2470 make_result(args[0]->get<
const json::number_float_t>() / args[1]->get<
const json::number_float_t>());
2473 const auto args = get_arguments<2>(node);
2474 if (args[0]->is_number_integer() && args[1]->get<
const json::number_integer_t>() >= 0) {
2475 const auto result =
static_cast<
json::number_integer_t>(
2476 std::pow(args[0]->get<
const json::number_integer_t>(), args[1]->get<
const json::number_integer_t>()));
2477 make_result(result);
2480 std::pow(args[0]->get<
const json::number_float_t>(), args[1]->get<
const json::number_integer_t>());
2481 make_result(result);
2485 const auto args = get_arguments<2>(node);
2486 make_result(args[0]->get<
const json::number_integer_t>() % args[1]->get<
const json::number_integer_t>());
2489 const auto container = get_arguments<1, 0,
false>(node)[0];
2500 const auto args = get_arguments<2>(node);
2501 if (args[0]->is_object()) {
2508 const auto test_arg = get_arguments<1, 0,
false>(node)[0];
2509 data_eval_stack.push(test_arg ? test_arg : get_arguments<1, 1>(node)[0]);
2512 const auto args = get_arguments<2>(node);
2513 const auto divisor = args[1]->get<
const json::number_integer_t>();
2514 make_result((divisor != 0) && (args[0]->get<
const json::number_integer_t>() % divisor == 0));
2517 make_result(get_arguments<1>(node)[0]->get<
const json::number_integer_t>() % 2 == 0);
2520 auto&& name = get_arguments<1>(node)[0]->get_ref<
const json::string_t&>();
2524 const auto args = get_arguments<2>(node);
2525 auto&& name = args[1]->get_ref<
const json::string_t&>();
2526 make_result(args[0]->find(name) != args[0]->end());
2529 const auto result = &get_arguments<1>(node)[0]->front();
2533 make_result(std::stod(get_arguments<1>(node)[0]->get_ref<
const json::string_t&>()));
2536 make_result(std::stoi(get_arguments<1>(node)[0]->get_ref<
const json::string_t&>()));
2539 const auto result = &get_arguments<1>(node)[0]->back();
2543 const auto val = get_arguments<1>(node)[0];
2544 if (val->is_string()) {
2545 make_result(val->get_ref<
const json::string_t&>().length());
2547 make_result(val->size());
2551 auto result = get_arguments<1>(node)[0]->get<
json::string_t>();
2552 std::transform(result.begin(), result.end(), result.begin(), [](
char c) {
2553 return static_cast<
char>(::tolower(c));
2555 make_result(std::move(result));
2558 const auto args = get_arguments<1>(node);
2559 const auto result = std::max_element(args[0]->begin(), args[0]->end());
2563 const auto args = get_arguments<1>(node);
2564 const auto result = std::min_element(args[0]->begin(), args[0]->end());
2568 make_result(get_arguments<1>(node)[0]->get<
const json::number_integer_t>() % 2 != 0);
2571 std::vector<
int> result(get_arguments<1>(node)[0]->get<std::vector<
int>::size_type>());
2572 std::iota(result.begin(), result.end(), 0);
2573 make_result(std::move(result));
2576 const auto args = get_arguments<2>(node);
2577 const int precision = args[1]->get<
int>();
2578 const double result =
2579 std::round(args[0]->get<
const json::number_float_t>() * std::pow(10.0, precision)) / std::pow(10.0, precision);
2580 if (precision == 0) {
2581 make_result(
int(result));
2583 make_result(result);
2587 auto result_ptr = std::make_shared<
json>(get_arguments<1>(node)[0]->get<std::vector<
json>>());
2588 std::sort(result_ptr->begin(), result_ptr->end());
2593 auto result = get_arguments<1>(node)[0]->get<
json::string_t>();
2594 std::transform(result.begin(), result.end(), result.begin(), [](
char c) {
2595 return static_cast<
char>(::toupper(c));
2597 make_result(std::move(result));
2600 make_result(get_arguments<1>(node)[0]->is_boolean());
2603 make_result(get_arguments<1>(node)[0]->is_number());
2606 make_result(get_arguments<1>(node)[0]->is_number_integer());
2609 make_result(get_arguments<1>(node)[0]->is_number_float());
2612 make_result(get_arguments<1>(node)[0]->is_object());
2615 make_result(get_arguments<1>(node)[0]->is_array());
2618 make_result(get_arguments<1>(node)[0]->is_string());
2621 auto args = get_argument_vector(node);
2625 const auto args = get_argument_vector(node);
2627 const size_t level_diff = (args.size() == 1) ? args[0]->get<size_t>() : 1;
2653 make_result(
nullptr);
2656 const auto args = get_arguments<2>(node);
2657 const auto separator = args[1]->get<
json::string_t>();
2658 std::ostringstream os;
2660 for (
const auto& value : *args[0]) {
2662 if (value.is_string()) {
2663 os << value.get<std::string>();
2669 make_result(os.str());
2688 if (!result->is_array()) {
2700 for (
auto it = result->begin(); it != result->end(); ++it) {
2708 if (index == result->size() - 1) {
2727 if (!result->is_object()) {
2738 for (
auto it = result->begin(); it != result->end(); ++it) {
2747 if (index == result->size() - 1) {
2766 if (truthy(result.get())) {
2786 const Template* parent_template = &included_template_it->second;
2809 std::string ptr = node
.key;
2822 void render_to(std::ostream& os,
const Template& tmpl,
const json& data,
json* loop_data =
nullptr) {
2849
2850
2873 Environment(
const std::string& input_path,
const std::string& output_path)
2948 std::string render(std::string_view input,
const json& data) {
2949 return render(
parse(input
), data);
2953 std::stringstream os;
2954 render_to(os, tmpl, data);
2958 std::string render_file(
const std::string& filename,
const json& data) {
2964 return render_file(filename, data);
2967 void write(
const std::string& filename,
const json& data,
const std::string& filename_out) {
2969 file << render_file(filename, data);
2973 void write(
const Template& temp,
const json& data,
const std::string& filename_out) {
2975 file << render(temp, data);
2979 void write_with_json_file(
const std::string& filename,
const std::string& filename_data,
const std::string& filename_out) {
2981 write(filename, data, filename_out);
2986 write(temp, data, filename_out);
2989 std::ostream& render_to(std::ostream& os,
const Template& tmpl,
const json& data) {
3006 return json::parse(std::istreambuf_iterator<
char>(file), std::istreambuf_iterator<
char>());
3010
3011
3012 void add_callback(
const std::string& name,
const CallbackFunction& callback) {
3013 add_callback(name, -1, callback);
3017
3018
3019 void add_void_callback(
const std::string& name,
const VoidCallbackFunction& callback) {
3020 add_void_callback(name, -1, callback);
3024
3025
3026 void add_callback(
const std::string& name,
int num_args,
const CallbackFunction& callback) {
3031
3032
3033 void add_void_callback(
const std::string& name,
int num_args,
const VoidCallbackFunction& callback) {
3041
3042
3043
3049
3050
3057
3058
3059 inline std::string render(std::string_view input,
const json& data) {
3064
3065
3066 inline void render_to(std::ostream& os, std::string_view input,
const json& data) {
3068 env.render_to(os, env
.parse(input
), data);
std::vector< mqtt::lib::Function > functions
std::vector< mqtt::lib::VoidFunction > voidFunctions
Base node class for the abstract syntax tree (AST).
AstNode & operator=(const AstNode &)=default
virtual void accept(NodeVisitor &v) const =0
AstNode(const AstNode &)=default
std::vector< std::shared_ptr< AstNode > > nodes
void accept(NodeVisitor &v) const override
void accept(NodeVisitor &v) const override
BlockStatementNode(BlockNode *const parent, const std::string &name, size_t pos)
static std::string convert_dot_to_ptr(std::string_view ptr_name)
void accept(NodeVisitor &v) const override
DataNode(std::string_view ptr_name, size_t pos)
const json::json_pointer ptr
Class for changing the configuration.
TemplateStorage template_storage
FunctionStorage function_storage
Environment(const std::string &input_path, const std::string &output_path)
void set_throw_at_missing_includes(bool will_throw)
Sets whether a missing include will throw an error.
void set_statement(const std::string &open, const std::string &close)
Sets the opener and closer for template statements.
void set_search_included_templates_in_files(bool search_in_files)
Sets the element notation syntax.
json load_json(const std::string &filename)
void set_trim_blocks(bool trim_blocks)
Sets whether to remove the first newline after a block.
std::string load_file(const std::string &filename)
RenderConfig render_config
std::string render_file_with_json_file(const std::string &filename, const std::string &filename_data)
void set_lstrip_blocks(bool lstrip_blocks)
Sets whether to strip the spaces and tabs from the start of a line to a block.
void set_comment(const std::string &open, const std::string &close)
Sets the opener and closer for template comments.
void set_line_statement(const std::string &open)
Sets the opener for template line statements.
void set_include_callback(const std::function< Template(const std::string &, const std::string &)> &callback)
Sets a function that is called when an included file is not found.
Template parse(std::string_view input)
Template parse_file(const std::string &filename)
void write_with_json_file(const Template &temp, const std::string &filename_data, const std::string &filename_out)
Template parse_template(const std::string &filename)
void set_expression(const std::string &open, const std::string &close)
Sets the opener and closer for template expressions.
void include_template(const std::string &name, const Template &tmpl)
void write_with_json_file(const std::string &filename, const std::string &filename_data, const std::string &filename_out)
Environment(const std::string &global_path)
ParserConfig parser_config
void accept(NodeVisitor &v) const override
ExpressionListNode(size_t pos)
std::shared_ptr< ExpressionNode > root
void accept(NodeVisitor &v) const override
ExpressionNode(size_t pos)
ExtendsStatementNode(const std::string &file, size_t pos)
void accept(NodeVisitor &v) const override
ForArrayStatementNode(const std::string &value, BlockNode *const parent, size_t pos)
void accept(NodeVisitor &v) const override
ForObjectStatementNode(const std::string &key, const std::string &value, BlockNode *const parent, size_t pos)
void accept(NodeVisitor &v) const override
ExpressionListNode condition
ForStatementNode(BlockNode *const parent, size_t pos)
virtual void accept(NodeVisitor &v) const override=0
std::vector< std::shared_ptr< ExpressionNode > > arguments
Associativity associativity
void accept(NodeVisitor &v) const override
CallbackFunction callback
FunctionNode(Op operation, size_t pos)
FunctionStorage::Operation Op
FunctionNode(std::string_view name, size_t pos)
Class for builtin functions and user-defined callbacks.
void add_builtin(std::string_view name, int num_args, Operation op)
std::map< std::pair< std::string, int >, FunctionData > function_storage
FunctionData find_function(std::string_view name, int num_args) const
void accept(NodeVisitor &v) const override
BlockNode false_statement
IfStatementNode(BlockNode *const parent, size_t pos)
ExpressionListNode condition
IfStatementNode(bool is_nested, BlockNode *const parent, size_t pos)
void accept(NodeVisitor &v) const override
IncludeStatementNode(const std::string &file, size_t pos)
Class for lexing an inja Template.
const LexerConfig & config
SourceLocation current_position() const
static std::string_view clear_final_line_if_whitespace(std::string_view text)
const LexerConfig & get_config() const
void skip_whitespaces_and_newlines()
Token make_token(Token::Kind kind) const
@ StatementStartForceLstrip
@ ExpressionStartForceLstrip
@ CommentStartForceLstrip
Token scan_body(std::string_view close, Token::Kind closeKind, std::string_view close_trim=std::string_view(), bool trim=false)
Lexer(const LexerConfig &config)
void skip_whitespaces_and_first_newline()
void start(std::string_view input)
void accept(NodeVisitor &v) const override
LiteralNode(std::string_view data_text, size_t pos)
virtual void visit(const DataNode &node)=0
virtual void visit(const SetStatementNode &node)=0
virtual void visit(const ExpressionListNode &node)=0
virtual ~NodeVisitor()=default
virtual void visit(const StatementNode &node)=0
virtual void visit(const ExtendsStatementNode &node)=0
virtual void visit(const IncludeStatementNode &node)=0
virtual void visit(const TextNode &node)=0
virtual void visit(const ForStatementNode &node)=0
virtual void visit(const LiteralNode &node)=0
virtual void visit(const ExpressionNode &node)=0
virtual void visit(const ForObjectStatementNode &node)=0
virtual void visit(const BlockStatementNode &node)=0
virtual void visit(const IfStatementNode &node)=0
virtual void visit(const FunctionNode &node)=0
virtual void visit(const ForArrayStatementNode &node)=0
virtual void visit(const BlockNode &node)=0
Class for parsing an inja Template.
std::string load_file(const std::string &filename)
Template parse(std::string_view input, std::string_view path)
void throw_parser_error(const std::string &message) const
std::string parse_filename() const
std::stack< BlockStatementNode * > block_statement_stack
std::stack< ForStatementNode * > for_statement_stack
ExpressionListNode * current_expression_list
bool parse_statement(Template &tmpl, Token::Kind closing, std::string_view path)
TemplateStorage & template_storage
std::shared_ptr< ExpressionNode > parse_expression(Template &tmpl)
void parse_into_template(Template &tmpl, std::string_view filename)
void parse_into(Template &tmpl, std::string_view path)
const FunctionStorage & function_storage
const ParserConfig & config
std::stack< IfStatementNode * > if_statement_stack
BlockNode * current_block
void add_to_template_storage(std::string_view path, std::string &template_name)
std::string_view literal_start
bool parse_expression(Template &tmpl, Token::Kind closing)
Class for rendering a Template with data.
void visit(const FunctionNode &node) override
void visit(const ExpressionListNode &node) override
const std::shared_ptr< json > eval_expression_list(const ExpressionListNode &expression_list)
std::vector< std::shared_ptr< json > > data_tmp_stack
void visit(const DataNode &node) override
void visit(const StatementNode &) override
std::ostream * output_stream
void throw_renderer_error(const std::string &message, const AstNode &node)
const RenderConfig config
std::stack< const json * > data_eval_stack
std::stack< const DataNode * > not_found_stack
void visit(const TextNode &node) override
std::vector< const BlockStatementNode * > block_statement_stack
const Template * current_template
void visit(const ExpressionNode &) override
void visit(const SetStatementNode &node) override
void visit(const IncludeStatementNode &node) override
void visit(const ForStatementNode &) override
FunctionStorage::Operation Op
std::vector< const Template * > template_stack
void visit(const ForArrayStatementNode &node) override
const FunctionStorage & function_storage
const TemplateStorage & template_storage
void visit(const IfStatementNode &node) override
void visit(const BlockNode &node) override
void visit(const LiteralNode &node) override
void visit(const ExtendsStatementNode &node) override
void visit(const ForObjectStatementNode &node) override
void visit(const BlockStatementNode &node) override
ExpressionListNode expression
SetStatementNode(const std::string &key, size_t pos)
void accept(NodeVisitor &v) const override
StatementNode(size_t pos)
virtual void accept(NodeVisitor &v) const override=0
A class for counting statistics on a Template.
void visit(const LiteralNode &) override
void visit(const IfStatementNode &node) override
void visit(const DataNode &) override
void visit(const IncludeStatementNode &) override
void visit(const ForArrayStatementNode &node) override
unsigned int variable_counter
void visit(const StatementNode &) override
void visit(const BlockNode &node) override
void visit(const FunctionNode &node) override
void visit(const ExpressionListNode &node) override
void visit(const ForStatementNode &) override
void visit(const SetStatementNode &) override
void visit(const ExtendsStatementNode &) override
void visit(const TextNode &) override
void visit(const ExpressionNode &) override
void visit(const ForObjectStatementNode &node) override
void visit(const BlockStatementNode &node) override
TextNode(size_t pos, size_t length)
void accept(NodeVisitor &v) const override
static void store(const inja::Arguments &args)
static double recall_as_float(const inja::Arguments &args)
static const std::string & recall(const inja::Arguments &args)
static bool exists(const inja::Arguments &args)
static bool is_empty(const inja::Arguments &args)
Storage & operator=(const Storage &)=delete
static int recall_as_int(const inja::Arguments &args)
std::map< std::string, std::string > storage
Storage(const Storage &)=delete
static Storage & instance()
#define INJA_THROW(exception)
std::pair< std::string_view, std::string_view > split(std::string_view view, char Separator)
bool starts_with(std::string_view view, std::string_view prefix)
std::string_view slice(std::string_view view, size_t start, size_t end)
std::vector< const nlohmann::json * > Arguments
void replace_substring(std::string &s, const std::string &f, const std::string &t)
SourceLocation get_source_location(std::string_view content, size_t pos)
DataError(const std::string &message, SourceLocation location)
FileError(const std::string &message)
FileError(const std::string &message, SourceLocation location)
const Operation operation
const CallbackFunction callback
InjaError(const std::string &type, const std::string &message)
InjaError(const std::string &type, const std::string &message, SourceLocation location)
const SourceLocation location
const std::string message
Class for lexer configuration.
std::string expression_open_force_lstrip
std::string expression_close
std::string expression_close_force_rstrip
std::string comment_open_force_lstrip
std::string comment_close
std::string statement_close
std::string expression_open
std::string comment_close_force_rstrip
std::string statement_open_force_lstrip
std::string statement_close_force_rstrip
std::string statement_open_no_lstrip
std::string statement_open
std::string line_statement
Class for parser configuration.
bool search_included_templates_in_files
std::function< Template(const std::string &, const std::string &)> include_callback
ParserError(const std::string &message, SourceLocation location)
Class for render configuration.
bool throw_at_missing_includes
RenderError(const std::string &message, SourceLocation location)
Template(const std::string &content)
unsigned int count_variables()
Return number of variables (total number, not distinct ones) in the template.
std::map< std::string, std::shared_ptr< BlockStatementNode > > block_storage
Helper-class for the inja Lexer.
constexpr Token()=default
std::string describe() const
constexpr Token(Kind kind, std::string_view text)