Properly delete Grammar hashtable content
[cascardo/grammar.git] / rdp.c
1 #include "rdp.h"
2 #include <stdlib.h>
3
4 rdp_t* rdp_new (nextcb cb, gpointer data, gint value)
5 {
6
7   rdp_t* parser;
8
9   parser = g_malloc (sizeof (rdp_t));
10   parser->cb = cb;
11   parser->data = data;
12   parser->start = symbol_new (FALSE, value);
13
14   parser->rules = NULL;
15
16   parser->buffer = g_list_append (NULL, NULL);
17
18   return parser;
19
20 }
21
22 void rdp_delete (rdp_t* parser)
23 {
24
25   g_free (parser->start);
26   g_free (parser);
27
28 }
29
30 gpointer leaf_new (gpointer data)
31 {
32   return g_node_new (data);
33 }
34
35 gpointer tree_new (rule_t* rule)
36 {
37   return g_node_new (rule);
38 }
39
40 gpointer tree_add (gpointer tree, gpointer data)
41 {
42   return g_node_append (tree, data);
43 }
44
45 void tree_delete (gpointer tree)
46 {
47   g_node_destroy (tree);
48 }
49
50 symbol_t* buffer_next (rdp_t* parser, gpointer* attrib)
51 {
52
53   buffer_t* buffer;
54
55   if (parser->buffer->next == NULL)
56     {
57       buffer = g_malloc (sizeof (buffer_t));
58       buffer->symbol = g_malloc (sizeof (symbol_t));
59       buffer->symbol->terminal = TRUE;
60       buffer->symbol->value = parser->cb (parser->data, &(buffer->attrib));
61       g_list_append (parser->buffer, buffer);
62     }
63
64   parser->buffer = g_list_next (parser->buffer);
65   buffer = (buffer_t*) parser->buffer->data;
66
67   if (attrib)
68     *attrib = buffer->attrib;
69
70   return buffer->symbol;
71       
72 }
73
74 gboolean rdp_step (rdp_t* parser, symbol_t* symbol, gpointer* attrib)
75 {
76
77   GList* l;
78   GList* buffer;
79   gpointer attr;
80
81   buffer = parser->buffer;
82
83   if (symbol != NULL && symbol->terminal)
84     {
85       symbol_t* s;
86       s = buffer_next (parser, &attr);
87       if (!symbol_equal (symbol, s))
88         {
89           parser->buffer = buffer;
90           return FALSE;
91         }
92       *attrib = leaf_new (attr);
93       return TRUE;
94     }
95
96   for (l = g_list_first (parser->rules); l != NULL; l = g_list_next (l))
97     {
98
99       rule_t* rule;
100
101       rule = (rule_t*) l->data;
102
103       if (symbol == NULL || symbol_equal (symbol, rule->left))
104         {
105
106           GList* m;
107
108           *attrib = tree_new (rule);
109
110           for (m = g_list_first (rule->right); m != NULL; m = g_list_next (m))
111             {
112
113               symbol_t* s;
114
115               s = (symbol_t*) m->data;
116
117               if (!rdp_step (parser, s, &attr))
118                 {
119                   parser->buffer = buffer;
120                   break;
121                 }
122
123               tree_add (*attrib, attr);
124
125             }
126
127           if (m == NULL)
128             return TRUE;
129           else
130             tree_delete (*attrib);
131
132         }
133
134     }
135
136   return FALSE;
137
138 }
139
140 gpointer rdp_build (rdp_t* parser)
141 {
142
143   gpointer attrib;
144
145   if (rdp_step (parser, parser->start, &attrib))
146     return attrib;
147
148   return NULL;
149
150 }