New version, much faster
This commit is contained in:
		
							parent
							
								
									42d0e056fb
								
							
						
					
					
						commit
						70a5d416d1
					
				
					 1 changed files with 113 additions and 179 deletions
				
			
		|  | @ -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) { | 	/* NOTREACHED */ | ||||||
| 				LLerror(0); | } | ||||||
| 				goto lab; | 
 | ||||||
| 				/* | LLerror(t) { | ||||||
| 				 * Ugly, but we want speed | 	register int i; | ||||||
| 			 	 * on possibly correct symbols !! | 
 | ||||||
| 			 	 * So, no breaks out of "for (;;)" | 	if ((LLcsymb = LLindex[LLsymb]) < 0) { | ||||||
| 			 	 */ | 		LLmessage(0); | ||||||
|  | 		LLread(); | ||||||
|  | 	} | ||||||
|  | 	i = LLindex[t]; | ||||||
|  | 	LLtcnt[i]++; | ||||||
|  | 	if (LLskip()) /* nothing */; | ||||||
|  | 	LLtcnt[i]--; | ||||||
|  | 	if (LLsymb != t) LLmessage(t); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # ifndef LLNOFIRSTS | ||||||
|  | LLfirst(x, d) { | ||||||
|  | 	register int i; | ||||||
|  | 
 | ||||||
|  | 	return (i = LLindex[x]) >= 0 && | ||||||
|  | 		(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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LLskip() { | ||||||
|  | 	register int i; | ||||||
|  | 	int retval; | ||||||
|  | 	int LLi, LLb; | ||||||
|  | 
 | ||||||
|  | 	retval = 0; | ||||||
|  | 	for (;;) { | ||||||
|  | 		if (LLtcnt[LLcsymb] != 0) return retval; | ||||||
|  | 		LLi = LLcsymb >> 3; | ||||||
|  | 		LLb = 1 << (LLcsymb & 07); | ||||||
|  | 		for (i = LL_NSETS - 1; i >= 0; i--) { | ||||||
|  | 			if (LLscnt[i] != 0) { | ||||||
|  | 				if (LLsets[LL_SSIZE*i+LLi] & LLb) return retval; | ||||||
| 			} | 			} | ||||||
| 			LLcsymb = i; |  | ||||||
| 			LLb = LLbyte[i]; |  | ||||||
| 			LLi = (i>>3); |  | ||||||
| 			LLscd = 1; |  | ||||||
| 		} | 		} | ||||||
| 		t = LLptr-1; | 		retval = 1; | ||||||
| 		i = *t; | 		LLmessage(0); | ||||||
| 		if (!((i<=0 && LLsets[LLi-i]&LLb)||i==LLsymb)) { | 		LLread(); | ||||||
| 			while (--t >= LLbase) { | 	} | ||||||
| 				/* | 	/* NOTREACHED */ | ||||||
| 			 	 * If the element on the stack is negative, | } | ||||||
| 			 	 * its opposite is an index in the setarray, | 
 | ||||||
| 			 	 * otherwise it is a terminal symbol | LLnewlevel(LLsinfo) unsigned int *LLsinfo; { | ||||||
| 			 	 */ | 	register int i; | ||||||
| 				i = *t; | 
 | ||||||
| 				if ((i<=0&&LLsets[LLi-i]&LLb)||i==LLsymb){ | 	if (LLlevel++) { | ||||||
| 					break; | 		LLsinfo[LL_NSETS+LL_NTERMINALS] = (unsigned) LLsymb; | ||||||
| 				} | 		LLsinfo[LL_NSETS+LL_NTERMINALS+1] = (unsigned) LLcsymb; | ||||||
| 			} | 		for (i = LL_NTERMINALS - 1; i >= 0; i--) { | ||||||
| 			if (t >= LLbase) break; | 			LLsinfo[i] = LLtcnt[i]; | ||||||
| 			LLerror(0); | 			LLtcnt[i] = 0; | ||||||
| 			LLscd = 0; |  | ||||||
| 		} | 		} | ||||||
| 		else { | 		for (i = LL_NSETS - 1; i >= 0; i--) { | ||||||
| 			return 1; | 			LLsinfo[LL_NTERMINALS+i] = LLscnt[i]; | ||||||
|  | 			LLscnt[i] = 0; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return t == LLptr - 1; | 	LLtincr(0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LLpop() { | LLoldlevel(LLsinfo) unsigned int *LLsinfo; { | ||||||
| 	register i; | 	register int i; | ||||||
| 
 | 
 | ||||||
| 	i = LLsskip(); | 	LLtdecr(0); | ||||||
| 	LLptr--; | # ifdef LL_DEBUG | ||||||
| 	return i; | 	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 | ||||||
| static |  | ||||||
| LLerror(d) { |  | ||||||
| 
 |  | ||||||
| 	LLmessage(d); |  | ||||||
| 	if (d < 0) exit(1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LLnewlevel() { |  | ||||||
| 	register struct LLsaved *p; |  | ||||||
| 
 |  | ||||||
| 	if (!LLlevel++) { |  | ||||||
| 		LLptr = LLstack; |  | ||||||
| 		LLbase = LLstack; |  | ||||||
| 		LLpush(EOFILE); |  | ||||||
| 	} |  | ||||||
| 	else { |  | ||||||
| 		if (LLlevel > LL_MAX) LLerror(-1); |  | ||||||
| 		p = &LLsaved[LLlevel - 2]; |  | ||||||
| 		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); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LLoldlevel() { |  | ||||||
| 	register struct LLsaved *p; |  | ||||||
| 
 |  | ||||||
| 	LLcheck(); |  | ||||||
| 	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 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue