X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=first.c;h=040a04ca25f0182f9c4b5d0760aa3ea794bf9d1d;hb=a62337e4820285aa154540d9ac30ec424f291892;hp=034e15a4d8f196a66e22e0c07f2325fa34748933;hpb=5686303d31f20b8b9b8ecadc18042e63178b4251;p=cascardo%2Fgrammar.git diff --git a/first.c b/first.c index 034e15a..040a04c 100644 --- a/first.c +++ b/first.c @@ -457,7 +457,7 @@ void first_check (gpointer key, gpointer val, gpointer data) * We should iterate through the rules for each nonterminal until only * terminals are known to be in the first set of it. */ -GHashTable* grammar_first (Grammar* grammar) +GHashTable* grammar_first (grammar_t* grammar) { GHashTable* first; gboolean stop; @@ -474,7 +474,7 @@ GHashTable* grammar_first (Grammar* grammar) return first; } -void put_key_on_list (gpointer key, gpointer val, gpointer data) +static void put_key_on_list (gpointer key, gpointer val, gpointer data) { GList** l; l = (GList**) data; @@ -490,8 +490,55 @@ GList* first_get (GHashTable* first, symbol_t* symbol) if (g_hash_table_lookup_extended (first, symbol, NULL, (gpointer*) &first_set)) { - g_hash_table_foreach (first->terminals, put_key_on_list, &l); + if (first_set->has_empty) + l = g_list_prepend (l, symbol_new (TRUE, 0)); + g_hash_table_foreach (first_set->terminals, put_key_on_list, &l); } return l; } + +GList* first_rule (GHashTable* first, rule_t* rule) +{ + + GHashTable* terminals; + GList* symbols; + GList* l; + + l = NULL; + + symbols = grammar_get_rule (rule); + + terminals = g_hash_table_new_full (symbol_hash, symbol_equal, g_free, NULL); + + while (symbols != NULL) + { + first_set_t* first_set; + symbol_t* symbol; + symbol = (symbol_t*) symbols->data; + if (symbol->terminal) + { + g_hash_table_insert (terminals, symbol_copy (symbol), NULL); + break; + } + if (!g_hash_table_lookup_extended (first, symbol, NULL, + (gpointer*) &first_set)) + { + g_hash_table_destroy (terminals); + return NULL; + } + first_set_union (terminals, first_set->terminals); + if (first_set->has_empty == FALSE) + break; + symbols = g_list_next (symbols); + } + + if (symbols == NULL) + l = g_list_prepend (l, symbol_new (TRUE, 0)); + g_hash_table_foreach (terminals, put_key_on_list, &l); + + g_hash_table_destroy (terminals); + + return l; + +}