xref: /original-bsd/usr.bin/yacc/lr0.c (revision 09b04dfe)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Paul Corbett.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)lr0.c	5.2 (Berkeley) 06/01/90";
13 #endif /* not lint */
14 
15 #include "defs.h"
16 
17 extern short *itemset;
18 extern short *itemsetend;
19 extern unsigned *ruleset;
20 
21 int nstates;
22 core *first_state;
23 shifts *first_shift;
24 reductions *first_reduction;
25 
26 int get_state();
27 core *new_state();
28 
29 static core *this_state;
30 static core *last_state;
31 static shifts *last_shift;
32 static reductions *last_reduction;
33 
34 static int nshifts;
35 static short *shift_symbol;
36 
37 static short *redset;
38 static short *shiftset;
39 
40 static short **kernel_base;
41 static short **kernel_end;
42 static short *kernel_items;
43 
44 static core **state_table;
45 
46 
47 allocate_itemsets()
48 {
49   register short *itemp;
50   register short *item_end;
51   register int symbol;
52   register int i;
53   register int count;
54   register int max;
55   register short *symbol_count;
56 
57   count = 0;
58   symbol_count = NEW2(nsyms, short);
59 
60   item_end = ritem + nitems;
61   for (itemp = ritem; itemp < item_end; itemp++)
62     {
63       symbol = *itemp;
64       if (symbol >= 0)
65 	{
66 	  count++;
67 	  symbol_count[symbol]++;
68 	}
69     }
70 
71   kernel_base = NEW2(nsyms, short *);
72   kernel_items = NEW2(count, short);
73 
74   count = 0;
75   max = 0;
76   for (i = 0; i < nsyms; i++)
77     {
78       kernel_base[i] = kernel_items + count;
79       count += symbol_count[i];
80       if (max < symbol_count[i])
81 	max = symbol_count[i];
82     }
83 
84   shift_symbol = symbol_count;
85   kernel_end = NEW2(nsyms, short *);
86 }
87 
88 
89 
90 allocate_storage()
91 {
92   allocate_itemsets();
93 
94   shiftset = NEW2(nsyms, short);
95   redset = NEW2(nrules + 1, short);
96   state_table = NEW2(nitems, core *);
97 }
98 
99 
100 
101 append_states()
102 {
103   register int i;
104   register int j;
105   register int symbol;
106 
107 #ifdef	TRACE
108   fprintf(stderr, "Entering append_states\n");
109 #endif
110 
111   for (i = 1; i < nshifts; i++)
112     {
113       symbol = shift_symbol[i];
114       j = i;
115       while (j > 0 && shift_symbol[j - 1] > symbol)
116 	{
117 	  shift_symbol[j] = shift_symbol[j - 1];
118 	  j--;
119 	}
120       shift_symbol[j] = symbol;
121     }
122 
123   for (i = 0; i < nshifts; i++)
124     {
125       symbol = shift_symbol[i];
126       shiftset[i] = get_state(symbol);
127     }
128 }
129 
130 
131 free_storage()
132 {
133   FREE(shift_symbol);
134   FREE(redset);
135   FREE(shiftset);
136   FREE(kernel_base);
137   FREE(kernel_end);
138   FREE(kernel_items);
139   FREE(state_table);
140 }
141 
142 
143 
144 generate_states()
145 {
146   allocate_storage();
147   itemset = NEW2(nitems, short);
148   ruleset = NEW2(WORDSIZE(nrules), unsigned);
149   set_first_derives();
150   initialize_states();
151 
152   while (this_state)
153     {
154       closure(this_state->items, this_state->nitems);
155       save_reductions();
156       new_itemsets();
157       append_states();
158 
159       if (nshifts > 0)
160         save_shifts();
161 
162       this_state = this_state->next;
163     }
164 
165   finalize_closure();
166   free_storage();
167 }
168 
169 
170 
171 int
172 get_state(symbol)
173 int symbol;
174 {
175   register int key;
176   register short *isp1;
177   register short *isp2;
178   register short *iend;
179   register core *sp;
180   register int found;
181 
182   int n;
183 
184 #ifdef	TRACE
185   fprintf(stderr, "Entering get_state, symbol = %d\n", symbol);
186 #endif
187 
188   isp1 = kernel_base[symbol];
189   iend = kernel_end[symbol];
190   n = iend - isp1;
191 
192   key = *isp1;
193   assert(0 <= key && key < nitems);
194   sp = state_table[key];
195   if (sp)
196     {
197       found = 0;
198       while (!found)
199 	{
200 	  if (sp->nitems == n)
201 	    {
202 	      found = 1;
203 	      isp1 = kernel_base[symbol];
204 	      isp2 = sp->items;
205 
206 	      while (found && isp1 < iend)
207 		{
208 		  if (*isp1++ != *isp2++)
209 		    found = 0;
210 		}
211 	    }
212 
213 	  if (!found)
214 	    {
215 	      if (sp->link)
216 		{
217 		  sp = sp->link;
218 		}
219 	      else
220 		{
221 		  sp = sp->link = new_state(symbol);
222 		  found = 1;
223 		}
224 	    }
225 	}
226     }
227   else
228     {
229       state_table[key] = sp = new_state(symbol);
230     }
231 
232   return (sp->number);
233 }
234 
235 
236 
237 initialize_states()
238 {
239     register int i;
240     register short *start_derives;
241     register core *p;
242 
243     start_derives = derives[start_symbol];
244     for (i = 0; start_derives[i] >= 0; ++i)
245 	continue;
246 
247     p = (core *) MALLOC(sizeof(core) + i*sizeof(short));
248     if (p == 0) no_space();
249 
250     p->next = 0;
251     p->link = 0;
252     p->number = 0;
253     p->accessing_symbol = 0;
254     p->nitems = i;
255 
256     for (i = 0;  start_derives[i] >= 0; ++i)
257 	p->items[i] = rrhs[start_derives[i]];
258 
259     first_state = last_state = this_state = p;
260     nstates = 1;
261 }
262 
263 
264 new_itemsets()
265 {
266   register int i;
267   register int shiftcount;
268   register short *isp;
269   register short *ksp;
270   register int symbol;
271 
272   for (i = 0; i < nsyms; i++)
273     kernel_end[i] = 0;
274 
275   shiftcount = 0;
276   isp = itemset;
277   while (isp < itemsetend)
278     {
279       i = *isp++;
280       symbol = ritem[i];
281       if (symbol > 0)
282 	{
283           ksp = kernel_end[symbol];
284 
285           if (!ksp)
286 	    {
287 	      shift_symbol[shiftcount++] = symbol;
288 	      ksp = kernel_base[symbol];
289 	    }
290 
291           *ksp++ = i + 1;
292           kernel_end[symbol] = ksp;
293 	}
294     }
295 
296   nshifts = shiftcount;
297 }
298 
299 
300 
301 core *
302 new_state(symbol)
303 int symbol;
304 {
305   register int n;
306   register core *p;
307   register short *isp1;
308   register short *isp2;
309   register short *iend;
310 
311 #ifdef	TRACE
312   fprintf(stderr, "Entering new_state, symbol = %d\n", symbol);
313 #endif
314 
315   if (nstates >= MAXSHORT)
316     fatal("too many states");
317 
318   isp1 = kernel_base[symbol];
319   iend = kernel_end[symbol];
320   n = iend - isp1;
321 
322   p = (core *) allocate((unsigned) (sizeof(core) + (n - 1) * sizeof(short)));
323   p->accessing_symbol = symbol;
324   p->number = nstates;
325   p->nitems = n;
326 
327   isp2 = p->items;
328   while (isp1 < iend)
329     *isp2++ = *isp1++;
330 
331   last_state->next = p;
332   last_state = p;
333 
334   nstates++;
335 
336   return (p);
337 }
338 
339 
340 /* show_cores is used for debugging */
341 
342 show_cores()
343 {
344     core *p;
345     int i, j, k, n;
346     int itemno;
347 
348     k = 0;
349     for (p = first_state; p; ++k, p = p->next)
350     {
351 	if (k) printf("\n");
352 	printf("state %d, number = %d, accessing symbol = %s\n",
353 		k, p->number, symbol_name[p->accessing_symbol]);
354 	n = p->nitems;
355 	for (i = 0; i < n; ++i)
356 	{
357 	    itemno = p->items[i];
358 	    printf("%4d  ", itemno);
359 	    j = itemno;
360 	    while (ritem[j] >= 0) ++j;
361 	    printf("%s :", symbol_name[rlhs[-ritem[j]]]);
362 	    j = rrhs[-ritem[j]];
363 	    while (j < itemno)
364 		printf(" %s", symbol_name[ritem[j++]]);
365 	    printf(" .");
366 	    while (ritem[j] >= 0)
367 		printf(" %s", symbol_name[ritem[j++]]);
368 	    printf("\n");
369 	    fflush(stdout);
370 	}
371     }
372 }
373 
374 
375 /* show_ritems is used for debugging */
376 
377 show_ritems()
378 {
379     int i;
380 
381     for (i = 0; i < nitems; ++i)
382 	printf("ritem[%d] = %d\n", i, ritem[i]);
383 }
384 
385 
386 /* show_rrhs is used for debugging */
387 show_rrhs()
388 {
389     int i;
390 
391     for (i = 0; i < nrules; ++i)
392 	printf("rrhs[%d] = %d\n", i, rrhs[i]);
393 }
394 
395 
396 /* show_shifts is used for debugging */
397 
398 show_shifts()
399 {
400     shifts *p;
401     int i, j, k;
402 
403     k = 0;
404     for (p = first_shift; p; ++k, p = p->next)
405     {
406 	if (k) printf("\n");
407 	printf("shift %d, number = %d, nshifts = %d\n", k, p->number,
408 		p->nshifts);
409 	j = p->nshifts;
410 	for (i = 0; i < j; ++i)
411 	    printf("\t%d\n", p->shift[i]);
412     }
413 }
414 
415 
416 save_shifts()
417 {
418   register shifts *p;
419   register short *sp1;
420   register short *sp2;
421   register short *send;
422 
423   p = (shifts *) allocate((unsigned) (sizeof(shifts) +
424 			(nshifts - 1) * sizeof(short)));
425 
426   p->number = this_state->number;
427   p->nshifts = nshifts;
428 
429   sp1 = shiftset;
430   sp2 = p->shift;
431   send = shiftset + nshifts;
432 
433   while (sp1 < send)
434     *sp2++ = *sp1++;
435 
436   if (last_shift)
437     {
438       last_shift->next = p;
439       last_shift = p;
440     }
441   else
442     {
443       first_shift = p;
444       last_shift = p;
445     }
446 }
447 
448 
449 
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   count = 0;
462   for (isp = itemset; isp < itemsetend; isp++)
463     {
464       item = ritem[*isp];
465       if (item < 0)
466 	{
467 	  redset[count++] = -item;
468 	}
469     }
470 
471   if (count)
472     {
473       p = (reductions *) allocate((unsigned) (sizeof(reductions) +
474 					(count - 1) * sizeof(short)));
475 
476       p->number = this_state->number;
477       p->nreds = count;
478 
479       rp1 = redset;
480       rp2 = p->rules;
481       rend = rp1 + count;
482 
483       while (rp1 < rend)
484 	*rp2++ = *rp1++;
485 
486       if (last_reduction)
487 	{
488 	  last_reduction->next = p;
489 	  last_reduction = p;
490 	}
491       else
492 	{
493 	  first_reduction = p;
494 	  last_reduction = p;
495 	}
496     }
497 }
498 
499 
500 set_derives()
501 {
502   register int i, k;
503   register int lhs;
504   register short *rules;
505 
506   derives = NEW2(nsyms, short *);
507   rules = NEW2(nvars + nrules, short);
508 
509   k = 0;
510   for (lhs = start_symbol; lhs < nsyms; lhs++)
511     {
512       derives[lhs] = rules + k;
513       for (i = 0; i < nrules; i++)
514 	{
515 	  if (rlhs[i] == lhs)
516 	    {
517 	      rules[k] = i;
518 	      k++;
519 	    }
520 	}
521       rules[k] = -1;
522       k++;
523     }
524 
525 #ifdef	DEBUG
526   print_derives();
527 #endif
528 }
529 
530 free_derives()
531 {
532   FREE(derives[start_symbol]);
533   FREE(derives);
534 }
535 
536 #ifdef	DEBUG
537 print_derives()
538 {
539   register int i;
540   register short *sp;
541 
542   printf("\nDERIVES\n\n");
543 
544   for (i = start_symbol; i < nsyms; i++)
545     {
546       printf("%s derives ", symbol_name[i]);
547       for (sp = derives[i]; *sp >= 0; sp++)
548 	{
549 	  printf("  %d", *sp);
550 	}
551       putchar('\n');
552     }
553 
554   putchar('\n');
555 }
556 #endif
557 
558 
559 set_nullable()
560 {
561     register int i, j;
562     register int empty;
563     int done;
564 
565     nullable = MALLOC(nsyms);
566     if (nullable == 0) no_space();
567 
568     for (i = 0; i < nsyms; ++i)
569 	nullable[i] = 0;
570 
571     done = 0;
572     while (!done)
573     {
574 	done = 1;
575 	for (i = 1; i < nitems; i++)
576 	{
577 	    empty = 1;
578 	    while ((j = ritem[i]) >= 0)
579 	    {
580 		if (!nullable[j])
581 		    empty = 0;
582 		++i;
583 	    }
584 	    if (empty)
585 	    {
586 		j = rlhs[-j];
587 		if (!nullable[j])
588 		{
589 		    nullable[j] = 1;
590 		    done = 0;
591 		}
592 	    }
593 	}
594     }
595 
596 #ifdef DEBUG
597     for (i = 0; i < nsyms; i++)
598     {
599 	if (nullable[i])
600 	    printf("%s is nullable\n", symbol_name[i]);
601 	else
602 	    printf("%s is not nullable\n", symbol_name[i]);
603     }
604 #endif
605 }
606 
607 
608 free_nullable()
609 {
610   FREE(nullable);
611 }
612 
613 
614 lr0()
615 {
616     set_derives();
617     set_nullable();
618     generate_states();
619 }
620