Fixed first
[cascardo/grammar.git] / grammar.c
index b73cd39..5f41708 100644 (file)
--- a/grammar.c
+++ b/grammar.c
@@ -5,7 +5,7 @@ struct _rule
   GList* right;
 };
 
-symbol_t* symbol_new (gboolean terminal, gint value)
+symbol_t* symbol_new (gboolean terminal, GQuark value)
 {
   symbol_t* symbol;
   symbol = g_malloc (sizeof (symbol_t));
@@ -14,17 +14,9 @@ symbol_t* symbol_new (gboolean terminal, gint value)
   return symbol;
 }
 
-rule_t* rule_new ()
-{
-  rule_t* rule;
-  rule = g_malloc (sizeof (rule_t));
-  rule->right = NULL;
-  return rule;
-}
-
-void rule_append (rule_t* rule, symbol_t* right)
+symbol_t* symbol_copy (symbol_t* symbol)
 {
-  rule->right = g_list_append (rule->right, right);
+  return symbol_new (symbol->terminal, symbol->value);
 }
 
 guint symbol_hash (gconstpointer data)
@@ -44,54 +36,142 @@ gboolean symbol_equal (gconstpointer data1, gconstpointer data2)
     symbol1->terminal == symbol2->terminal;
 }
 
-static void grammar_init (GTypeInstance* instance, gpointer g_class)
+gint symbol_cmp (symbol_t* a, symbol_t* b)
 {
-  Grammar* self = GRAMMAR(instance);
-  self->grammar = g_hash_table_new_full (symbol_hash, symbol_equal,
-                                        g_free, g_free);
+  if (a->terminal == b->terminal)
+    {
+      if (a->value < b->value)
+       return -1;
+      else if (a->value > b->value)
+       return 1;
+      return 0;
+    }
+  else if (a->terminal == FALSE)
+    {
+      return -1;
+    }
+  return 1;
 }
 
-static void grammar_finalize (GObject* obj)
+rule_t* rule_new ()
 {
-  GrammarClass* klass;
-  GObject* parent_class;
-  Grammar* self;
-  self = GRAMMAR(obj);
-  g_hash_table_destroy (self->grammar);
-  klass = GRAMMAR_GET_CLASS(obj);
-  parent_class = g_type_class_peek_parent (klass);
-  G_OBJECT_CLASS(parent_class)->finalize (obj);
+  rule_t* rule;
+  rule = g_malloc (sizeof (rule_t));
+  rule->right = NULL;
+  return rule;
 }
 
-static void grammar_class_init (GrammarClass* klass)
+void rule_append (rule_t* rule, symbol_t* right)
 {
-  GObjectClass* gobj_class = G_OBJECT_CLASS(klass);
-  gobj_class->finalize = grammar_finalize;
+  rule->right = g_list_append (rule->right, right);
 }
 
-GType grammar_get_type ()
+rule_t* rule_copy (rule_t* rule)
 {
-  static GType type = 0;
-  if (type == 0)
+  rule_t* new_rule;
+  GList* r;
+  new_rule = rule_new ();
+  r = rule->right;
+  while (r != NULL)
     {
-      static const GTypeInfo info =
-       {
-         sizeof (GrammarClass),
-         NULL,
-         NULL,
-         (GClassInitFunc)grammar_class_init,
-         NULL,
-         NULL,
-         sizeof (Grammar),
-         0,
-         grammar_init
-       };
-      type = g_type_register_static (G_TYPE_OBJECT, "GrammarType", &info, 0);
+      rule_append (new_rule, symbol_copy (r->data));
+      r = g_list_next (r);
     }
-  return type;
+  return new_rule;
 }
 
-rule_t* grammar_rule_new (Grammar* grammar, symbol_t* left)
+gint rule_cmp (rule_t* a, rule_t* b)
+{
+  GList* la;
+  GList* lb;
+  la = grammar_get_rule (a);
+  lb = grammar_get_rule (b);
+  while (la != NULL && lb != NULL)
+    {
+      int c;
+      if ((c = symbol_cmp (la->data, lb->data)) != 0)
+       return c;
+      la = g_list_next (la);
+      lb = g_list_next (lb);
+    }
+  if (la == lb)
+    return 0;
+  else if (la == NULL)
+    return -1;
+  return 1;
+}
+
+gboolean rule_equal (gconstpointer data1, gconstpointer data2)
+{
+  return (rule_cmp (data1, data2) == 0);
+}
+
+guint rule_hash (gconstpointer data)
+{
+  GList* l;
+  guint hash;
+  l = grammar_get_rule (data);
+  hash = 0;
+  while (l != NULL)
+    {
+      hash = 37 * hash + symbol_hash (l->data);
+      l = g_list_next (l);
+    }
+  return hash;
+}
+
+symbol_t* rule_pop (rule_t* rule)
+{
+  GList* r;
+  if ((r = g_list_first (rule->right)) == NULL)
+    return NULL;
+  rule->right = g_list_remove_link (r, r);
+  g_free (r->data);
+  g_list_free (r);
+  if (rule->right == NULL)
+    return NULL;
+  return rule->right->data;
+}
+
+void rule_delete (rule_t* rule)
+{
+  GList* l;
+  for (l = g_list_first (rule->right); l != NULL; l = g_list_next (l))
+    {
+      g_free (l->data);
+    }
+  g_list_free (rule->right);
+  g_free (rule);
+}
+
+void rules_delete (GList** list)
+{
+  GList* l;
+  for (l = g_list_first (*list); l != NULL; l = g_list_next (l))
+    {
+      rule_delete (l->data);
+    }
+  g_list_free (*list);
+  g_free (list);
+}
+
+grammar_t* grammar_new ()
+{
+  grammar_t* grammar;
+  grammar = g_malloc (sizeof (grammar_t*));
+  grammar->grammar = g_hash_table_new_full (symbol_hash, symbol_equal,
+                                           g_free,
+                                           (GDestroyNotify) rules_delete);
+  return grammar;
+}
+
+void grammar_delete (grammar_t* grammar)
+{
+  g_hash_table_destroy (grammar->grammar);
+  g_free (grammar);
+}
+
+rule_t* grammar_rule_new (grammar_t* grammar, symbol_t* left)
 {
 
   GList** l;
@@ -101,6 +181,7 @@ rule_t* grammar_rule_new (Grammar* grammar, symbol_t* left)
                                     left, NULL, (gpointer*)&l))
     {
       l = g_malloc (sizeof (GList**));
+      *l = NULL;
       g_hash_table_insert (grammar->grammar, left, l);
     }
 
@@ -112,7 +193,18 @@ rule_t* grammar_rule_new (Grammar* grammar, symbol_t* left)
 
 }
 
-void grammar_rule_append (rule_t* rule, symbol_t* right)
+GList* grammar_get_rules (grammar_t* grammar, symbol_t* left)
+{
+  GList** l;
+  if (!g_hash_table_lookup_extended (grammar->grammar,
+                                    left, NULL, (gpointer*)&l))
+    {
+      return NULL;
+    }
+  return g_list_first (*l);
+}
+
+GList* grammar_get_rule (rule_t* rule)
 {
-  rule_append (rule, right);
+  return rule->right;
 }