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;
}
|