]> git.saurik.com Git - bison.git/blame - src/LR0.c
Don't define PACKAGE here, since config.h defines it.
[bison.git] / src / LR0.c
CommitLineData
40675e7c
DM
1/* Generate the nondeterministic finite state machine for bison,
2 Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
3
4This file is part of Bison, the GNU Compiler Compiler.
5
6Bison is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11Bison is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Bison; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21/* See comments in state.h for the data structures that represent it.
22 The entry point is generate_states. */
23
24#include <stdio.h>
25#include "system.h"
26#include "machine.h"
7612000c 27#include "alloc.h"
40675e7c
DM
28#include "gram.h"
29#include "state.h"
30
31
32extern char *nullable;
33extern short *itemset;
34extern short *itemsetend;
35
36
37int nstates;
38int final_state;
39core *first_state;
40shifts *first_shift;
41reductions *first_reduction;
42
d2729d44
JT
43int get_state PARAMS((int));
44core *new_state PARAMS((int));
45
46void allocate_itemsets PARAMS((void));
47void allocate_storage PARAMS((void));
48void free_storage PARAMS((void));
49void generate_states PARAMS((void));
50void new_itemsets PARAMS((void));
51void append_states PARAMS((void));
52void initialize_states PARAMS((void));
53void save_shifts PARAMS((void));
54void save_reductions PARAMS((void));
55void augment_automaton PARAMS((void));
56void insert_start_shift PARAMS((void));
57extern void initialize_closure PARAMS((int));
58extern void closure PARAMS((short *, int));
59extern void finalize_closure PARAMS((void));
60extern void toomany PARAMS((char *));
40675e7c
DM
61
62static core *this_state;
63static core *last_state;
64static shifts *last_shift;
65static reductions *last_reduction;
66
67static int nshifts;
68static short *shift_symbol;
69
70static short *redset;
71static short *shiftset;
72
73static short **kernel_base;
74static short **kernel_end;
75static short *kernel_items;
76
77/* hash table for states, to recognize equivalent ones. */
78
79#define STATE_TABLE_SIZE 1009
80static core **state_table;
81
82
83
84void
d2729d44 85allocate_itemsets (void)
40675e7c
DM
86{
87 register short *itemp;
88 register int symbol;
89 register int i;
90 register int count;
91 register short *symbol_count;
92
93 count = 0;
94 symbol_count = NEW2(nsyms, short);
95
96 itemp = ritem;
97 symbol = *itemp++;
98 while (symbol)
99 {
100 if (symbol > 0)
101 {
102 count++;
103 symbol_count[symbol]++;
104 }
105 symbol = *itemp++;
106 }
107
108 /* see comments before new_itemsets. All the vectors of items
109 live inside kernel_items. The number of active items after
110 some symbol cannot be more than the number of times that symbol
111 appears as an item, which is symbol_count[symbol].
112 We allocate that much space for each symbol. */
113
114 kernel_base = NEW2(nsyms, short *);
115 kernel_items = NEW2(count, short);
116
117 count = 0;
118 for (i = 0; i < nsyms; i++)
119 {
120 kernel_base[i] = kernel_items + count;
121 count += symbol_count[i];
122 }
123
124 shift_symbol = symbol_count;
125 kernel_end = NEW2(nsyms, short *);
126}
127
128
129void
d2729d44 130allocate_storage (void)
40675e7c
DM
131{
132 allocate_itemsets();
133
134 shiftset = NEW2(nsyms, short);
135 redset = NEW2(nrules + 1, short);
136 state_table = NEW2(STATE_TABLE_SIZE, core *);
137}
138
139
140void
d2729d44 141free_storage (void)
40675e7c
DM
142{
143 FREE(shift_symbol);
144 FREE(redset);
145 FREE(shiftset);
146 FREE(kernel_base);
147 FREE(kernel_end);
148 FREE(kernel_items);
149 FREE(state_table);
150}
151
152
153
154/* compute the nondeterministic finite state machine (see state.h for details)
155from the grammar. */
156void
d2729d44 157generate_states (void)
40675e7c
DM
158{
159 allocate_storage();
160 initialize_closure(nitems);
161 initialize_states();
162
163 while (this_state)
164 {
165 /* Set up ruleset and itemset for the transitions out of this state.
166 ruleset gets a 1 bit for each rule that could reduce now.
167 itemset gets a vector of all the items that could be accepted next. */
168 closure(this_state->items, this_state->nitems);
169 /* record the reductions allowed out of this state */
170 save_reductions();
171 /* find the itemsets of the states that shifts can reach */
172 new_itemsets();
173 /* find or create the core structures for those states */
174 append_states();
175
176 /* create the shifts structures for the shifts to those states,
177 now that the state numbers transitioning to are known */
178 if (nshifts > 0)
179 save_shifts();
180
181 /* states are queued when they are created; process them all */
182 this_state = this_state->next;
183 }
184
185 /* discard various storage */
186 finalize_closure();
187 free_storage();
188
189 /* set up initial and final states as parser wants them */
190 augment_automaton();
191}
192
193
194
195/* Find which symbols can be shifted in the current state,
196 and for each one record which items would be active after that shift.
197 Uses the contents of itemset.
198 shift_symbol is set to a vector of the symbols that can be shifted.
199 For each symbol in the grammar, kernel_base[symbol] points to
200 a vector of item numbers activated if that symbol is shifted,
201 and kernel_end[symbol] points after the end of that vector. */
202void
d2729d44 203new_itemsets (void)
40675e7c
DM
204{
205 register int i;
206 register int shiftcount;
207 register short *isp;
208 register short *ksp;
209 register int symbol;
210
211#ifdef TRACE
212 fprintf(stderr, "Entering new_itemsets\n");
213#endif
214
215 for (i = 0; i < nsyms; i++)
216 kernel_end[i] = NULL;
217
218 shiftcount = 0;
219
220 isp = itemset;
221
222 while (isp < itemsetend)
223 {
224 i = *isp++;
225 symbol = ritem[i];
226 if (symbol > 0)
227 {
228 ksp = kernel_end[symbol];
229
230 if (!ksp)
231 {
232 shift_symbol[shiftcount++] = symbol;
233 ksp = kernel_base[symbol];
234 }
235
236 *ksp++ = i + 1;
237 kernel_end[symbol] = ksp;
238 }
239 }
240
241 nshifts = shiftcount;
242}
243
244
245
246/* Use the information computed by new_itemsets to find the state numbers
247 reached by each shift transition from the current state.
248
249 shiftset is set up as a vector of state numbers of those states. */
250void
d2729d44 251append_states (void)
40675e7c
DM
252{
253 register int i;
254 register int j;
255 register int symbol;
256
257#ifdef TRACE
258 fprintf(stderr, "Entering append_states\n");
259#endif
260
261 /* first sort shift_symbol into increasing order */
262
263 for (i = 1; i < nshifts; i++)
264 {
265 symbol = shift_symbol[i];
266 j = i;
267 while (j > 0 && shift_symbol[j - 1] > symbol)
268 {
269 shift_symbol[j] = shift_symbol[j - 1];
270 j--;
271 }
272 shift_symbol[j] = symbol;
273 }
274
275 for (i = 0; i < nshifts; i++)
276 {
277 symbol = shift_symbol[i];
278 shiftset[i] = get_state(symbol);
279 }
280}
281
282
283
284/* find the state number for the state we would get to
285(from the current state) by shifting symbol.
286Create a new state if no equivalent one exists already.
287Used by append_states */
288
289int
d2729d44 290get_state (int symbol)
40675e7c
DM
291{
292 register int key;
293 register short *isp1;
294 register short *isp2;
295 register short *iend;
296 register core *sp;
297 register int found;
298
299 int n;
300
301#ifdef TRACE
302 fprintf(stderr, "Entering get_state, symbol = %d\n", symbol);
303#endif
304
305 isp1 = kernel_base[symbol];
306 iend = kernel_end[symbol];
307 n = iend - isp1;
308
309 /* add up the target state's active item numbers to get a hash key */
310 key = 0;
311 while (isp1 < iend)
312 key += *isp1++;
313
314 key = key % STATE_TABLE_SIZE;
315
316 sp = state_table[key];
317
318 if (sp)
319 {
320 found = 0;
321 while (!found)
322 {
323 if (sp->nitems == n)
324 {
325 found = 1;
326 isp1 = kernel_base[symbol];
327 isp2 = sp->items;
328
329 while (found && isp1 < iend)
330 {
331 if (*isp1++ != *isp2++)
332 found = 0;
333 }
334 }
335
336 if (!found)
337 {
338 if (sp->link)
339 {
340 sp = sp->link;
341 }
342 else /* bucket exhausted and no match */
343 {
344 sp = sp->link = new_state(symbol);
345 found = 1;
346 }
347 }
348 }
349 }
350 else /* bucket is empty */
351 {
352 state_table[key] = sp = new_state(symbol);
353 }
354
355 return (sp->number);
356}
357
358
359
360/* subroutine of get_state. create a new state for those items, if necessary. */
361
362core *
d2729d44 363new_state (int symbol)
40675e7c
DM
364{
365 register int n;
366 register core *p;
367 register short *isp1;
368 register short *isp2;
369 register short *iend;
370
371#ifdef TRACE
372 fprintf(stderr, "Entering new_state, symbol = %d\n", symbol);
373#endif
374
375 if (nstates >= MAXSHORT)
376 toomany("states");
377
378 isp1 = kernel_base[symbol];
379 iend = kernel_end[symbol];
380 n = iend - isp1;
381
382 p = (core *) xmalloc((unsigned) (sizeof(core) + (n - 1) * sizeof(short)));
383 p->accessing_symbol = symbol;
384 p->number = nstates;
385 p->nitems = n;
386
387 isp2 = p->items;
388 while (isp1 < iend)
389 *isp2++ = *isp1++;
390
391 last_state->next = p;
392 last_state = p;
393
394 nstates++;
395
396 return (p);
397}
398
399
400void
d2729d44 401initialize_states (void)
40675e7c
DM
402{
403 register core *p;
404/* register unsigned *rp1; JF unused */
405/* register unsigned *rp2; JF unused */
406/* register unsigned *rend; JF unused */
407
408 p = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short)));
409 first_state = last_state = this_state = p;
410 nstates = 1;
411}
412
413
414void
d2729d44 415save_shifts (void)
40675e7c
DM
416{
417 register shifts *p;
418 register short *sp1;
419 register short *sp2;
420 register short *send;
421
422 p = (shifts *) xmalloc((unsigned) (sizeof(shifts) +
d2729d44 423 (nshifts - 1) * sizeof(short)));
40675e7c
DM
424
425 p->number = this_state->number;
426 p->nshifts = nshifts;
427
428 sp1 = shiftset;
429 sp2 = p->shifts;
430 send = shiftset + nshifts;
431
432 while (sp1 < send)
433 *sp2++ = *sp1++;
434
435 if (last_shift)
436 {
437 last_shift->next = p;
438 last_shift = p;
439 }
440 else
441 {
442 first_shift = p;
443 last_shift = p;
444 }
445}
446
447
448
449/* find which rules can be used for reduction transitions from the current state
450 and make a reductions structure for the state to record their rule numbers. */
451void
d2729d44 452save_reductions (void)
40675e7c
DM
453{
454 register short *isp;
455 register short *rp1;
456 register short *rp2;
457 register int item;
458 register int count;
459 register reductions *p;
460
461 short *rend;
462
463 /* find and count the active items that represent ends of rules */
464
465 count = 0;
466 for (isp = itemset; isp < itemsetend; isp++)
467 {
468 item = ritem[*isp];
469 if (item < 0)
470 {
471 redset[count++] = -item;
472 }
473 }
474
475 /* make a reductions structure and copy the data into it. */
476
477 if (count)
478 {
479 p = (reductions *) xmalloc((unsigned) (sizeof(reductions) +
d2729d44 480 (count - 1) * sizeof(short)));
40675e7c
DM
481
482 p->number = this_state->number;
483 p->nreds = count;
484
485 rp1 = redset;
486 rp2 = p->rules;
487 rend = rp1 + count;
488
489 while (rp1 < rend)
490 *rp2++ = *rp1++;
491
492 if (last_reduction)
493 {
494 last_reduction->next = p;
495 last_reduction = p;
496 }
497 else
498 {
499 first_reduction = p;
500 last_reduction = p;
501 }
502 }
503}
504
505
506
507/* Make sure that the initial state has a shift that accepts the
508grammar's start symbol and goes to the next-to-final state,
509which has a shift going to the final state, which has a shift
510to the termination state.
511Create such states and shifts if they don't happen to exist already. */
512void
d2729d44 513augment_automaton (void)
40675e7c
DM
514{
515 register int i;
516 register int k;
517/* register int found; JF unused */
518 register core *statep;
519 register shifts *sp;
520 register shifts *sp2;
521 register shifts *sp1;
522
523 sp = first_shift;
524
525 if (sp)
526 {
527 if (sp->number == 0)
528 {
529 k = sp->nshifts;
530 statep = first_state->next;
531
532 /* The states reached by shifts from first_state are numbered 1...K.
533 Look for one reached by start_symbol. */
534 while (statep->accessing_symbol < start_symbol
535 && statep->number < k)
536 statep = statep->next;
537
538 if (statep->accessing_symbol == start_symbol)
539 {
540 /* We already have a next-to-final state.
541 Make sure it has a shift to what will be the final state. */
542 k = statep->number;
543
544 while (sp && sp->number < k)
545 {
546 sp1 = sp;
547 sp = sp->next;
548 }
549
550 if (sp && sp->number == k)
551 {
552 sp2 = (shifts *) xmalloc((unsigned) (sizeof(shifts)
d2729d44 553 + sp->nshifts * sizeof(short)));
40675e7c
DM
554 sp2->number = k;
555 sp2->nshifts = sp->nshifts + 1;
556 sp2->shifts[0] = nstates;
557 for (i = sp->nshifts; i > 0; i--)
558 sp2->shifts[i] = sp->shifts[i - 1];
559
560 /* Patch sp2 into the chain of shifts in place of sp,
561 following sp1. */
562 sp2->next = sp->next;
563 sp1->next = sp2;
564 if (sp == last_shift)
565 last_shift = sp2;
566 FREE(sp);
567 }
568 else
569 {
570 sp2 = NEW(shifts);
571 sp2->number = k;
572 sp2->nshifts = 1;
573 sp2->shifts[0] = nstates;
574
575 /* Patch sp2 into the chain of shifts between sp1 and sp. */
576 sp2->next = sp;
577 sp1->next = sp2;
578 if (sp == 0)
579 last_shift = sp2;
580 }
581 }
582 else
583 {
584 /* There is no next-to-final state as yet. */
585 /* Add one more shift in first_shift,
586 going to the next-to-final state (yet to be made). */
587 sp = first_shift;
588
589 sp2 = (shifts *) xmalloc(sizeof(shifts)
590 + sp->nshifts * sizeof(short));
591 sp2->nshifts = sp->nshifts + 1;
592
593 /* Stick this shift into the vector at the proper place. */
594 statep = first_state->next;
595 for (k = 0, i = 0; i < sp->nshifts; k++, i++)
596 {
597 if (statep->accessing_symbol > start_symbol && i == k)
598 sp2->shifts[k++] = nstates;
599 sp2->shifts[k] = sp->shifts[i];
600 statep = statep->next;
601 }
602 if (i == k)
603 sp2->shifts[k++] = nstates;
604
605 /* Patch sp2 into the chain of shifts
606 in place of sp, at the beginning. */
607 sp2->next = sp->next;
608 first_shift = sp2;
609 if (last_shift == sp)
610 last_shift = sp2;
611
612 FREE(sp);
613
614 /* Create the next-to-final state, with shift to
615 what will be the final state. */
616 insert_start_shift();
617 }
618 }
619 else
620 {
621 /* The initial state didn't even have any shifts.
622 Give it one shift, to the next-to-final state. */
623 sp = NEW(shifts);
624 sp->nshifts = 1;
625 sp->shifts[0] = nstates;
626
627 /* Patch sp into the chain of shifts at the beginning. */
628 sp->next = first_shift;
629 first_shift = sp;
630
631 /* Create the next-to-final state, with shift to
632 what will be the final state. */
633 insert_start_shift();
634 }
635 }
636 else
637 {
638 /* There are no shifts for any state.
639 Make one shift, from the initial state to the next-to-final state. */
640
641 sp = NEW(shifts);
642 sp->nshifts = 1;
643 sp->shifts[0] = nstates;
644
645 /* Initialize the chain of shifts with sp. */
646 first_shift = sp;
647 last_shift = sp;
648
649 /* Create the next-to-final state, with shift to
650 what will be the final state. */
651 insert_start_shift();
652 }
653
654 /* Make the final state--the one that follows a shift from the
655 next-to-final state.
656 The symbol for that shift is 0 (end-of-file). */
657 statep = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short)));
658 statep->number = nstates;
659 last_state->next = statep;
660 last_state = statep;
661
662 /* Make the shift from the final state to the termination state. */
663 sp = NEW(shifts);
664 sp->number = nstates++;
665 sp->nshifts = 1;
666 sp->shifts[0] = nstates;
667 last_shift->next = sp;
668 last_shift = sp;
669
670 /* Note that the variable `final_state' refers to what we sometimes call
671 the termination state. */
672 final_state = nstates;
673
674 /* Make the termination state. */
675 statep = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short)));
676 statep->number = nstates++;
677 last_state->next = statep;
678 last_state = statep;
679}
680
681
682/* subroutine of augment_automaton.
683 Create the next-to-final state, to which a shift has already been made in
684 the initial state. */
685void
d2729d44 686insert_start_shift (void)
40675e7c
DM
687{
688 register core *statep;
689 register shifts *sp;
690
691 statep = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short)));
692 statep->number = nstates;
693 statep->accessing_symbol = start_symbol;
694
695 last_state->next = statep;
696 last_state = statep;
697
698 /* Make a shift from this state to (what will be) the final state. */
699 sp = NEW(shifts);
700 sp->number = nstates++;
701 sp->nshifts = 1;
702 sp->shifts[0] = nstates;
703
704 last_shift->next = sp;
705 last_shift = sp;
706}