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