Fixed the code to build a list from keys of a hashtable
[cascardo/grammar.git] / grammar.c
1 #include <grammar.h>
2
3 struct _rule
4 {
5   GList* right;
6 };
7
8 symbol_t* symbol_new (gboolean terminal, GQuark value)
9 {
10   symbol_t* symbol;
11   symbol = g_malloc (sizeof (symbol_t));
12   symbol->terminal = terminal;
13   symbol->value = value;
14   return symbol;
15 }
16
17 symbol_t* symbol_copy (symbol_t* symbol)
18 {
19   return symbol_new (symbol->terminal, symbol->value);
20 }
21
22 guint symbol_hash (gconstpointer data)
23 {
24   symbol_t* symbol;
25   symbol = (symbol_t*) data;
26   return g_direct_hash ((gpointer)symbol->value);
27 }
28
29 gboolean symbol_equal (gconstpointer data1, gconstpointer data2)
30 {
31   symbol_t* symbol1;
32   symbol_t* symbol2;
33   symbol1 = (symbol_t*) data1;
34   symbol2 = (symbol_t*) data2;
35   return symbol1->value == symbol2->value &&
36     symbol1->terminal == symbol2->terminal;
37 }
38
39 rule_t* rule_new ()
40 {
41   rule_t* rule;
42   rule = g_malloc (sizeof (rule_t));
43   rule->right = NULL;
44   return rule;
45 }
46
47 void rule_append (rule_t* rule, symbol_t* right)
48 {
49   rule->right = g_list_append (rule->right, right);
50 }
51
52 rule_t* rule_copy (rule_t* rule)
53 {
54   rule_t* new_rule;
55   GList* r;
56   new_rule = rule_new ();
57   r = rule->right;
58   while (r != NULL)
59     {
60       rule_append (new_rule, symbol_copy (r->data));
61       r = g_list_next (r);
62     }
63   return new_rule;
64 }
65
66 symbol_t* rule_pop (rule_t* rule)
67 {
68   GList* r;
69   if ((r = g_list_first (rule->right)) == NULL)
70     return NULL;
71   rule->right = g_list_remove_link (r, r);
72   g_free (r->data);
73   g_list_free (r);
74   if (rule->right == NULL)
75     return NULL;
76   return rule->right->data;
77 }
78
79 void rule_delete (rule_t* rule)
80 {
81   GList* l;
82   for (l = g_list_first (rule->right); l != NULL; l = g_list_next (l))
83     {
84       g_free (l->data);
85     }
86   g_list_free (rule->right);
87   g_free (rule);
88 }
89
90 void rules_delete (GList** list)
91 {
92   GList* l;
93   for (l = g_list_first (*list); l != NULL; l = g_list_next (l))
94     {
95       rule_delete (l->data);
96     }
97   g_list_free (*list);
98   g_free (list);
99 }
100
101 static void grammar_init (GTypeInstance* instance, gpointer g_class)
102 {
103   Grammar* self = GRAMMAR(instance);
104   self->grammar = g_hash_table_new_full (symbol_hash, symbol_equal,
105                                          g_free,
106                                          (GDestroyNotify) rules_delete);
107 }
108
109 static void grammar_finalize (GObject* obj)
110 {
111   GrammarClass* klass;
112   GObject* parent_class;
113   Grammar* self;
114   self = GRAMMAR(obj);
115   g_hash_table_destroy (self->grammar);
116   klass = GRAMMAR_GET_CLASS(obj);
117   parent_class = g_type_class_peek_parent (klass);
118   G_OBJECT_CLASS(parent_class)->finalize (obj);
119 }
120
121 static void grammar_class_init (GrammarClass* klass)
122 {
123   GObjectClass* gobj_class = G_OBJECT_CLASS(klass);
124   gobj_class->finalize = grammar_finalize;
125 }
126
127 GType grammar_get_type ()
128 {
129   static GType type = 0;
130   if (type == 0)
131     {
132       static const GTypeInfo info =
133         {
134           sizeof (GrammarClass),
135           NULL,
136           NULL,
137           (GClassInitFunc)grammar_class_init,
138           NULL,
139           NULL,
140           sizeof (Grammar),
141           0,
142           grammar_init
143         };
144       type = g_type_register_static (G_TYPE_OBJECT, "GrammarType", &info, 0);
145     }
146   return type;
147 }
148
149 rule_t* grammar_rule_new (Grammar* grammar, symbol_t* left)
150 {
151
152   GList** l;
153   rule_t* rule;
154
155   if (!g_hash_table_lookup_extended (grammar->grammar,
156                                      left, NULL, (gpointer*)&l))
157     {
158       l = g_malloc (sizeof (GList**));
159       *l = NULL;
160       g_hash_table_insert (grammar->grammar, left, l);
161     }
162
163   rule = rule_new ();
164
165   *l = g_list_append (*l, rule);
166
167   return rule;
168
169 }
170
171 GList* grammar_get_rules (Grammar* grammar, symbol_t* left)
172 {
173   GList** l;
174   if (!g_hash_table_lookup_extended (grammar->grammar,
175                                      left, NULL, (gpointer*)&l))
176     {
177       return NULL;
178     }
179   return g_list_first (*l);
180 }
181
182 GList* grammar_get_rule (rule_t* rule)
183 {
184   return rule->right;
185 }