perl plugin: Removed commented code
[collectd.git] / src / liboconfig / parser.y
1 /**
2  * oconfig - src/parser.y
3  * Copyright (C) 2007,2008  Florian octo Forster <octo at verplant.org>
4  *
5  * This program 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; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  */
18
19 %{
20 #include <stdlib.h>
21 #include <string.h>
22 #include "oconfig.h"
23 #include "aux_types.h"
24
25 static char *unquote (const char *orig);
26 static int yyerror (const char *s);
27
28 /* Lexer variables */
29 extern int yylineno;
30 extern char *yytext;
31 extern int yylex (void);
32
33 extern oconfig_item_t *ci_root;
34 extern char           *c_file;
35 %}
36
37 %start entire_file
38
39 %union {
40         double  number;
41         int     boolean;
42         char   *string;
43         oconfig_value_t  cv;
44         oconfig_item_t   ci;
45         argument_list_t  al;
46         statement_list_t sl;
47 }
48
49 %token <number> NUMBER
50 %token <boolean> BTRUE BFALSE
51 %token <string> QUOTED_STRING UNQUOTED_STRING
52 %token SLASH OPENBRAC CLOSEBRAC EOL
53
54 %type <string> string
55 %type <string> identifier
56 /* arguments */
57 %type <cv> argument
58 %type <al> argument_list
59 /* blocks */
60 %type <ci> block_begin
61 %type <ci> block
62 %type <string> block_end
63 /* statements */
64 %type <ci> option
65 %type <ci> statement
66 %type <sl> statement_list
67 %type <ci> entire_file
68
69 /* pass an verbose, specific error message to yyerror() */
70 %error-verbose
71
72 %%
73 string:
74         QUOTED_STRING           {$$ = unquote ($1);}
75         | UNQUOTED_STRING       {$$ = strdup ($1);}
76         ;
77
78 argument:
79         NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
80         | BTRUE                 {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
81         | BFALSE                {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
82         | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
83         ;
84
85 argument_list:
86         argument_list argument
87         {
88          $$ = $1;
89          $$.argument_num++;
90          $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
91          $$.argument[$$.argument_num-1] = $2;
92         }
93         | argument
94         {
95          $$.argument = malloc (sizeof (oconfig_value_t));
96          $$.argument[0] = $1;
97          $$.argument_num = 1;
98         }
99         ;
100
101 identifier:
102         UNQUOTED_STRING                 {$$ = strdup ($1);}
103         ;
104
105 option:
106         identifier argument_list EOL
107         {
108          memset (&$$, '\0', sizeof ($$));
109          $$.key = $1;
110          $$.values = $2.argument;
111          $$.values_num = $2.argument_num;
112         }
113         ;
114
115 block_begin:
116         OPENBRAC identifier CLOSEBRAC EOL
117         {
118          memset (&$$, '\0', sizeof ($$));
119          $$.key = $2;
120         }
121         |
122         OPENBRAC identifier argument_list CLOSEBRAC EOL
123         {
124          memset (&$$, '\0', sizeof ($$));
125          $$.key = $2;
126          $$.values = $3.argument;
127          $$.values_num = $3.argument_num;
128         }
129         ;
130
131 block_end:
132         OPENBRAC SLASH identifier CLOSEBRAC EOL
133         {
134          $$ = $3;
135         }
136         ;
137
138 block:
139         block_begin statement_list block_end
140         {
141          if (strcmp ($1.key, $3) != 0)
142          {
143                 printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
144                 yyerror ("Block not closed..\n");
145                 exit (1);
146          }
147          free ($3); $3 = NULL;
148          $$ = $1;
149          $$.children = $2.statement;
150          $$.children_num = $2.statement_num;
151         }
152         | block_begin block_end
153         {
154          if (strcmp ($1.key, $2) != 0)
155          {
156                 printf ("block_begin = %s; block_end = %s;\n", $1.key, $2);
157                 yyerror ("Block not closed..\n");
158                 exit (1);
159          }
160          free ($2); $2 = NULL;
161          $$ = $1;
162          $$.children = NULL;
163          $$.children_num = 0;
164         }
165         ;
166
167 statement:
168         option          {$$ = $1;}
169         | block         {$$ = $1;}
170         | EOL           {$$.values_num = 0;}
171         ;
172
173 statement_list:
174         statement_list statement
175         {
176          $$ = $1;
177          if (($2.values_num > 0) || ($2.children_num > 0))
178          {
179                  $$.statement_num++;
180                  $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
181                  $$.statement[$$.statement_num-1] = $2;
182          }
183         }
184         | statement
185         {
186          if (($1.values_num > 0) || ($1.children_num > 0))
187          {
188                  $$.statement = malloc (sizeof (oconfig_item_t));
189                  $$.statement[0] = $1;
190                  $$.statement_num = 1;
191          }
192          else
193          {
194                 $$.statement = NULL;
195                 $$.statement_num = 0;
196          }
197         }
198         ;
199
200 entire_file:
201         statement_list
202         {
203          ci_root = malloc (sizeof (oconfig_item_t));
204          memset (ci_root, '\0', sizeof (oconfig_item_t));
205          ci_root->children = $1.statement;
206          ci_root->children_num = $1.statement_num;
207         }
208         | /* epsilon */
209         {
210          ci_root = malloc (sizeof (oconfig_item_t));
211          memset (ci_root, '\0', sizeof (oconfig_item_t));
212          ci_root->children = NULL;
213          ci_root->children_num = 0;
214         }
215         ;
216
217 %%
218 static int yyerror (const char *s)
219 {
220         char *text;
221
222         if (*yytext == '\n')
223                 text = "<newline>";
224         else
225                 text = yytext;
226
227         fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
228                 c_file, yylineno, text, s);
229         return (-1);
230 } /* int yyerror */
231
232 static char *unquote (const char *orig)
233 {
234         char *ret = strdup (orig);
235         int len;
236         int i;
237
238         if (ret == NULL)
239                 return (NULL);
240
241         len = strlen (ret);
242
243         if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
244                 return (ret);
245
246         len -= 2;
247         memmove (ret, ret + 1, len);
248         ret[len] = '\0';
249
250         for (i = 0; i < len; i++)
251         {
252                 if (ret[i] == '\\')
253                 {
254                         memmove (ret + i, ret + (i + 1), len - i);
255                         len--;
256                 }
257         }
258
259         return (ret);
260 } /* char *unquote */