memory leak at bnf loader
[cascardo/grammar.git] / bnf.c
1 #include <grammar.h>
2 #include <rdp.h>
3 #include <scanner.h>
4 #include <assert.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8
9 static gint scanner_next (scanner_t* scanner, GString** val)
10 {
11
12   int state;
13   int start;
14   int stop;
15   int i;
16   gchar* buffer;
17   GString* lexeme;
18
19   state = NONE;
20   start = 0;
21   stop = 0;
22   buffer = malloc (256);
23
24   for (i = 0; stop == 0; i++)
25     {
26
27       gchar c;
28
29       if (scanner->buffer->len == 0)
30         {
31           int r;
32           r = scanner->cb (scanner->data, buffer, 256);
33           if (r == 0)
34             g_string_append_c (scanner->buffer, 0);
35           else
36             g_string_append_len (scanner->buffer, buffer, r);
37         }
38
39       c = scanner->buffer->str[i];
40
41       switch (state)
42         {
43         case NONE:
44           if (g_ascii_isalpha (c))
45             {
46               start = i;
47               state = ID;
48               break;
49             }
50           else if (g_ascii_isspace (c))
51             {
52               if (c == '\n')
53                 {
54                   start = i;
55                   state = EOL;
56                 }
57               break;
58             }
59           else if (c == ':')
60             {
61               start = i;
62               state = EQUAL;
63               break;
64             }
65           else if (c == '"')
66             {
67               start = i;
68               state = STRING;
69               break;
70             }
71           else if (c == 0)
72             {
73               stop = i;
74               break;
75             }
76         case ID:
77           if (g_ascii_isalnum (c))
78             {
79               break;
80             }
81           else if (g_ascii_isspace (c) || c == 0)
82             {
83               stop = i;
84               break;
85             }
86         case EOL:
87         case EQUAL:
88           stop = i;
89           break;
90         case STRING:
91           if (c == '"')
92             stop = i+1;
93           break;
94         }
95               
96     }
97
98   free (buffer);
99
100   g_string_erase (scanner->buffer, 0, start);
101   lexeme = g_string_new_len (scanner->buffer->str, stop - start);
102   g_string_erase (scanner->buffer, 0, stop - start);
103
104   if (val)
105     {
106       *val = lexeme;
107     }
108   else
109     {
110       g_string_free (lexeme, TRUE);
111     }
112
113   return state;
114
115 }
116
117 enum
118   {
119     BNF_GRAMMAR = 1,
120     BNF_RULES,
121     BNF_RULE,
122     BNF_LEFT,
123     BNF_RIGHT,
124     BNF_SYMBOL,
125     BNF_TERMINAL,
126     BNF_NONTERMINAL
127   };
128
129 void grammar_tree (grammar_t* grammar, GNode* tree)
130 {
131
132   GNode* child_rules;
133   GNode* child_rule;
134   GNode* child_left;
135   GNode* child_right;
136   GNode* child_symbol;
137   GNode* child_nonterminal;
138   GNode* child_terminal;
139   GNode* child;
140   symbol_t* symbol;
141   rule_t* rule;
142   GString* sym;
143   GQuark value;
144
145   assert (G_NODE_IS_LEAF(tree) == FALSE);
146   symbol = tree->data;
147   assert (symbol->value == BNF_GRAMMAR);
148
149   child_rules = tree->children;
150
151   while (child_rules->children != NULL)
152     {
153
154       assert (G_NODE_IS_LEAF(child_rules) == FALSE);
155       symbol = child_rules->data;
156       assert (symbol->value == BNF_RULES);
157
158       child_rule = child_rules->children;
159       assert (G_NODE_IS_LEAF(child_rule) == FALSE);
160       symbol = child_rule->data;
161       assert (symbol->value == BNF_RULE);
162
163       child_left = child_rule->children;
164       assert (G_NODE_IS_LEAF (child_left) == FALSE);
165       symbol = child_left->data;
166       assert (symbol->value == BNF_LEFT);
167
168       child_nonterminal = child_left->children;
169       assert (G_NODE_IS_LEAF (child_nonterminal) == FALSE);
170       symbol = child_nonterminal->data;
171       assert (symbol->value == BNF_NONTERMINAL);
172       assert (child_nonterminal->next == NULL);
173
174       child = child_nonterminal->children;
175       assert (G_NODE_IS_LEAF (child));
176       sym = child->data;
177
178       /* Create new rule */
179       value = g_quark_from_string (sym->str);
180       rule = grammar_rule_new (grammar, symbol_new (FALSE, value));
181
182       child_right = child_left->next->next;
183       while (child_right->children != NULL)
184         {
185
186           assert (G_NODE_IS_LEAF(child_right) == FALSE);
187           symbol = child_right->data;
188           assert (symbol->value == BNF_RIGHT);
189
190           child_symbol = child_right->children;
191           assert (G_NODE_IS_LEAF(child_symbol) == FALSE);
192           symbol = child_symbol->data;
193           assert (symbol->value == BNF_SYMBOL);
194
195           child = child_symbol->children;
196           symbol = child->data;
197           if (symbol->value == BNF_NONTERMINAL)
198             {
199               child_nonterminal = child;
200               assert (G_NODE_IS_LEAF (child_nonterminal) == FALSE);
201               assert (child_nonterminal->next == NULL);
202               child = child_nonterminal->children;
203               assert (G_NODE_IS_LEAF (child));
204               sym = child->data;
205               /* Append nonterminal to rule */
206               value = g_quark_from_string (sym->str);
207               rule_append (rule, symbol_new (FALSE, value));
208             }
209           else if (symbol->value == BNF_TERMINAL)
210             {
211               child_terminal = child;
212               assert (G_NODE_IS_LEAF (child_terminal) == FALSE);
213               assert (child_terminal->next == NULL);
214               child = child_terminal->children;
215               assert (G_NODE_IS_LEAF (child));
216               sym = child->data;
217               /* Append terminal to rule */
218               value = g_quark_from_string (sym->str);
219               rule_append (rule, symbol_new (TRUE, value));
220             }
221           else
222             {
223               assert (TRUE);
224             }
225
226           child_right = child_symbol->next;
227
228         }
229
230       child_rules = child_rule->next;
231
232     }
233
234 }
235
236 grammar_t* grammar_load (char* filename)
237 {
238
239   grammar_t* grammar;
240   rule_t* rule;
241
242   scanner_t* scanner;
243   rdp_t* parser;
244   GNode* tree;
245
246   int fd;
247
248   fd = open (filename, O_RDONLY);
249
250   scanner = scanner_new (read, fd);
251
252   grammar = grammar_new ();
253   parser = rdp_new (scanner_next, scanner, BNF_GRAMMAR, grammar);
254
255   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_GRAMMAR));
256   rule_append (rule, symbol_new (FALSE, BNF_RULES));
257   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RULES));
258   rule_append (rule, symbol_new (FALSE, BNF_RULE));
259   rule_append (rule, symbol_new (FALSE, BNF_RULES));
260   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RULES));
261   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RULE));
262   rule_append (rule, symbol_new (FALSE, BNF_LEFT));
263   rule_append (rule, symbol_new (TRUE, EQUAL));
264   rule_append (rule, symbol_new (FALSE, BNF_RIGHT));
265   rule_append (rule, symbol_new (TRUE, EOL));
266   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_LEFT));
267   rule_append (rule, symbol_new (FALSE, BNF_NONTERMINAL));
268   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RIGHT));
269   rule_append (rule, symbol_new (FALSE, BNF_SYMBOL));
270   rule_append (rule, symbol_new (FALSE, BNF_RIGHT));
271   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_RIGHT));
272   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_SYMBOL));
273   rule_append (rule, symbol_new (FALSE, BNF_TERMINAL));
274   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_SYMBOL));
275   rule_append (rule, symbol_new (FALSE, BNF_NONTERMINAL));
276   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_TERMINAL));
277   rule_append (rule, symbol_new (TRUE, STRING));
278   rule = grammar_rule_new (grammar, symbol_new (FALSE, BNF_NONTERMINAL));
279   rule_append (rule, symbol_new (TRUE, ID));
280
281   tree = rdp_build (parser);
282
283   close (fd);
284   scanner_delete (scanner);
285   rdp_delete (rdp);
286   grammar_delete (grammar);
287
288   if (tree == NULL)
289     {
290       return NULL;
291     }
292   else
293     {
294       grammar_t* gr;
295       gr = g_object_new (GRAMMAR_TYPE, NULL);
296       grammar_tree (gr, tree);
297       return gr;
298     }
299
300 }