+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;
+}
+