diff options
Diffstat (limited to 'src/meta1-gram.y')
-rw-r--r-- | src/meta1-gram.y | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/meta1-gram.y b/src/meta1-gram.y new file mode 100644 index 0000000..8ddcbfb --- /dev/null +++ b/src/meta1-gram.y | |||
@@ -0,0 +1,217 @@ | |||
1 | %{ | ||
2 | /* MeTA1 configuration parser for Grecs. | ||
3 | Copyright (C) 2007-2011 Sergey Poznyakoff | ||
4 | |||
5 | Grecs is free software; you can redistribute it and/or modify it | ||
6 | under the terms of the GNU General Public License as published by the | ||
7 | Free Software Foundation; either version 3 of the License, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | Grecs is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License along | ||
16 | with Grecs. If not, see <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | #include <errno.h> | ||
22 | #include <string.h> | ||
23 | #include "grecs.h" | ||
24 | |||
25 | int yylex(void); | ||
26 | int yyerror(char *s); | ||
27 | |||
28 | static struct grecs_node *parse_tree; | ||
29 | extern int yy_flex_debug; | ||
30 | %} | ||
31 | |||
32 | %union { | ||
33 | struct { | ||
34 | grecs_locus_t locus; | ||
35 | char *string; | ||
36 | } ident; | ||
37 | char *string; | ||
38 | grecs_value_t svalue, *pvalue; | ||
39 | struct grecs_list *list; | ||
40 | struct { struct grecs_node *head, *tail; } node_list; | ||
41 | struct grecs_node *node; | ||
42 | } | ||
43 | |||
44 | %token <ident> META1_IDENT | ||
45 | %token <string> META1_STRING | ||
46 | %type <node> stmt simple block | ||
47 | %type <node_list> stmtlist | ||
48 | %type <pvalue> tag value | ||
49 | %type <string> string slist | ||
50 | %type <list> slist0 | ||
51 | %type <list> values list | ||
52 | %% | ||
53 | |||
54 | input : stmtlist | ||
55 | { | ||
56 | parse_tree = grecs_node_create(grecs_node_root, | ||
57 | &grecs_current_locus); | ||
58 | parse_tree->v.texttab = grecs_text_table(); | ||
59 | grecs_node_bind(parse_tree, $1.head, 1); | ||
60 | } | ||
61 | ; | ||
62 | |||
63 | stmtlist: stmt | ||
64 | { | ||
65 | $$.head = $$.tail = $1; | ||
66 | } | ||
67 | | stmtlist stmt | ||
68 | { | ||
69 | grecs_node_bind($1.tail, $2, 0); | ||
70 | } | ||
71 | ; | ||
72 | |||
73 | stmt : simple | ||
74 | | block | ||
75 | ; | ||
76 | |||
77 | simple : META1_IDENT '=' value opt_sc | ||
78 | { | ||
79 | $$ = grecs_node_create(grecs_node_stmt, | ||
80 | &$1.locus); | ||
81 | $$->ident = $1.string; | ||
82 | $$->v.value = $3; | ||
83 | } | ||
84 | ; | ||
85 | |||
86 | block : META1_IDENT tag '{' stmtlist '}' opt_sc | ||
87 | { | ||
88 | $$ = grecs_node_create(grecs_node_block, | ||
89 | &$1.locus); | ||
90 | $$->ident = $1.string; | ||
91 | $$->v.value = $2; | ||
92 | grecs_node_bind($$, $4.head, 1); | ||
93 | } | ||
94 | ; | ||
95 | |||
96 | tag : /* empty */ | ||
97 | { | ||
98 | $$ = NULL; | ||
99 | } | ||
100 | | META1_IDENT | ||
101 | { | ||
102 | $$ = grecs_malloc(sizeof($$[0])); | ||
103 | $$->type = GRECS_TYPE_STRING; | ||
104 | $$->v.string = $1.string; | ||
105 | } | ||
106 | ; | ||
107 | |||
108 | value : string | ||
109 | { | ||
110 | $$ = grecs_malloc(sizeof($$[0])); | ||
111 | $$->type = GRECS_TYPE_STRING; | ||
112 | $$->v.string = $1; | ||
113 | } | ||
114 | | list | ||
115 | { | ||
116 | $$ = grecs_malloc(sizeof($$[0])); | ||
117 | $$->type = GRECS_TYPE_LIST; | ||
118 | $$->v.list = $1; | ||
119 | } | ||
120 | ; | ||
121 | |||
122 | string : META1_IDENT | ||
123 | { | ||
124 | $$ = $1.string; | ||
125 | } | ||
126 | | slist | ||
127 | ; | ||
128 | |||
129 | slist : slist0 | ||
130 | { | ||
131 | struct grecs_list_entry *ep; | ||
132 | |||
133 | grecs_line_begin(); | ||
134 | for (ep = $1->head; ep; ep = ep->next) { | ||
135 | grecs_line_add(ep->data, strlen(ep->data)); | ||
136 | free(ep->data); | ||
137 | ep->data = NULL; | ||
138 | } | ||
139 | $$ = grecs_line_finish(); | ||
140 | grecs_list_free($1); | ||
141 | } | ||
142 | |||
143 | slist0 : META1_STRING | ||
144 | { | ||
145 | $$ = grecs_list_create(); | ||
146 | grecs_list_append($$, $1); | ||
147 | } | ||
148 | | slist0 META1_STRING | ||
149 | { | ||
150 | grecs_list_append($1, $2); | ||
151 | $$ = $1; | ||
152 | } | ||
153 | ; | ||
154 | |||
155 | list : '{' values '}' | ||
156 | { | ||
157 | $$ = $2; | ||
158 | } | ||
159 | | '{' values ',' '}' | ||
160 | { | ||
161 | $$ = $2; | ||
162 | } | ||
163 | ; | ||
164 | |||
165 | values : value | ||
166 | { | ||
167 | $$ = grecs_value_list_create(); | ||
168 | grecs_list_append($$, $1); | ||
169 | } | ||
170 | | values ',' value | ||
171 | { | ||
172 | grecs_list_append($1, $3); | ||
173 | $$ = $1; | ||
174 | } | ||
175 | ; | ||
176 | |||
177 | opt_sc : /* empty */ | ||
178 | | ';' | ||
179 | ; | ||
180 | |||
181 | %% | ||
182 | int | ||
183 | yyerror(char *s) | ||
184 | { | ||
185 | grecs_error(&grecs_current_locus, 0, "%s", s); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | struct grecs_node * | ||
190 | grecs_meta1_parser(const char *name, int traceflags) | ||
191 | { | ||
192 | int rc; | ||
193 | FILE *fp; | ||
194 | |||
195 | fp = fopen(name, "r"); | ||
196 | if (!fp) { | ||
197 | grecs_error(NULL, errno, _("Cannot open `%s'"), name); | ||
198 | return NULL; | ||
199 | } | ||
200 | yyset_in(fp); | ||
201 | |||
202 | yy_flex_debug = traceflags & GRECS_TRACE_LEX; | ||
203 | yydebug = traceflags & GRECS_TRACE_GRAM; | ||
204 | parse_tree = NULL; | ||
205 | grecs_line_acc_create(); | ||
206 | rc = yyparse(); | ||
207 | fclose(fp); | ||
208 | if (grecs_error_count) | ||
209 | rc = 1; | ||
210 | grecs_line_acc_free(); | ||
211 | if (rc) { | ||
212 | grecs_tree_free(parse_tree); | ||
213 | parse_tree = NULL; | ||
214 | } | ||
215 | return parse_tree; | ||
216 | } | ||
217 | |||