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