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