196 |
last_state = p; |
last_state = p; |
197 |
nstates++; |
nstates++; |
198 |
|
|
199 |
|
/* If this is the eoftoken, then this is the final state. */ |
200 |
|
if (symbol == 0) |
201 |
|
final_state = p->number; |
202 |
|
|
203 |
return p; |
return p; |
204 |
} |
} |
205 |
|
|
325 |
} |
} |
326 |
|
|
327 |
|
|
|
/*------------------------------------------------------------------. |
|
|
| Subroutine of augment_automaton. Create the next-to-final state, | |
|
|
| to which a shift has already been made in the initial state. | |
|
|
| | |
|
|
| The task of this state consists in shifting (actually, it's a | |
|
|
| goto, but shifts and gotos are both stored in SHIFTS) the start | |
|
|
| symbols, hence the name. | |
|
|
`------------------------------------------------------------------*/ |
|
|
|
|
|
static void |
|
|
insert_start_shifting_state (void) |
|
|
{ |
|
|
state_t *statep; |
|
|
shifts *sp; |
|
|
|
|
|
statep = STATE_ALLOC (0); |
|
|
statep->number = nstates++; |
|
|
|
|
|
/* The distinctive feature of this state from the |
|
|
eof_shifting_state, is that it is labeled as post-start-symbol |
|
|
shifting. I fail to understand why this state, and the |
|
|
post-start-start can't be merged into one. But it does fail if |
|
|
you try. --akim */ |
|
|
statep->accessing_symbol = start_symbol; |
|
|
|
|
|
last_state->next = statep; |
|
|
last_state = statep; |
|
|
|
|
|
/* Make a shift from this state to (what will be) the final state. */ |
|
|
sp = shifts_new (1); |
|
|
statep->shifts = sp; |
|
|
sp->shifts[0] = nstates; |
|
|
} |
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------. |
|
|
| Subroutine of augment_automaton. Create the final state, which | |
|
|
| shifts `0', the end of file. The initial state shifts the start | |
|
|
| symbol, and goes to here. | |
|
|
`-----------------------------------------------------------------*/ |
|
|
|
|
|
static void |
|
|
insert_eof_shifting_state (void) |
|
|
{ |
|
|
state_t *statep; |
|
|
shifts *sp; |
|
|
|
|
|
/* Make the final state--the one that follows a shift from the |
|
|
next-to-final state. |
|
|
The symbol for that shift is 0 (end-of-file). */ |
|
|
statep = STATE_ALLOC (0); |
|
|
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); |
|
|
statep->shifts = sp; |
|
|
sp->shifts[0] = nstates; |
|
|
} |
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------. |
|
|
| Subroutine of augment_automaton. Create the accepting state. | |
|
|
`---------------------------------------------------------------*/ |
|
|
|
|
|
static void |
|
|
insert_accepting_state (void) |
|
|
{ |
|
|
state_t *statep; |
|
|
|
|
|
/* Note that the variable `final_state' refers to what we sometimes |
|
|
call the termination state. */ |
|
|
final_state = nstates; |
|
|
|
|
|
/* Make the termination state. */ |
|
|
statep = STATE_ALLOC (0); |
|
|
statep->number = nstates++; |
|
|
last_state->next = statep; |
|
|
last_state = statep; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------. |
|
|
| Make sure that the initial state has a shift that accepts the | |
|
|
| grammar's start symbol and goes to the next-to-final state, which | |
|
|
| has a shift going to the final state, which has a shift to the | |
|
|
| termination state. Create such states and shifts if they don't | |
|
|
| happen to exist already. | |
|
|
`------------------------------------------------------------------*/ |
|
|
|
|
|
static void |
|
|
augment_automaton (void) |
|
|
{ |
|
|
if (!first_state->shifts->nshifts) |
|
|
{ |
|
|
/* 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; |
|
|
|
|
|
/* Create the next-to-final state, with shift to |
|
|
what will be the final state. */ |
|
|
insert_start_shifting_state (); |
|
|
} |
|
|
else |
|
|
{ |
|
|
state_t *statep = first_state->next; |
|
|
/* The states reached by shifts from FIRST_STATE are numbered |
|
|
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 < first_state->shifts->nshifts) |
|
|
statep = statep->next; |
|
|
|
|
|
if (statep->accessing_symbol == start_symbol) |
|
|
{ |
|
|
/* 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; |
|
|
|
|
|
/* 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 *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) |
|
|
sp1->shifts[k++] = nstates; |
|
|
sp1->shifts[k] = sp->shifts[i]; |
|
|
statep = statep->next; |
|
|
} |
|
|
if (i == k) |
|
|
sp1->shifts[k++] = nstates; |
|
|
|
|
|
XFREE (sp); |
|
|
|
|
|
/* Create the next-to-final state, with shift to what will |
|
|
be the final state. Corresponds to `start: start . ...'. */ |
|
|
insert_start_shifting_state (); |
|
|
} |
|
|
} |
|
|
|
|
|
insert_accepting_state (); |
|
|
} |
|
|
|
|
|
|
|
328 |
/*----------------------------------------------------------------. |
/*----------------------------------------------------------------. |
329 |
| Find which rules can be used for reduction transitions from the | |
| Find which rules can be used for reduction transitions from the | |
330 |
| current state and make a reductions structure for the state to | |
| current state and make a reductions structure for the state to | |
334 |
static void |
static void |
335 |
save_reductions (void) |
save_reductions (void) |
336 |
{ |
{ |
337 |
int count; |
int count = 0; |
338 |
int i; |
int i; |
339 |
|
|
340 |
/* Find and count the active items that represent ends of rules. */ |
/* If this is the final state, we want it to have no reductions at |
341 |
|
all, although it has one for `START_SYMBOL EOF .'. */ |
342 |
|
if (this_state->number == final_state) |
343 |
|
return; |
344 |
|
|
345 |
count = 0; |
/* Find and count the active items that represent ends of rules. */ |
346 |
for (i = 0; i < nitemset; ++i) |
for (i = 0; i < nitemset; ++i) |
347 |
{ |
{ |
348 |
int item = ritem[itemset[i]]; |
int item = ritem[itemset[i]]; |
423 |
free_closure (); |
free_closure (); |
424 |
free_storage (); |
free_storage (); |
425 |
|
|
|
/* set up initial and final states as parser wants them */ |
|
|
augment_automaton (); |
|
|
|
|
426 |
/* Set up STATE_TABLE. */ |
/* Set up STATE_TABLE. */ |
427 |
set_state_table (); |
set_state_table (); |
428 |
} |
} |