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