xref: /aosp_15_r20/external/libconfig/lib/grammar.y (revision 2e9d491483b805f09ea864149eadd5680efcc72a)
1 /* -*- mode: C -*- */
2 /* ----------------------------------------------------------------------------
3    libconfig - A library for processing structured configuration files
4    Copyright (C) 2005-2018  Mark A Lindner
5 
6    This file is part of libconfig.
7 
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12 
13    This library is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17 
18    You should have received a copy of the GNU Library General Public
19    License along with this library; if not, see
20    <http://www.gnu.org/licenses/>.
21    ----------------------------------------------------------------------------
22 */
23 
24 %defines
25 %output "y.tab.c"
26 %pure-parser
27 %lex-param{void *scanner}
28 %parse-param{void *scanner}
29 %parse-param{struct parse_context *ctx}
30 %parse-param{struct scan_context *scan_ctx}
31 
32 %{
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include "libconfig.h"
37 #include "parsectx.h"
38 #include "scanctx.h"
39 #include "util.h"
40 #include "wincompat.h"
41 
42 /* These declarations are provided to suppress compiler warnings. */
43 extern int libconfig_yylex();
44 extern int libconfig_yyget_lineno();
45 
46 static const char *err_array_elem_type = "mismatched element type in array";
47 static const char *err_duplicate_setting = "duplicate setting name";
48 
49 #define IN_ARRAY() \
50   (ctx->parent && (ctx->parent->type == CONFIG_TYPE_ARRAY))
51 
52 #define IN_LIST() \
53   (ctx->parent && (ctx->parent->type == CONFIG_TYPE_LIST))
54 
55 static void capture_parse_pos(void *scanner, struct scan_context *scan_ctx,
56                               config_setting_t *setting)
57 {
58   setting->line = (unsigned int)libconfig_yyget_lineno(scanner);
59   setting->file = libconfig_scanctx_current_filename(scan_ctx);
60 }
61 
62 #define CAPTURE_PARSE_POS(S) \
63   capture_parse_pos(scanner, scan_ctx, (S))
64 
65 void libconfig_yyerror(void *scanner, struct parse_context *ctx,
66                        struct scan_context *scan_ctx, char const *s)
67 {
68   if(ctx->config->error_text) return;
69   ctx->config->error_line = libconfig_yyget_lineno(scanner);
70   ctx->config->error_text = s;
71 }
72 
73 %}
74 
75 %union
76 {
77   int ival;
78   long long llval;
79   double fval;
80   char *sval;
81 }
82 
83 %token <ival> TOK_BOOLEAN TOK_INTEGER TOK_HEX
84 %token <llval> TOK_INTEGER64 TOK_HEX64
85 %token <fval> TOK_FLOAT
86 %token <sval> TOK_STRING TOK_NAME
87 %token TOK_EQUALS TOK_NEWLINE TOK_ARRAY_START TOK_ARRAY_END TOK_LIST_START TOK_LIST_END TOK_COMMA TOK_GROUP_START TOK_GROUP_END TOK_SEMICOLON TOK_GARBAGE TOK_ERROR
88 %destructor { free($$); } TOK_STRING
89 
90 %%
91 
92 configuration:
93     /* empty */
94   | setting_list
95   ;
96 
97 setting_list:
98     setting
99   | setting_list setting
100   ;
101 
102 setting_list_optional:
103     /* empty */
104   | setting_list
105   ;
106 
107 setting_terminator:
108     /* empty */
109   | TOK_SEMICOLON
110   | TOK_COMMA
111   ;
112 
113 setting:
114   TOK_NAME
115   {
116     ctx->setting = config_setting_add(ctx->parent, $1, CONFIG_TYPE_NONE);
117 
118     if(ctx->setting == NULL)
119     {
120       libconfig_yyerror(scanner, ctx, scan_ctx, err_duplicate_setting);
121       YYABORT;
122     }
123     else
124     {
125       CAPTURE_PARSE_POS(ctx->setting);
126     }
127   }
128 
129   TOK_EQUALS value setting_terminator
130   ;
131 
132 array:
133   TOK_ARRAY_START
134   {
135     if(IN_LIST())
136     {
137       ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_ARRAY);
138       CAPTURE_PARSE_POS(ctx->parent);
139     }
140     else
141     {
142       ctx->setting->type = CONFIG_TYPE_ARRAY;
143       ctx->parent = ctx->setting;
144       ctx->setting = NULL;
145     }
146   }
147   simple_value_list_optional
148   TOK_ARRAY_END
149   {
150     if(ctx->parent)
151       ctx->parent = ctx->parent->parent;
152   }
153   ;
154 
155 list:
156   TOK_LIST_START
157   {
158     if(IN_LIST())
159     {
160       ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_LIST);
161       CAPTURE_PARSE_POS(ctx->parent);
162     }
163     else
164     {
165       ctx->setting->type = CONFIG_TYPE_LIST;
166       ctx->parent = ctx->setting;
167       ctx->setting = NULL;
168     }
169   }
170   value_list_optional
171   TOK_LIST_END
172   {
173     if(ctx->parent)
174       ctx->parent = ctx->parent->parent;
175   }
176   ;
177 
178 value:
179     simple_value
180   | array
181   | list
182   | group
183   ;
184 
185 string:
186   TOK_STRING { libconfig_parsectx_append_string(ctx, $1); free($1); }
187   | string TOK_STRING { libconfig_parsectx_append_string(ctx, $2); free($2); }
188   ;
189 
190 simple_value:
191     TOK_BOOLEAN
192   {
193     if(IN_ARRAY() || IN_LIST())
194     {
195       config_setting_t *e = config_setting_set_bool_elem(ctx->parent, -1,
196                                                          (int)$1);
197 
198       if(! e)
199       {
200         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
201         YYABORT;
202       }
203       else
204       {
205         CAPTURE_PARSE_POS(e);
206       }
207     }
208     else
209       config_setting_set_bool(ctx->setting, (int)$1);
210   }
211   | TOK_INTEGER
212   {
213     if(IN_ARRAY() || IN_LIST())
214     {
215       config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, $1);
216       if(! e)
217       {
218         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
219         YYABORT;
220       }
221       else
222       {
223         config_setting_set_format(e, CONFIG_FORMAT_DEFAULT);
224         CAPTURE_PARSE_POS(e);
225       }
226     }
227     else
228     {
229       config_setting_set_int(ctx->setting, $1);
230       config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT);
231     }
232   }
233   | TOK_INTEGER64
234   {
235     if(IN_ARRAY() || IN_LIST())
236     {
237       config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, $1);
238       if(! e)
239       {
240         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
241         YYABORT;
242       }
243       else
244       {
245         config_setting_set_format(e, CONFIG_FORMAT_DEFAULT);
246         CAPTURE_PARSE_POS(e);
247       }
248     }
249     else
250     {
251       config_setting_set_int64(ctx->setting, $1);
252       config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT);
253     }
254   }
255   | TOK_HEX
256   {
257     if(IN_ARRAY() || IN_LIST())
258     {
259       config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, $1);
260       if(! e)
261       {
262         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
263         YYABORT;
264       }
265       else
266       {
267         config_setting_set_format(e, CONFIG_FORMAT_HEX);
268         CAPTURE_PARSE_POS(e);
269       }
270     }
271     else
272     {
273       config_setting_set_int(ctx->setting, $1);
274       config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX);
275     }
276   }
277   | TOK_HEX64
278   {
279     if(IN_ARRAY() || IN_LIST())
280     {
281       config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, $1);
282       if(! e)
283       {
284         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
285         YYABORT;
286       }
287       else
288       {
289         config_setting_set_format(e, CONFIG_FORMAT_HEX);
290         CAPTURE_PARSE_POS(e);
291       }
292     }
293     else
294     {
295       config_setting_set_int64(ctx->setting, $1);
296       config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX);
297     }
298   }
299   | TOK_FLOAT
300   {
301     if(IN_ARRAY() || IN_LIST())
302     {
303       config_setting_t *e = config_setting_set_float_elem(ctx->parent, -1, $1);
304       if(! e)
305       {
306         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
307         YYABORT;
308       }
309       else
310       {
311         CAPTURE_PARSE_POS(e);
312       }
313     }
314     else
315       config_setting_set_float(ctx->setting, $1);
316   }
317   | string
318   {
319     if(IN_ARRAY() || IN_LIST())
320     {
321       const char *s = libconfig_parsectx_take_string(ctx);
322       config_setting_t *e = config_setting_set_string_elem(ctx->parent, -1, s);
323       __delete(s);
324 
325       if(! e)
326       {
327         libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
328         YYABORT;
329       }
330       else
331       {
332         CAPTURE_PARSE_POS(e);
333       }
334     }
335     else
336     {
337       const char *s = libconfig_parsectx_take_string(ctx);
338       config_setting_set_string(ctx->setting, s);
339       __delete(s);
340     }
341   }
342   ;
343 
344 value_list:
345     value
346   | value_list TOK_COMMA value
347   | value_list TOK_COMMA
348   ;
349 
350 value_list_optional:
351     /* empty */
352   | value_list
353   ;
354 
355 simple_value_list:
356     simple_value
357   | simple_value_list TOK_COMMA simple_value
358   | simple_value_list TOK_COMMA
359   ;
360 
361 simple_value_list_optional:
362     /* empty */
363   | simple_value_list
364   ;
365 
366 group:
367   TOK_GROUP_START
368   {
369     if(IN_LIST())
370     {
371       ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_GROUP);
372       CAPTURE_PARSE_POS(ctx->parent);
373     }
374     else
375     {
376       ctx->setting->type = CONFIG_TYPE_GROUP;
377       ctx->parent = ctx->setting;
378       ctx->setting = NULL;
379     }
380   }
381   setting_list_optional
382   TOK_GROUP_END
383   {
384     if(ctx->parent)
385       ctx->parent = ctx->parent->parent;
386   }
387   ;
388 
389 %%
390