diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile.am | 21 | ||||
-rw-r--r-- | src/main.c | 12 | ||||
-rw-r--r-- | src/source-grammar.h | 22 | ||||
-rw-r--r-- | src/source-grammar.leg | 116 | ||||
-rw-r--r-- | tests/check_source_grammar.c | 49 |
6 files changed, 217 insertions, 5 deletions
@@ -40,10 +40,12 @@ Makefile.in /blogc # tests +/tests/check_source_grammar /tests/check_template_grammar /tests/check_utils # leg generated source +/src/source-grammar.c /src/template-grammar.c # tarballs diff --git a/Makefile.am b/Makefile.am index 59cbe18..b1548bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,7 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \ EXTRA_DIST = \ autogen.sh \ README.md \ + src/source-grammar.leg \ src/template-grammar.leg \ $(NULL) @@ -21,6 +22,7 @@ CLEANFILES = \ $(NULL) noinst_HEADERS = \ + src/source-grammar.h \ src/template-grammar.h \ src/utils/utils.h \ $(NULL) @@ -41,6 +43,7 @@ check_PROGRAMS = \ libblogc_la_SOURCES = \ + src/source-grammar.c \ src/template-grammar.c \ src/utils/slist.c \ src/utils/strings.c \ @@ -89,10 +92,28 @@ endif if USE_CMOCKA check_PROGRAMS += \ + tests/check_source_grammar \ tests/check_template_grammar \ tests/check_utils \ $(NULL) +tests_check_source_grammar_SOURCES = \ + tests/check_source_grammar.c \ + $(NULL) + +tests_check_source_grammar_CFLAGS = \ + $(CMOCKA_CFLAGS) \ + $(NULL) + +tests_check_source_grammar_LDFLAGS = \ + -no-install \ + $(NULL) + +tests_check_source_grammar_LDADD = \ + $(CMOCKA_LIBS) \ + libblogc.la \ + $(NULL) + tests_check_template_grammar_SOURCES = \ tests/check_template_grammar.c \ $(NULL) @@ -12,16 +12,18 @@ #include <stdio.h> -#include "template-grammar.h" +#include "source-grammar.h" int main(int argc, char **argv) { - b_slist_t *t = blogc_template_parse( - "<html>{{ BOLA }}</html>\n" - "{% block single_source %}\n"); - printf("%s\n", (char*) ((blogc_template_stmt_t*)t->next->next->next->data)->value); + blogc_source_t *t = blogc_source_parse( + "\n \nBOLA: guda\n\t\n\n\n\n" + "CHUNDA: asd\n" + "----\n" + "{% block single_source %}\nbola\n\nzas\n"); + printf("%s\n", t->content); printf("Hello, World!\n"); return 0; } diff --git a/src/source-grammar.h b/src/source-grammar.h new file mode 100644 index 0000000..540c21b --- /dev/null +++ b/src/source-grammar.h @@ -0,0 +1,22 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the LGPL-2 License. + * See the file COPYING. + */ + +#ifndef _SOURCE_GRAMAR_H +#define _SOURCE_GRAMAR_H + +#include "utils/utils.h" + +typedef struct { + b_trie_t *config; + char *content; +} blogc_source_t; + +blogc_source_t* blogc_source_parse(const char *tmpl); +void blogc_source_free(blogc_source_t *source); + +#endif /* _SOURCE_GRAMAR_H */ diff --git a/src/source-grammar.leg b/src/source-grammar.leg new file mode 100644 index 0000000..faab9a4 --- /dev/null +++ b/src/source-grammar.leg @@ -0,0 +1,116 @@ +# +# 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 "source-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_trie_t *config = NULL; +static const char *charbuf = NULL; +static char *key = NULL; +static char *content = NULL; + + +static void +blogc_source_config_key(const char *value) +{ + if (key != NULL) { + fprintf(stderr, "Syntax error: configuration key already set: %s\n", key); + exit(1); + } + key = b_strdup(value); +} + + +static void +blogc_source_config_value(const char *value) +{ + if (key == NULL) { + fprintf(stderr, "Syntax error: configuration value without a key: %s\n", value); + exit(1); + } + b_trie_insert(config, key, b_str_strip(b_strdup(value))); + free(key); + key = NULL; +} + + +static void +blogc_source_content(const char *value) +{ + if (content != NULL) { + fprintf(stderr, "Syntax error: content set twice\n"); + exit(1); + } + content = b_strdup(value); +} + +%} + +page = ( ( - eol )* ( config ( - eol )* )+ '----' '-'* eol content eof ) | 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 + +# Configuration +config_key = < id > { blogc_source_config_key(yytext); } +config_value = < anything > { blogc_source_config_value(yytext); } +config = config_key ':' ' '+ config_value + +# Generic content +content = < ( !eof . )+ > { blogc_source_content(yytext); } + +%% + + +void +blogc_source_free(blogc_source_t *source) +{ + if (source == NULL) + return; + free(source->content); + b_trie_free(source->config); + free(source); +} + + +static void +blogc_source_config_free(void *ptr) +{ + free(ptr); +} + + +blogc_source_t* +blogc_source_parse(const char *tmpl) +{ + charbuf = tmpl; + config = b_trie_new(blogc_source_config_free); + key = NULL; + content = NULL; + while(yyparse()); + blogc_source_t *rv = malloc(sizeof(blogc_source_t)); + rv->content = content; + rv->config = config; + charbuf = NULL; + return rv; +} diff --git a/tests/check_source_grammar.c b/tests/check_source_grammar.c new file mode 100644 index 0000000..a80be8e --- /dev/null +++ b/tests/check_source_grammar.c @@ -0,0 +1,49 @@ +/* + * blogc: A blog 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include "../src/source-grammar.h" + + +static void +test_source_parse(void **state) +{ + blogc_source_t *source = blogc_source_parse( + "VAR1: asd asd\n" + "VAR2: 123chunda\n" + "----------\n" + "# This is a test\n" + "\n" + "bola\n"); + assert_non_null(source); + assert_int_equal(b_trie_size(source->config), 2); + assert_string_equal(b_trie_lookup(source->config, "VAR1"), "asd asd"); + assert_string_equal(b_trie_lookup(source->config, "VAR2"), "123chunda"); + assert_string_equal(source->content, + "# This is a test\n" + "\n" + "bola\n"); + blogc_source_free(source); +} + + +int +main(void) +{ + const UnitTest tests[] = { + unit_test(test_source_parse), + }; + return run_tests(tests); +} |