599 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			599 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| #include "defs.h"
 | |
| 
 | |
| extern short *itemset;
 | |
| extern short *itemsetend;
 | |
| extern unsigned *ruleset;
 | |
| 
 | |
| int nstates;
 | |
| core *first_state;
 | |
| shifts *first_shift;
 | |
| reductions *first_reduction;
 | |
| 
 | |
| int get_state();
 | |
| core *new_state();
 | |
| 
 | |
| static core **state_set;
 | |
| static core *this_state;
 | |
| static core *last_state;
 | |
| static shifts *last_shift;
 | |
| static reductions *last_reduction;
 | |
| 
 | |
| static int nshifts;
 | |
| static short *shift_symbol;
 | |
| 
 | |
| static short *redset;
 | |
| static short *shiftset;
 | |
| 
 | |
| static short **kernel_base;
 | |
| static short **kernel_end;
 | |
| static short *kernel_items;
 | |
| 
 | |
| 
 | |
| allocate_itemsets()
 | |
| {
 | |
|     register short *itemp;
 | |
|     register short *item_end;
 | |
|     register int symbol;
 | |
|     register int i;
 | |
|     register int count;
 | |
|     register int max;
 | |
|     register short *symbol_count;
 | |
| 
 | |
|     count = 0;
 | |
|     symbol_count = NEW2(nsyms, short);
 | |
| 
 | |
|     item_end = ritem + nitems;
 | |
|     for (itemp = ritem; itemp < item_end; itemp++)
 | |
|     {
 | |
| 	symbol = *itemp;
 | |
| 	if (symbol >= 0)
 | |
| 	{
 | |
| 	    count++;
 | |
| 	    symbol_count[symbol]++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     kernel_base = NEW2(nsyms, short *);
 | |
|     kernel_items = NEW2(count, short);
 | |
| 
 | |
|     count = 0;
 | |
|     max = 0;
 | |
|     for (i = 0; i < nsyms; i++)
 | |
|     {
 | |
| 	kernel_base[i] = kernel_items + count;
 | |
| 	count += symbol_count[i];
 | |
| 	if (max < symbol_count[i])
 | |
| 	    max = symbol_count[i];
 | |
|     }
 | |
| 
 | |
|     shift_symbol = symbol_count;
 | |
|     kernel_end = NEW2(nsyms, short *);
 | |
| }
 | |
| 
 | |
| 
 | |
| allocate_storage()
 | |
| {
 | |
|     allocate_itemsets();
 | |
|     shiftset = NEW2(nsyms, short);
 | |
|     redset = NEW2(nrules + 1, short);
 | |
|     state_set = NEW2(nitems, core *);
 | |
| }
 | |
| 
 | |
| 
 | |
| append_states()
 | |
| {
 | |
|     register int i;
 | |
|     register int j;
 | |
|     register int symbol;
 | |
| 
 | |
| #ifdef	TRACE
 | |
|     fprintf(stderr, "Entering append_states()\n");
 | |
| #endif
 | |
|     for (i = 1; i < nshifts; i++)
 | |
|     {
 | |
| 	symbol = shift_symbol[i];
 | |
| 	j = i;
 | |
| 	while (j > 0 && shift_symbol[j - 1] > symbol)
 | |
| 	{
 | |
| 	    shift_symbol[j] = shift_symbol[j - 1];
 | |
| 	    j--;
 | |
| 	}
 | |
| 	shift_symbol[j] = symbol;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < nshifts; i++)
 | |
|     {
 | |
| 	symbol = shift_symbol[i];
 | |
| 	shiftset[i] = get_state(symbol);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| free_storage()
 | |
| {
 | |
|     FREE(shift_symbol);
 | |
|     FREE(redset);
 | |
|     FREE(shiftset);
 | |
|     FREE(kernel_base);
 | |
|     FREE(kernel_end);
 | |
|     FREE(kernel_items);
 | |
|     FREE(state_set);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| generate_states()
 | |
| {
 | |
|     allocate_storage();
 | |
|     itemset = NEW2(nitems, short);
 | |
|     ruleset = NEW2(WORDSIZE(nrules), unsigned);
 | |
|     set_first_derives();
 | |
|     initialize_states();
 | |
| 
 | |
|     while (this_state)
 | |
|     {
 | |
| 	closure(this_state->items, this_state->nitems);
 | |
| 	save_reductions();
 | |
| 	new_itemsets();
 | |
| 	append_states();
 | |
| 
 | |
| 	if (nshifts > 0)
 | |
| 	    save_shifts();
 | |
| 
 | |
| 	this_state = this_state->next;
 | |
|     }
 | |
| 
 | |
|     finalize_closure();
 | |
|     free_storage();
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| int
 | |
| get_state(symbol)
 | |
| int symbol;
 | |
| {
 | |
|     register int key;
 | |
|     register short *isp1;
 | |
|     register short *isp2;
 | |
|     register short *iend;
 | |
|     register core *sp;
 | |
|     register int found;
 | |
|     register int n;
 | |
| 
 | |
| #ifdef	TRACE
 | |
|     fprintf(stderr, "Entering get_state(%d)\n", symbol);
 | |
| #endif
 | |
| 
 | |
|     isp1 = kernel_base[symbol];
 | |
|     iend = kernel_end[symbol];
 | |
|     n = iend - isp1;
 | |
| 
 | |
|     key = *isp1;
 | |
|     assert(0 <= key && key < nitems);
 | |
|     sp = state_set[key];
 | |
|     if (sp)
 | |
|     {
 | |
| 	found = 0;
 | |
| 	while (!found)
 | |
| 	{
 | |
| 	    if (sp->nitems == n)
 | |
| 	    {
 | |
| 		found = 1;
 | |
| 		isp1 = kernel_base[symbol];
 | |
| 		isp2 = sp->items;
 | |
| 
 | |
| 		while (found && isp1 < iend)
 | |
| 		{
 | |
| 		    if (*isp1++ != *isp2++)
 | |
| 			found = 0;
 | |
| 		}
 | |
| 	    }
 | |
| 
 | |
| 	    if (!found)
 | |
| 	    {
 | |
| 		if (sp->link)
 | |
| 		{
 | |
| 		    sp = sp->link;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    sp = sp->link = new_state(symbol);
 | |
| 		    found = 1;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	state_set[key] = sp = new_state(symbol);
 | |
|     }
 | |
| 
 | |
|     return (sp->number);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| initialize_states()
 | |
| {
 | |
|     register int i;
 | |
|     register short *start_derives;
 | |
|     register core *p;
 | |
| 
 | |
|     start_derives = derives[start_symbol];
 | |
|     for (i = 0; start_derives[i] >= 0; ++i)
 | |
| 	continue;
 | |
| 
 | |
|     p = (core *) MALLOC(sizeof(core) + i*sizeof(short));
 | |
|     if (p == 0) no_space();
 | |
| 
 | |
|     p->next = 0;
 | |
|     p->link = 0;
 | |
|     p->number = 0;
 | |
|     p->accessing_symbol = 0;
 | |
|     p->nitems = i;
 | |
| 
 | |
|     for (i = 0;  start_derives[i] >= 0; ++i)
 | |
| 	p->items[i] = rrhs[start_derives[i]];
 | |
| 
 | |
|     first_state = last_state = this_state = p;
 | |
|     nstates = 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| new_itemsets()
 | |
| {
 | |
|     register int i;
 | |
|     register int shiftcount;
 | |
|     register short *isp;
 | |
|     register short *ksp;
 | |
|     register int symbol;
 | |
| 
 | |
|     for (i = 0; i < nsyms; i++)
 | |
| 	kernel_end[i] = 0;
 | |
| 
 | |
|     shiftcount = 0;
 | |
|     isp = itemset;
 | |
|     while (isp < itemsetend)
 | |
|     {
 | |
| 	i = *isp++;
 | |
| 	symbol = ritem[i];
 | |
| 	if (symbol > 0)
 | |
| 	{
 | |
| 	    ksp = kernel_end[symbol];
 | |
| 	    if (!ksp)
 | |
| 	    {
 | |
| 		shift_symbol[shiftcount++] = symbol;
 | |
| 		ksp = kernel_base[symbol];
 | |
| 	    }
 | |
| 
 | |
| 	    *ksp++ = i + 1;
 | |
| 	    kernel_end[symbol] = ksp;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     nshifts = shiftcount;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| core *
 | |
| new_state(symbol)
 | |
| int symbol;
 | |
| {
 | |
|     register int n;
 | |
|     register core *p;
 | |
|     register short *isp1;
 | |
|     register short *isp2;
 | |
|     register short *iend;
 | |
| 
 | |
| #ifdef	TRACE
 | |
|     fprintf(stderr, "Entering new_state(%d)\n", symbol);
 | |
| #endif
 | |
| 
 | |
|     if (nstates >= MAXSHORT)
 | |
| 	fatal("too many states");
 | |
| 
 | |
|     isp1 = kernel_base[symbol];
 | |
|     iend = kernel_end[symbol];
 | |
|     n = iend - isp1;
 | |
| 
 | |
|     p = (core *) allocate((unsigned) (sizeof(core) + (n - 1) * sizeof(short)));
 | |
|     p->accessing_symbol = symbol;
 | |
|     p->number = nstates;
 | |
|     p->nitems = n;
 | |
| 
 | |
|     isp2 = p->items;
 | |
|     while (isp1 < iend)
 | |
| 	*isp2++ = *isp1++;
 | |
| 
 | |
|     last_state->next = p;
 | |
|     last_state = p;
 | |
| 
 | |
|     nstates++;
 | |
| 
 | |
|     return (p);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* show_cores is used for debugging */
 | |
| 
 | |
| show_cores()
 | |
| {
 | |
|     core *p;
 | |
|     int i, j, k, n;
 | |
|     int itemno;
 | |
| 
 | |
|     k = 0;
 | |
|     for (p = first_state; p; ++k, p = p->next)
 | |
|     {
 | |
| 	if (k) printf("\n");
 | |
| 	printf("state %d, number = %d, accessing symbol = %s\n",
 | |
| 		k, p->number, symbol_name[p->accessing_symbol]);
 | |
| 	n = p->nitems;
 | |
| 	for (i = 0; i < n; ++i)
 | |
| 	{
 | |
| 	    itemno = p->items[i];
 | |
| 	    printf("%4d  ", itemno);
 | |
| 	    j = itemno;
 | |
| 	    while (ritem[j] >= 0) ++j;
 | |
| 	    printf("%s :", symbol_name[rlhs[-ritem[j]]]);
 | |
| 	    j = rrhs[-ritem[j]];
 | |
| 	    while (j < itemno)
 | |
| 		printf(" %s", symbol_name[ritem[j++]]);
 | |
| 	    printf(" .");
 | |
| 	    while (ritem[j] >= 0)
 | |
| 		printf(" %s", symbol_name[ritem[j++]]);
 | |
| 	    printf("\n");
 | |
| 	    fflush(stdout);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* show_ritems is used for debugging */
 | |
| 
 | |
| show_ritems()
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < nitems; ++i)
 | |
| 	printf("ritem[%d] = %d\n", i, ritem[i]);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* show_rrhs is used for debugging */
 | |
| show_rrhs()
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < nrules; ++i)
 | |
| 	printf("rrhs[%d] = %d\n", i, rrhs[i]);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* show_shifts is used for debugging */
 | |
| 
 | |
| show_shifts()
 | |
| {
 | |
|     shifts *p;
 | |
|     int i, j, k;
 | |
| 
 | |
|     k = 0;
 | |
|     for (p = first_shift; p; ++k, p = p->next)
 | |
|     {
 | |
| 	if (k) printf("\n");
 | |
| 	printf("shift %d, number = %d, nshifts = %d\n", k, p->number,
 | |
| 		p->nshifts);
 | |
| 	j = p->nshifts;
 | |
| 	for (i = 0; i < j; ++i)
 | |
| 	    printf("\t%d\n", p->shift[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| save_shifts()
 | |
| {
 | |
|     register shifts *p;
 | |
|     register short *sp1;
 | |
|     register short *sp2;
 | |
|     register short *send;
 | |
| 
 | |
|     p = (shifts *) allocate((unsigned) (sizeof(shifts) +
 | |
| 			(nshifts - 1) * sizeof(short)));
 | |
| 
 | |
|     p->number = this_state->number;
 | |
|     p->nshifts = nshifts;
 | |
| 
 | |
|     sp1 = shiftset;
 | |
|     sp2 = p->shift;
 | |
|     send = shiftset + nshifts;
 | |
| 
 | |
|     while (sp1 < send)
 | |
| 	*sp2++ = *sp1++;
 | |
| 
 | |
|     if (last_shift)
 | |
|     {
 | |
| 	last_shift->next = p;
 | |
| 	last_shift = p;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	first_shift = p;
 | |
| 	last_shift = p;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| save_reductions()
 | |
| {
 | |
|     register short *isp;
 | |
|     register short *rp1;
 | |
|     register short *rp2;
 | |
|     register int item;
 | |
|     register int count;
 | |
|     register reductions *p;
 | |
|     register short *rend;
 | |
| 
 | |
|     count = 0;
 | |
|     for (isp = itemset; isp < itemsetend; isp++)
 | |
|     {
 | |
| 	item = ritem[*isp];
 | |
| 	if (item < 0)
 | |
| 	{
 | |
| 	    redset[count++] = -item;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (count)
 | |
|     {
 | |
| 	p = (reductions *) allocate((unsigned) (sizeof(reductions) +
 | |
| 					(count - 1) * sizeof(short)));
 | |
| 
 | |
| 	p->number = this_state->number;
 | |
| 	p->nreds = count;
 | |
| 
 | |
| 	rp1 = redset;
 | |
| 	rp2 = p->rules;
 | |
| 	rend = rp1 + count;
 | |
| 
 | |
| 	while (rp1 < rend)
 | |
| 	    *rp2++ = *rp1++;
 | |
| 
 | |
| 	if (last_reduction)
 | |
| 	{
 | |
| 	    last_reduction->next = p;
 | |
| 	    last_reduction = p;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    first_reduction = p;
 | |
| 	    last_reduction = p;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| set_derives()
 | |
| {
 | |
|     register int i, k;
 | |
|     register int lhs;
 | |
|     register short *rules;
 | |
| 
 | |
|     derives = NEW2(nsyms, short *);
 | |
|     rules = NEW2(nvars + nrules, short);
 | |
| 
 | |
|     k = 0;
 | |
|     for (lhs = start_symbol; lhs < nsyms; lhs++)
 | |
|     {
 | |
| 	derives[lhs] = rules + k;
 | |
| 	for (i = 0; i < nrules; i++)
 | |
| 	{
 | |
| 	    if (rlhs[i] == lhs)
 | |
| 	    {
 | |
| 		rules[k] = i;
 | |
| 		k++;
 | |
| 	    }
 | |
| 	}
 | |
| 	rules[k] = -1;
 | |
| 	k++;
 | |
|     }
 | |
| 
 | |
| #ifdef	DEBUG
 | |
|     print_derives();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| free_derives()
 | |
| {
 | |
|     FREE(derives[start_symbol]);
 | |
|     FREE(derives);
 | |
| }
 | |
| 
 | |
| #ifdef	DEBUG
 | |
| print_derives()
 | |
| {
 | |
|     register int i;
 | |
|     register short *sp;
 | |
| 
 | |
|     printf("\nDERIVES\n\n");
 | |
| 
 | |
|     for (i = start_symbol; i < nsyms; i++)
 | |
|     {
 | |
| 	printf("%s derives ", symbol_name[i]);
 | |
| 	for (sp = derives[i]; *sp >= 0; sp++)
 | |
| 	{
 | |
| 	    printf("  %d", *sp);
 | |
| 	}
 | |
| 	putchar('\n');
 | |
|     }
 | |
| 
 | |
|     putchar('\n');
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| set_nullable()
 | |
| {
 | |
|     register int i, j;
 | |
|     register int empty;
 | |
|     int done;
 | |
| 
 | |
|     nullable = MALLOC(nsyms);
 | |
|     if (nullable == 0) no_space();
 | |
| 
 | |
|     for (i = 0; i < nsyms; ++i)
 | |
| 	nullable[i] = 0;
 | |
| 
 | |
|     done = 0;
 | |
|     while (!done)
 | |
|     {
 | |
| 	done = 1;
 | |
| 	for (i = 1; i < nitems; i++)
 | |
| 	{
 | |
| 	    empty = 1;
 | |
| 	    while ((j = ritem[i]) >= 0)
 | |
| 	    {
 | |
| 		if (!nullable[j])
 | |
| 		    empty = 0;
 | |
| 		++i;
 | |
| 	    }
 | |
| 	    if (empty)
 | |
| 	    {
 | |
| 		j = rlhs[-j];
 | |
| 		if (!nullable[j])
 | |
| 		{
 | |
| 		    nullable[j] = 1;
 | |
| 		    done = 0;
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
| #ifdef DEBUG
 | |
|     for (i = 0; i < nsyms; i++)
 | |
|     {
 | |
| 	if (nullable[i])
 | |
| 	    printf("%s is nullable\n", symbol_name[i]);
 | |
| 	else
 | |
| 	    printf("%s is not nullable\n", symbol_name[i]);
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| free_nullable()
 | |
| {
 | |
|     FREE(nullable);
 | |
| }
 | |
| 
 | |
| 
 | |
| lr0()
 | |
| {
 | |
|     set_derives();
 | |
|     set_nullable();
 | |
|     generate_states();
 | |
| }
 | 
