mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-19 17:23:02 +00:00
Use hash.h for the state hash table.
* src/LR0.c (STATE_HASH_SIZE, state_hash): Remove. (allocate_storage): Use state_hash_new. (free_storage): Use state_hash_free. (new_state, get_state): Adjust. * src/lalr.h, src/lalr.c (states): Move to... * src/states.h (state_t): Remove the `link' member, no longer used. * src/states.h, src/states.c: here. (state_hash_new, state_hash_free, state_hash_lookup) (state_hash_insert, states_free): New. * src/states.c (state_table, state_compare, state_hash): New. * src/output.c (output_actions): Do not free states now, since we still need to know the final_state number in `prepare', called afterwards. Do it... * src/main.c (main): here: call states_free after `output'.
This commit is contained in:
21
ChangeLog
21
ChangeLog
@@ -1,3 +1,24 @@
|
|||||||
|
2002-06-30 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
|
Use hash.h for the state hash table.
|
||||||
|
|
||||||
|
* src/LR0.c (STATE_HASH_SIZE, state_hash): Remove.
|
||||||
|
(allocate_storage): Use state_hash_new.
|
||||||
|
(free_storage): Use state_hash_free.
|
||||||
|
(new_state, get_state): Adjust.
|
||||||
|
* src/lalr.h, src/lalr.c (states): Move to...
|
||||||
|
* src/states.h (state_t): Remove the `link' member, no longer
|
||||||
|
used.
|
||||||
|
* src/states.h, src/states.c: here.
|
||||||
|
(state_hash_new, state_hash_free, state_hash_lookup)
|
||||||
|
(state_hash_insert, states_free): New.
|
||||||
|
* src/states.c (state_table, state_compare, state_hash): New.
|
||||||
|
* src/output.c (output_actions): Do not free states now, since we
|
||||||
|
still need to know the final_state number in `prepare', called
|
||||||
|
afterwards. Do it...
|
||||||
|
* src/main.c (main): here: call states_free after `output'.
|
||||||
|
|
||||||
|
|
||||||
2002-06-30 Akim Demaille <akim@epita.fr>
|
2002-06-30 Akim Demaille <akim@epita.fr>
|
||||||
|
|
||||||
* src/state.h, src/state.c (state_new): New, extracted from...
|
* src/state.h, src/state.c (state_new): New, extracted from...
|
||||||
|
|||||||
55
src/LR0.c
55
src/LR0.c
@@ -52,11 +52,6 @@ static item_number_t **kernel_base = NULL;
|
|||||||
static int *kernel_size = NULL;
|
static int *kernel_size = NULL;
|
||||||
static item_number_t *kernel_items = NULL;
|
static item_number_t *kernel_items = NULL;
|
||||||
|
|
||||||
/* hash table for states, to recognize equivalent ones. */
|
|
||||||
|
|
||||||
#define STATE_HASH_SIZE 1009
|
|
||||||
static state_t **state_hash = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
allocate_itemsets (void)
|
allocate_itemsets (void)
|
||||||
@@ -107,7 +102,7 @@ allocate_storage (void)
|
|||||||
|
|
||||||
shiftset = XCALLOC (state_number_t, nsyms);
|
shiftset = XCALLOC (state_number_t, nsyms);
|
||||||
redset = XCALLOC (short, nrules + 1);
|
redset = XCALLOC (short, nrules + 1);
|
||||||
state_hash = XCALLOC (state_t *, STATE_HASH_SIZE);
|
state_hash_new ();
|
||||||
shift_symbol = XCALLOC (symbol_number_t, nsyms);
|
shift_symbol = XCALLOC (symbol_number_t, nsyms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +116,7 @@ free_storage (void)
|
|||||||
free (kernel_base);
|
free (kernel_base);
|
||||||
free (kernel_size);
|
free (kernel_size);
|
||||||
XFREE (kernel_items);
|
XFREE (kernel_items);
|
||||||
free (state_hash);
|
state_hash_free ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -185,6 +180,7 @@ new_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
|||||||
nstates, symbol, symbol_tag_get (symbols[symbol]));
|
nstates, symbol, symbol_tag_get (symbols[symbol]));
|
||||||
|
|
||||||
res = state_new (symbol, core_size, core);
|
res = state_new (symbol, core_size, core);
|
||||||
|
state_hash_insert (res);
|
||||||
|
|
||||||
/* If this is the eoftoken, and this is not the initial state, then
|
/* If this is the eoftoken, and this is not the initial state, then
|
||||||
this is the final state. */
|
this is the final state. */
|
||||||
@@ -210,8 +206,6 @@ new_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
|||||||
static state_number_t
|
static state_number_t
|
||||||
get_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
get_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
||||||
{
|
{
|
||||||
int key;
|
|
||||||
size_t i;
|
|
||||||
state_t *sp;
|
state_t *sp;
|
||||||
|
|
||||||
if (trace_flag)
|
if (trace_flag)
|
||||||
@@ -219,45 +213,9 @@ get_state (symbol_number_t symbol, size_t core_size, item_number_t *core)
|
|||||||
this_state->number, symbol,
|
this_state->number, symbol,
|
||||||
symbol_tag_get (symbols[symbol]));
|
symbol_tag_get (symbols[symbol]));
|
||||||
|
|
||||||
/* Add up the target state's active item numbers to get a hash key.
|
sp = state_hash_lookup (core_size, core);
|
||||||
*/
|
if (!sp)
|
||||||
key = 0;
|
sp = new_state (symbol, core_size, core);
|
||||||
for (i = 0; i < core_size; ++i)
|
|
||||||
key += core[i];
|
|
||||||
key = key % STATE_HASH_SIZE;
|
|
||||||
sp = state_hash[key];
|
|
||||||
|
|
||||||
if (sp)
|
|
||||||
{
|
|
||||||
int found = 0;
|
|
||||||
while (!found)
|
|
||||||
{
|
|
||||||
if (sp->nitems == core_size)
|
|
||||||
{
|
|
||||||
found = 1;
|
|
||||||
for (i = 0; i < core_size; ++i)
|
|
||||||
if (core[i] != sp->items[i])
|
|
||||||
found = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
if (sp->link)
|
|
||||||
{
|
|
||||||
sp = sp->link;
|
|
||||||
}
|
|
||||||
else /* bucket exhausted and no match */
|
|
||||||
{
|
|
||||||
sp = sp->link = new_state (symbol, core_size, core);
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* bucket is empty */
|
|
||||||
{
|
|
||||||
state_hash[key] = sp = new_state (symbol, core_size, core);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trace_flag)
|
if (trace_flag)
|
||||||
fprintf (stderr, "Exiting get_state => %d\n", sp->number);
|
fprintf (stderr, "Exiting get_state => %d\n", sp->number);
|
||||||
@@ -386,6 +344,7 @@ set_states (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------.
|
/*-------------------------------------------------------------------.
|
||||||
| Compute the nondeterministic finite state machine (see state.h for |
|
| Compute the nondeterministic finite state machine (see state.h for |
|
||||||
| details) from the grammar. |
|
| details) from the grammar. |
|
||||||
|
|||||||
@@ -39,9 +39,6 @@
|
|||||||
#include "derives.h"
|
#include "derives.h"
|
||||||
#include "getargs.h"
|
#include "getargs.h"
|
||||||
|
|
||||||
/* All the decorated states, indexed by the state number. */
|
|
||||||
state_t **states = NULL;
|
|
||||||
|
|
||||||
rule_t **LArule = NULL;
|
rule_t **LArule = NULL;
|
||||||
bitsetv LA = NULL;
|
bitsetv LA = NULL;
|
||||||
size_t nLA;
|
size_t nLA;
|
||||||
|
|||||||
@@ -71,7 +71,4 @@ extern rule_t **LArule;
|
|||||||
extern bitsetv LA;
|
extern bitsetv LA;
|
||||||
|
|
||||||
|
|
||||||
/* All the states, indexed by the state number. */
|
|
||||||
extern state_t **states;
|
|
||||||
|
|
||||||
#endif /* !LALR_H_ */
|
#endif /* !LALR_H_ */
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ main (int argc, char *argv[])
|
|||||||
/* Output the tables and the parser to ftable. In file output. */
|
/* Output the tables and the parser to ftable. In file output. */
|
||||||
output ();
|
output ();
|
||||||
|
|
||||||
|
states_free ();
|
||||||
reduce_free ();
|
reduce_free ();
|
||||||
conflicts_free ();
|
conflicts_free ();
|
||||||
free_nullable ();
|
free_nullable ();
|
||||||
|
|||||||
11
src/output.c
11
src/output.c
@@ -1132,8 +1132,6 @@ output_check (void)
|
|||||||
static void
|
static void
|
||||||
output_actions (void)
|
output_actions (void)
|
||||||
{
|
{
|
||||||
state_number_t i;
|
|
||||||
|
|
||||||
/* That's a poor way to make sure the sizes are properly corelated,
|
/* That's a poor way to make sure the sizes are properly corelated,
|
||||||
in particular the signedness is not taking into account, but it's
|
in particular the signedness is not taking into account, but it's
|
||||||
not useless. */
|
not useless. */
|
||||||
@@ -1165,15 +1163,6 @@ output_actions (void)
|
|||||||
output_conflicts ();
|
output_conflicts ();
|
||||||
|
|
||||||
output_check ();
|
output_check ();
|
||||||
|
|
||||||
for (i = 0; i < nstates; ++i)
|
|
||||||
{
|
|
||||||
free (states[i]->shifts);
|
|
||||||
XFREE (states[i]->reductions);
|
|
||||||
free (states[i]->errs);
|
|
||||||
free (states[i]);
|
|
||||||
}
|
|
||||||
XFREE (states);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
131
src/state.c
131
src/state.c
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
#include "hash.h"
|
||||||
#include "complain.h"
|
#include "complain.h"
|
||||||
#include "gram.h"
|
#include "gram.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
@@ -30,9 +31,9 @@
|
|||||||
`-------------------*/
|
`-------------------*/
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------.
|
/*---------------------------------------.
|
||||||
| Create a new array of N shitfs. |
|
| Create a new array of N shifts/gotos. |
|
||||||
`---------------------------------*/
|
`---------------------------------------*/
|
||||||
|
|
||||||
#define SHIFTS_ALLOC(Nshifts) \
|
#define SHIFTS_ALLOC(Nshifts) \
|
||||||
(shifts *) xcalloc ((unsigned) (sizeof (shifts) \
|
(shifts *) xcalloc ((unsigned) (sizeof (shifts) \
|
||||||
@@ -116,6 +117,10 @@ state_number_t nstates = 0;
|
|||||||
accessing symbol: EOF. */
|
accessing symbol: EOF. */
|
||||||
state_t *final_state = NULL;
|
state_t *final_state = NULL;
|
||||||
|
|
||||||
|
#define STATE_ALLOC(Nitems) \
|
||||||
|
(state_t *) xcalloc ((unsigned) (sizeof (state_t) \
|
||||||
|
+ (Nitems - 1) * sizeof (item_number_t)), 1)
|
||||||
|
|
||||||
/*------------------------------------------------------------.
|
/*------------------------------------------------------------.
|
||||||
| Create a new state with ACCESSING_SYMBOL, for those items. |
|
| Create a new state with ACCESSING_SYMBOL, for those items. |
|
||||||
`------------------------------------------------------------*/
|
`------------------------------------------------------------*/
|
||||||
@@ -129,10 +134,6 @@ state_new (symbol_number_t accessing_symbol,
|
|||||||
if (nstates >= STATE_NUMBER_MAX)
|
if (nstates >= STATE_NUMBER_MAX)
|
||||||
fatal (_("too many states (max %d)"), STATE_NUMBER_MAX);
|
fatal (_("too many states (max %d)"), STATE_NUMBER_MAX);
|
||||||
|
|
||||||
#define STATE_ALLOC(Nitems) \
|
|
||||||
(state_t *) xcalloc ((unsigned) (sizeof (state_t) \
|
|
||||||
+ (Nitems - 1) * sizeof (item_number_t)), 1)
|
|
||||||
|
|
||||||
res = STATE_ALLOC (core_size);
|
res = STATE_ALLOC (core_size);
|
||||||
res->accessing_symbol = accessing_symbol;
|
res->accessing_symbol = accessing_symbol;
|
||||||
res->number = nstates;
|
res->number = nstates;
|
||||||
@@ -177,3 +178,119 @@ state_rule_lookaheads_print (state_t *state, rule_t *rule, FILE *out)
|
|||||||
fprintf (out, "]");
|
fprintf (out, "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------.
|
||||||
|
| A state hash table. |
|
||||||
|
`----------------------*/
|
||||||
|
|
||||||
|
/* Initial capacity of states hash table. */
|
||||||
|
#define HT_INITIAL_CAPACITY 257
|
||||||
|
|
||||||
|
static struct hash_table *state_table = NULL;
|
||||||
|
|
||||||
|
/* Two states are equal if they have the same core items. */
|
||||||
|
static bool
|
||||||
|
state_compare (const state_t *s1, const state_t *s2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (s1->nitems != s2->nitems)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < s1->nitems; ++i)
|
||||||
|
if (s1->items[i] != s2->items[i])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
state_hash (const state_t *state, unsigned int tablesize)
|
||||||
|
{
|
||||||
|
/* Add up the state's item numbers to get a hash key. */
|
||||||
|
int key = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < state->nitems; ++i)
|
||||||
|
key += state->items[i];
|
||||||
|
return key % tablesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------.
|
||||||
|
| Create the states hash table. |
|
||||||
|
`-------------------------------*/
|
||||||
|
|
||||||
|
void
|
||||||
|
state_hash_new (void)
|
||||||
|
{
|
||||||
|
state_table = hash_initialize (HT_INITIAL_CAPACITY,
|
||||||
|
NULL,
|
||||||
|
(Hash_hasher) state_hash,
|
||||||
|
(Hash_comparator) state_compare,
|
||||||
|
(Hash_data_freer) NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------.
|
||||||
|
| Free the states hash table, not the states. |
|
||||||
|
`---------------------------------------------*/
|
||||||
|
|
||||||
|
void
|
||||||
|
state_hash_free (void)
|
||||||
|
{
|
||||||
|
hash_free (state_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------.
|
||||||
|
| Insert STATE in the state hash table. |
|
||||||
|
`---------------------------------------*/
|
||||||
|
|
||||||
|
void
|
||||||
|
state_hash_insert (state_t *state)
|
||||||
|
{
|
||||||
|
hash_insert (state_table, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------.
|
||||||
|
| Find the state associated to the CORE, and return it. If it does |
|
||||||
|
| not exist yet, return NULL. |
|
||||||
|
`------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
state_t *
|
||||||
|
state_hash_lookup (size_t core_size, item_number_t *core)
|
||||||
|
{
|
||||||
|
state_t *probe = STATE_ALLOC (core_size);
|
||||||
|
state_t *entry;
|
||||||
|
|
||||||
|
probe->nitems = core_size;
|
||||||
|
memcpy (probe->items, core, core_size * sizeof (core[0]));
|
||||||
|
entry = hash_lookup (state_table, probe);
|
||||||
|
free (probe);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All the decorated states, indexed by the state number. */
|
||||||
|
state_t **states = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------.
|
||||||
|
| Free all the states. |
|
||||||
|
`----------------------*/
|
||||||
|
|
||||||
|
void
|
||||||
|
states_free (void)
|
||||||
|
{
|
||||||
|
state_number_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < nstates; ++i)
|
||||||
|
{
|
||||||
|
free (states[i]->shifts);
|
||||||
|
XFREE (states[i]->reductions);
|
||||||
|
free (states[i]->errs);
|
||||||
|
free (states[i]);
|
||||||
|
}
|
||||||
|
XFREE (states);
|
||||||
|
}
|
||||||
|
|||||||
21
src/state.h
21
src/state.h
@@ -44,10 +44,6 @@
|
|||||||
Each core contains a vector of NITEMS items which are the indices
|
Each core contains a vector of NITEMS items which are the indices
|
||||||
in the RITEMS vector of the items that are selected in this state.
|
in the RITEMS vector of the items that are selected in this state.
|
||||||
|
|
||||||
The link field is used for chaining symbols that hash states by
|
|
||||||
their itemsets. This is for recognizing equivalent states and
|
|
||||||
combining them when the states are generated.
|
|
||||||
|
|
||||||
The two types of transitions are shifts (push the lookahead token
|
The two types of transitions are shifts (push the lookahead token
|
||||||
and read another) and reductions (combine the last n things on the
|
and read another) and reductions (combine the last n things on the
|
||||||
stack via a rule, replace them with the symbol that the rule
|
stack via a rule, replace them with the symbol that the rule
|
||||||
@@ -180,7 +176,6 @@ reductions *reductions_new PARAMS ((int n));
|
|||||||
typedef struct state_s
|
typedef struct state_s
|
||||||
{
|
{
|
||||||
struct state_s *next;
|
struct state_s *next;
|
||||||
struct state_s *link;
|
|
||||||
|
|
||||||
state_number_t number;
|
state_number_t number;
|
||||||
symbol_number_t accessing_symbol;
|
symbol_number_t accessing_symbol;
|
||||||
@@ -220,4 +215,20 @@ state_t *state_new PARAMS ((symbol_number_t accessing_symbol,
|
|||||||
void state_rule_lookaheads_print PARAMS ((state_t *state, rule_t *rule,
|
void state_rule_lookaheads_print PARAMS ((state_t *state, rule_t *rule,
|
||||||
FILE *out));
|
FILE *out));
|
||||||
|
|
||||||
|
/* Create/destroy the states hash table. */
|
||||||
|
void state_hash_new PARAMS ((void));
|
||||||
|
void state_hash_free PARAMS ((void));
|
||||||
|
|
||||||
|
/* Find the state associated to the CORE, and return it. If it does
|
||||||
|
not exist yet, return NULL. */
|
||||||
|
state_t *state_hash_lookup PARAMS ((size_t core_size, item_number_t *core));
|
||||||
|
|
||||||
|
/* Insert STATE in the state hash table. */
|
||||||
|
void state_hash_insert PARAMS ((state_t *state));
|
||||||
|
|
||||||
|
/* All the states, indexed by the state number. */
|
||||||
|
extern state_t **states;
|
||||||
|
|
||||||
|
/* Free all the states. */
|
||||||
|
void states_free PARAMS ((void));
|
||||||
#endif /* !STATE_H_ */
|
#endif /* !STATE_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user