aboutsummaryrefslogtreecommitdiffstats
path: root/src/template-grammar.leg
diff options
context:
space:
mode:
Diffstat (limited to 'src/template-grammar.leg')
-rw-r--r--src/template-grammar.leg200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/template-grammar.leg b/src/template-grammar.leg
new file mode 100644
index 0000000..63e2a69
--- /dev/null
+++ b/src/template-grammar.leg
@@ -0,0 +1,200 @@
+#
+# blogc: A balde compiler.
+# Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+#
+# This program can be distributed under the terms of the BSD License.
+# See the file COPYING.
+#
+
+%{
+
+#include <stdio.h>
+#include "utils/utils.h"
+#include "template-grammar.h"
+
+#define YY_INPUT(buf, result, max_size) \
+{ \
+ int yyc = (charbuf && *charbuf != '\0') ? *charbuf++ : EOF; \
+ result = (EOF == yyc) ? 0 : (*buf = yyc, 1); \
+}
+
+
+static b_slist_t *stmts = NULL;
+static int if_count = 0;
+static int block_count = 0;
+static const char *charbuf = NULL;
+
+
+static void
+blogc_template_if_stmt(const char *value)
+{
+ if (block_count <= 0) {
+ fprintf(stderr, "Syntax error: {" "%% if ... %%" "} statement before "
+ "any {" "%% block ... %%" "} statement\n");
+ exit(1);
+ }
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = b_strdup(value);
+ stmt->type = BLOGC_TEMPLATE_IF_STMT;
+ stmts = b_slist_append(stmts, stmt);
+ if_count++;
+}
+
+
+static void
+blogc_template_else_stmt(void)
+{
+ if (if_count <= 0) {
+ fprintf(stderr, "Syntax error: {" "%% else %%" "} statement without "
+ "any open {" "%% if ... %%" "} statement\n");
+ exit(1);
+ }
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = NULL;
+ stmt->type = BLOGC_TEMPLATE_ELSE_STMT;
+ stmts = b_slist_append(stmts, stmt);
+}
+
+
+static void
+blogc_template_endif_stmt(void)
+{
+ if (if_count-- <= 0) {
+ fprintf(stderr, "Syntax error: {" "%% endif %%" "} statement before "
+ "any {" "%% if ... %%" "} statement\n");
+ exit(1);
+ }
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = NULL;
+ stmt->type = BLOGC_TEMPLATE_ENDIF_STMT;
+ stmts = b_slist_append(stmts, stmt);
+}
+
+
+static void
+blogc_template_block_stmt(const char *value)
+{
+ if (block_count > 0) {
+ fprintf(stderr, "Syntax error: {" "%% block %%" "} statements "
+ "can't be nested\n");
+ exit(1);
+ }
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = b_strdup(value);
+ stmt->type = BLOGC_TEMPLATE_BLOCK_STMT;
+ stmts = b_slist_append(stmts, stmt);
+ block_count++;
+}
+
+
+static void
+blogc_template_endblock_stmt(void)
+{
+ if (block_count-- <= 0) {
+ fprintf(stderr, "Syntax error: {" "%% endblock %%" "} statement before "
+ "any {" "%% block ... %%" "} statement\n");
+ exit(1);
+ }
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = NULL;
+ stmt->type = BLOGC_TEMPLATE_ENDBLOCK_STMT;
+ stmts = b_slist_append(stmts, stmt);
+}
+
+
+static void
+blogc_template_variable_stmt(const char *value)
+{
+ if (block_count <= 0) {
+ fprintf(stderr, "Syntax error: {{ ... }} statement before "
+ "any {" "%% block ... %%" "} statement\n");
+ exit(1);
+ }
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = b_strdup(value);
+ stmt->type = BLOGC_TEMPLATE_VARIABLE_STMT;
+ stmts = b_slist_append(stmts, stmt);
+}
+
+
+static void
+blogc_template_content_stmt(const char *value)
+{
+ blogc_template_stmt_t *stmt = malloc(sizeof(blogc_template_stmt_t));
+ stmt->value = b_strdup(value);
+ stmt->type = BLOGC_TEMPLATE_CONTENT_STMT;
+ stmts = b_slist_append(stmts, stmt);
+}
+
+%}
+
+page = if | else | endif | block | endblock | print | content | anything
+ { fprintf(stderr, "Syntax error near: %s\n", yytext); exit(1); }
+
+
+# Useful rules
+eol = '\n' | '\r\n' | '\r'
+eof = !.
+- = [\t ]*
+id = [A-Z][A-Z0-9_]*
+anything = < ( !eol . )* > eol
+
+# Conditionals
+if_open = '{%' -
+if_close = - '%}'
+if = if_open 'if' ' '+ < id > if_close { blogc_template_if_stmt(yytext); }
+else = if_open 'else' if_close { blogc_template_else_stmt(); }
+endif = if_open 'endif' if_close { blogc_template_endif_stmt(); }
+
+# Blocks
+block_open = '{%' -
+block_close = - '%}'
+block_name = ( 'single_source' | 'multiple_sources_once' | 'multiple_sources' )
+block = block_open 'block' ' '+ < block_name > block_close { blogc_template_block_stmt(yytext); }
+endblock = block_open 'endblock' block_close { blogc_template_endblock_stmt(); }
+
+# Print calls
+print_open = '{{' -
+print_close = - '}}'
+print_var = < id > { blogc_template_variable_stmt(yytext); }
+print = print_open print_var print_close
+
+# Generic content
+content = < ( !eof !if_open !if_close !block_open !block_close !print_open !print_close . )+ >
+ { blogc_template_content_stmt(yytext); }
+
+%%
+
+
+void
+blogc_template_free_stmts(b_slist_t *stmts)
+{
+ for (b_slist_t *tmp = stmts; tmp != NULL; tmp = tmp->next) {
+ blogc_template_stmt_t *data = tmp->data;
+ free(data->value);
+ free(data);
+ }
+ b_slist_free(stmts);
+}
+
+
+b_slist_t*
+blogc_template_parse(const char *tmpl)
+{
+ if_count = 0;
+ block_count = 0;
+ charbuf = tmpl;
+ while(yyparse());
+ if (if_count != 0) {
+ fprintf(stderr, "Syntax error: You left %d open {" "%% if ... %%" "} statements.\n", if_count);
+ exit(1);
+ }
+ if (block_count != 0) {
+ fprintf(stderr, "Syntax error: You left %d open {" "%% block ... %%" "} statements.\n", block_count);
+ exit(1);
+ }
+ b_slist_t *rv = stmts;
+ charbuf = NULL;
+ stmts = NULL;
+ return rv;
+}