ack/util/LLgen/lib/rec

377 lines
7.4 KiB
Plaintext
Raw Permalink Normal View History

1984-10-08 14:14:53 +00:00
/*
* Some grammar independent code.
* This file is copied into Lpars.c.
*/
1991-11-26 15:38:41 +00:00
#ifndef lint
1994-06-24 11:31:16 +00:00
static char *rcsid = "$Id$";
1991-11-26 15:38:41 +00:00
#endif
1984-10-08 14:14:53 +00:00
1985-11-25 15:50:19 +00:00
unsigned int LLtcnt[LL_NTERMINALS];
unsigned int LLscnt[LL_NSETS];
int LLcsymb, LLsymb;
1984-10-08 14:14:53 +00:00
static int LLlevel;
#if LL_NON_CORR
int LLstartsymb;
static int fake_eof = 0;
#endif
#define LL_VOIDCST (void)
1991-11-26 15:38:41 +00:00
void LLmessage(int);
#ifdef LL_USERHOOK
1991-12-02 15:25:01 +00:00
static int LLdoskip(int);
1991-11-26 15:38:41 +00:00
static int LLuserhook(int, int*);
#endif
#ifndef LL_FASTER
1991-11-26 15:38:41 +00:00
void LLscan(int t)
{
1984-10-08 14:14:53 +00:00
/*
* Check if the next symbol is equal to the parameter
*/
#if LL_NON_CORR
/* See if the error recovery has eaten an eof */
if (fake_eof) {
LLsymb = EOFILE;
fake_eof = 0;
}
else {
LLsymb = LL_LEXI();
}
if (LLsymb == t) {
#else
if ((LLsymb = LL_LEXI()) == t) {
#endif
#if LL_NON_CORR
/* Check if a previous parser has 'crashed', in that
* case continue with non-correcting parser
*/
if (err_seen && !nc_done) {
LLnc_recover();
nc_done = 1;
/* Remember that the error recovery has eaten an eof */
fake_eof = 1;
if (t != LLsymb) {
LLerror(t);
}
else
return;
}
#endif
1985-11-25 15:50:19 +00:00
return;
1984-10-08 14:14:53 +00:00
}
/*
* If we come here, an error has been detected
*/
1985-11-25 15:50:19 +00:00
LLerror(t);
}
1988-06-24 14:55:27 +00:00
#endif
1985-11-25 15:50:19 +00:00
1991-11-26 15:38:41 +00:00
void LLread(void) {
#if LL_NON_CORR
/* Again, check if another parser has crashed,
* in that case intercept and go to the
* non-correcting parser
*/
if (err_seen && !nc_done) {
LLnc_recover();
nc_done = 1;
/* Pretend we read end of file */
LLsymb = EOFILE;
LLcsymb = LLindex[EOFILE];
fake_eof = 0;
return;
}
if (fake_eof) {
LLsymb = EOFILE;
LLcsymb = LLindex[EOFILE];
fake_eof = 0;
return;
}
#endif
1985-11-25 15:50:19 +00:00
for (;;) {
if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
1985-11-25 15:50:19 +00:00
LLmessage(0);
1984-10-08 14:14:53 +00:00
}
1985-11-25 15:50:19 +00:00
/* NOTREACHED */
1984-10-08 14:14:53 +00:00
}
1991-11-26 15:38:41 +00:00
void LLerror(int t)
{
1985-11-25 15:50:19 +00:00
register int i;
1984-10-08 14:14:53 +00:00
if (t == EOFILE && LLsymb <= 0) return;
#ifdef LL_NEWMESS
if (t == EOFILE) {
1987-03-02 16:15:07 +00:00
#ifdef LL_USERHOOK
1987-04-13 16:34:46 +00:00
static int lst[] = { EOFILE, 0 };
LL_VOIDCST LLuserhook(EOFILE, lst);
1991-11-26 15:38:41 +00:00
#endif /* LL_USERHOOK */
if (LLsymb != EOFILE && LLsymb > 0) {
1987-03-02 16:15:07 +00:00
LLmessage(-1);
while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
/* nothing */ ;
1987-03-02 16:15:07 +00:00
}
return;
}
#endif
#if LL_NON_CORR
if ((!nc_done) && (LLsymb > 0) && (LLsymb != EOFILE)) {
LLmessage(0);
LLnc_recover();
nc_done = 1;
LLsymb = EOFILE;
}
#endif
1985-11-25 15:50:19 +00:00
if ((LLcsymb = LLindex[LLsymb]) < 0) {
LLmessage(0);
LLread();
1984-10-08 14:14:53 +00:00
}
1985-11-25 15:50:19 +00:00
i = LLindex[t];
LLtcnt[i]++;
1987-02-23 10:50:15 +00:00
#ifdef LL_USERHOOK
LL_VOIDCST LLdoskip(t);
1987-02-23 10:50:15 +00:00
#else
LL_VOIDCST LLskip();
1987-02-23 10:50:15 +00:00
#endif
1985-11-25 15:50:19 +00:00
LLtcnt[i]--;
if (LLsymb != t) {
#if LL_NON_CORR
/* A little kludge here; when using non-correcting recovery
* it can happen that a program is correct but incomplete.
* Here, we test this, and make sure the appropriate
* message is generated
*/
if (! nc_done) {
int oldLLsymb;
oldLLsymb = LLsymb;
LLsymb = EOFILE;
LLmessage(0);
nc_done = 1;
/* Not really, but to prevent more than 1 error message */
LLsymb = oldLLsymb;
}
#endif
LLmessage(t);
}
1984-10-08 14:14:53 +00:00
}
void LLsafeerror(int t)
{
if (t == EOFILE && LLsymb <= 0) return;
#ifdef LL_NEWMESS
if (t == EOFILE) {
#ifdef LL_USERHOOK
static int lst[] = { EOFILE, 0 };
LL_VOIDCST LLuserhook(EOFILE, lst);
#endif /* LL_USERHOOK */
if (LLsymb != EOFILE && LLsymb > 0) {
LLmessage(-1);
while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
/* nothing */ ;
}
return;
}
#endif
#if LL_NON_CORR
if ((!nc_done) && (LLsymb > 0) && (LLsymb != EOFILE)) {
LLmessage(0);
LLnc_recover();
nc_done = 1;
LLsymb = EOFILE;
}
/* A little kludge here; when using non-correcting recovery
* it can happen that a program is correct but incomplete.
* Here, we test this, and make sure the appropriate
* message is generated
*/
if (! nc_done) {
int oldLLsymb;
oldLLsymb = LLsymb;
LLsymb = EOFILE;
LLmessage(0);
nc_done = 1;
/* Not really, but to prevent more than 1 error message */
LLsymb = oldLLsymb;
}
#endif
LLmessage(t);
}
1991-11-26 15:38:41 +00:00
#ifndef LLNOFIRSTS
int LLfirst(int x, int d) {
1985-11-25 15:50:19 +00:00
register int i;
1984-10-08 14:14:53 +00:00
1985-11-25 15:50:19 +00:00
return (i = LLindex[x]) >= 0 &&
(LLsets[d + (i >> 3)] & (1 << (i & 07)));
1984-10-08 14:14:53 +00:00
}
1991-11-26 15:38:41 +00:00
#endif
1984-10-08 14:14:53 +00:00
1991-11-26 15:38:41 +00:00
int LLnext(int n)
{
/* returns: 0 if the current symbol is'nt skipped, and it
is'nt a member of "n",
1 if we have a new symbol, but it is'nt a member,
2 if the current symbol is a member,
and 3 if we have a new symbol and it is a member.
So, the low order bit indicates wether we have a new symbol,
and the next bit indicates wether it is a member of "n".
*/
int retval = 0;
if (LLskip()) retval = 1;
if (n <= 0 && LLsets[(LLcsymb >> 3) - n] & (1 << (LLcsymb & 07))) {
retval |= 2;
}
else if (n > 0 && LLcsymb == LLindex[n]) retval |= 2;
return retval;
1984-10-08 14:14:53 +00:00
}
1991-11-26 15:38:41 +00:00
int LLskip(void) {
/* returns 0 if the current symbol is'nt skipped, and
1 if it is, t.i., we have a new symbol
*/
#ifdef LL_USERHOOK
1987-02-23 10:50:15 +00:00
return LLdoskip(0);
}
1991-11-26 15:38:41 +00:00
extern void LL_USERHOOK(int, int *);
static int LLuserhook(int e, int *list)
1987-03-02 16:15:07 +00:00
{
int old = LLsymb;
1991-11-26 15:38:41 +00:00
LL_USERHOOK(e, list);
1987-03-02 16:15:07 +00:00
LLread();
return LLsymb != old;
}
1991-11-26 15:38:41 +00:00
static void LLmklist(register int *list)
1987-04-13 16:34:46 +00:00
{
char Xset[LL_SSIZE];
register char *p;
register int i;
for (p = &Xset[0]; p < &Xset[LL_SSIZE]; ) *p++ = 0;
for (i = 0; i < LL_NTERMINALS; i++) {
if (LLtcnt[i] != 0) Xset[i >> 3] |= (1 << (i & 07));
}
for (i = LL_NSETS - 1; i >= 0; i--) if (LLscnt[i] != 0) {
register char *q = &LLsets[LL_SSIZE * i];
p = &Xset[0];
while (p < &Xset[LL_SSIZE]) *p++ |= *q++;
}
for (i = 0; i < LL_NTERMINALS; i++) {
if (Xset[i >> 3] & (1 << (i & 07))) {
*list++ = LLtok[i];
}
}
*list = 0;
}
1991-11-26 15:38:41 +00:00
static int LLdoskip(int e)
{
int LLx;
1987-04-13 16:34:46 +00:00
int list[LL_NTERMINALS+1];
1991-11-26 15:38:41 +00:00
#endif /* LL_USERHOOK */
1985-11-25 15:50:19 +00:00
register int i;
int retval;
int LLi, LLb;
1984-10-08 14:14:53 +00:00
1985-11-25 15:50:19 +00:00
retval = 0;
1987-03-02 16:15:07 +00:00
#ifdef LL_USERHOOK
1987-04-13 16:34:46 +00:00
LLmklist(list);
1991-11-26 15:38:41 +00:00
LLx = LLuserhook(e, list);
if (LLx) retval = 1;
1991-11-26 15:38:41 +00:00
#endif /* LL_USERHOOK */
for (;;) {
1987-04-13 16:34:46 +00:00
if (LLtcnt[LLcsymb] != 0) {
#ifdef LL_USERHOOK
1991-11-26 15:38:41 +00:00
if (!e || !LLx || LLcsymb == LLindex[e])
1987-04-13 16:34:46 +00:00
#endif
return retval;
}
1985-11-25 15:50:19 +00:00
LLi = LLcsymb >> 3;
LLb = 1 << (LLcsymb & 07);
for (i = LL_NSETS - 1; i >= 0; i--) {
if (LLscnt[i] != 0) {
1987-03-02 16:15:07 +00:00
if (LLsets[LL_SSIZE*i+LLi] & LLb) {
1987-04-13 16:34:46 +00:00
#ifdef LL_USERHOOK
1991-11-26 15:38:41 +00:00
if (!e || !LLx || LLcsymb == LLindex[e])
1987-04-13 16:34:46 +00:00
#endif
1987-03-02 16:15:07 +00:00
return retval;
}
1985-11-25 15:50:19 +00:00
}
}
#ifdef LL_USERHOOK
1987-04-13 16:34:46 +00:00
if (LLx) {
1991-11-26 15:38:41 +00:00
LLx = LLuserhook(e, list);
1987-04-13 16:34:46 +00:00
continue;
}
1991-11-26 15:38:41 +00:00
#endif /* LL_USERHOOK */
#if LL_NON_CORR
if ((!nc_done) && (LLsymb > 0)) {
LLmessage(0);
LLnc_recover();
nc_done = 1;
fake_eof = 1;
}
else {
LLmessage(0);
}
#else
1985-11-25 15:50:19 +00:00
LLmessage(0);
#endif
1987-02-23 10:50:15 +00:00
retval = 1;
1985-11-25 15:50:19 +00:00
LLread();
}
/* NOTREACHED */
1984-10-08 14:14:53 +00:00
}
1991-11-26 15:38:41 +00:00
void LLnewlevel(unsigned int *LLsinfo) {
1985-11-25 15:50:19 +00:00
register int i;
1984-10-08 14:14:53 +00:00
1985-11-25 15:50:19 +00:00
if (LLlevel++) {
LLsinfo[LL_NSETS+LL_NTERMINALS] = (unsigned) LLsymb;
LLsinfo[LL_NSETS+LL_NTERMINALS+1] = (unsigned) LLcsymb;
for (i = LL_NTERMINALS - 1; i >= 0; i--) {
LLsinfo[i] = LLtcnt[i];
LLtcnt[i] = 0;
}
for (i = LL_NSETS - 1; i >= 0; i--) {
LLsinfo[LL_NTERMINALS+i] = LLscnt[i];
LLscnt[i] = 0;
}
1984-10-08 14:14:53 +00:00
}
1985-11-25 15:50:19 +00:00
LLtincr(0);
1984-10-08 14:14:53 +00:00
}
1991-11-26 15:38:41 +00:00
void LLoldlevel(unsigned int *LLsinfo) {
1985-11-25 15:50:19 +00:00
register int i;
1984-10-08 14:14:53 +00:00
1985-11-25 15:50:19 +00:00
LLtdecr(0);
1991-11-26 15:38:41 +00:00
#ifdef LL_DEBUG
1985-11-25 15:50:19 +00:00
for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
1991-11-26 15:38:41 +00:00
#endif
1984-10-08 14:14:53 +00:00
if (--LLlevel) {
1985-11-25 15:50:19 +00:00
for (i = LL_NSETS - 1; i >= 0; i--) {
LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
}
for (i = LL_NTERMINALS - 1; i >= 0; i--) {
LLtcnt[i] = LLsinfo[i];
}
LLsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS];
LLcsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS+1];
1984-10-08 14:14:53 +00:00
}
}