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/source-parser.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/source-parser.c (limited to 'src/source-parser.c') 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); +} -- cgit v1.2.3-18-g5258