xref: /csrg-svn/old/yacc/y1.c (revision 37812)
110932Srrh #ifndef lint
2*37812Sbostic static char sccsid[] = "@(#)y1.c	4.2	(Berkeley)	05/10/89";
310932Srrh #endif not lint
410932Srrh 
510932Srrh # include "dextern"
6*37812Sbostic # include "pathnames.h"
710932Srrh 
810932Srrh 	/* variables used locally */
910932Srrh 
1010932Srrh 	/* lookahead computations */
1110932Srrh 
1210932Srrh int tbitset;  /* size of lookahead sets */
1310932Srrh struct looksets lkst [ LSETSIZE ];
1410932Srrh int nlset = 0; /* next lookahead set index */
1510932Srrh int nolook = 0; /* flag to suppress lookahead computations */
1610932Srrh struct looksets clset;  /* temporary storage for lookahead computations */
1710932Srrh 
1810932Srrh 	/* working set computations */
1910932Srrh 
2010932Srrh struct wset wsets[ WSETSIZE ];
2110932Srrh struct wset *cwp;
2210932Srrh 
2310932Srrh 	/* state information */
2410932Srrh 
2510932Srrh int nstate = 0;		/* number of states */
2610932Srrh struct item *pstate[NSTATES+2];	/* pointers to the descriptions of the states */
2710932Srrh int tystate[NSTATES];	/* contains type information about the states */
2810932Srrh int indgo[NSTATES];		/* index to the stored goto table */
2910932Srrh int tstates[ NTERMS ]; /* states generated by terminal gotos */
3010932Srrh int ntstates[ NNONTERM ]; /* states generated by nonterminal gotos */
3110932Srrh int mstates[ NSTATES ]; /* chain of overflows of term/nonterm generation lists  */
3210932Srrh 
3310932Srrh 	/* storage for the actions in the parser */
3410932Srrh 
3510932Srrh int amem[ACTSIZE];	/* action table storage */
3610932Srrh int *memp = amem;	/* next free action table position */
3710932Srrh 
3810932Srrh 	/* other storage areas */
3910932Srrh 
4010932Srrh int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or states */
4110932Srrh int lineno= 1; /* current input line number */
4210932Srrh int fatfl = 1;  	/* if on, error is fatal */
4310932Srrh int nerrors = 0;	/* number of errors */
4410932Srrh 
4510932Srrh 	/* storage for information about the nonterminals */
4610932Srrh 
4710932Srrh int **pres[NNONTERM+2];  /* vector of pointers to productions yielding each nonterminal */
4810932Srrh struct looksets *pfirst[NNONTERM+2];  /* vector of pointers to first sets for each nonterminal */
4910932Srrh int pempty[NNONTERM+1];  /* vector of nonterminals nontrivially deriving e */
5010932Srrh 
main(argc,argv)5110932Srrh main(argc,argv) int argc; char *argv[]; {
5210932Srrh 
5310932Srrh 	setup(argc,argv); /* initialize and read productions */
5410932Srrh 	tbitset = NWORDS(ntokens);
5510932Srrh 	cpres(); /* make table of which productions yield a given nonterminal */
5610932Srrh 	cempty(); /* make a table of which nonterminals can match the empty string */
5710932Srrh 	cpfir(); /* make a table of firsts of nonterminals */
5810932Srrh 	stagen(); /* generate the states */
5910932Srrh 	output();  /* write the states and the tables */
6010932Srrh 	go2out();
6110932Srrh 	hideprod();
6210932Srrh 	summary();
6310932Srrh 	callopt();
6410932Srrh 	others();
6510932Srrh 	exit(0);
6610932Srrh 	}
6710932Srrh 
others()6810932Srrh others(){ /* put out other arrays, copy the parsers */
6910932Srrh 	register c, i, j;
7010932Srrh 
71*37812Sbostic 	finput = fopen( _PATH_PARSER, "r" );
72*37812Sbostic 	if( finput == NULL ) error( "cannot find parser %s", _PATH_PARSER);
7310932Srrh 
7410932Srrh 	warray( "yyr1", levprd, nprod );
7510932Srrh 
7610932Srrh 	aryfil( temp1, nprod, 0 );
7710932Srrh 	PLOOP(1,i)temp1[i] = prdptr[i+1]-prdptr[i]-2;
7810932Srrh 	warray( "yyr2", temp1, nprod );
7910932Srrh 
8010932Srrh 	aryfil( temp1, nstate, -1000 );
8110932Srrh 	TLOOP(i){
8210932Srrh 		for( j=tstates[i]; j!=0; j=mstates[j] ){
8310932Srrh 			temp1[j] = tokset[i].value;
8410932Srrh 			}
8510932Srrh 		}
8610932Srrh 	NTLOOP(i){
8710932Srrh 		for( j=ntstates[i]; j!=0; j=mstates[j] ){
8810932Srrh 			temp1[j] = -i;
8910932Srrh 			}
9010932Srrh 		}
9110932Srrh 	warray( "yychk", temp1, nstate );
9210932Srrh 
9310932Srrh 	warray( "yydef", defact, nstate );
9410932Srrh 
9510932Srrh 	/* copy parser text */
9610932Srrh 
9710932Srrh 	while( (c=getc(finput) ) != EOF ){
9810932Srrh 		if( c == '$' ){
9910932Srrh 			if( (c=getc(finput)) != 'A' ) putc( '$', ftable );
10010932Srrh 			else { /* copy actions */
10110932Srrh 				faction = fopen( ACTNAME, "r" );
10210932Srrh 				if( faction == NULL ) error( "cannot reopen action tempfile" );
10310932Srrh 				while( (c=getc(faction) ) != EOF ) putc( c, ftable );
10410932Srrh 				fclose(faction);
10510932Srrh 				ZAPFILE(ACTNAME);
10610932Srrh 				c = getc(finput);
10710932Srrh 				}
10810932Srrh 			}
10910932Srrh 		putc( c, ftable );
11010932Srrh 		}
11110932Srrh 
11210932Srrh 	fclose( ftable );
11310932Srrh 	}
11410932Srrh 
chcopy(p,q)11510932Srrh char *chcopy( p, q )  char *p, *q; {
11610932Srrh 	/* copies string q into p, returning next free char ptr */
11710932Srrh 	while( *p = *q++ ) ++p;
11810932Srrh 	return( p );
11910932Srrh 	}
12010932Srrh 
12110932Srrh # define ISIZE 400
writem(pp)12210932Srrh char *writem(pp) int *pp; { /* creates output string for item pointed to by pp */
12310932Srrh 	int i,*p;
12410932Srrh 	static char sarr[ISIZE];
12510932Srrh 	char *q;
12610932Srrh 
12710932Srrh 	for( p=pp; *p>0 ; ++p ) ;
12810932Srrh 	p = prdptr[-*p];
12910932Srrh 	q = chcopy( sarr, nontrst[*p-NTBASE].name );
13010932Srrh 	q = chcopy( q, " : " );
13110932Srrh 
13210932Srrh 	for(;;){
13310932Srrh 		*q++ = ++p==pp ? '_' : ' ';
13410932Srrh 		*q = '\0';
13510932Srrh 		if((i = *p) <= 0) break;
13610932Srrh 		q = chcopy( q, symnam(i) );
13710932Srrh 		if( q> &sarr[ISIZE-30] ) error( "item too big" );
13810932Srrh 		}
13910932Srrh 
14010932Srrh 	if( (i = *pp) < 0 ){ /* an item calling for a reduction */
14110932Srrh 		q = chcopy( q, "    (" );
14210932Srrh 		sprintf( q, "%d)", -i );
14310932Srrh 		}
14410932Srrh 
14510932Srrh 	return( sarr );
14610932Srrh 	}
14710932Srrh 
symnam(i)14810932Srrh char *symnam(i){ /* return a pointer to the name of symbol i */
14910932Srrh 	char *cp;
15010932Srrh 
15110932Srrh 	cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : tokset[i].name ;
15210932Srrh 	if( *cp == ' ' ) ++cp;
15310932Srrh 	return( cp );
15410932Srrh 	}
15510932Srrh 
15610932Srrh struct wset *zzcwp = wsets;
15710932Srrh int zzgoent = 0;
15810932Srrh int zzgobest = 0;
15910932Srrh int zzacent = 0;
16010932Srrh int zzexcp = 0;
16110932Srrh int zzclose = 0;
16210932Srrh int zzsrconf = 0;
16310932Srrh int * zzmemsz = mem0;
16410932Srrh int zzrrconf = 0;
16510932Srrh 
summary()16610932Srrh summary(){ /* output the summary on the tty */
16710932Srrh 
16810932Srrh 	if( foutput!=NULL ){
16910932Srrh 		fprintf( foutput, "\n%d/%d terminals, %d/%d nonterminals\n", ntokens, NTERMS,
17010932Srrh 			    nnonter, NNONTERM );
17110932Srrh 		fprintf( foutput, "%d/%d grammar rules, %d/%d states\n", nprod, NPROD, nstate, NSTATES );
17210932Srrh 		fprintf( foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf );
17310932Srrh 		fprintf( foutput, "%d/%d working sets used\n", zzcwp-wsets,  WSETSIZE );
17410932Srrh 		fprintf( foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz-mem0, MEMSIZE,
17510932Srrh 			    memp-amem, ACTSIZE );
17610932Srrh 		fprintf( foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE );
17710932Srrh 		fprintf( foutput, "%d extra closures\n", zzclose - 2*nstate );
17810932Srrh 		fprintf( foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp );
17910932Srrh 		fprintf( foutput, "%d goto entries\n", zzgoent );
18010932Srrh 		fprintf( foutput, "%d entries saved by goto default\n", zzgobest );
18110932Srrh 		}
18210932Srrh 	if( zzsrconf!=0 || zzrrconf!=0 ){
18310932Srrh 		  fprintf( stdout,"\nconflicts: ");
18410932Srrh 		  if( zzsrconf )fprintf( stdout, "%d shift/reduce" , zzsrconf );
18510932Srrh 		  if( zzsrconf && zzrrconf )fprintf( stdout, ", " );
18610932Srrh 		  if( zzrrconf )fprintf( stdout, "%d reduce/reduce" , zzrrconf );
18710932Srrh 		  fprintf( stdout, "\n" );
18810932Srrh 		  }
18910932Srrh 
19010932Srrh 	fclose( ftemp );
19110932Srrh 	if( fdefine != NULL ) fclose( fdefine );
19210932Srrh 	}
19310932Srrh 
19410932Srrh /* VARARGS1 */
error(s,a1)19510932Srrh error(s,a1) char *s; { /* write out error comment */
19610932Srrh 
19710932Srrh 	++nerrors;
19810932Srrh 	fprintf( stderr, "\n fatal error: ");
19910932Srrh 	fprintf( stderr, s,a1);
20010932Srrh 	fprintf( stderr, ", line %d\n", lineno );
20110932Srrh 	if( !fatfl ) return;
20210932Srrh 	summary();
20310932Srrh 	exit(1);
20410932Srrh 	}
20510932Srrh 
aryfil(v,n,c)20610932Srrh aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */
20710932Srrh 	int i;
20810932Srrh 	for( i=0; i<n; ++i ) v[i] = c;
20910932Srrh 	}
21010932Srrh 
setunion(a,b)21110932Srrh setunion( a, b ) register *a, *b; {
21210932Srrh 	/* set a to the union of a and b */
21310932Srrh 	/* return 1 if b is not a subset of a, 0 otherwise */
21410932Srrh 	register i, x, sub;
21510932Srrh 
21610932Srrh 	sub = 0;
21710932Srrh 	SETLOOP(i){
21810932Srrh 		*a = (x = *a)|*b++;
21910932Srrh 		if( *a++ != x ) sub = 1;
22010932Srrh 		}
22110932Srrh 	return( sub );
22210932Srrh 	}
22310932Srrh 
22410932Srrh prlook( p ) struct looksets *p;{
22510932Srrh 	register j, *pp;
22610932Srrh 	pp = p->lset;
22710932Srrh 	if( pp == 0 ) fprintf( foutput, "\tNULL");
22810932Srrh 	else {
22910932Srrh 		fprintf( foutput, " { " );
TLOOP(j)23010932Srrh 		TLOOP(j) {
23110932Srrh 			if( BIT(pp,j) ) fprintf( foutput,  "%s ", symnam(j) );
23210932Srrh 			}
23310932Srrh 		fprintf( foutput,  "}" );
23410932Srrh 		}
23510932Srrh 	}
23610932Srrh 
cpres()23710932Srrh cpres(){ /* compute an array with the beginnings of  productions yielding given nonterminals
23810932Srrh 	The array pres points to these lists */
23910932Srrh 	/* the array pyield has the lists: the total size is only NPROD+1 */
24010932Srrh 	register **pmem;
24110932Srrh 	register c, j, i;
24210932Srrh 	static int * pyield[NPROD];
24310932Srrh 
24410932Srrh 	pmem = pyield;
24510932Srrh 
24610932Srrh 	NTLOOP(i){
24710932Srrh 		c = i+NTBASE;
24810932Srrh 		pres[i] = pmem;
24910932Srrh 		fatfl = 0;  /* make undefined  symbols  nonfatal */
25010932Srrh 		PLOOP(0,j){
25110932Srrh 			if (*prdptr[j] == c) *pmem++ =  prdptr[j]+1;
25210932Srrh 			}
25310932Srrh 		if(pres[i] == pmem){
25410932Srrh 			error("nonterminal %s not defined!", nontrst[i].name);
25510932Srrh 			}
25610932Srrh 		}
25710932Srrh 	pres[i] = pmem;
25810932Srrh 	fatfl = 1;
25910932Srrh 	if( nerrors ){
26010932Srrh 		summary();
26110932Srrh 		exit(1);
26210932Srrh 		}
26310932Srrh 	if( pmem != &pyield[nprod] ) error( "internal Yacc error: pyield %d", pmem-&pyield[nprod] );
26410932Srrh 	}
26510932Srrh 
26610932Srrh int indebug = 0;
cpfir()26710932Srrh cpfir() {
26810932Srrh 	/* compute an array with the first of nonterminals */
26910932Srrh 	register *p, **s, i, **t, ch, changes;
27010932Srrh 
27110932Srrh 	zzcwp = &wsets[nnonter];
27210932Srrh 	NTLOOP(i){
27310932Srrh 		aryfil( wsets[i].ws.lset, tbitset, 0 );
27410932Srrh 		t = pres[i+1];
27510932Srrh 		for( s=pres[i]; s<t; ++s ){ /* initially fill the sets */
27610932Srrh 			for( p = *s; (ch = *p) > 0 ; ++p ) {
27710932Srrh 				if( ch < NTBASE ) {
27810932Srrh 					SETBIT( wsets[i].ws.lset, ch );
27910932Srrh 					break;
28010932Srrh 					}
28110932Srrh 				else if( !pempty[ch-NTBASE] ) break;
28210932Srrh 				}
28310932Srrh 			}
28410932Srrh 		}
28510932Srrh 
28610932Srrh 	/* now, reflect transitivity */
28710932Srrh 
28810932Srrh 	changes = 1;
28910932Srrh 	while( changes ){
29010932Srrh 		changes = 0;
29110932Srrh 		NTLOOP(i){
29210932Srrh 			t = pres[i+1];
29310932Srrh 			for( s=pres[i]; s<t; ++s ){
29410932Srrh 				for( p = *s; ( ch = (*p-NTBASE) ) >= 0; ++p ) {
29510932Srrh 					changes |= setunion( wsets[i].ws.lset, wsets[ch].ws.lset );
29610932Srrh 					if( !pempty[ch] ) break;
29710932Srrh 					}
29810932Srrh 				}
29910932Srrh 			}
30010932Srrh 		}
30110932Srrh 
30210932Srrh 	NTLOOP(i) pfirst[i] = flset( &wsets[i].ws );
30310932Srrh 	if( !indebug ) return;
30410932Srrh 	if( (foutput!=NULL) ){
30510932Srrh 		NTLOOP(i) {
30610932Srrh 			fprintf( foutput,  "\n%s: ", nontrst[i].name );
30710932Srrh 			prlook( pfirst[i] );
30810932Srrh 			fprintf( foutput,  " %d\n", pempty[i] );
30910932Srrh 			}
31010932Srrh 		}
31110932Srrh 	}
31210932Srrh 
state(c)31310932Srrh state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */
31410932Srrh 	int size1,size2;
31510932Srrh 	register i;
31610932Srrh 	struct item *p1, *p2, *k, *l, *q1, *q2;
31710932Srrh 	p1 = pstate[nstate];
31810932Srrh 	p2 = pstate[nstate+1];
31910932Srrh 	if(p1==p2) return(0); /* null state */
32010932Srrh 	/* sort the items */
32110932Srrh 	for(k=p2-1;k>p1;k--) {	/* make k the biggest */
32210932Srrh 		for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){
32310932Srrh 			int *s;
32410932Srrh 			struct looksets *ss;
32510932Srrh 			s = k->pitem;
32610932Srrh 			k->pitem = l->pitem;
32710932Srrh 			l->pitem = s;
32810932Srrh 			ss = k->look;
32910932Srrh 			k->look = l->look;
33010932Srrh 			l->look = ss;
33110932Srrh 			}
33210932Srrh 		}
33310932Srrh 	size1 = p2 - p1; /* size of state */
33410932Srrh 
33510932Srrh 	for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) {
33610932Srrh 		/* get ith state */
33710932Srrh 		q1 = pstate[i];
33810932Srrh 		q2 = pstate[i+1];
33910932Srrh 		size2 = q2 - q1;
34010932Srrh 		if (size1 != size2) continue;
34110932Srrh 		k=p1;
34210932Srrh 		for(l=q1;l<q2;l++) {
34310932Srrh 			if( l->pitem != k->pitem ) break;
34410932Srrh 			++k;
34510932Srrh 			}
34610932Srrh 		if (l != q2) continue;
34710932Srrh 		/* found it */
34810932Srrh 		pstate[nstate+1] = pstate[nstate]; /* delete last state */
34910932Srrh 		/* fix up lookaheads */
35010932Srrh 		if( nolook ) return(i);
35110932Srrh 		for( l=q1,k=p1; l<q2; ++l,++k ){
35210932Srrh 			int s;
35310932Srrh 			SETLOOP(s) clset.lset[s] = l->look->lset[s];
35410932Srrh 			if( setunion( clset.lset, k->look->lset ) ) {
35510932Srrh 				tystate[i] = MUSTDO;
35610932Srrh 				/* register the new set */
35710932Srrh 				l->look = flset( &clset );
35810932Srrh 				}
35910932Srrh 			}
36010932Srrh 		return (i);
36110932Srrh 		}
36210932Srrh 	/* state is new */
36310932Srrh 	if( nolook ) error( "yacc state/nolook error" );
36410932Srrh 	pstate[nstate+2] = p2;
36510932Srrh 	if(nstate+1 >= NSTATES) error("too many states" );
36610932Srrh 	if( c >= NTBASE ){
36710932Srrh 		mstates[ nstate ] = ntstates[ c-NTBASE ];
36810932Srrh 		ntstates[ c-NTBASE ] = nstate;
36910932Srrh 		}
37010932Srrh 	else {
37110932Srrh 		mstates[ nstate ] = tstates[ c ];
37210932Srrh 		tstates[ c ] = nstate;
37310932Srrh 		}
37410932Srrh 	tystate[nstate]=MUSTDO;
37510932Srrh 	return(nstate++);
37610932Srrh 	}
37710932Srrh 
37810932Srrh int pidebug = 0; /* debugging flag for putitem */
putitem(ptr,lptr)37910932Srrh putitem( ptr, lptr )  int *ptr;  struct looksets *lptr; {
38010932Srrh 	register struct item *j;
38110932Srrh 
38210932Srrh 	if( pidebug && (foutput!=NULL) ) {
38310932Srrh 		fprintf( foutput, "putitem(%s), state %d\n", writem(ptr), nstate );
38410932Srrh 		}
38510932Srrh 	j = pstate[nstate+1];
38610932Srrh 	j->pitem = ptr;
38710932Srrh 	if( !nolook ) j->look = flset( lptr );
38810932Srrh 	pstate[nstate+1] = ++j;
38910932Srrh 	if( (int *)j > zzmemsz ){
39010932Srrh 		zzmemsz = (int *)j;
39110932Srrh 		if( zzmemsz >=  &mem0[MEMSIZE] ) error( "out of state space" );
39210932Srrh 		}
39310932Srrh 	}
39410932Srrh 
cempty()39510932Srrh cempty(){ /* mark nonterminals which derive the empty string */
39610932Srrh 	/* also, look for nonterminals which don't derive any token strings */
39710932Srrh 
39810932Srrh # define EMPTY 1
39910932Srrh # define WHOKNOWS 0
40010932Srrh # define OK 1
40110932Srrh 
40210932Srrh 	register i, *p;
40310932Srrh 
40410932Srrh 	/* first, use the array pempty to detect productions that can never be reduced */
40510932Srrh 	/* set pempty to WHONOWS */
40610932Srrh 	aryfil( pempty, nnonter+1, WHOKNOWS );
40710932Srrh 
40810932Srrh 	/* now, look at productions, marking nonterminals which derive something */
40910932Srrh 
41010932Srrh 	more:
41110932Srrh 	PLOOP(0,i){
41210932Srrh 		if( pempty[ *prdptr[i] - NTBASE ] ) continue;
41310932Srrh 		for( p=prdptr[i]+1; *p>=0; ++p ){
41410932Srrh 			if( *p>=NTBASE && pempty[ *p-NTBASE ] == WHOKNOWS ) break;
41510932Srrh 			}
41610932Srrh 		if( *p < 0 ){ /* production can be derived */
41710932Srrh 			pempty[ *prdptr[i]-NTBASE ] = OK;
41810932Srrh 			goto more;
41910932Srrh 			}
42010932Srrh 		}
42110932Srrh 
42210932Srrh 	/* now, look at the nonterminals, to see if they are all OK */
42310932Srrh 
42410932Srrh 	NTLOOP(i){
42510932Srrh 		/* the added production rises or falls as the start symbol ... */
42610932Srrh 		if( i == 0 ) continue;
42710932Srrh 		if( pempty[ i ] != OK ) {
42810932Srrh 			fatfl = 0;
42910932Srrh 			error( "nonterminal %s never derives any token string", nontrst[i].name );
43010932Srrh 			}
43110932Srrh 		}
43210932Srrh 
43310932Srrh 	if( nerrors ){
43410932Srrh 		summary();
43510932Srrh 		exit(1);
43610932Srrh 		}
43710932Srrh 
43810932Srrh 	/* now, compute the pempty array, to see which nonterminals derive the empty string */
43910932Srrh 
44010932Srrh 	/* set pempty to WHOKNOWS */
44110932Srrh 
44210932Srrh 	aryfil( pempty, nnonter+1, WHOKNOWS );
44310932Srrh 
44410932Srrh 	/* loop as long as we keep finding empty nonterminals */
44510932Srrh 
44610932Srrh again:
44710932Srrh 	PLOOP(1,i){
44810932Srrh 		if( pempty[ *prdptr[i]-NTBASE ]==WHOKNOWS ){ /* not known to be empty */
44910932Srrh 			for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]==EMPTY ; ++p ) ;
45010932Srrh 			if( *p < 0 ){ /* we have a nontrivially empty nonterminal */
45110932Srrh 				pempty[*prdptr[i]-NTBASE] = EMPTY;
45210932Srrh 				goto again; /* got one ... try for another */
45310932Srrh 				}
45410932Srrh 			}
45510932Srrh 		}
45610932Srrh 
45710932Srrh 	}
45810932Srrh 
45910932Srrh int gsdebug = 0;
stagen()46010932Srrh stagen(){ /* generate the states */
46110932Srrh 
46210932Srrh 	int i, j;
46310932Srrh 	register c;
46410932Srrh 	register struct wset *p, *q;
46510932Srrh 
46610932Srrh 	/* initialize */
46710932Srrh 
46810932Srrh 	nstate = 0;
46910932Srrh 	/* THIS IS FUNNY from the standpoint of portability */
47010932Srrh 	/* it represents the magic moment when the mem0 array, which has
47110932Srrh 	/* been holding the productions, starts to hold item pointers, of a
47210932Srrh 	/* different type... */
47310932Srrh 	/* someday, alloc should be used to allocate all this stuff... for now, we
47410932Srrh 	/* accept that if pointers don't fit in integers, there is a problem... */
47510932Srrh 
47610932Srrh 	pstate[0] = pstate[1] = (struct item *)mem;
47710932Srrh 	aryfil( clset.lset, tbitset, 0 );
47810932Srrh 	putitem( prdptr[0]+1, &clset );
47910932Srrh 	tystate[0] = MUSTDO;
48010932Srrh 	nstate = 1;
48110932Srrh 	pstate[2] = pstate[1];
48210932Srrh 
48310932Srrh 	aryfil( amem, ACTSIZE, 0 );
48410932Srrh 
48510932Srrh 	/* now, the main state generation loop */
48610932Srrh 
48710932Srrh 	more:
48810932Srrh 	SLOOP(i){
48910932Srrh 		if( tystate[i] != MUSTDO ) continue;
49010932Srrh 		tystate[i] = DONE;
49110932Srrh 		aryfil( temp1, nnonter+1, 0 );
49210932Srrh 		/* take state i, close it, and do gotos */
49310932Srrh 		closure(i);
49410932Srrh 		WSLOOP(wsets,p){ /* generate goto's */
49510932Srrh 			if( p->flag ) continue;
49610932Srrh 			p->flag = 1;
49710932Srrh 			c = *(p->pitem);
49810932Srrh 			if( c <= 1 ) {
49910932Srrh 				if( pstate[i+1]-pstate[i] <= p-wsets ) tystate[i] = MUSTLOOKAHEAD;
50010932Srrh 				continue;
50110932Srrh 				}
50210932Srrh 			/* do a goto on c */
50310932Srrh 			WSLOOP(p,q){
50410932Srrh 				if( c == *(q->pitem) ){ /* this item contributes to the goto */
50510932Srrh 					putitem( q->pitem + 1, &q->ws );
50610932Srrh 					q->flag = 1;
50710932Srrh 					}
50810932Srrh 				}
50910932Srrh 			if( c < NTBASE ) {
51010932Srrh 				state(c);  /* register new state */
51110932Srrh 				}
51210932Srrh 			else {
51310932Srrh 				temp1[c-NTBASE] = state(c);
51410932Srrh 				}
51510932Srrh 			}
51610932Srrh 		if( gsdebug && (foutput!=NULL) ){
51710932Srrh 			fprintf( foutput,  "%d: ", i );
51810932Srrh 			NTLOOP(j) {
51910932Srrh 				if( temp1[j] ) fprintf( foutput,  "%s %d, ", nontrst[j].name, temp1[j] );
52010932Srrh 				}
52110932Srrh 			fprintf( foutput, "\n");
52210932Srrh 			}
52310932Srrh 		indgo[i] = apack( &temp1[1], nnonter-1 ) - 1;
52410932Srrh 		goto more; /* we have done one goto; do some more */
52510932Srrh 		}
52610932Srrh 	/* no more to do... stop */
52710932Srrh 	}
52810932Srrh 
52910932Srrh int cldebug = 0; /* debugging flag for closure */
closure(i)53010932Srrh closure(i){ /* generate the closure of state i */
53110932Srrh 
53210932Srrh 	int c, ch, work, k;
53310932Srrh 	register struct wset *u, *v;
53410932Srrh 	int *pi;
53510932Srrh 	int **s, **t;
53610932Srrh 	struct item *q;
53710932Srrh 	register struct item *p;
53810932Srrh 
53910932Srrh 	++zzclose;
54010932Srrh 
54110932Srrh 	/* first, copy kernel of state i to wsets */
54210932Srrh 
54310932Srrh 	cwp = wsets;
54410932Srrh 	ITMLOOP(i,p,q){
54510932Srrh 		cwp->pitem = p->pitem;
54610932Srrh 		cwp->flag = 1;    /* this item must get closed */
54710932Srrh 		SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k];
54810932Srrh 		WSBUMP(cwp);
54910932Srrh 		}
55010932Srrh 
55110932Srrh 	/* now, go through the loop, closing each item */
55210932Srrh 
55310932Srrh 	work = 1;
55410932Srrh 	while( work ){
55510932Srrh 		work = 0;
55610932Srrh 		WSLOOP(wsets,u){
55710932Srrh 
55810932Srrh 			if( u->flag == 0 ) continue;
55910932Srrh 			c = *(u->pitem);  /* dot is before c */
56010932Srrh 
56110932Srrh 			if( c < NTBASE ){
56210932Srrh 				u->flag = 0;
56310932Srrh 				continue;  /* only interesting case is where . is before nonterminal */
56410932Srrh 				}
56510932Srrh 
56610932Srrh 			/* compute the lookahead */
56710932Srrh 			aryfil( clset.lset, tbitset, 0 );
56810932Srrh 
56910932Srrh 			/* find items involving c */
57010932Srrh 
57110932Srrh 			WSLOOP(u,v){
57210932Srrh 				if( v->flag == 1 && *(pi=v->pitem) == c ){
57310932Srrh 					v->flag = 0;
57410932Srrh 					if( nolook ) continue;
57510932Srrh 					while( (ch= *++pi)>0 ){
57610932Srrh 						if( ch < NTBASE ){ /* terminal symbol */
57710932Srrh 							SETBIT( clset.lset, ch );
57810932Srrh 							break;
57910932Srrh 							}
58010932Srrh 						/* nonterminal symbol */
58110932Srrh 						setunion( clset.lset, pfirst[ch-NTBASE]->lset );
58210932Srrh 						if( !pempty[ch-NTBASE] ) break;
58310932Srrh 						}
58410932Srrh 					if( ch<=0 ) setunion( clset.lset, v->ws.lset );
58510932Srrh 					}
58610932Srrh 				}
58710932Srrh 
58810932Srrh 			/*  now loop over productions derived from c */
58910932Srrh 
59010932Srrh 			c -= NTBASE; /* c is now nonterminal number */
59110932Srrh 
59210932Srrh 			t = pres[c+1];
59310932Srrh 			for( s=pres[c]; s<t; ++s ){
59410932Srrh 				/* put these items into the closure */
59510932Srrh 				WSLOOP(wsets,v){ /* is the item there */
59610932Srrh 					if( v->pitem == *s ){ /* yes, it is there */
59710932Srrh 						if( nolook ) goto nexts;
59810932Srrh 						if( setunion( v->ws.lset, clset.lset ) ) v->flag = work = 1;
59910932Srrh 						goto nexts;
60010932Srrh 						}
60110932Srrh 					}
60210932Srrh 
60310932Srrh 				/*  not there; make a new entry */
60410932Srrh 				if( cwp-wsets+1 >= WSETSIZE ) error( "working set overflow" );
60510932Srrh 				cwp->pitem = *s;
60610932Srrh 				cwp->flag = 1;
60710932Srrh 				if( !nolook ){
60810932Srrh 					work = 1;
60910932Srrh 					SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
61010932Srrh 					}
61110932Srrh 				WSBUMP(cwp);
61210932Srrh 
61310932Srrh 			nexts: ;
61410932Srrh 				}
61510932Srrh 
61610932Srrh 			}
61710932Srrh 		}
61810932Srrh 
61910932Srrh 	/* have computed closure; flags are reset; return */
62010932Srrh 
62110932Srrh 	if( cwp > zzcwp ) zzcwp = cwp;
62210932Srrh 	if( cldebug && (foutput!=NULL) ){
62310932Srrh 		fprintf( foutput, "\nState %d, nolook = %d\n", i, nolook );
62410932Srrh 		WSLOOP(wsets,u){
62510932Srrh 			if( u->flag ) fprintf( foutput, "flag set!\n");
62610932Srrh 			u->flag = 0;
62710932Srrh 			fprintf( foutput, "\t%s", writem(u->pitem));
62810932Srrh 			prlook( &u->ws );
62910932Srrh 			fprintf( foutput,  "\n" );
63010932Srrh 			}
63110932Srrh 		}
63210932Srrh 	}
63310932Srrh 
flset(p)63410932Srrh struct looksets *flset( p )   struct looksets *p; {
63510932Srrh 	/* decide if the lookahead set pointed to by p is known */
63610932Srrh 	/* return pointer to a perminent location for the set */
63710932Srrh 
63810932Srrh 	register struct looksets *q;
63910932Srrh 	int j, *w;
64010932Srrh 	register *u, *v;
64110932Srrh 
64210932Srrh 	for( q = &lkst[nlset]; q-- > lkst; ){
64310932Srrh 		u = p->lset;
64410932Srrh 		v = q->lset;
64510932Srrh 		w = & v[tbitset];
64610932Srrh 		while( v<w) if( *u++ != *v++ ) goto more;
64710932Srrh 		/* we have matched */
64810932Srrh 		return( q );
64910932Srrh 		more: ;
65010932Srrh 		}
65110932Srrh 	/* add a new one */
65210932Srrh 	q = &lkst[nlset++];
65310932Srrh 	if( nlset >= LSETSIZE )error("too many lookahead sets" );
65410932Srrh 	SETLOOP(j){
65510932Srrh 		q->lset[j] = p->lset[j];
65610932Srrh 		}
65710932Srrh 	return( q );
65810932Srrh 	}
659