X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/0ab3728b128584655dec71591b8e5ba0093baece..4ec8e00f609b4a44c3c9e5a25c82706b393a0e16:/src/LR0.c diff --git a/src/LR0.c b/src/LR0.c index 7770ecbc..5e8caef0 100644 --- a/src/LR0.c +++ b/src/LR0.c @@ -35,12 +35,10 @@ int nstates; int final_state; -state_t *first_state = NULL; -shifts *first_shift = NULL; +static state_t *first_state = NULL; static state_t *this_state = NULL; static state_t *last_state = NULL; -static shifts *last_shift = NULL; static int nshifts; static short *shift_symbol = NULL; @@ -318,16 +316,8 @@ static void save_shifts (void) { shifts *p = shifts_new (nshifts); - - p->number = this_state->number; - shortcpy (p->shifts, shiftset, nshifts); - - if (last_shift) - last_shift->next = p; - else - first_shift = p; - last_shift = p; + this_state->shifts = p; } @@ -347,7 +337,7 @@ insert_start_shifting_state (void) shifts *sp; statep = STATE_ALLOC (0); - statep->number = nstates; + statep->number = nstates++; /* The distinctive feature of this state from the eof_shifting_state, is that it is labeled as post-start-symbol @@ -361,11 +351,8 @@ insert_start_shifting_state (void) /* Make a shift from this state to (what will be) the final state. */ sp = shifts_new (1); - sp->number = nstates++; + statep->shifts = sp; sp->shifts[0] = nstates; - - last_shift->next = sp; - last_shift = sp; } @@ -385,18 +372,15 @@ insert_eof_shifting_state (void) next-to-final state. The symbol for that shift is 0 (end-of-file). */ statep = STATE_ALLOC (0); - statep->number = nstates; + statep->number = nstates++; last_state->next = statep; last_state = statep; /* Make the shift from the final state to the termination state. */ sp = shifts_new (1); - sp->number = nstates++; + statep->shifts = sp; sp->shifts[0] = nstates; - - last_shift->next = sp; - last_shift = sp; } @@ -435,127 +419,82 @@ insert_accepting_state (void) static void augment_automaton (void) { - if (!first_shift->nshifts) + if (!first_state->shifts->nshifts) { - /* There are no shifts for any state. Make one shift, from the + /* The first state has no shifts. Make one shift, from the initial state to the next-to-final state. */ shifts *sp = shifts_new (1); + first_state->shifts = sp; sp->shifts[0] = nstates; - /* Initialize the chain of shifts with sp. */ - first_shift = sp; - last_shift = sp; - /* Create the next-to-final state, with shift to what will be the final state. */ insert_start_shifting_state (); } - else if (first_shift->number == 0) + else { state_t *statep = first_state->next; - shifts *sp = first_shift; - shifts *sp1 = NULL; /* The states reached by shifts from FIRST_STATE are numbered - 1..(SP->NSHIFTS). Look for one reached by START_SYMBOL. */ + 1..(SP->NSHIFTS). Look for one reached by START_SYMBOL. + This is typical of `start: start ... ;': there is a state + with the item `start: start . ...'. We want to add a `shift + on EOF to eof-shifting state here. */ while (statep->accessing_symbol != start_symbol - && statep->number < sp->nshifts) + && statep->number < first_state->shifts->nshifts) statep = statep->next; if (statep->accessing_symbol == start_symbol) { - /* We already have a next-to-final state. - Make sure it has a shift to what will be the final state. */ - while (sp && sp->number < statep->number) - { - sp1 = sp; - sp = sp->next; - } + /* We already have STATEP, a next-to-final state for `start: + start . ...'. Make sure it has a shift to what will be + the final state. */ + int i; - if (sp && sp->number == statep->number) - { - int i; - shifts *sp2 = shifts_new (sp->nshifts + 1); - sp2->number = statep->number; - sp2->shifts[0] = nstates; - for (i = sp->nshifts; i > 0; i--) - sp2->shifts[i] = sp->shifts[i - 1]; - - /* Patch sp2 into the chain of shifts in place of sp, - following sp1. */ - sp2->next = sp->next; - sp1->next = sp2; - if (sp == last_shift) - last_shift = sp2; - XFREE (sp); - } - else - { - shifts *sp2 = shifts_new (1); - sp2->number = statep->number; - sp2->shifts[0] = nstates; - - /* Patch sp2 into the chain of shifts between sp1 and sp. */ - sp2->next = sp; - sp1->next = sp2; - if (sp == 0) - last_shift = sp2; - } + /* Find the shift of the inital state that leads to STATEP. */ + shifts *sp = statep->shifts; + + shifts *sp1 = shifts_new (sp->nshifts + 1); + statep->shifts = sp1; + sp1->shifts[0] = nstates; + for (i = sp->nshifts; i > 0; i--) + sp1->shifts[i] = sp->shifts[i - 1]; + + XFREE (sp); + + insert_eof_shifting_state (); } else { + /* There is no state for `start: start . ...'. */ int i, k; - shifts *sp2; - sp = first_shift; - - /* There is no next-to-final state as yet. */ - /* Add one more shift in first_shift, - going to the next-to-final state (yet to be made). */ - sp2 = shifts_new (sp->nshifts + 1); + shifts *sp = first_state->shifts; + shifts *sp1 = NULL; + /* Add one more shift to the initial state, going to the + next-to-final state (yet to be made). */ + sp1 = shifts_new (sp->nshifts + 1); + first_state->shifts = sp1; /* Stick this shift into the vector at the proper place. */ statep = first_state->next; for (k = 0, i = 0; i < sp->nshifts; k++, i++) { if (statep->accessing_symbol > start_symbol && i == k) - sp2->shifts[k++] = nstates; - sp2->shifts[k] = sp->shifts[i]; + sp1->shifts[k++] = nstates; + sp1->shifts[k] = sp->shifts[i]; statep = statep->next; } if (i == k) - sp2->shifts[k++] = nstates; - - /* Patch sp2 into the chain of shifts - in place of sp, at the beginning. */ - sp2->next = sp->next; - first_shift = sp2; - if (last_shift == sp) - last_shift = sp2; + sp1->shifts[k++] = nstates; XFREE (sp); - /* Create the next-to-final state, with shift to - what will be the final state. */ + /* Create the next-to-final state, with shift to what will + be the final state. Corresponds to `start: start . ...'. */ insert_start_shifting_state (); } } - else - { - /* The initial state didn't even have any shifts. - Give it one shift, to the next-to-final state. */ - shifts *sp = shifts_new (1); - sp->shifts[0] = nstates; - - /* Patch sp into the chain of shifts at the beginning. */ - sp->next = first_shift; - first_shift = sp; - - /* Create the next-to-final state, with shift to - what will be the final state. */ - insert_start_shifting_state (); - } - insert_eof_shifting_state (); insert_accepting_state (); } @@ -595,6 +534,34 @@ save_reductions (void) } +/*--------------------. +| Build STATE_TABLE. | +`--------------------*/ + +static void +set_state_table (void) +{ + /* NSTATES + 1 because lookahead for the pseudo state number NSTATES + might be used (see conflicts.c). It is too opaque for me to + provide a probably less hacky implementation. --akim */ + state_table = XCALLOC (state_t *, nstates + 1); + + { + state_t *sp; + for (sp = first_state; sp; sp = sp->next) + state_table[sp->number] = sp; + } + + /* Pessimization, but simplification of the code: make sure all the + states have a shifts, even if reduced to 0 shifts. */ + { + int i; + for (i = 0; i < nstates; i++) + if (!state_table[i]->shifts) + state_table[i]->shifts = shifts_new (0); + } +} + /*-------------------------------------------------------------------. | Compute the nondeterministic finite state machine (see state.h for | | details) from the grammar. | @@ -638,4 +605,7 @@ generate_states (void) /* set up initial and final states as parser wants them */ augment_automaton (); + + /* Set up STATE_TABLE. */ + set_state_table (); }