mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-24 13:37:01 +02:00
jinja : parse unary +/- before variables (#29244)
* jinja : parse unary +/- before variables Lexer already emits unary_operator for -n / +n, and runtime executes unary -. Parse them at multiplicative precedence so slices like items[:-n] and GigaChat indent[:-indent_factor] work. * jinja : keep filters/tests outside unary operands Unary +/- must bind only the primary/postfix operand so -n|abs is (-n)|abs, not -(n|abs). Add unary + and filter/test regression coverage. Signed-off-by: sinksilk <[email protected]> --------- Signed-off-by: sinksilk <[email protected]>
This commit is contained in:
+11
-1
@@ -437,7 +437,8 @@ private:
|
||||
}
|
||||
|
||||
statement_ptr parse_filter_expression() {
|
||||
auto operand = parse_call_member_expression();
|
||||
// Filters/tests bind outside unary so -n|abs is (-n)|abs, not -(n|abs).
|
||||
auto operand = parse_unary_expression();
|
||||
while (is(token::pipe)) {
|
||||
size_t start_pos = current;
|
||||
++current; // consume pipe
|
||||
@@ -448,6 +449,15 @@ private:
|
||||
return operand;
|
||||
}
|
||||
|
||||
statement_ptr parse_unary_expression() {
|
||||
if (is(token::unary_operator)) {
|
||||
size_t start_pos = current;
|
||||
auto op = next();
|
||||
return mk_stmt<unary_expression>(start_pos, op, parse_unary_expression());
|
||||
}
|
||||
return parse_call_member_expression();
|
||||
}
|
||||
|
||||
statement_ptr parse_call_member_expression() {
|
||||
// Handle member expressions recursively
|
||||
auto member = parse_member_expression(parse_primary_expression());
|
||||
|
||||
@@ -450,6 +450,11 @@ value unary_expression::execute_impl(context & ctx) const {
|
||||
} else {
|
||||
throw std::runtime_error("Unary - operator requires numeric operand");
|
||||
}
|
||||
} else if (op.value == "+") {
|
||||
if (is_val<value_int>(operand_val) || is_val<value_float>(operand_val)) {
|
||||
return operand_val;
|
||||
}
|
||||
throw std::runtime_error("Unary + operator requires numeric operand");
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unknown unary operator '" + op.value + "'");
|
||||
|
||||
@@ -458,6 +458,49 @@ static void test_expressions(testing & t) {
|
||||
"['b']"
|
||||
);
|
||||
|
||||
test_template(t, "array slice negative variable",
|
||||
"{{ items[:-n]|string }}",
|
||||
{{"items", json::array({"a", "b", "c"})}, {"n", 1}},
|
||||
"['a', 'b']"
|
||||
);
|
||||
|
||||
test_template(t, "array slice negative variable indent",
|
||||
"{{ indent[:-indent_factor] }}",
|
||||
{{"indent", " "}, {"indent_factor", 2}},
|
||||
" "
|
||||
);
|
||||
|
||||
test_template(t, "unary minus variable",
|
||||
"{{ -n }}",
|
||||
{{"n", 3}},
|
||||
"-3"
|
||||
);
|
||||
|
||||
test_template(t, "unary plus variable",
|
||||
"{{ +n }}",
|
||||
{{"n", -3}},
|
||||
"-3"
|
||||
);
|
||||
|
||||
test_template(t, "unary plus float",
|
||||
"{{ +x }}",
|
||||
{{"x", -1.5}},
|
||||
"-1.5"
|
||||
);
|
||||
|
||||
// Unary binds tighter than filter: -n|abs == (-n)|abs, not -(n|abs)
|
||||
test_template(t, "unary minus then abs filter",
|
||||
"{{ -n|abs }}",
|
||||
{{"n", -3}},
|
||||
"3"
|
||||
);
|
||||
|
||||
test_template(t, "unary minus then number test",
|
||||
"{{ -n is number }}",
|
||||
{{"n", 3}},
|
||||
"True"
|
||||
);
|
||||
|
||||
test_template(t, "array slice step",
|
||||
"{{ items[::2]|string }}",
|
||||
{{"items", json::array({"a", "b", "c"})}},
|
||||
|
||||
Reference in New Issue
Block a user