aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2016-07-03 03:25:12 +0200
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2016-07-03 03:25:12 +0200
commit9acb03e669e20180b9bc95ca02b21460761fef87 (patch)
tree376d2c46c207daaf5b6c1939c805e4191f02a036 /src
parent82995655dca72297155c5632029284dacbcccc87 (diff)
downloadblogc-9acb03e669e20180b9bc95ca02b21460761fef87.tar.gz
blogc-9acb03e669e20180b9bc95ca02b21460761fef87.tar.bz2
blogc-9acb03e669e20180b9bc95ca02b21460761fef87.zip
template-parser: renderer: implemented 'else' support in templates
yeah, this is stupid. after more than 320 commits and 26 releases, we finally support the 'else' statement in the template engine. I don't know if I'm dumb or what, but it took me that long to find a "simple" solution to this basic issue. yep, no more `{% ifdef FOO %}...{% endif %}{% ifndef FOO %}...{% endif %}` blocks. but seriously, who cares?! :/
Diffstat (limited to 'src')
-rw-r--r--src/debug.c3
-rw-r--r--src/renderer.c49
-rw-r--r--src/template-parser.c31
-rw-r--r--src/template-parser.h1
4 files changed, 80 insertions, 4 deletions
diff --git a/src/debug.c b/src/debug.c
index 767e1a5..7039608 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -55,6 +55,9 @@ blogc_debug_template(sb_slist_t *stmts)
fprintf(stderr, "IF: %s %s %s", data->value,
get_operator(data->op), data->value2);
break;
+ case BLOGC_TEMPLATE_ELSE_STMT:
+ fprintf(stderr, "ELSE");
+ break;
case BLOGC_TEMPLATE_ENDIF_STMT:
fprintf(stderr, "ENDIF");
break;
diff --git a/src/renderer.c b/src/renderer.c
index 0f71ba7..351dfb1 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -188,6 +188,7 @@ blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config, bool list
bool if_not = false;
bool inside_block = false;
bool evaluate = false;
+ bool valid_else = false;
int cmp = 0;
@@ -343,13 +344,23 @@ blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config, bool list
if_count++;
continue;
}
+ if ((stmt->type == BLOGC_TEMPLATE_ELSE_STMT) &&
+ (if_count == 0))
+ {
+ // this is somewhat complex. only an else statement
+ // right after a non evaluated block should be considered
+ // valid, because all the inner conditionals were just
+ // skipped, and all the outter conditionals evaluated
+ // to true.
+ valid_else = true;
+ break;
+ }
if (stmt->type == BLOGC_TEMPLATE_ENDIF_STMT) {
if (if_count > 0) {
if_count--;
continue;
}
- if (if_count == 0)
- break;
+ break;
}
}
}
@@ -358,7 +369,41 @@ blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config, bool list
if_not = false;
break;
+ case BLOGC_TEMPLATE_ELSE_STMT:
+ if_count = 0;
+ if (!valid_else) {
+
+ // at this point we can just skip anything, counting the
+ // number of 'if's, to know how many 'endif's we need to
+ // skip as well.
+ while (1) {
+ tmp = tmp->next;
+ stmt = tmp->data;
+ if ((stmt->type == BLOGC_TEMPLATE_IF_STMT) ||
+ (stmt->type == BLOGC_TEMPLATE_IFDEF_STMT) ||
+ (stmt->type == BLOGC_TEMPLATE_IFNDEF_STMT))
+ {
+ if_count++;
+ continue;
+ }
+ // no need to handle else statements here, because every
+ // if should have an endif.
+ if (stmt->type == BLOGC_TEMPLATE_ENDIF_STMT) {
+ if (if_count > 0) {
+ if_count--;
+ continue;
+ }
+ break;
+ }
+ }
+ }
+ valid_else = false;
+ break;
+
case BLOGC_TEMPLATE_ENDIF_STMT:
+ // any endif statement should invalidate valid_else, to avoid
+ // propagation to outter conditionals.
+ valid_else = false;
if (if_count > 0)
if_count--;
break;
diff --git a/src/template-parser.c b/src/template-parser.c
index 525f5f5..344e398 100644
--- a/src/template-parser.c
+++ b/src/template-parser.c
@@ -69,6 +69,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
blogc_template_stmt_operator_t tmp_op = 0;
unsigned int if_count = 0;
+ bool else_open = false;
bool foreach_open = false;
sb_slist_t *stmts = NULL;
@@ -224,6 +225,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
type = BLOGC_TEMPLATE_IFDEF_STMT;
start = current;
if_count++;
+ else_open = false;
break;
}
else if ((current - start == 6) &&
@@ -233,6 +235,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
type = BLOGC_TEMPLATE_IFNDEF_STMT;
start = current;
if_count++;
+ else_open = false;
break;
}
else if ((current - start == 2) &&
@@ -242,6 +245,29 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
type = BLOGC_TEMPLATE_IF_STMT;
start = current;
if_count++;
+ else_open = false;
+ break;
+ }
+ else if ((current - start == 4) &&
+ (0 == strncmp("else", src + start, 4)))
+ {
+ if (if_count > 0) {
+ if (!else_open) {
+ state = TEMPLATE_BLOCK_END_WHITESPACE_CLEANER;
+ type = BLOGC_TEMPLATE_ELSE_STMT;
+ else_open = true;
+ break;
+ }
+ *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER,
+ src, src_len, current,
+ "More than one 'else' statement for an open 'if', "
+ "'ifdef' or 'ifndef' statement.");
+ break;
+ }
+ *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER,
+ src, src_len, current,
+ "'else' statement without an open 'if', 'ifdef' or "
+ "'ifndef' statement.");
break;
}
else if ((current - start == 5) &&
@@ -251,12 +277,13 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
state = TEMPLATE_BLOCK_END_WHITESPACE_CLEANER;
type = BLOGC_TEMPLATE_ENDIF_STMT;
if_count--;
+ else_open = false;
break;
}
*err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER,
src, src_len, current,
- "'endif' statement without an open 'ifdef' or 'ifndef' "
- "statement.");
+ "'endif' statement without an open 'if', 'ifdef' or "
+ "'ifndef' statement.");
break;
}
else if ((current - start == 7) &&
diff --git a/src/template-parser.h b/src/template-parser.h
index 46223ec..fe2721e 100644
--- a/src/template-parser.h
+++ b/src/template-parser.h
@@ -21,6 +21,7 @@ typedef enum {
BLOGC_TEMPLATE_IFDEF_STMT = 1,
BLOGC_TEMPLATE_IFNDEF_STMT,
BLOGC_TEMPLATE_IF_STMT,
+ BLOGC_TEMPLATE_ELSE_STMT,
BLOGC_TEMPLATE_ENDIF_STMT,
BLOGC_TEMPLATE_FOREACH_STMT,
BLOGC_TEMPLATE_ENDFOREACH_STMT,