New version, much faster

This commit is contained in:
ceriel 1985-11-25 15:50:19 +00:00
parent 42d0e056fb
commit 70a5d416d1

View file

@ -3,215 +3,149 @@
* This file is copied into Lpars.c. * This file is copied into Lpars.c.
*/ */
# ifndef NORCSID # ifndef lint
static char *rcsid = "$Header$"; static char *rcsid = "$Header$";
# endif # endif
#define LLSTSIZ 1024 # ifdef LL_DEBUG
static short LLstack[LLSTSIZ]; /* Recovery stack */ # include <stdio.h>
short * LLptr; /* ptr in it */ # endif
#define LLmax (&LLstack[LLSTSIZ-1]) /* if beyond this, overflow */
int LLscd; /* lookahead done or not? */
int LLb,LLi;
int LLsymb;
int LLcsymb;
static int LLlevel;
static short * LLbase;
static struct LLsaved { int LLsymb;
int LLs_i, LLs_b, LLs_s, LLs_c, LLs_t; unsigned int LLtcnt[LL_NTERMINALS];
short *LLs_p, *LLs_x; unsigned int LLscnt[LL_NSETS];
} LLsaved[LL_MAX]; int LLcsymb, LLsymb;
static int LLlevel;
/* In this file are defined: */ /* In this file are defined: */
extern LLcheck(); extern LLread();
extern int LLskip();
extern int LLnext();
extern LLscan(); extern LLscan();
extern LLpush(); extern LLerror();
extern LLlpush(); # ifndef LLNOFIRSTS
extern int LLpop(); extern int LLfirst();
extern int LLsskip(); # endif
static LLerror();
extern LLnewlevel(); extern LLnewlevel();
extern LLoldlevel(); extern LLoldlevel();
LLcheck() {
register c;
/*
* The symbol to be checked is on the stack.
*/
if (!LLscd) {
if ((c = LL_LEXI()) <= 0) c = EOFILE;
LLsymb = c;
}
else LLscd = 0;
if (LLsymb == *--LLptr) return;
/*
* If we come here, an error has been detected.
* LLpop will try and recover
*/
LLptr++;
while (LLindex[LLsymb] < 0) {
LLerror(0);
if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
}
LLcsymb = LLindex[LLsymb];
LLb = LLbyte[LLcsymb];
LLi = LLcsymb>>3;
LLscd = 1;
if (!LLpop()) LLerror(*LLptr);
LLscd = 0;
}
LLscan(t) { LLscan(t) {
/* /*
* Check if the next symbol is equal to the parameter * Check if the next symbol is equal to the parameter
*/ */
if (!LLscd) {
if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE; if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
if (LLsymb == t) {
return;
} }
else LLscd = 0;
if (LLsymb == t) return;
/* /*
* If we come here, an error has been detected * If we come here, an error has been detected
*/ */
LLpush(t); LLerror(t);
LLscd = 1;
while (LLindex[LLsymb] < 0) {
LLerror(0);
if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
}
LLcsymb = LLindex[LLsymb];
LLb = LLbyte[LLcsymb];
LLi = LLcsymb>>3;
if (!LLpop()) LLerror(t);
LLscd = 0;
} }
LLpush(t) { LLread() {
if (LLptr == LLmax) {
LLerror(-1);
}
*LLptr++ = t;
}
LLlpush(d) {
register i;
register short *p;
p = &LLlists[d];
i = *p++;
while(i--) {
if (LLptr == LLmax) {
LLerror(-1);
}
*LLptr++ = *p++;
}
}
LLsskip() {
/*
* Error recovery, and not only that!
* Skip symbols until one is found that is on the stack.
* Return 1 if it is on top of the stack
*/
register short *t;
register i;
for (;;) { for (;;) {
if (!LLscd) { if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
lab: if ((LLcsymb = LLindex[LLsymb]) >= 0) return;
if ((i = LL_LEXI()) <= 0) i = EOFILE; LLmessage(0);
LLsymb = i;
if ((i = LLindex[i]) < 0) {
LLerror(0);
goto lab;
/*
* Ugly, but we want speed
* on possibly correct symbols !!
* So, no breaks out of "for (;;)"
*/
} }
LLcsymb = i; /* NOTREACHED */
LLb = LLbyte[i];
LLi = (i>>3);
LLscd = 1;
}
t = LLptr-1;
i = *t;
if (!((i<=0 && LLsets[LLi-i]&LLb)||i==LLsymb)) {
while (--t >= LLbase) {
/*
* If the element on the stack is negative,
* its opposite is an index in the setarray,
* otherwise it is a terminal symbol
*/
i = *t;
if ((i<=0&&LLsets[LLi-i]&LLb)||i==LLsymb){
break;
}
}
if (t >= LLbase) break;
LLerror(0);
LLscd = 0;
}
else {
return 1;
}
}
return t == LLptr - 1;
} }
LLpop() { LLerror(t) {
register i; register int i;
i = LLsskip(); if ((LLcsymb = LLindex[LLsymb]) < 0) {
LLptr--; LLmessage(0);
return i; LLread();
}
i = LLindex[t];
LLtcnt[i]++;
if (LLskip()) /* nothing */;
LLtcnt[i]--;
if (LLsymb != t) LLmessage(t);
} }
static # ifndef LLNOFIRSTS
LLerror(d) { LLfirst(x, d) {
register int i;
LLmessage(d); return (i = LLindex[x]) >= 0 &&
if (d < 0) exit(1); (LLsets[d + (i >> 3)] & (1 << (i & 07)));
}
# endif
LLnext(n) {
if (LLskip()) /* nothing */;
if (n <= 0) return (LLsets[(LLcsymb >> 3) - n] & (1 << (LLcsymb & 07)));
return LLsymb == n;
} }
LLnewlevel() { LLskip() {
register struct LLsaved *p; register int i;
int retval;
int LLi, LLb;
if (!LLlevel++) { retval = 0;
LLptr = LLstack; for (;;) {
LLbase = LLstack; if (LLtcnt[LLcsymb] != 0) return retval;
LLpush(EOFILE); LLi = LLcsymb >> 3;
} LLb = 1 << (LLcsymb & 07);
else { for (i = LL_NSETS - 1; i >= 0; i--) {
if (LLlevel > LL_MAX) LLerror(-1); if (LLscnt[i] != 0) {
p = &LLsaved[LLlevel - 2]; if (LLsets[LL_SSIZE*i+LLi] & LLb) return retval;
p->LLs_p = LLptr;
p->LLs_i = LLi;
p->LLs_b = LLb;
p->LLs_s = LLsymb;
p->LLs_t = LLcsymb;
p->LLs_c = LLscd;
p->LLs_x = LLbase;
LLbase = LLptr;
LLpush(EOFILE);
} }
} }
retval = 1;
LLmessage(0);
LLread();
}
/* NOTREACHED */
}
LLoldlevel() { LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
register struct LLsaved *p; register int i;
LLcheck(); 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;
}
}
LLtincr(0);
}
LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
register int i;
LLtdecr(0);
# ifdef LL_DEBUG
for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
# endif
if (--LLlevel) { if (--LLlevel) {
p = &LLsaved[LLlevel-1]; for (i = LL_NSETS - 1; i >= 0; i--) {
LLptr = p->LLs_p; LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
LLi = p->LLs_i; }
LLb = p->LLs_b; for (i = LL_NTERMINALS - 1; i >= 0; i--) {
LLsymb = p->LLs_s; LLtcnt[i] = LLsinfo[i];
LLcsymb = p->LLs_t; }
LLbase = p->LLs_x; LLsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS];
LLscd = p->LLs_c; LLcsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS+1];
} }
} }
# ifdef LL_DEBUG
LL_badassertion(asstr,file,line) char *asstr, *file; {
fprintf(stderr,"Assertion \"%s\" failed %s(%d)\n",asstr,file,line);
abort();
}
# endif