1 %{
2 /* MeTA1 configuration parser for Grecs.
3 Copyright (C) 2007-2016 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 const *s);
27
28 static struct grecs_node *parse_tree;
29 extern int yy_flex_debug;
30 extern void yyset_in(FILE *);
31 %}
32
33 %error-verbose
34 %locations
35
36 %union {
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 <string> META1_STRING META1_IDENT
45 %type <node> stmt simple block maybe_stmtlist
46 %type <node_list> stmtlist
47 %type <pvalue> tag value
48 %type <string> string slist
49 %type <list> slist0
50 %type <list> values list
51 %%
52
53 input : maybe_stmtlist
54 {
55 parse_tree = grecs_node_create(grecs_node_root, &@1);
56 parse_tree->v.texttab = grecs_text_table();
57 grecs_node_bind(parse_tree, $1, 1);
58 }
59 ;
60
61 maybe_stmtlist:
62 /* empty */
63 {
64 $$ = NULL;
65 }
66 | stmtlist
67 {
68 $$ = $1.head;
69 }
70 ;
71
72 stmtlist: stmt
73 {
74 $$.head = $$.tail = $1;
75 }
76 | stmtlist stmt
77 {
78 grecs_node_bind($1.tail, $2, 0);
79 }
80 ;
81
82 stmt : simple
83 | block
84 ;
85
86 simple : META1_IDENT '=' value opt_sc
87 {
88 $$ = grecs_node_create_points(grecs_node_stmt,
89 @1.beg, @3.end);
90 $$->ident = $1;
91 $$->idloc = @1;
92 $$->v.value = $3;
93 }
94 ;
95
96 block : META1_IDENT tag '{' stmtlist '}' opt_sc
97 {
98 $$ = grecs_node_create_points(grecs_node_block,
99 @1.beg, @5.end);
100 $$->ident = $1;
101 $$->idloc = @1;
102 $$->v.value = $2;
103 grecs_node_bind($$, $4.head, 1);
104 }
105 ;
106
107 tag : /* empty */
108 {
109 $$ = NULL;
110 }
111 | META1_IDENT
112 {
113 $$ = grecs_malloc(sizeof($$[0]));
114 $$->type = GRECS_TYPE_STRING;
115 $$->v.string = $1;
116 }
117 ;
118
119 value : string
120 {
121 $$ = grecs_malloc(sizeof($$[0]));
122 $$->type = GRECS_TYPE_STRING;
123 $$->locus = @1;
124 $$->v.string = $1;
125 }
126 | list
127 {
128 $$ = grecs_malloc(sizeof($$[0]));
129 $$->type = GRECS_TYPE_LIST;
130 $$->locus = @1;
131 $$->v.list = $1;
132 }
133 ;
134
135 string : META1_IDENT
136 | slist
137 ;
138
139 slist : slist0
140 {
141 struct grecs_list_entry *ep;
142
143 grecs_line_begin();
144 for (ep = $1->head; ep; ep = ep->next) {
145 grecs_line_add(ep->data, strlen(ep->data));
146 free(ep->data);
147 ep->data = NULL;
148 }
149 $$ = grecs_line_finish();
150 grecs_list_free($1);
151 }
152
153 slist0 : META1_STRING
154 {
155 $$ = grecs_list_create();
156 grecs_list_append($$, $1);
157 }
158 | slist0 META1_STRING
159 {
160 grecs_list_append($1, $2);
161 $$ = $1;
162 }
163 ;
164
165 list : '{' values '}'
166 {
167 $$ = $2;
168 }
169 | '{' values ',' '}'
170 {
171 $$ = $2;
172 }
173 ;
174
175 values : value
176 {
177 $$ = grecs_value_list_create();
178 grecs_list_append($$, $1);
179 }
180 | values ',' value
181 {
182 grecs_list_append($1, $3);
183 $$ = $1;
184 }
185 ;
186
187 opt_sc : /* empty */
188 | ';'
189 ;
190
191 %%
192 int
193 yyerror(char const *s)
194 {
195 grecs_error(&yylloc, 0, "%s", s);
196 return 0;
197 }
198
199 struct grecs_node *
grecs_meta1_parser(const char * name,int traceflags)200 grecs_meta1_parser(const char *name, int traceflags)
201 {
202 int rc;
203 FILE *fp;
204
205 fp = fopen(name, "r");
206 if (!fp) {
207 grecs_error(NULL, errno, _("Cannot open `%s'"), name);
208 return NULL;
209 }
210 yyset_in(fp);
211 yy_flex_debug = traceflags & GRECS_TRACE_LEX;
212 yydebug = traceflags & GRECS_TRACE_GRAM;
213 parse_tree = NULL;
214 grecs_line_acc_create();
215 rc = yyparse();
216 fclose(fp);
217 if (grecs_error_count)
218 rc = 1;
219 grecs_line_acc_free();
220 if (rc) {
221 grecs_tree_free(parse_tree);
222 parse_tree = NULL;
223 }
224 return parse_tree;
225 }
226
227