mirror of
https://github.com/pantor/inja.git
synced 2026-05-01 03:29:25 +00:00
add atid operation
This commit is contained in:
@@ -36,6 +36,7 @@ public:
|
||||
Division,
|
||||
Power,
|
||||
Modulo,
|
||||
AtId,
|
||||
At,
|
||||
Default,
|
||||
DivisibleBy,
|
||||
|
||||
@@ -108,6 +108,8 @@ class Lexer {
|
||||
return make_token(Token::Kind::Power);
|
||||
case '%':
|
||||
return make_token(Token::Kind::Percent);
|
||||
case '.':
|
||||
return make_token(Token::Kind::Dot);
|
||||
case ',':
|
||||
return make_token(Token::Kind::Comma);
|
||||
case ':':
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
size_t number_args;
|
||||
CallbackFunction callback;
|
||||
|
||||
explicit FunctionNode(nonstd::string_view name, size_t pos) : ExpressionNode(pos), precedence(5), associativity(Associativity::Left), operation(Op::Callback), name(name), number_args(1) { }
|
||||
explicit FunctionNode(nonstd::string_view name, size_t pos) : ExpressionNode(pos), precedence(8), associativity(Associativity::Left), operation(Op::Callback), name(name), number_args(1) { }
|
||||
explicit FunctionNode(Op operation, size_t pos) : ExpressionNode(pos), operation(operation), number_args(1) {
|
||||
switch (operation) {
|
||||
case Op::Not: {
|
||||
@@ -208,6 +208,10 @@ public:
|
||||
precedence = 4;
|
||||
associativity = Associativity::Left;
|
||||
} break;
|
||||
case Op::AtId: {
|
||||
precedence = 8;
|
||||
associativity = Associativity::Left;
|
||||
} break;
|
||||
default: {
|
||||
precedence = 1;
|
||||
associativity = Associativity::Left;
|
||||
|
||||
@@ -166,7 +166,8 @@ class Parser {
|
||||
case Token::Kind::Times:
|
||||
case Token::Kind::Slash:
|
||||
case Token::Kind::Power:
|
||||
case Token::Kind::Percent: {
|
||||
case Token::Kind::Percent:
|
||||
case Token::Kind::Dot: {
|
||||
|
||||
parse_operator:
|
||||
FunctionStorage::Operation operation;
|
||||
@@ -220,6 +221,9 @@ class Parser {
|
||||
case Token::Kind::Percent: {
|
||||
operation = FunctionStorage::Operation::Modulo;
|
||||
} break;
|
||||
case Token::Kind::Dot: {
|
||||
operation = FunctionStorage::Operation::AtId;
|
||||
} break;
|
||||
default: {
|
||||
throw_parser_error("unknown operator in parser.");
|
||||
}
|
||||
|
||||
@@ -311,6 +311,16 @@ class Renderer : public NodeVisitor {
|
||||
json_tmp_stack.push_back(result_ptr);
|
||||
json_eval_stack.push(result_ptr.get());
|
||||
} break;
|
||||
case Op::AtId: {
|
||||
json_eval_stack.pop(); // Pop id nullptr
|
||||
auto container = get_arguments<1, false>(node)[0];
|
||||
if (not_found_stack.empty()) {
|
||||
throw_renderer_error("could not find element with given name", node);
|
||||
}
|
||||
auto id_node = not_found_stack.top();
|
||||
not_found_stack.pop();
|
||||
json_eval_stack.push(&container->at(id_node->name));
|
||||
} break;
|
||||
case Op::At: {
|
||||
auto args = get_arguments<2>(node);
|
||||
json_eval_stack.push(&args[0]->at(args[1]->get<int>()));
|
||||
|
||||
@@ -33,6 +33,7 @@ struct Token {
|
||||
Percent, // %
|
||||
Power, // ^
|
||||
Comma, // ,
|
||||
Dot, // .
|
||||
Colon, // :
|
||||
LeftParen, // (
|
||||
RightParen, // )
|
||||
|
||||
@@ -1550,6 +1550,7 @@ public:
|
||||
Division,
|
||||
Power,
|
||||
Modulo,
|
||||
AtId,
|
||||
At,
|
||||
Default,
|
||||
DivisibleBy,
|
||||
@@ -1770,6 +1771,7 @@ struct Token {
|
||||
Percent, // %
|
||||
Power, // ^
|
||||
Comma, // ,
|
||||
Dot, // .
|
||||
Colon, // :
|
||||
LeftParen, // (
|
||||
RightParen, // )
|
||||
@@ -1984,6 +1986,8 @@ class Lexer {
|
||||
return make_token(Token::Kind::Power);
|
||||
case '%':
|
||||
return make_token(Token::Kind::Percent);
|
||||
case '.':
|
||||
return make_token(Token::Kind::Dot);
|
||||
case ',':
|
||||
return make_token(Token::Kind::Comma);
|
||||
case ':':
|
||||
@@ -2849,7 +2853,8 @@ class Parser {
|
||||
case Token::Kind::Times:
|
||||
case Token::Kind::Slash:
|
||||
case Token::Kind::Power:
|
||||
case Token::Kind::Percent: {
|
||||
case Token::Kind::Percent:
|
||||
case Token::Kind::Dot: {
|
||||
|
||||
parse_operator:
|
||||
FunctionStorage::Operation operation;
|
||||
@@ -2903,6 +2908,10 @@ class Parser {
|
||||
case Token::Kind::Percent: {
|
||||
operation = FunctionStorage::Operation::Modulo;
|
||||
} break;
|
||||
case Token::Kind::Dot: {
|
||||
std::cout << "test" << std::endl;
|
||||
operation = FunctionStorage::Operation::AtId;
|
||||
} break;
|
||||
default: {
|
||||
throw_parser_error("unknown operator in parser.");
|
||||
}
|
||||
@@ -3553,6 +3562,21 @@ class Renderer : public NodeVisitor {
|
||||
json_tmp_stack.push_back(result_ptr);
|
||||
json_eval_stack.push(result_ptr.get());
|
||||
} break;
|
||||
case Op::AtId: {
|
||||
std::cout << "test" << std::endl;
|
||||
auto container = get_arguments<1, false>(node)[0];
|
||||
auto id = get_arguments<1, false>(node)[0];
|
||||
if (id == nullptr) {
|
||||
auto id_node = not_found_stack.top();
|
||||
not_found_stack.pop();
|
||||
|
||||
auto ptr = json::json_pointer(id_node->ptr);
|
||||
json_eval_stack.push(&container->at(ptr));
|
||||
|
||||
} else {
|
||||
json_eval_stack.push(id);
|
||||
}
|
||||
} break;
|
||||
case Op::At: {
|
||||
auto args = get_arguments<2>(node);
|
||||
json_eval_stack.push(&args[0]->at(args[1]->get<int>()));
|
||||
|
||||
@@ -254,6 +254,7 @@ TEST_CASE("combinations") {
|
||||
data["brother"]["daughters"] = {"Maria", "Helen"};
|
||||
data["brother"]["daughter0"] = {{"name", "Maria"}};
|
||||
data["is_happy"] = true;
|
||||
data["list_of_objects"] = {{{"a", 2}}, {{"b", 3}}, {{"c", 4}}, {{"d", 5}}};
|
||||
|
||||
CHECK(env.render("{% if upper(\"Peter\") == \"PETER\" %}TRUE{% endif %}", data) == "TRUE");
|
||||
CHECK(env.render("{% if lower(upper(name)) == \"peter\" %}TRUE{% endif %}", data) == "TRUE");
|
||||
@@ -263,4 +264,7 @@ TEST_CASE("combinations") {
|
||||
CHECK(env.render("{{ upper(first(sort(brother.daughters)) + \"_test\") }}", data) == "HELEN_TEST");
|
||||
CHECK(env.render("{% for i in range(3) %}{{ at(names, i) }}{% endfor %}", data) == "JeffSebChris");
|
||||
CHECK(env.render("{% if not is_happy or age > 26 %}TRUE{% endif %}", data) == "TRUE");
|
||||
CHECK(env.render("{{ last(list_of_objects).d * 2}}", data) == "10");
|
||||
CHECK(env.render("{{ last(range(5)) * 2 }}", data) == "8");
|
||||
CHECK(env.render("{{ last(range(5 * 2)) }}", data) == "9");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user