X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fgrammar.git;a=blobdiff_plain;f=grammar.c;h=5f417080e337940be2751a262255dfa5001bf196;hp=72248e0a06d6b27938dbc7b303c7c2a2031b7953;hb=a823a9bfed3bad6a91d05904b535b63282b8c286;hpb=fecd14f5105395f94825326ea177e77956af2b04 diff --git a/grammar.c b/grammar.c index 72248e0..5f41708 100644 --- 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,6 +14,11 @@ symbol_t* symbol_new (gboolean terminal, gint value) return symbol; } +symbol_t* symbol_copy (symbol_t* symbol) +{ + return symbol_new (symbol->terminal, symbol->value); +} + guint symbol_hash (gconstpointer data) { symbol_t* symbol; @@ -31,6 +36,23 @@ gboolean symbol_equal (gconstpointer data1, gconstpointer data2) symbol1->terminal == symbol2->terminal; } +gint symbol_cmp (symbol_t* a, symbol_t* b) +{ + 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; +} + rule_t* rule_new () { rule_t* rule; @@ -44,6 +66,73 @@ void rule_append (rule_t* rule, symbol_t* right) rule->right = g_list_append (rule->right, right); } +rule_t* rule_copy (rule_t* rule) +{ + rule_t* new_rule; + GList* r; + new_rule = rule_new (); + r = rule->right; + while (r != NULL) + { + rule_append (new_rule, symbol_copy (r->data)); + r = g_list_next (r); + } + return new_rule; +} + +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; @@ -66,55 +155,23 @@ void rules_delete (GList** list) g_free (list); } -static void grammar_init (GTypeInstance* instance, gpointer g_class) -{ - Grammar* self = GRAMMAR(instance); - self->grammar = g_hash_table_new_full (symbol_hash, symbol_equal, - g_free, - (GDestroyNotify) rules_delete); -} - -static void grammar_finalize (GObject* obj) -{ - 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); -} - -static void grammar_class_init (GrammarClass* klass) +grammar_t* grammar_new () { - GObjectClass* gobj_class = G_OBJECT_CLASS(klass); - gobj_class->finalize = grammar_finalize; + 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; } -GType grammar_get_type () +void grammar_delete (grammar_t* grammar) { - static GType type = 0; - if (type == 0) - { - 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); - } - return type; + g_hash_table_destroy (grammar->grammar); + g_free (grammar); } -rule_t* grammar_rule_new (Grammar* grammar, symbol_t* left) +rule_t* grammar_rule_new (grammar_t* grammar, symbol_t* left) { GList** l; @@ -124,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); } @@ -135,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; }