911363c9142522e8575028ce421aa69e39a97616
[liboconfig.git] / src / parser.y
1 %{
2 #include <stdlib.h>
3 #include <string.h>
4 #include "oconfig.h"
5
6 static oconfig_item_t *ci_root;
7 static oconfig_item_t *ci_current;
8
9 static oconfig_item_t  *statement_list;
10 static int              statement_list_num;
11
12 static oconfig_value_t *argument_list;
13 static int              argument_list_num;
14
15 struct statement_list_s
16 {
17         oconfig_item_t *statement;
18         int             statement_num;
19 };
20 typedef struct statement_list_s statement_list_t;
21
22 struct argument_list_s
23 {
24         oconfig_value_t *argument;
25         int              argument_num;
26 };
27 typedef struct argument_list_s argument_list_t;
28
29 static void dump_ci (oconfig_item_t *ci, int shift);
30 %}
31
32 %start entire_file
33
34 %union {
35         double  number;
36         int     boolean;
37         char   *string;
38         oconfig_value_t  cv;
39         oconfig_value_t *cvp;
40         oconfig_item_t   ci;
41         argument_list_t  al;
42         statement_list_t sl;
43 }
44
45 %token <number> NUMBER
46 %token <boolean> TRUE FALSE
47 %token <string> QUOTED_STRING UNQUOTED_STRING
48 %token SLASH OPENBRAC CLOSEBRAC EOL
49
50 %type <string> string
51 %type <string> identifier
52 %type <string> block_end
53 %type <cv> argument
54 %type <al> argument_list
55 %type <ci> block_begin
56 %type <ci> block
57 %type <ci> option
58 %type <ci> statement
59 %type <sl> statement_list
60
61 %%
62 string:
63         QUOTED_STRING           {$$ = $1;}
64         | UNQUOTED_STRING       {$$ = $1;}
65         ;
66
67 argument:
68         NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
69         | TRUE                  {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
70         | FALSE                 {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
71         | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
72         ;
73
74 argument_list:
75         argument_list argument
76         {
77          $$ = $1;
78          $$.argument_num++;
79          $$.argument = realloc ($$.argument, $$.argument_num * sizeof (argument_list_t));
80          $$.argument[$$.argument_num-1] = $2;
81         }
82         | argument
83         {
84          $$.argument = malloc (sizeof (argument_list_t));
85          $$.argument[0] = $1;
86          $$.argument_num = 1;
87         }
88         ;
89
90 identifier:
91         UNQUOTED_STRING                 {$$ = $1;}
92         ;
93
94 option:
95         identifier argument_list EOL
96         {
97          memset (&$$, '\0', sizeof ($$));
98          $$.key = $1;
99          $$.values = $2.argument;
100          $$.values_num = $2.argument_num;
101          printf ("Option `%s' has %i arguments\n", $$.key, $$.values_num);
102         }
103         ;
104
105 block_begin:
106         OPENBRAC identifier argument_list CLOSEBRAC EOL
107         {
108          memset (&$$, '\0', sizeof ($$));
109          $$.key = $2;
110          $$.values = $3.argument;
111          $$.values_num = $3.argument_num;
112          printf ("Begin block `%s'\n", $2);
113         }
114         ;
115
116 block_end:
117         OPENBRAC SLASH identifier CLOSEBRAC EOL {$$ = $3; printf ("End block `%s'\n", $3);}
118         ;
119
120 block:
121         block_begin statement_list block_end
122         {
123          if (strcmp ($1.key, $3) != 0)
124                 yyerror ("Block %s not closed..\n", $1);
125          $$ = $1;
126          $$.children = $2.statement;
127         }
128         ;
129
130 statement:
131         option          {$$ = $1;}
132         | block         {$$ = $1;}
133         | EOL           {/* ignore */}
134         ;
135
136 statement_list:
137         statement_list statement
138         {
139          $$ = $1;
140          $$.statement_num++;
141          $$.statement = realloc ($$.statement, $$.statement_num * sizeof (statement_list_t));
142          $$.statement[$$.statement_num-1] = $2;
143          printf ("statement_list: length = %i\n", $$.statement_num);
144         }
145         | statement
146         {
147          $$.statement = malloc (sizeof (statement_list_t));
148          $$.statement[0] = $1;
149          $$.statement_num = 1;
150         }
151         ;
152
153 entire_file:
154         statement_list
155         {
156          int i;
157          for (i = 0; i < $1.statement_num; i++)
158                 dump_ci ($1.statement + i, 0);
159         }
160         ;
161
162 %%
163 #include "lex.yy.c"
164
165 /*
166 void yyerror (char *s)
167 {
168         fprintf (stderr, "%s\n", s);
169 }
170
171 int yylex (void)
172 {
173         return (getc (stdin));
174 }
175 */
176
177 int main (int argc, char **argv)
178 {
179         yyparse ();
180         return (0);
181 }
182
183 static void dump_ci (oconfig_item_t *ci, int shift)
184 {
185         int i;
186
187         if (shift > 0)
188                 printf ("%*s", "", shift);
189
190         printf ("%s", ci->key);
191         for (i = 0; i < ci->values_num; i++)
192         {
193                 oconfig_value_t cv = ci->values[i];
194
195                 if (cv.type == OCONFIG_TYPE_STRING)
196                         printf (" `%s'", cv.value.string);
197                 else if (cv.type == OCONFIG_TYPE_NUMBER)
198                         printf (" %lf", cv.value.number);
199                 else if (cv.type == OCONFIG_TYPE_BOOLEAN)
200                         printf (" %s", cv.value.boolean ? "true" : "false");
201                 else
202                         printf ("<unknown type %i>", cv.type);
203         }
204         printf ("\n");
205
206         for (i = 0; i < ci->children_num; i++)
207                 dump_ci (ci->children + i, shift + 1);
208 }