home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume19
/
wacco
/
part01
/
build.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-19
|
6KB
|
312 lines
// Copyright (c) 1991 by Parag Patel. All Rights Reserved.
static const char rcs_id[] = "$Header: build.C,v 1.5 91/02/22 16:07:15 hmgr Exp $";
#include "defs.h"
static void markempty()
{
symbol *sym, *s;
symnode *or, *next, *node;
int i, num;
boolean done;
num = numsymbols();
do
{
done = TRUE;
for (i = START; i < num; i++)
{
sym = getsymbol(i);
if (sym->type != NONTERMINAL)
continue;
for (or = sym->node; or != NULL; or = or->or)
{
for (node = or; node != NULL; node = node->next)
if (node->sym->type != CODE)
break;
if (node == NULL)
continue;
s = node->sym;
if (s->id == EMPTY && !sym->toempty)
{
sym->toempty = TRUE;
done = FALSE;
}
for (next = node; next != NULL; next = next->next)
if (next->sym->type != CODE && !next->sym->toempty)
break;
if (next == NULL && !sym->toempty)
{
sym->toempty = TRUE;
done = FALSE;
}
}
}
} while (!done);
}
static void first()
{
symbol *sym, *s;
symnode *or, *next, *node;
int i, num;
boolean done;
num = numsymbols();
do
{
done = TRUE;
for (i = START; i < num; i++)
{
sym = getsymbol(i);
if (sym->type == CODE)
continue;
if (sym->type == TERMINAL)
{
if (sym->first->isin(sym->id))
continue;
*sym->first += sym->id;
done = FALSE;
continue;
}
for (or = sym->node; or != NULL; or = or->or)
{
for (node = or; node != NULL; node = node->next)
if (node->sym->type != CODE)
break;
if (node == NULL)
continue;
s = node->sym;
if (s->id == EMPTY)
{
if (!sym->first->isin(EMPTY))
{
*sym->first += EMPTY;
done = FALSE;
}
continue;
}
for (next = node; next != NULL; next = next->next)
{
s = next->sym;
if (s->type == CODE)
continue;
if (!(*s->first <= *sym->first))
{
*sym->first |= *s->first;
done = FALSE;
}
if (!s->toempty)
break;
}
}
}
} while (!done);
}
static void follow()
{
symbol *sym, *s;
symnode *or, *node, *next, *n;
int i, num;
boolean done;
Bitset set;
num = numsymbols();
*startsymbol->follow += END;
do
{
done = TRUE;
for (i = START; i < num; i++)
{
sym = getsymbol(i);
if (sym->type != NONTERMINAL)
continue;
for (or = sym->node; or != NULL; or = or->or)
{
for (node = or; node != NULL; node = node->next)
{
s = node->sym;
if (s->type == CODE)
continue;
for (next = node->next; next != NULL; next = next->next)
if (next->sym->type != CODE)
break;
for (n = next; n != NULL; n = n->next)
if (n->sym->type != CODE && !n->sym->toempty)
break;
if (n == NULL)
{
if (*sym->follow <= *s->follow)
continue;
*s->follow |= *sym->follow;
done = FALSE;
}
if (next != NULL)
{
set = *next->sym->first;
set -= EMPTY;
if (!(set <= *s->follow))
{
*s->follow |= set;
done = FALSE;
}
}
}
}
}
} while (!done);
}
static void mksymresync(symbol *sym)
{
if (sym->list == NULL)
return;
Bitset *set = new Bitset;
resynclist *x;
for (resynclist *r = sym->list; r != NULL; x = r, r = r->next, delete x)
{
symbol *s;
if (r->name != NULL)
{
s = findsymbol(r->name);
if (s == NULL)
{
error("Symbol \"%s\" doesn't exist for \"%s\" resync set",
r->name, sym->name);
continue;
}
}
else if (r->paren == 0)
s = getsymbol(EMPTY);
else
{
error("Cannot handle paren groups in skip-set for \"%s\"",
sym->name);
continue;
}
if (r->first > 0 || (r->first == 0 && r->follow == 0))
*set |= *s->first;
else if (r->first < 0)
*set -= *s->first;
if (r->follow > 0)
*set |= *s->follow;
else if (r->follow < 0)
*set -= *s->follow;
}
sym->resync = &settab[set];
}
static void mkresync(symbol *sym, symnode *start, symnode *n)
{
Bitset *set = new Bitset;
symnode *t = n;
for (int i = 0; t != NULL && i <= 3; t = t->next, i++)
*set |= *t->sym->first;
resynclist *x;
for (resynclist *r = n->list; r != NULL; x = r, r = r->next, delete x)
{
symbol *s;
if (r->name != NULL)
{
s = findsymbol(r->name);
if (s == NULL)
{
for (symnode *t = start; t != NULL; t = t->next)
if (t->alias != NULL && strcmp(t->alias, r->name) == 0)
break;
if (t != NULL)
s = t->sym;
}
if (s == NULL)
{
error("Symbol \"%s\" doesn't exist for \"%s\" resync set",
r->name, sym->name);
continue;
}
}
else if (r->paren == 0)
s = getsymbol(EMPTY);
else
{
for (symnode *t = start; t != NULL; t = t->next)
if (t->sym->realname != NULL
&& t->sym->realname != t->sym->name)
if (--(*r).paren <= 0)
break;
if (t == NULL)
{
error("Paren group %d does not exist in rule for \"%s\"",
r->paren, sym->name);
continue;
}
s = t->sym;
}
if (r->first > 0 || (r->first == 0 && r->follow == 0))
*set |= *s->first;
else if (r->first < 0)
*set -= *s->first;
if (r->follow > 0)
*set |= *s->follow;
else if (r->follow < 0)
*set -= *s->follow;
}
n->resync = &settab[set];
}
static void resync()
{
int i;
symbol *sym;
int num = numsymbols();
symnode *or;
for (i = START; i < num; i++)
{
sym = getsymbol(i);
if (sym->type == CODE)
continue;
mksymresync(sym);
for (or = sym->node; or != NULL; or = or->or)
for (symnode *n = or; n != NULL; n = n->next)
mkresync(sym, or, n);
}
}
void buildsets()
{
markempty();
first();
follow();
resync();
}