diff options
author | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-04-15 20:01:17 -0300 |
---|---|---|
committer | Rafael G. Martins <rafael@rafaelmartins.eng.br> | 2015-04-15 19:26:45 -0300 |
commit | ec86e13f144d4d8de6a93b8b04117ea5028893d1 (patch) | |
tree | e0413858979d9e517529ff528038ffbf2dc5e044 /src/template-grammar.leg | |
parent | 0b694d89cefae8e8ca3422bbdbfbca4d5920ac4b (diff) | |
download | blogc-ec86e13f144d4d8de6a93b8b04117ea5028893d1.tar.gz blogc-ec86e13f144d4d8de6a93b8b04117ea5028893d1.tar.bz2 blogc-ec86e13f144d4d8de6a93b8b04117ea5028893d1.zip |
added template grammar
Diffstat (limited to 'src/template-grammar.leg')
-rw-r--r-- | src/template-grammar.leg | 200 |
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; +} |