version 1.16, 2014/01/13 23:14:17 |
version 1.17, 2014/03/13 00:59:34 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: lr0.c,v 1.4 1996/03/19 03:21:35 jtc Exp $ */ |
/* $NetBSD: lr0.c,v 1.4 1996/03/19 03:21:35 jtc Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1989 The Regents of the University of California. |
* Copyright (c) 1989 The Regents of the University of California. |
|
|
void |
void |
allocate_itemsets(void) |
allocate_itemsets(void) |
{ |
{ |
short *itemp; |
short *itemp; |
short *item_end; |
short *item_end; |
int symbol; |
int symbol; |
int i; |
int i; |
int count; |
int count; |
int max; |
int max; |
short *symbol_count; |
short *symbol_count; |
|
|
count = 0; |
count = 0; |
symbol_count = NEW2(nsyms, short); |
symbol_count = NEW2(nsyms, short); |
|
|
item_end = ritem + nitems; |
item_end = ritem + nitems; |
for (itemp = ritem; itemp < item_end; itemp++) |
for (itemp = ritem; itemp < item_end; itemp++) { |
{ |
symbol = *itemp; |
symbol = *itemp; |
if (symbol >= 0) { |
if (symbol >= 0) |
count++; |
{ |
symbol_count[symbol]++; |
count++; |
} |
symbol_count[symbol]++; |
|
} |
} |
} |
|
|
|
kernel_base = NEW2(nsyms, short *); |
kernel_base = NEW2(nsyms, short *); |
kernel_items = NEW2(count, short); |
kernel_items = NEW2(count, short); |
|
|
count = 0; |
count = 0; |
max = 0; |
max = 0; |
for (i = 0; i < nsyms; i++) |
for (i = 0; i < nsyms; i++) { |
{ |
kernel_base[i] = kernel_items + count; |
kernel_base[i] = kernel_items + count; |
count += symbol_count[i]; |
count += symbol_count[i]; |
if (max < symbol_count[i]) |
if (max < symbol_count[i]) |
max = symbol_count[i]; |
max = symbol_count[i]; |
} |
} |
|
|
|
shift_symbol = symbol_count; |
shift_symbol = symbol_count; |
kernel_end = NEW2(nsyms, short *); |
kernel_end = NEW2(nsyms, short *); |
} |
} |
|
|
void |
void |
allocate_storage(void) |
allocate_storage(void) |
{ |
{ |
allocate_itemsets(); |
allocate_itemsets(); |
shiftset = NEW2(nsyms, short); |
shiftset = NEW2(nsyms, short); |
redset = NEW2(nrules + 1, short); |
redset = NEW2(nrules + 1, short); |
state_set = NEW2(nitems, core *); |
state_set = NEW2(nitems, core *); |
} |
} |
|
|
void |
void |
append_states(void) |
append_states(void) |
{ |
{ |
int i; |
int i; |
int j; |
int j; |
int symbol; |
int symbol; |
|
|
#ifdef TRACE |
#ifdef TRACE |
fprintf(stderr, "Entering append_states()\n"); |
fprintf(stderr, "Entering append_states()\n"); |
#endif |
#endif |
for (i = 1; i < nshifts; i++) |
for (i = 1; i < nshifts; i++) { |
{ |
symbol = shift_symbol[i]; |
symbol = shift_symbol[i]; |
j = i; |
j = i; |
while (j > 0 && shift_symbol[j - 1] > symbol) { |
while (j > 0 && shift_symbol[j - 1] > symbol) |
shift_symbol[j] = shift_symbol[j - 1]; |
{ |
j--; |
shift_symbol[j] = shift_symbol[j - 1]; |
} |
j--; |
shift_symbol[j] = symbol; |
} |
} |
shift_symbol[j] = symbol; |
|
} |
|
|
|
for (i = 0; i < nshifts; i++) |
for (i = 0; i < nshifts; i++) { |
{ |
symbol = shift_symbol[i]; |
symbol = shift_symbol[i]; |
shiftset[i] = get_state(symbol); |
shiftset[i] = get_state(symbol); |
} |
} |
|
} |
} |
|
|
void |
void |
free_storage(void) |
free_storage(void) |
{ |
{ |
free(shift_symbol); |
free(shift_symbol); |
free(redset); |
free(redset); |
free(shiftset); |
free(shiftset); |
free(kernel_base); |
free(kernel_base); |
free(kernel_end); |
free(kernel_end); |
free(kernel_items); |
free(kernel_items); |
free(state_set); |
free(state_set); |
} |
} |
|
|
|
|
void |
void |
generate_states(void) |
generate_states(void) |
{ |
{ |
allocate_storage(); |
allocate_storage(); |
itemset = NEW2(nitems, short); |
itemset = NEW2(nitems, short); |
ruleset = NEW2(WORDSIZE(nrules), unsigned); |
ruleset = NEW2(WORDSIZE(nrules), unsigned); |
set_first_derives(); |
set_first_derives(); |
initialize_states(); |
initialize_states(); |
|
|
while (this_state) |
while (this_state) { |
{ |
closure(this_state->items, this_state->nitems); |
closure(this_state->items, this_state->nitems); |
save_reductions(); |
save_reductions(); |
new_itemsets(); |
new_itemsets(); |
append_states(); |
append_states(); |
|
|
|
if (nshifts > 0) |
if (nshifts > 0) |
save_shifts(); |
save_shifts(); |
|
|
this_state = this_state->next; |
this_state = this_state->next; |
} |
} |
|
|
finalize_closure(); |
finalize_closure(); |
free_storage(); |
free_storage(); |
} |
} |
|
|
|
|
|
|
short |
short |
get_state(int symbol) |
get_state(int symbol) |
{ |
{ |
int key; |
int key; |
short *isp1; |
short *isp1; |
short *isp2; |
short *isp2; |
short *iend; |
short *iend; |
core *sp; |
core *sp; |
int found; |
int found; |
int n; |
int n; |
|
|
#ifdef TRACE |
#ifdef TRACE |
fprintf(stderr, "Entering get_state(%d)\n", symbol); |
fprintf(stderr, "Entering get_state(%d)\n", symbol); |
#endif |
#endif |
|
|
isp1 = kernel_base[symbol]; |
isp1 = kernel_base[symbol]; |
iend = kernel_end[symbol]; |
iend = kernel_end[symbol]; |
n = iend - isp1; |
n = iend - isp1; |
|
|
key = *isp1; |
key = *isp1; |
assert(0 <= key && key < nitems); |
assert(0 <= key && key < nitems); |
sp = state_set[key]; |
sp = state_set[key]; |
if (sp) |
if (sp) { |
{ |
found = 0; |
found = 0; |
while (!found) { |
while (!found) |
if (sp->nitems == n) { |
{ |
found = 1; |
if (sp->nitems == n) |
isp1 = kernel_base[symbol]; |
{ |
isp2 = sp->items; |
found = 1; |
|
isp1 = kernel_base[symbol]; |
|
isp2 = sp->items; |
|
|
|
while (found && isp1 < iend) |
while (found && isp1 < iend) { |
{ |
if (*isp1++ != *isp2++) |
if (*isp1++ != *isp2++) |
found = 0; |
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); |
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); |
return (sp->number); |
} |
} |
|
|
|
|
void |
void |
initialize_states(void) |
initialize_states(void) |
{ |
{ |
int i; |
int i; |
short *start_derives; |
short *start_derives; |
core *p; |
core *p; |
|
|
start_derives = derives[start_symbol]; |
start_derives = derives[start_symbol]; |
for (i = 0; start_derives[i] >= 0; ++i) |
for (i = 0; start_derives[i] >= 0; ++i) |
continue; |
continue; |
|
|
p = (core *) malloc(sizeof(core) + i*sizeof(short)); |
p = malloc(sizeof(core) + i * sizeof(short)); |
if (p == 0) no_space(); |
if (p == NULL) |
|
no_space(); |
|
|
p->next = 0; |
p->next = 0; |
p->link = 0; |
p->link = 0; |
p->number = 0; |
p->number = 0; |
p->accessing_symbol = 0; |
p->accessing_symbol = 0; |
p->nitems = i; |
p->nitems = i; |
|
|
for (i = 0; start_derives[i] >= 0; ++i) |
for (i = 0; start_derives[i] >= 0; ++i) |
p->items[i] = rrhs[start_derives[i]]; |
p->items[i] = rrhs[start_derives[i]]; |
|
|
first_state = last_state = this_state = p; |
first_state = last_state = this_state = p; |
nstates = 1; |
nstates = 1; |
} |
} |
|
|
void |
void |
new_itemsets(void) |
new_itemsets(void) |
{ |
{ |
int i; |
int i; |
int shiftcount; |
int shiftcount; |
short *isp; |
short *isp; |
short *ksp; |
short *ksp; |
int symbol; |
int symbol; |
|
|
memset(kernel_end, 0, nsyms * sizeof(short *)); |
memset(kernel_end, 0, nsyms * sizeof(short *)); |
|
|
shiftcount = 0; |
shiftcount = 0; |
isp = itemset; |
isp = itemset; |
while (isp < itemsetend) |
while (isp < itemsetend) { |
{ |
i = *isp++; |
i = *isp++; |
symbol = ritem[i]; |
symbol = ritem[i]; |
if (symbol > 0) { |
if (symbol > 0) |
ksp = kernel_end[symbol]; |
{ |
if (!ksp) { |
ksp = kernel_end[symbol]; |
shift_symbol[shiftcount++] = symbol; |
if (!ksp) |
ksp = kernel_base[symbol]; |
{ |
} |
shift_symbol[shiftcount++] = symbol; |
*ksp++ = i + 1; |
ksp = kernel_base[symbol]; |
kernel_end[symbol] = ksp; |
} |
} |
|
|
*ksp++ = i + 1; |
|
kernel_end[symbol] = ksp; |
|
} |
} |
} |
|
|
|
nshifts = shiftcount; |
nshifts = shiftcount; |
} |
} |
|
|
|
|
|
|
core * |
core * |
new_state(int symbol) |
new_state(int symbol) |
{ |
{ |
int n; |
int n; |
core *p; |
core *p; |
short *isp1; |
short *isp1; |
short *isp2; |
short *isp2; |
short *iend; |
short *iend; |
|
|
#ifdef TRACE |
#ifdef TRACE |
fprintf(stderr, "Entering new_state(%d)\n", symbol); |
fprintf(stderr, "Entering new_state(%d)\n", symbol); |
#endif |
#endif |
|
|
if (nstates >= MAXSHORT) |
if (nstates >= MAXSHORT) |
fatal("too many states"); |
fatal("too many states"); |
|
|
isp1 = kernel_base[symbol]; |
isp1 = kernel_base[symbol]; |
iend = kernel_end[symbol]; |
iend = kernel_end[symbol]; |
n = iend - isp1; |
n = iend - isp1; |
|
|
p = allocate(sizeof(core) + (n - 1) * sizeof(short)); |
p = allocate(sizeof(core) + (n - 1) * sizeof(short)); |
p->accessing_symbol = symbol; |
p->accessing_symbol = symbol; |
p->number = nstates; |
p->number = nstates; |
p->nitems = n; |
p->nitems = n; |
|
|
isp2 = p->items; |
isp2 = p->items; |
while (isp1 < iend) |
while (isp1 < iend) |
*isp2++ = *isp1++; |
*isp2++ = *isp1++; |
|
|
last_state->next = p; |
last_state->next = p; |
last_state = p; |
last_state = p; |
|
|
nstates++; |
nstates++; |
|
|
return (p); |
return (p); |
} |
} |
|
|
|
|
void |
void |
save_shifts(void) |
save_shifts(void) |
{ |
{ |
shifts *p; |
shifts *p; |
short *sp1; |
short *sp1; |
short *sp2; |
short *sp2; |
short *send; |
short *send; |
|
|
p = allocate(sizeof(shifts) + (nshifts - 1) * sizeof(short)); |
p = allocate(sizeof(shifts) + (nshifts - 1) * sizeof(short)); |
|
|
p->number = this_state->number; |
p->number = this_state->number; |
p->nshifts = nshifts; |
p->nshifts = nshifts; |
|
|
sp1 = shiftset; |
sp1 = shiftset; |
sp2 = p->shift; |
sp2 = p->shift; |
send = shiftset + nshifts; |
send = shiftset + nshifts; |
|
|
while (sp1 < send) |
while (sp1 < send) |
*sp2++ = *sp1++; |
*sp2++ = *sp1++; |
|
|
if (last_shift) |
if (last_shift) { |
{ |
last_shift->next = p; |
last_shift->next = p; |
last_shift = p; |
last_shift = p; |
} else { |
} |
first_shift = p; |
else |
last_shift = p; |
{ |
} |
first_shift = p; |
|
last_shift = p; |
|
} |
|
} |
} |
|
|
|
|
void |
void |
save_reductions(void) |
save_reductions(void) |
{ |
{ |
short *isp; |
short *isp; |
short *rp1; |
short *rp1; |
short *rp2; |
short *rp2; |
int item; |
int item; |
int count; |
int count; |
reductions *p; |
reductions *p; |
short *rend; |
short *rend; |
|
|
count = 0; |
count = 0; |
for (isp = itemset; isp < itemsetend; isp++) |
for (isp = itemset; isp < itemsetend; isp++) { |
{ |
item = ritem[*isp]; |
item = ritem[*isp]; |
if (item < 0) { |
if (item < 0) |
redset[count++] = -item; |
{ |
} |
redset[count++] = -item; |
|
} |
} |
} |
|
|
|
if (count) |
if (count) { |
{ |
p = allocate(sizeof(reductions) + (count - 1) * sizeof(short)); |
p = allocate(sizeof(reductions) + (count - 1) * sizeof(short)); |
|
|
|
p->number = this_state->number; |
p->number = this_state->number; |
p->nreds = count; |
p->nreds = count; |
|
|
rp1 = redset; |
rp1 = redset; |
rp2 = p->rules; |
rp2 = p->rules; |
rend = rp1 + count; |
rend = rp1 + count; |
|
|
while (rp1 < rend) |
while (rp1 < rend) |
*rp2++ = *rp1++; |
*rp2++ = *rp1++; |
|
|
if (last_reduction) |
if (last_reduction) { |
{ |
last_reduction->next = p; |
last_reduction->next = p; |
last_reduction = p; |
last_reduction = p; |
} else { |
|
first_reduction = p; |
|
last_reduction = p; |
|
} |
} |
} |
else |
|
{ |
|
first_reduction = p; |
|
last_reduction = p; |
|
} |
|
} |
|
} |
} |
|
|
void |
void |
set_derives(void) |
set_derives(void) |
{ |
{ |
int i, k; |
int i, k; |
int lhs; |
int lhs; |
short *rules; |
short *rules; |
|
|
derives = NEW2(nsyms, short *); |
derives = NEW2(nsyms, short *); |
rules = NEW2(nvars + nrules, short); |
rules = NEW2(nvars + nrules, short); |
|
|
k = 0; |
k = 0; |
for (lhs = start_symbol; lhs < nsyms; lhs++) |
for (lhs = start_symbol; lhs < nsyms; lhs++) { |
{ |
derives[lhs] = rules + k; |
derives[lhs] = rules + k; |
for (i = 0; i < nrules; i++) { |
for (i = 0; i < nrules; i++) |
if (rlhs[i] == lhs) { |
{ |
rules[k] = i; |
if (rlhs[i] == lhs) |
k++; |
{ |
} |
rules[k] = i; |
} |
|
rules[k] = -1; |
k++; |
k++; |
} |
|
} |
} |
rules[k] = -1; |
|
k++; |
|
} |
|
|
|
#ifdef DEBUG |
#ifdef DEBUG |
print_derives(); |
print_derives(); |
#endif |
#endif |
} |
} |
|
|
void |
void |
free_derives(void) |
free_derives(void) |
{ |
{ |
free(derives[start_symbol]); |
free(derives[start_symbol]); |
free(derives); |
free(derives); |
} |
} |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
void |
void |
print_derives(void) |
print_derives(void) |
{ |
{ |
int i; |
int i; |
short *sp; |
short *sp; |
|
|
printf("\nDERIVES\n\n"); |
printf("\nDERIVES\n\n"); |
|
|
for (i = start_symbol; i < nsyms; i++) |
for (i = start_symbol; i < nsyms; i++) { |
{ |
printf("%s derives ", symbol_name[i]); |
printf("%s derives ", symbol_name[i]); |
for (sp = derives[i]; *sp >= 0; sp++) { |
for (sp = derives[i]; *sp >= 0; sp++) |
printf(" %d", *sp); |
{ |
} |
printf(" %d", *sp); |
putchar('\n'); |
} |
} |
putchar('\n'); |
|
} |
|
|
|
putchar('\n'); |
putchar('\n'); |
} |
} |
#endif |
#endif |
|
|
void |
void |
set_nullable(void) |
set_nullable(void) |
{ |
{ |
int i, j; |
int i, j; |
int empty; |
int empty; |
int done; |
int done; |
|
|
nullable = calloc(1, nsyms); |
nullable = calloc(1, nsyms); |
if (nullable == 0) no_space(); |
if (nullable == NULL) |
|
no_space(); |
|
|
done = 0; |
done = 0; |
while (!done) |
while (!done) { |
{ |
done = 1; |
done = 1; |
for (i = 1; i < nitems; i++) { |
for (i = 1; i < nitems; i++) |
empty = 1; |
{ |
while ((j = ritem[i]) >= 0) { |
empty = 1; |
if (!nullable[j]) |
while ((j = ritem[i]) >= 0) |
empty = 0; |
{ |
++i; |
if (!nullable[j]) |
} |
empty = 0; |
if (empty) { |
++i; |
j = rlhs[-j]; |
} |
if (!nullable[j]) { |
if (empty) |
nullable[j] = 1; |
{ |
done = 0; |
j = rlhs[-j]; |
} |
if (!nullable[j]) |
} |
{ |
|
nullable[j] = 1; |
|
done = 0; |
|
} |
} |
} |
|
} |
} |
} |
|
|
|
#ifdef DEBUG |
#ifdef DEBUG |
for (i = 0; i < nsyms; i++) |
for (i = 0; i < nsyms; i++) { |
{ |
if (nullable[i]) |
if (nullable[i]) |
printf("%s is nullable\n", symbol_name[i]); |
printf("%s is nullable\n", symbol_name[i]); |
else |
else |
printf("%s is not nullable\n", symbol_name[i]); |
printf("%s is not nullable\n", symbol_name[i]); |
} |
} |
|
#endif |
#endif |
} |
} |
|
|
void |
void |
free_nullable(void) |
free_nullable(void) |
{ |
{ |
free(nullable); |
free(nullable); |
} |
} |
|
|
void |
void |
lr0(void) |
lr0(void) |
{ |
{ |
set_derives(); |
set_derives(); |
set_nullable(); |
set_nullable(); |
generate_states(); |
generate_states(); |
} |
} |