598 lines
		
	
	
	
		
			9.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			598 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();
 | 
						|
}
 |