aboutsummaryrefslogtreecommitdiffstats
path: root/src/source-grammar.leg
blob: faab9a41228bf5fdd8539749b10f04a052279cf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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;
}