xref: /csrg-svn/usr.bin/pascal/eyacc/ey3.c (revision 62087)
147968Sbostic /*-
2*62087Sbostic  * Copyright (c) 1979, 1993
3*62087Sbostic  *	The Regents of the University of California.  All rights reserved.
447968Sbostic  *
547968Sbostic  * %sccs.include.proprietary.c%
619572Smckusick  */
719572Smckusick 
819572Smckusick #ifndef lint
9*62087Sbostic static char sccsid[] = "@(#)ey3.c	8.1 (Berkeley) 06/06/93";
1047968Sbostic #endif /* not lint */
1119572Smckusick 
1219572Smckusick # include "ey.h"
1319572Smckusick 
cpres()1419572Smckusick cpres(){ /* conpute an array with the beginnings of  productions yielding given nonterminals
1519572Smckusick 	The array pres points to these lists */
1619572Smckusick 	int i,j,c;
1719572Smckusick 	pres = (int ***)yalloc(nnonter+1);
1819572Smckusick 	for(i=0;i<=nnonter;i++){
1919572Smckusick 		c = i+NTBASE;
2019572Smckusick 		pres[i] = (int **)mem;
2119572Smckusick 		fatfl = 0;  /* make undefined  symbols  nonfatal */
2219572Smckusick 		for(j=0;j<nprod;j++)
2319572Smckusick 		if (*prdptr[j] == c) *mem++ =  (int)(prdptr[j]+1);
2419572Smckusick 		if(pres[i] == (int **)mem){
2519572Smckusick 			error("nonterminal %s not defined!", nontrst[i].name);
2619572Smckusick 			}
2719572Smckusick 		}
2819572Smckusick 	pres[i] = (int **)mem;
2919572Smckusick 	fatfl = 1;
3019572Smckusick 	if( nerrors ){
3119572Smckusick 		summary();
3219572Smckusick 		cexit(1);
3319572Smckusick 		}
3419572Smckusick 	}
3519572Smckusick 
3619572Smckusick int indebug = 0;
cpfir()3719572Smckusick cpfir() {
3819572Smckusick   /* compute an array with the first of nonterminals */
3919572Smckusick   int i, ch, **s, **t, changes, *p;
4019572Smckusick 
4119572Smckusick   pfirst = (struct looksets **)yalloc(nnonter+1);
4219572Smckusick   for (i=0;i<=nnonter;i++) {
4319572Smckusick     aryfil( wsets[i].ws, tbitset, 0 );
4419572Smckusick     t = pres[i+1];
4519572Smckusick     for( s=pres[i]; s<t; ++s ){ /* initially fill the sets */
4619572Smckusick       for( p = *s; (ch = *p) > 0 ; ++p ) {
4719572Smckusick         if( ch < NTBASE ) {
4819572Smckusick           wsets[i].ws[ch>>4] |= (1 << (ch&017) );
4919572Smckusick           break;
5019572Smckusick           }
5119572Smckusick         else if( !pempty[ch-NTBASE] ) break;
5219572Smckusick         }
5319572Smckusick       }
5419572Smckusick     }
5519572Smckusick 
5619572Smckusick   /* now, reflect transitivity */
5719572Smckusick 
5819572Smckusick   changes = 1;
5919572Smckusick   while( changes ){
6019572Smckusick     changes = 0;
6119572Smckusick     for( i=0; i<=nnonter; ++i ){
6219572Smckusick       t = pres[i+1];
6319572Smckusick       for( s=pres[i]; s<t; ++s ){
6419572Smckusick         for( p = *s; ( ch = (*p-NTBASE) ) >= 0; ++p ) {
6519572Smckusick           changes |= UNION( wsets[i].ws, wsets[i].ws, wsets[ch].ws );
6619572Smckusick           if( !pempty[ch] ) break;
6719572Smckusick           }
6819572Smckusick         }
6919572Smckusick       }
7019572Smckusick     }
7119572Smckusick 
7219572Smckusick   for( i=0; i<=nnonter; i++ ) pfirst[i] = flset( wsets[i].ws );
7319572Smckusick   if( !indebug ) return;
7419572Smckusick   settty();
7519572Smckusick   for( i=0; i<=nnonter; i++ ){
7619572Smckusick     fprintf( cout ,  "\n%s: ", nontrst[i].name );
7719572Smckusick     prlook( pfirst[i] );
7819572Smckusick     fprintf( cout ,  " %d\n", pempty[i] );
7919572Smckusick     }
8019572Smckusick   }
8119572Smckusick 
state(c)8219572Smckusick state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */
8319572Smckusick 	int *s,size1,size2;
8419572Smckusick 	struct looksets *lp;
8519572Smckusick 	_REGISTER i;
8619572Smckusick 	struct item *p1, *p2, *k, *l, *q1, *q2;
8719572Smckusick 	p1 = pstate[nstate];
8819572Smckusick 	p2 = pstate[nstate+1];
8919572Smckusick 	if(p1==p2) return(0); /* null state */
9019572Smckusick 	/* sort the items */
9119572Smckusick 	for(k=p2-1;k>p1;k--) {	/* make k the biggest */
9219572Smckusick 		for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){
9319572Smckusick 			s = k->pitem;
9419572Smckusick 			k->pitem = l->pitem;
9519572Smckusick 			l->pitem = s;
9619572Smckusick 			lp = k->look;
9719572Smckusick 			k->look = l->look;
9819572Smckusick 			l->look = lp;
9919572Smckusick 			}
10019572Smckusick 		}
10119572Smckusick 	size1 = p2 - p1; /* size of state */
10219572Smckusick 
10319572Smckusick 	for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) {
10419572Smckusick 		/* get ith state */
10519572Smckusick 		q1 = pstate[i];
10619572Smckusick 		q2 = pstate[i+1];
10719572Smckusick 		size2 = q2 - q1;
10819572Smckusick 		if (size1 != size2) continue;
10919572Smckusick 		k=p1;
11019572Smckusick 		for(l=q1;l<q2;l++) {
11119572Smckusick 			if( l->pitem != k->pitem ) break;
11219572Smckusick 			++k;
11319572Smckusick 			}
11419572Smckusick 		if (l != q2) continue;
11519572Smckusick 		/* found it */
11619572Smckusick 		pstate[nstate+1] = pstate[nstate]; /* delete last state */
11719572Smckusick 		/* fix up lookaheads */
11819572Smckusick 		k=p1;
11919572Smckusick 		for( l=q1; l<q2; ++l ){
12019572Smckusick 			if( UNION( clset.lset, l->look->lset, k->look->lset ) ) {
12119572Smckusick 				tystate[i] = 1;
12219572Smckusick 				/* register the new set */
12319572Smckusick 				l->look = flset( &clset );
12419572Smckusick 				}
12519572Smckusick 			++k;
12619572Smckusick 			}
12719572Smckusick 		return (i);
12819572Smckusick 		}
12919572Smckusick /* state is new */
13019572Smckusick 	pstate[nstate+2] = p2;
13119572Smckusick 	if(nstate+1 >= stsize) error("too many states");
13219572Smckusick 	if( c >= NTBASE ){
13319572Smckusick 		mstates[ nstate ] = ntstates[ c-NTBASE ];
13419572Smckusick 		ntstates[ c-NTBASE ] = nstate;
13519572Smckusick 		}
13619572Smckusick 	else {
13719572Smckusick 		mstates[ nstate ] = tstates[ c ];
13819572Smckusick 		tstates[ c ] = nstate;
13919572Smckusick 		}
14019572Smckusick 	tystate[nstate]=1;
14119572Smckusick 	return(nstate++);
14219572Smckusick 	}
14319572Smckusick 
14419572Smckusick int pidebug = 0; /* debugging flag for putitem */
putitem(ptr,lptr)14519572Smckusick putitem ( ptr, lptr )		int *ptr; struct looksets *lptr;{
14619572Smckusick 	int *jip, k;
14719572Smckusick 	struct item *i, *j;
14819572Smckusick 
14919572Smckusick         if( pidebug ) {
15019572Smckusick           settty();
15119572Smckusick 	  fprintf( cout , "putitem(%s), state %d\n", writem(&ptr), nstate );
15219572Smckusick           }
15319572Smckusick 	/* see if it's there */
15419572Smckusick 	j = pstate[nstate+1];
15519572Smckusick         for( i=pstate[nstate]; i<j; ++i )
15619572Smckusick 		if(i->pitem == ptr) {
15719572Smckusick 			error("yacc error--duplicate item");
15819572Smckusick 			}
15919572Smckusick 	/* not there */
16019572Smckusick 	j->pitem = ptr;
16119572Smckusick 	j->look = flset( lptr );
16219572Smckusick 	pstate[nstate+1] = ++j;
16319572Smckusick 	jip = (int *)j;
16419572Smckusick 	if(jip-mem0 >= memsiz) error("out of state space");
16519572Smckusick 	}
16619572Smckusick 
cempty()16719572Smckusick cempty(){ /* mark nonterminals which derive the empty string */
16819572Smckusick 
16919572Smckusick   int i, *p;
17019572Smckusick 
17119572Smckusick   /* set pempty to 0 */
17219572Smckusick   pempty = (char *)yalloc( nnonter / sizeof(int) + 1 );
17319572Smckusick   aryfil( pempty, nnonter+1, 0 );
17419572Smckusick   for( i=1; i<nprod; ++i ) /* loop over productions */
17519572Smckusick     if( prdptr[i][1] <= 0 ) /* i is empty production */
17619572Smckusick       pempty[ *prdptr[i]-NTBASE ] = 1;
17719572Smckusick 
17819572Smckusick   /* now, all explicitly empty nonterminals marked with pempty = 1 */
17919572Smckusick 
18019572Smckusick   /* loop as long as we keep finding nontrivial empty nonterminals */
18119572Smckusick 
18219572Smckusick again:
18319572Smckusick   for( i=1; i<nprod; ++i ){
18419572Smckusick     if( pempty[ *prdptr[i]-NTBASE ]==0 ){ /* not known to be empty */
18519572Smckusick       for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]!=0 ; ++p ) ;
18619572Smckusick       if( *p < 0 ){ /* we have a nontrivially empty nonterminal */
18719572Smckusick         pempty[*prdptr[i]-NTBASE] = 1;
18819572Smckusick         goto again; /* got one ... try for another */
18919572Smckusick         }
19019572Smckusick       }
19119572Smckusick     }
19219572Smckusick   }
19319572Smckusick 
19419572Smckusick int gsdebug = 0;
stagen()19519572Smckusick stagen(){ /* generate the states */
19619572Smckusick 
19719572Smckusick   int i, j, k, c;
19819572Smckusick 
19919572Smckusick   /* initialize */
20019572Smckusick 
20119572Smckusick   nstate = 0;
20219572Smckusick   pstate[0] = pstate[1] = (struct item *)mem;
20319572Smckusick   aryfil( clset.lset, tbitset, 0 );
20419572Smckusick   putitem( prdptr[0]+1, &clset );
20519572Smckusick   tystate[0] = 1;
20619572Smckusick   nstate = 1;
20719572Smckusick   pstate[2] = pstate[1];
20819572Smckusick 
20919572Smckusick   memact = 0;
21019572Smckusick   aryfil( amem, actsiz, 0 );
21119572Smckusick 
21219572Smckusick   /* now, the main state generation loop */
21319572Smckusick 
21419572Smckusick   more:
21519572Smckusick   for( i=0; i<nstate; ++i ){
21619572Smckusick     /* if tystate == 2, set to zero */
21719572Smckusick     if( tystate[i] != 1 ) continue;
21819572Smckusick     tystate[i] = 0;
21919572Smckusick     aryfil( temp1, nterms+nnonter+1, 0 );
22019572Smckusick     /* take state i, close it, and do gotos */
22119572Smckusick     closure(i);
22219572Smckusick     for( j=0; j<cwset; ++j ){ /* generate gotos */
22319572Smckusick       if( wsets[j].flag ) continue;
22419572Smckusick       wsets[j].flag = 1;
22519572Smckusick       c = *(wsets[j].pitem);
22619572Smckusick       /* if no symbols after the dot (ie empty rule) */
22719572Smckusick       if( c <= 1 ) {
22819572Smckusick 	/* if not in kernel then tystate = 2 unless not done with it */
22919572Smckusick 	if( pstate[i+1]-pstate[i] <= j ) tystate[i] = (tystate[i]==1)?1:2;
23019572Smckusick 	continue;
23119572Smckusick 	}
23219572Smckusick       /* do a goto on c */
23319572Smckusick       for( k=j; k<cwset; ++k ){
23419572Smckusick         if( c == *(wsets[k].pitem) ){ /* this item contributes to the goto */
23519572Smckusick           putitem( wsets[k].pitem + 1, wsets[k].ws );
23619572Smckusick           wsets[k].flag = 1;
23719572Smckusick           }
23819572Smckusick         }
23919572Smckusick       if( c < NTBASE ) temp1[c] = state(c);
24019572Smckusick       else temp1[c-NTBASE+nterms] = state(c);
24119572Smckusick       }
24219572Smckusick     if( gsdebug ){
24319572Smckusick       settty();
24419572Smckusick       fprintf( cout ,  "%d: ", i );
24519572Smckusick       for( j=1; j<=nterms; ++j ){
24619572Smckusick         if( temp1[j] != 0 ) fprintf( cout ,  "%s %d, ", symnam(j), temp1[j]);
24719572Smckusick         }
24819572Smckusick       for( j=1; j<=nnonter; ++j ){
24919572Smckusick         if( temp1[j+nterms] ) fprintf( cout ,  "%s %d, ", nontrst[j].name, temp1[j+nterms] );
25019572Smckusick         }
25119572Smckusick       fprintf( cout , "\n");
25219572Smckusick       }
25319572Smckusick     apstate[i] = apack( &temp1[0], nterms );
25419572Smckusick     indgo[i] = apack( &temp1[nterms+1], nnonter-1 ) - 1;
25519572Smckusick     goto more; /* we have done one goto; do some more */
25619572Smckusick     }
25719572Smckusick   /* no more to do... stop */
25819572Smckusick   }
25919572Smckusick 
26019572Smckusick int cldebug = 0; /* debugging flag for closure */
closure(i)26119572Smckusick closure(i){ /* generate the closure of state i */
26219572Smckusick 
26319572Smckusick   int c, ch, work;
26419572Smckusick   _REGISTER j, k;
26519572Smckusick   int *pi;
26619572Smckusick   int **s, **t;
26719572Smckusick   struct item *q;
26819572Smckusick   _REGISTER struct item *p;
26919572Smckusick 
27019572Smckusick   ++zzclose;
27119572Smckusick 
27219572Smckusick   /* first, copy kernel of state i to wsets */
27319572Smckusick 
27419572Smckusick   lambdarule = -1;
27519572Smckusick   cwset = 0;
27619572Smckusick   q = pstate[i+1];
27719572Smckusick   /* for every item in the kernel */
27819572Smckusick   for( p=pstate[i]; p<q; ++p ){
27919572Smckusick     wsets[cwset].pitem = p->pitem;
28019572Smckusick     wsets[cwset].flag = 1;    /* this item must get closed */
28119572Smckusick     for( k=0; k<tbitset; ++k ) wsets[cwset].ws[k] = p->look->lset[k];
28219572Smckusick     ++cwset;
28319572Smckusick     }
28419572Smckusick 
28519572Smckusick   /* now, go through the loop, closing each item */
28619572Smckusick 
28719572Smckusick   work = 1;
28819572Smckusick   while( work ){
28919572Smckusick     work = 0;
29019572Smckusick     for( j=0; j<cwset; ++j ){
29119572Smckusick 
29219572Smckusick       /* for every item in state, if terminal after dot, flag = 0 */
29319572Smckusick       if( wsets[j].flag == 0 ) continue;
29419572Smckusick       /* dot is before c, since pitem of X -> A.B is B */
29519572Smckusick       c = *(wsets[j].pitem);
29619572Smckusick 
29719572Smckusick       if( c < NTBASE ){
29819572Smckusick         wsets[j].flag = 0;
29919572Smckusick         continue;  /* only interesting case is where . is before nonterminal */
30019572Smckusick         }
30119572Smckusick 
30219572Smckusick       /* compute the lookahead */
30319572Smckusick       aryfil( clset.lset, tbitset, 0 );
30419572Smckusick 
30519572Smckusick       /* find items involving c */
30619572Smckusick 
30719572Smckusick       /* for all the rest of the items in the state */
30819572Smckusick       for( k=j; k<cwset; ++k ){
30919572Smckusick         if( wsets[k].flag == 1 && *(pi=wsets[k].pitem) == c ){
31019572Smckusick           wsets[k].flag = 0;
31119572Smckusick           if( nolook ) continue;
31219572Smckusick           while( (ch= *++pi)>0 ){
31319572Smckusick             if( ch < NTBASE ){ /* terminal symbol */
31419572Smckusick 	      /* put ch in clset */
31519572Smckusick               clset.lset[ch>>4] |= (1<<(ch&017));
31619572Smckusick               break;
31719572Smckusick               }
31819572Smckusick             /* nonterminal symbol */
31919572Smckusick 	    /* clset <- clset U first(ch) */
32019572Smckusick             UNION( clset.lset, clset.lset, pfirst[ch-NTBASE] );
32119572Smckusick 	    /* if ch cannot derive lambda we are done */
32219572Smckusick             if( !pempty[ch-NTBASE] ) break;
32319572Smckusick             }
32419572Smckusick 	  /* if end of rule the clset <- clset U (lookahead for LHS) */
32519572Smckusick           if( ch<=0 ) UNION( clset.lset, clset.lset, wsets[k].ws );
32619572Smckusick           }
32719572Smckusick         }
32819572Smckusick 
32919572Smckusick       /*  now loop over productions derived from c */
33019572Smckusick 
33119572Smckusick       c -= NTBASE; /* c is now nonterminal number */
33219572Smckusick 
33319572Smckusick       t = pres[c+1];
33419572Smckusick       /* for each rule that c derives */
33519572Smckusick       for( s=pres[c]; s<t; ++s ){
33619572Smckusick         /* put these items into the closure */
33719572Smckusick         for( k=0; k<cwset; ++k ){ /* is the item there */
33819572Smckusick           if( wsets[k].pitem == *s ){ /* yes, it is there */
33919572Smckusick             if( nolook ) goto nexts;
34019572Smckusick 	    /* if something new in ws, set flag = 1 */
34119572Smckusick             if( UNION( wsets[k].ws, wsets[k].ws, clset.lset ) )
34219572Smckusick 	      wsets[k].flag = work = 1;
34319572Smckusick             goto nexts;
34419572Smckusick             }
34519572Smckusick           }
34619572Smckusick 
34719572Smckusick         /*  not there; make a new entry */
34819572Smckusick         if( cwset+1 >= wssize ) error( "working set overflow" );
34919572Smckusick         wsets[cwset].pitem = *s;
35019572Smckusick         wsets[cwset].flag = 1;
35119572Smckusick 	if (**s < 0)
35219572Smckusick 	  lambdarule = cwset;
35319572Smckusick         if( nolook ){
35419572Smckusick           cwset++;
35519572Smckusick           goto nexts;
35619572Smckusick           }
35719572Smckusick         work = 1;
35819572Smckusick         for( k=0; k<tbitset; ++k ) wsets[cwset].ws[k] = clset.lset[k];
35919572Smckusick         cwset++;
36019572Smckusick 
36119572Smckusick       nexts: ;
36219572Smckusick         }
36319572Smckusick 
36419572Smckusick       }
36519572Smckusick     }
36619572Smckusick 
36719572Smckusick   /* have computed closure; flags are reset; return */
36819572Smckusick 
36919572Smckusick   if( cwset > zzcwset ) zzcwset = cwset;
37019572Smckusick   if( !cldebug ) return;
37119572Smckusick   settty();
37219572Smckusick   fprintf( cout , "\nState %d, nolook = %d\n", i, nolook );
37319572Smckusick   for( j=0; j<cwset; ++j ){
37419572Smckusick     if( wsets[j].flag ) fprintf( cout , "flag set!\n");
37519572Smckusick     wsets[j].flag = 0;
37619572Smckusick     fprintf( cout , "\t%s", writem(&wsets[j].pitem));
37719572Smckusick     prlook( wsets[j].ws );
37819572Smckusick     fprintf( cout ,  "\n" );
37919572Smckusick     }
38019572Smckusick 
38119572Smckusick   }
38219572Smckusick 
flset(p)38319572Smckusick struct looksets *flset( p )
38419572Smckusick 	struct looksets *p;
38519572Smckusick 	{
38619572Smckusick 	/* decide if the lookahead set pointed to by p is known */
38719572Smckusick 	/* return pointer to a perminent location for the set */
38819572Smckusick 
38919572Smckusick 	int j, *w;
39019572Smckusick 	_REGISTER *u, *v, i;
39119572Smckusick 
39219572Smckusick 	for( i=0; i<nlset; ++i ){
39319572Smckusick 		u = p->lset;
39419572Smckusick 		v = lkst[i].lset;
39519572Smckusick 		w = & v[tbitset];
39619572Smckusick 		while( v<w) if( *u++ != *v++ ) goto more;
39719572Smckusick 		/* we have matched */
39819572Smckusick 		return( & lkst[i] );
39919572Smckusick 		more: ;
40019572Smckusick 		}
40119572Smckusick 	/* add a new one */
40219572Smckusick 	if( nlset+1 >= lsetsz )error("too many lookahead sets");
40319572Smckusick 	for( j=0; j<tbitset; ++j ){
40419572Smckusick 		lkst[nlset].lset[j] = p->lset[j];
40519572Smckusick 		}
40619572Smckusick 	return( & lkst[nlset++]);
40719572Smckusick 	}
408