215 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /* 
 | |
|  * Some grammar independent code.
 | |
|  * This file is copied into Lpars.c.
 | |
|  */
 | |
| 
 | |
| static char *rcsid = "$Header$";
 | |
| 
 | |
| #define LLSTSIZ	1024
 | |
| static short	LLstack[LLSTSIZ];		/* Recovery stack */
 | |
| short *		LLptr;				/* ptr in it */
 | |
| #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 LLs_i, LLs_b, LLs_s, LLs_c, LLs_t;
 | |
| 	short *LLs_p, *LLs_x;
 | |
| } LLsaved[LL_MAX];
 | |
| 
 | |
| /* In this file are defined: */
 | |
| extern		LLcheck();
 | |
| extern		LLscan();
 | |
| extern		LLpush();
 | |
| extern		LLlpush();
 | |
| extern int	LLpop();
 | |
| extern int	LLsskip();
 | |
| static		LLerror();
 | |
| extern		LLnewlevel();
 | |
| 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) {
 | |
| 	/*
 | |
| 	 * Check if the next symbol is equal to the parameter
 | |
| 	 */
 | |
| 	if (!LLscd) {
 | |
| 		if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
 | |
| 	}
 | |
| 	else LLscd = 0;
 | |
| 	if (LLsymb == t) return;
 | |
| 	/*
 | |
| 	 * If we come here, an error has been detected
 | |
| 	 */
 | |
| 	LLpush(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) {
 | |
| 	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 (;;) {
 | |
| 		if (!LLscd) {
 | |
| lab:
 | |
| 			if ((i = LL_LEXI()) <= 0) i = EOFILE;
 | |
| 			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;
 | |
| 			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() {
 | |
| 	register i;
 | |
| 
 | |
| 	i = LLsskip();
 | |
| 	LLptr--;
 | |
| 	return i;
 | |
| }
 | |
| 
 | |
| 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) {
 | |
| 		p = &LLsaved[LLlevel-1]; 
 | |
| 		LLptr = p->LLs_p;
 | |
| 		LLi = p->LLs_i;
 | |
| 		LLb = p->LLs_b;
 | |
| 		LLsymb = p->LLs_s;
 | |
| 		LLcsymb = p->LLs_t;
 | |
| 		LLbase = p->LLs_x;
 | |
| 		LLscd = p->LLs_c;
 | |
| 	}
 | |
| }
 | |
| 
 |