4a550b32a1c8e6fa9ad89ec338a1c11c282cd25d
1 /**
2 * collectd - src/liboconfig/parser.y
3 * Copyright (C) 2007,2008 Florian Forster
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Florian Forster <octo at collectd.org>
25 */
27 %{
28 #include <stdlib.h>
29 #include <string.h>
30 #include "oconfig.h"
31 #include "aux_types.h"
33 static char *unquote (const char *orig);
34 static int yyerror (const char *s);
36 /* Lexer variables */
37 extern int yylineno;
38 extern char *yytext;
39 extern int yylex (void);
41 extern oconfig_item_t *ci_root;
42 extern char *c_file;
43 %}
45 %start entire_file
47 %union {
48 double number;
49 int boolean;
50 char *string;
51 oconfig_value_t cv;
52 oconfig_item_t ci;
53 argument_list_t al;
54 statement_list_t sl;
55 }
57 %token <number> NUMBER
58 %token <boolean> BTRUE BFALSE
59 %token <string> QUOTED_STRING UNQUOTED_STRING
60 %token SLASH OPENBRAC CLOSEBRAC EOL
62 %type <string> string
63 %type <string> identifier
64 /* arguments */
65 %type <cv> argument
66 %type <al> argument_list
67 /* blocks */
68 %type <ci> block_begin
69 %type <ci> block
70 %type <string> block_end
71 /* statements */
72 %type <ci> option
73 %type <ci> statement
74 %type <sl> statement_list
75 %type <ci> entire_file
77 /* pass an verbose, specific error message to yyerror() */
78 %error-verbose
80 %%
81 string:
82 QUOTED_STRING {$$ = unquote ($1);}
83 | UNQUOTED_STRING {$$ = strdup ($1);}
84 ;
86 argument:
87 NUMBER {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
88 | BTRUE {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
89 | BFALSE {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
90 | string {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
91 ;
93 argument_list:
94 argument_list argument
95 {
96 $$ = $1;
97 $$.argument_num++;
98 $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
99 $$.argument[$$.argument_num-1] = $2;
100 }
101 | argument
102 {
103 $$.argument = malloc (sizeof (oconfig_value_t));
104 $$.argument[0] = $1;
105 $$.argument_num = 1;
106 }
107 ;
109 identifier:
110 UNQUOTED_STRING {$$ = strdup ($1);}
111 ;
113 option:
114 identifier argument_list EOL
115 {
116 memset (&$$, '\0', sizeof ($$));
117 $$.key = $1;
118 $$.values = $2.argument;
119 $$.values_num = $2.argument_num;
120 }
121 ;
123 block_begin:
124 OPENBRAC identifier CLOSEBRAC EOL
125 {
126 memset (&$$, '\0', sizeof ($$));
127 $$.key = $2;
128 }
129 |
130 OPENBRAC identifier argument_list CLOSEBRAC EOL
131 {
132 memset (&$$, '\0', sizeof ($$));
133 $$.key = $2;
134 $$.values = $3.argument;
135 $$.values_num = $3.argument_num;
136 }
137 ;
139 block_end:
140 OPENBRAC SLASH identifier CLOSEBRAC EOL
141 {
142 $$ = $3;
143 }
144 ;
146 block:
147 block_begin statement_list block_end
148 {
149 if (strcmp ($1.key, $3) != 0)
150 {
151 printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
152 yyerror ("Block not closed..\n");
153 exit (1);
154 }
155 free ($3); $3 = NULL;
156 $$ = $1;
157 $$.children = $2.statement;
158 $$.children_num = $2.statement_num;
159 }
160 | block_begin block_end
161 {
162 if (strcmp ($1.key, $2) != 0)
163 {
164 printf ("block_begin = %s; block_end = %s;\n", $1.key, $2);
165 yyerror ("Block not closed..\n");
166 exit (1);
167 }
168 free ($2); $2 = NULL;
169 $$ = $1;
170 $$.children = NULL;
171 $$.children_num = 0;
172 }
173 ;
175 statement:
176 option {$$ = $1;}
177 | block {$$ = $1;}
178 | EOL {$$.values_num = 0;}
179 ;
181 statement_list:
182 statement_list statement
183 {
184 $$ = $1;
185 if (($2.values_num > 0) || ($2.children_num > 0))
186 {
187 $$.statement_num++;
188 $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
189 $$.statement[$$.statement_num-1] = $2;
190 }
191 }
192 | statement
193 {
194 if (($1.values_num > 0) || ($1.children_num > 0))
195 {
196 $$.statement = malloc (sizeof (oconfig_item_t));
197 $$.statement[0] = $1;
198 $$.statement_num = 1;
199 }
200 else
201 {
202 $$.statement = NULL;
203 $$.statement_num = 0;
204 }
205 }
206 ;
208 entire_file:
209 statement_list
210 {
211 ci_root = calloc (1, sizeof (*ci_root));
212 ci_root->children = $1.statement;
213 ci_root->children_num = $1.statement_num;
214 }
215 | /* epsilon */
216 {
217 ci_root = calloc (1, sizeof (*ci_root));
218 ci_root->children = NULL;
219 ci_root->children_num = 0;
220 }
221 ;
223 %%
224 static int yyerror (const char *s)
225 {
226 const char *text;
228 if (*yytext == '\n')
229 text = "<newline>";
230 else
231 text = yytext;
233 fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
234 c_file, yylineno, text, s);
235 return (-1);
236 } /* int yyerror */
238 static char *unquote (const char *orig)
239 {
240 char *ret = strdup (orig);
241 int len;
243 if (ret == NULL)
244 return (NULL);
246 len = strlen (ret);
248 if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
249 return (ret);
251 len -= 2;
252 memmove (ret, ret + 1, len);
253 ret[len] = '\0';
255 for (int i = 0; i < len; i++)
256 {
257 if (ret[i] == '\\')
258 {
259 memmove (ret + i, ret + (i + 1), len - i);
260 len--;
261 }
262 }
264 return (ret);
265 } /* char *unquote */