aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am21
-rw-r--r--src/main.c12
-rw-r--r--src/source-grammar.h22
-rw-r--r--src/source-grammar.leg116
-rw-r--r--tests/check_source_grammar.c49
6 files changed, 217 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index 2751756..b7c5f8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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)
diff --git a/src/main.c b/src/main.c
index 65e45ee..3dbf325 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
+}