]>
git.saurik.com Git - bison.git/blob - src/LR0.c
1 /* Generate the nondeterministic finite state machine for bison,
2 Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
4 This file is part of Bison, the GNU Compiler Compiler.
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 /* See comments in state.h for the data structures that represent it.
23 The entry point is generate_states. */
32 extern char *nullable
;
33 extern short *itemset
;
34 extern short *itemsetend
;
41 reductions
*first_reduction
;
43 extern void generate_states
PARAMS((void));
45 static int get_state
PARAMS((int));
46 static core
*new_state
PARAMS((int));
47 static void allocate_itemsets
PARAMS((void));
48 static void allocate_storage
PARAMS((void));
49 static void free_storage
PARAMS((void));
50 static void new_itemsets
PARAMS((void));
51 static void append_states
PARAMS((void));
52 static void initialize_states
PARAMS((void));
53 static void save_shifts
PARAMS((void));
54 static void save_reductions
PARAMS((void));
55 static void augment_automaton
PARAMS((void));
56 static void insert_start_shift
PARAMS((void));
57 extern void initialize_closure
PARAMS((int));
58 extern void closure
PARAMS((short *, int));
59 extern void finalize_closure
PARAMS((void));
61 static core
*this_state
;
62 static core
*last_state
;
63 static shifts
*last_shift
;
64 static reductions
*last_reduction
;
67 static short *shift_symbol
;
70 static short *shiftset
;
72 static short **kernel_base
;
73 static short **kernel_end
;
74 static short *kernel_items
;
76 /* hash table for states, to recognize equivalent ones. */
78 #define STATE_TABLE_SIZE 1009
79 static core
**state_table
;
84 allocate_itemsets (void)
86 register short *itemp
;
90 register short *symbol_count
;
93 symbol_count
= NEW2(nsyms
, short);
102 symbol_count
[symbol
]++;
107 /* see comments before new_itemsets. All the vectors of items
108 live inside kernel_items. The number of active items after
109 some symbol cannot be more than the number of times that symbol
110 appears as an item, which is symbol_count[symbol].
111 We allocate that much space for each symbol. */
113 kernel_base
= NEW2(nsyms
, short *);
114 kernel_items
= NEW2(count
, short);
117 for (i
= 0; i
< nsyms
; i
++)
119 kernel_base
[i
] = kernel_items
+ count
;
120 count
+= symbol_count
[i
];
123 shift_symbol
= symbol_count
;
124 kernel_end
= NEW2(nsyms
, short *);
129 allocate_storage (void)
133 shiftset
= NEW2(nsyms
, short);
134 redset
= NEW2(nrules
+ 1, short);
135 state_table
= NEW2(STATE_TABLE_SIZE
, core
*);
153 /* compute the nondeterministic finite state machine (see state.h for details)
156 generate_states (void)
159 initialize_closure(nitems
);
164 /* Set up ruleset and itemset for the transitions out of this state.
165 ruleset gets a 1 bit for each rule that could reduce now.
166 itemset gets a vector of all the items that could be accepted next. */
167 closure(this_state
->items
, this_state
->nitems
);
168 /* record the reductions allowed out of this state */
170 /* find the itemsets of the states that shifts can reach */
172 /* find or create the core structures for those states */
175 /* create the shifts structures for the shifts to those states,
176 now that the state numbers transitioning to are known */
180 /* states are queued when they are created; process them all */
181 this_state
= this_state
->next
;
184 /* discard various storage */
188 /* set up initial and final states as parser wants them */
194 /* Find which symbols can be shifted in the current state,
195 and for each one record which items would be active after that shift.
196 Uses the contents of itemset.
197 shift_symbol is set to a vector of the symbols that can be shifted.
198 For each symbol in the grammar, kernel_base[symbol] points to
199 a vector of item numbers activated if that symbol is shifted,
200 and kernel_end[symbol] points after the end of that vector. */
205 register int shiftcount
;
211 fprintf(stderr
, "Entering new_itemsets\n");
214 for (i
= 0; i
< nsyms
; i
++)
215 kernel_end
[i
] = NULL
;
221 while (isp
< itemsetend
)
227 ksp
= kernel_end
[symbol
];
231 shift_symbol
[shiftcount
++] = symbol
;
232 ksp
= kernel_base
[symbol
];
236 kernel_end
[symbol
] = ksp
;
240 nshifts
= shiftcount
;
245 /* Use the information computed by new_itemsets to find the state numbers
246 reached by each shift transition from the current state.
248 shiftset is set up as a vector of state numbers of those states. */
257 fprintf(stderr
, "Entering append_states\n");
260 /* first sort shift_symbol into increasing order */
262 for (i
= 1; i
< nshifts
; i
++)
264 symbol
= shift_symbol
[i
];
266 while (j
> 0 && shift_symbol
[j
- 1] > symbol
)
268 shift_symbol
[j
] = shift_symbol
[j
- 1];
271 shift_symbol
[j
] = symbol
;
274 for (i
= 0; i
< nshifts
; i
++)
276 symbol
= shift_symbol
[i
];
277 shiftset
[i
] = get_state(symbol
);
283 /* find the state number for the state we would get to
284 (from the current state) by shifting symbol.
285 Create a new state if no equivalent one exists already.
286 Used by append_states */
289 get_state (int symbol
)
292 register short *isp1
;
293 register short *isp2
;
294 register short *iend
;
301 fprintf(stderr
, "Entering get_state, symbol = %d\n", symbol
);
304 isp1
= kernel_base
[symbol
];
305 iend
= kernel_end
[symbol
];
308 /* add up the target state's active item numbers to get a hash key */
313 key
= key
% STATE_TABLE_SIZE
;
315 sp
= state_table
[key
];
325 isp1
= kernel_base
[symbol
];
328 while (found
&& isp1
< iend
)
330 if (*isp1
++ != *isp2
++)
341 else /* bucket exhausted and no match */
343 sp
= sp
->link
= new_state(symbol
);
349 else /* bucket is empty */
351 state_table
[key
] = sp
= new_state(symbol
);
359 /* subroutine of get_state. create a new state for those items, if necessary. */
362 new_state (int symbol
)
366 register short *isp1
;
367 register short *isp2
;
368 register short *iend
;
371 fprintf(stderr
, "Entering new_state, symbol = %d\n", symbol
);
374 if (nstates
>= MAXSHORT
)
375 fatal (_("too many states (max %d)"), MAXSHORT
);
377 isp1
= kernel_base
[symbol
];
378 iend
= kernel_end
[symbol
];
381 p
= (core
*) xmalloc((unsigned) (sizeof(core
) + (n
- 1) * sizeof(short)));
382 p
->accessing_symbol
= symbol
;
390 last_state
->next
= p
;
400 initialize_states (void)
403 /* register unsigned *rp1; JF unused */
404 /* register unsigned *rp2; JF unused */
405 /* register unsigned *rend; JF unused */
407 p
= (core
*) xmalloc((unsigned) (sizeof(core
) - sizeof(short)));
408 first_state
= last_state
= this_state
= p
;
419 register short *send
;
421 p
= (shifts
*) xmalloc((unsigned) (sizeof(shifts
) +
422 (nshifts
- 1) * sizeof(short)));
424 p
->number
= this_state
->number
;
425 p
->nshifts
= nshifts
;
429 send
= shiftset
+ nshifts
;
436 last_shift
->next
= p
;
448 /* find which rules can be used for reduction transitions from the current state
449 and make a reductions structure for the state to record their rule numbers. */
451 save_reductions (void)
458 register reductions
*p
;
462 /* find and count the active items that represent ends of rules */
465 for (isp
= itemset
; isp
< itemsetend
; isp
++)
470 redset
[count
++] = -item
;
474 /* make a reductions structure and copy the data into it. */
478 p
= (reductions
*) xmalloc((unsigned) (sizeof(reductions
) +
479 (count
- 1) * sizeof(short)));
481 p
->number
= this_state
->number
;
493 last_reduction
->next
= p
;
506 /* Make sure that the initial state has a shift that accepts the
507 grammar's start symbol and goes to the next-to-final state,
508 which has a shift going to the final state, which has a shift
509 to the termination state.
510 Create such states and shifts if they don't happen to exist already. */
512 augment_automaton (void)
516 /* register int found; JF unused */
517 register core
*statep
;
519 register shifts
*sp2
;
520 register shifts
*sp1
= NULL
;
529 statep
= first_state
->next
;
531 /* The states reached by shifts from first_state are numbered 1...K.
532 Look for one reached by start_symbol. */
533 while (statep
->accessing_symbol
< start_symbol
534 && statep
->number
< k
)
535 statep
= statep
->next
;
537 if (statep
->accessing_symbol
== start_symbol
)
539 /* We already have a next-to-final state.
540 Make sure it has a shift to what will be the final state. */
543 while (sp
&& sp
->number
< k
)
549 if (sp
&& sp
->number
== k
)
551 sp2
= (shifts
*) xmalloc((unsigned) (sizeof(shifts
)
552 + sp
->nshifts
* sizeof(short)));
554 sp2
->nshifts
= sp
->nshifts
+ 1;
555 sp2
->shifts
[0] = nstates
;
556 for (i
= sp
->nshifts
; i
> 0; i
--)
557 sp2
->shifts
[i
] = sp
->shifts
[i
- 1];
559 /* Patch sp2 into the chain of shifts in place of sp,
561 sp2
->next
= sp
->next
;
563 if (sp
== last_shift
)
572 sp2
->shifts
[0] = nstates
;
574 /* Patch sp2 into the chain of shifts between sp1 and sp. */
583 /* There is no next-to-final state as yet. */
584 /* Add one more shift in first_shift,
585 going to the next-to-final state (yet to be made). */
588 sp2
= (shifts
*) xmalloc(sizeof(shifts
)
589 + sp
->nshifts
* sizeof(short));
590 sp2
->nshifts
= sp
->nshifts
+ 1;
592 /* Stick this shift into the vector at the proper place. */
593 statep
= first_state
->next
;
594 for (k
= 0, i
= 0; i
< sp
->nshifts
; k
++, i
++)
596 if (statep
->accessing_symbol
> start_symbol
&& i
== k
)
597 sp2
->shifts
[k
++] = nstates
;
598 sp2
->shifts
[k
] = sp
->shifts
[i
];
599 statep
= statep
->next
;
602 sp2
->shifts
[k
++] = nstates
;
604 /* Patch sp2 into the chain of shifts
605 in place of sp, at the beginning. */
606 sp2
->next
= sp
->next
;
608 if (last_shift
== sp
)
613 /* Create the next-to-final state, with shift to
614 what will be the final state. */
615 insert_start_shift();
620 /* The initial state didn't even have any shifts.
621 Give it one shift, to the next-to-final state. */
624 sp
->shifts
[0] = nstates
;
626 /* Patch sp into the chain of shifts at the beginning. */
627 sp
->next
= first_shift
;
630 /* Create the next-to-final state, with shift to
631 what will be the final state. */
632 insert_start_shift();
637 /* There are no shifts for any state.
638 Make one shift, from the initial state to the next-to-final state. */
642 sp
->shifts
[0] = nstates
;
644 /* Initialize the chain of shifts with sp. */
648 /* Create the next-to-final state, with shift to
649 what will be the final state. */
650 insert_start_shift();
653 /* Make the final state--the one that follows a shift from the
655 The symbol for that shift is 0 (end-of-file). */
656 statep
= (core
*) xmalloc((unsigned) (sizeof(core
) - sizeof(short)));
657 statep
->number
= nstates
;
658 last_state
->next
= statep
;
661 /* Make the shift from the final state to the termination state. */
663 sp
->number
= nstates
++;
665 sp
->shifts
[0] = nstates
;
666 last_shift
->next
= sp
;
669 /* Note that the variable `final_state' refers to what we sometimes call
670 the termination state. */
671 final_state
= nstates
;
673 /* Make the termination state. */
674 statep
= (core
*) xmalloc((unsigned) (sizeof(core
) - sizeof(short)));
675 statep
->number
= nstates
++;
676 last_state
->next
= statep
;
681 /* subroutine of augment_automaton.
682 Create the next-to-final state, to which a shift has already been made in
683 the initial state. */
685 insert_start_shift (void)
687 register core
*statep
;
690 statep
= (core
*) xmalloc((unsigned) (sizeof(core
) - sizeof(short)));
691 statep
->number
= nstates
;
692 statep
->accessing_symbol
= start_symbol
;
694 last_state
->next
= statep
;
697 /* Make a shift from this state to (what will be) the final state. */
699 sp
->number
= nstates
++;
701 sp
->shifts
[0] = nstates
;
703 last_shift
->next
= sp
;