From 047e4e3753c597628024847a524d44ca67fa1382 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Fri, 17 Apr 2015 01:47:41 -0300 Subject: replaced leg-based parser with handmade parser for source files --- src/main.c | 10 ++-- src/output.c | 39 +++++++++++++ src/output.h | 17 ++++++ src/source-grammar.h | 22 -------- src/source-grammar.leg | 116 -------------------------------------- src/source-parser.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ src/source-parser.h | 23 ++++++++ src/utils/trie.c | 2 + src/utils/utils.h | 1 + 9 files changed, 235 insertions(+), 142 deletions(-) create mode 100644 src/output.c create mode 100644 src/output.h delete mode 100644 src/source-grammar.h delete mode 100644 src/source-grammar.leg create mode 100644 src/source-parser.c create mode 100644 src/source-parser.h (limited to 'src') diff --git a/src/main.c b/src/main.c index 3dbf325..d05c8d6 100644 --- a/src/main.c +++ b/src/main.c @@ -12,17 +12,19 @@ #include -#include "source-grammar.h" +#include "source-parser.h" +#include int main(int argc, char **argv) { - blogc_source_t *t = blogc_source_parse( - "\n \nBOLA: guda\n\t\n\n\n\n" + const char *a = + "\n \nBOLA : guda\n\t\n\n\n\n" "CHUNDA: asd\n" "----\n" - "{% block single_source %}\nbola\n\nzas\n"); + "{% block single_source %}\nbola\n\nzas\n"; + blogc_source_t *t = blogc_source_parse(a, strlen(a)); printf("%s\n", t->content); printf("Hello, World!\n"); return 0; diff --git a/src/output.c b/src/output.c new file mode 100644 index 0000000..bd96b8e --- /dev/null +++ b/src/output.c @@ -0,0 +1,39 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include +#include "utils/utils.h" +#include "output.h" + + +void +blogc_parser_syntax_error(const char *name, const char *src, size_t src_len, + size_t current) +{ + b_string_t *msg = b_string_new(); + + while (current < src_len) { + char c = src[current]; + + if (c == '\r' || c == '\n') + break; + + b_string_append_c(msg, c); + + current++; + } + + fprintf(stderr, "%s parser error: syntax error near \"%s\"\n", name, + msg->str); + + b_string_free(msg, true); +} diff --git a/src/output.h b/src/output.h new file mode 100644 index 0000000..b2f3cf3 --- /dev/null +++ b/src/output.h @@ -0,0 +1,17 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins + * + * This program can be distributed under the terms of the LGPL-2 License. + * See the file COPYING. + */ + +#ifndef _OUTPUT_H +#define _OUTPUT_H + +#include + +void blogc_parser_syntax_error(const char *name, const char *src, + size_t src_len, size_t current); + +#endif /* _OUTPUT_H */ diff --git a/src/source-grammar.h b/src/source-grammar.h deleted file mode 100644 index 540c21b..0000000 --- a/src/source-grammar.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2015 Rafael G. Martins - * - * 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 deleted file mode 100644 index faab9a4..0000000 --- a/src/source-grammar.leg +++ /dev/null @@ -1,116 +0,0 @@ -# -# blogc: A balde compiler. -# Copyright (C) 2015 Rafael G. Martins -# -# This program can be distributed under the terms of the BSD License. -# See the file COPYING. -# - -%{ - -#include -#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/src/source-parser.c b/src/source-parser.c new file mode 100644 index 0000000..ad7e77d --- /dev/null +++ b/src/source-parser.c @@ -0,0 +1,147 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include + +#include "utils/utils.h" +#include "source-parser.h" +#include "output.h" + + +typedef enum { + SOURCE_START = 1, + SOURCE_CONFIG_KEY, + SOURCE_CONFIG_VALUE_START, + SOURCE_CONFIG_VALUE, + SOURCE_SEPARATOR, + SOURCE_CONTENT_START, + SOURCE_CONTENT, +} blogc_source_parser_state_t; + + +blogc_source_t* +blogc_source_parse(const char *src, size_t src_len) +{ + size_t current = 0; + size_t start = 0; + + bool error = false; + char *key = NULL; + char *tmp = NULL; + b_trie_t *config = b_trie_new(free); + char *content = NULL; + + blogc_source_parser_state_t state = SOURCE_START; + + while (current < src_len) { + char c = src[current]; + + switch (state) { + + case SOURCE_START: + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + break; + if (c >= 'A' && c <= 'Z') { + state = SOURCE_CONFIG_KEY; + start = current; + break; + } + if (c == '-') { + state = SOURCE_SEPARATOR; + break; + } + error = true; + break; + + case SOURCE_CONFIG_KEY: + if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') + break; + if (c == ':') { + key = b_strndup(src + start, current - start); + state = SOURCE_CONFIG_VALUE_START; + break; + } + error = true; + break; + + case SOURCE_CONFIG_VALUE_START: + if (c != '\n' && c != '\r') { + state = SOURCE_CONFIG_VALUE; + start = current; + break; + } + error = true; + break; + + case SOURCE_CONFIG_VALUE: + if (c == '\n' || c == '\r') { + tmp = b_strndup(src + start, current - start); + b_trie_insert(config, key, b_strdup(b_str_strip(tmp))); + free(tmp); + free(key); + key = NULL; + state = SOURCE_START; + } + break; + + case SOURCE_SEPARATOR: + if (c == '-') + break; + if (c == '\n' || c == '\r') { + state = SOURCE_CONTENT_START; + break; + } + error = true; + break; + + case SOURCE_CONTENT_START: + start = current; + state = SOURCE_CONTENT; + break; + + case SOURCE_CONTENT: + if (current == (src_len - 1)) + content = b_strndup(src + start, src_len - start); + break; + } + + if (error) + break; + + current++; + } + + if (error) { + free(key); + free(content); + b_trie_free(config); + blogc_parser_syntax_error("source", src, src_len, current); + return NULL; + } + + blogc_source_t *rv = malloc(sizeof(blogc_source_t)); + rv->config = config; + rv->content = content; + + return rv; +} + + +void +blogc_source_free(blogc_source_t *source) +{ + if (source == NULL) + return; + free(source->content); + b_trie_free(source->config); + free(source); +} diff --git a/src/source-parser.h b/src/source-parser.h new file mode 100644 index 0000000..6f41c14 --- /dev/null +++ b/src/source-parser.h @@ -0,0 +1,23 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins + * + * This program can be distributed under the terms of the LGPL-2 License. + * See the file COPYING. + */ + +#ifndef _SOURCE_PARSER_H +#define _SOURCE_PARSER_H + +#include +#include "utils/utils.h" + +typedef struct { + b_trie_t *config; + char *content; +} blogc_source_t; + +blogc_source_t* blogc_source_parse(const char *src, size_t src_len); +void blogc_source_free(blogc_source_t *source); + +#endif /* _SOURCE_PARSER_H */ diff --git a/src/utils/trie.c b/src/utils/trie.c index f447860..b92573f 100644 --- a/src/utils/trie.c +++ b/src/utils/trie.c @@ -38,6 +38,8 @@ b_trie_free_node(b_trie_t *trie, b_trie_node_t *node) void b_trie_free(b_trie_t *trie) { + if (trie == NULL) + return; b_trie_free_node(trie, trie->root); free(trie); } diff --git a/src/utils/utils.h b/src/utils/utils.h index 20259d8..55b9c59 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -10,6 +10,7 @@ #define _UTILS_UTILS_H #include +#include #include #define B_STRING_CHUNK_SIZE 128 -- cgit v1.2.3-18-g5258