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