From 9f4d4ab24e7a539621bcd810b84201b0127c0870 Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Fri, 20 Mar 2020 14:01:49 +0100 Subject: allow negating singular terms & add loop variables --- src/template.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/template.c b/src/template.c index a1439c4..e8fcf36 100644 --- a/src/template.c +++ b/src/template.c @@ -90,7 +90,7 @@ mpc_parser_t *parser_init() { " number : /[0-9]+/ ;" " text : /[^{][^{%#]*/;" " string : '\"' /([^\"])*/ '\"' ;" - " factor : '(' ')' | | | ;" + " factor : | | ;" " term : ( ('*' | '/' | '%') )* ;" " lexp : ( ('+' | '-') )* ;" " expression: '>' " @@ -99,6 +99,7 @@ mpc_parser_t *parser_init() { " | \"<=\" " " | \"!=\" " " | \"==\" " + " | \"not\" " " | ;" " print : /{{2}-? */ / *-?}}/ ;" " comment : \"{#\" /[^#][^#}]*/ \"#}\" ;" @@ -329,7 +330,7 @@ void object_free(struct unja_object *obj) { int object_is_truthy(struct unja_object *obj) { switch (obj->type) { case OBJ_NULL: return 0; - case OBJ_STRING: return strlen(obj->string) > 0; + case OBJ_STRING: return strlen(obj->string) > 0 && strcmp(obj->string, "0") != 0; case OBJ_INT: return obj->integer > 0; } @@ -356,6 +357,7 @@ struct unja_object *eval_expression_value(mpc_ast_t* node, struct context *ctx) if (value == NULL) { return &null_object; } + return make_string_object(value, NULL); } else if(strstr(node->tag, "number|")) { return make_int_object(atoi(node->contents)); @@ -434,9 +436,18 @@ struct unja_object *eval_expression(mpc_ast_t* expr, struct context *ctx) { return eval_expression_value(expr, ctx); } - /* otherwise: with operator */ - int offset = 0; struct unja_object *result; + + /* singular negated term */ + if (strcmp(expr->children[0]->contents, "not") == 0) { + result = eval_expression_value(expr->children[2], ctx); + struct unja_object *negated = make_int_object(!object_to_int(result)); + object_free(result); + return negated; + } + + /* otherwise: with operator */ + unsigned int offset = 0; mpc_ast_t *left_node = expr->children[0]; struct unja_object *left = eval_expression(left_node, ctx); @@ -511,12 +522,32 @@ int eval(struct buffer *buf, mpc_ast_t* t, struct context *ctx) { char *tmp_key = t->children[2]->contents; char *iterator_key = t->children[4]->contents; struct vector *list = hashmap_resolve(ctx->vars, iterator_key); + + /* add "loop" variable to context */ + struct hashmap *loop = hashmap_new(); + char index[8], first[2], last[2]; + hashmap_insert(loop, "index", index); + hashmap_insert(loop, "first", first); + hashmap_insert(loop, "last", last); + hashmap_insert(ctx->vars, "loop", loop); + + /* loop over values in vector */ for (int i=0; i < list->size; i++) { + /* set loop variable values */ + sprintf(index, "%d", i); + sprintf(first, "%d", i == 0); + sprintf(last, "%d", i == (list->size - 1)); hashmap_insert(ctx->vars, tmp_key, list->values[i]); trim_whitespace = strstr(t->children[5]->contents, "-") ? 1 : 0; + + /* evaluate body */ eval(buf, t->children[6], ctx); } + /* remove "loop" variable from context */ + hashmap_remove(ctx->vars, "loop"); + hashmap_free(loop); + /* trim trailing whitespace if closing tag has minus sign */ if (strstr(t->children[7]->contents, "-")) { buf->string = trim_trailing_whitespace(buf->string); -- cgit v1.2.3