Build lexer and parser from libCom/Makefile. Since libCom now includes asLib.c and asLib_lex.c we must build antelope and flex without linking them to Com. This works because they only need epicsTempFile anyway. However make doesn't like a subdirectory with the same name as a target object, so the antelope source directory is now called yacc. The two main.c files were also renamed to avoid other build problems. Merge asHost into Com and remove mentions in CONFIG_BASE Lots of noise since SRCS must be renamed to Com_SRCS
614 lines
9.8 KiB
C
614 lines
9.8 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2002 The Regents of the University of California, as
|
|
* Operator of Los Alamos National Laboratory.
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
|
|
#include "defs.h"
|
|
|
|
extern short *itemset;
|
|
extern short *itemsetend;
|
|
extern unsigned *ruleset;
|
|
|
|
int nstates;
|
|
core *first_state;
|
|
shifts *first_shift;
|
|
reductions *first_reduction;
|
|
|
|
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;
|
|
|
|
static int get_state(int symbol);
|
|
static void initialize_states(void);
|
|
static void new_itemsets(void);
|
|
static core *new_state(int symbol);
|
|
static void save_shifts(void);
|
|
static void save_reductions(void);
|
|
#ifdef DEBUG
|
|
static void print_derives(void);
|
|
#endif
|
|
|
|
|
|
static void
|
|
allocate_itemsets(void)
|
|
{
|
|
short *itemp;
|
|
short *item_end;
|
|
int symbol;
|
|
int i;
|
|
int count;
|
|
int max;
|
|
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 *);
|
|
}
|
|
|
|
static void
|
|
allocate_storage(void)
|
|
{
|
|
allocate_itemsets();
|
|
shiftset = NEW2(nsyms, short);
|
|
redset = NEW2(nrules + 1, short);
|
|
state_set = NEW2(nitems, core *);
|
|
}
|
|
|
|
static void
|
|
append_states(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void
|
|
free_storage(void)
|
|
{
|
|
FREE(shift_symbol);
|
|
FREE(redset);
|
|
FREE(shiftset);
|
|
FREE(kernel_base);
|
|
FREE(kernel_end);
|
|
FREE(kernel_items);
|
|
FREE(state_set);
|
|
}
|
|
|
|
|
|
static void
|
|
generate_states(void)
|
|
{
|
|
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();
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
get_state(int symbol)
|
|
{
|
|
int key;
|
|
short *isp1;
|
|
short *isp2;
|
|
short *iend;
|
|
core *sp;
|
|
int found;
|
|
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);
|
|
}
|
|
|
|
|
|
static void
|
|
initialize_states(void)
|
|
{
|
|
int i;
|
|
short *start_derives;
|
|
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;
|
|
}
|
|
|
|
static void
|
|
new_itemsets(void)
|
|
{
|
|
int i;
|
|
int shiftcount;
|
|
short *isp;
|
|
short *ksp;
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
static core *
|
|
new_state(int symbol)
|
|
{
|
|
int n;
|
|
core *p;
|
|
short *isp1;
|
|
short *isp2;
|
|
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);
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
static void
|
|
show_cores(void)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
show_ritems(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nitems; ++i)
|
|
printf("ritem[%d] = %d\n", i, ritem[i]);
|
|
}
|
|
|
|
|
|
static void
|
|
show_rrhs(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < nrules; ++i)
|
|
printf("rrhs[%d] = %d\n", i, rrhs[i]);
|
|
}
|
|
|
|
|
|
static void
|
|
show_shifts(void)
|
|
{
|
|
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]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
save_shifts(void)
|
|
{
|
|
shifts *p;
|
|
short *sp1;
|
|
short *sp2;
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
save_reductions(void)
|
|
{
|
|
short *isp;
|
|
short *rp1;
|
|
short *rp2;
|
|
int item;
|
|
int count;
|
|
reductions *p;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
set_derives(void)
|
|
{
|
|
int i, k;
|
|
int lhs;
|
|
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
|
|
}
|
|
|
|
void
|
|
free_derives(void)
|
|
{
|
|
FREE(derives[start_symbol]);
|
|
FREE(derives);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
static void
|
|
print_derives(void)
|
|
{
|
|
int i;
|
|
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
|
|
|
|
static void
|
|
set_nullable(void)
|
|
{
|
|
int i, j;
|
|
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
|
|
}
|
|
|
|
void
|
|
free_nullable(void)
|
|
{
|
|
FREE(nullable);
|
|
}
|
|
|
|
void
|
|
lr0(void)
|
|
{
|
|
set_derives();
|
|
set_nullable();
|
|
generate_states();
|
|
}
|