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