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