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%
619573Smckusick */
719573Smckusick
819573Smckusick #ifndef lint
9*62087Sbostic static char sccsid[] = "@(#)ey4.c 8.1 (Berkeley) 06/06/93";
1047968Sbostic #endif /* not lint */
1119573Smckusick
1219573Smckusick # include "ey.h"
1319573Smckusick
output()1419573Smckusick output(){ /* print the output for the states */
1519573Smckusick
1619573Smckusick int i, j, k, c;
1719573Smckusick
1819573Smckusick settab();
1919573Smckusick arrset("yyact");
2019573Smckusick
2119573Smckusick for( i=0; i<nstate; ++i ){ /* output the stuff for state i */
2219573Smckusick nolook = (tystate[i]==0);
2319573Smckusick closure(i);
2419573Smckusick /* output actions */
2519573Smckusick aryfil( temp1, nterms+1, 0 );
2619573Smckusick for( j=0; j<cwset; ++j ){ /* look at the items */
2719573Smckusick c = *( wsets[j].pitem );
2819573Smckusick if( c>0 && c<NTBASE && temp1[c]==0 ) temp1[c] = go2(i,c);
2919573Smckusick }
3019573Smckusick
3119573Smckusick if( i == 1 ) temp1[1] = ACCEPTCODE;
3219573Smckusick
3319573Smckusick /* now, we have the shifts; look at the reductions */
3419573Smckusick
3519573Smckusick lastred = 0;
3619573Smckusick for( j=0; j<cwset; ++j ){
3719573Smckusick c = *( wsets[j].pitem );
3819573Smckusick if( c<=0 ){ /* reduction */
3919573Smckusick lastred = -c;
4019573Smckusick for( k=1; k<=nterms; ++k ){
4119573Smckusick if( ((wsets[j].ws[k>>4])&(1<<(k&017))) != 0 ) {
4219573Smckusick if( temp1[k] == 0 ) temp1[k] = c;
4319573Smckusick else if( temp1[k]<0 ){ /* reduce/reduce conflict */
4419573Smckusick settty();
4519573Smckusick fprintf( cout , "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s",
4619573Smckusick i, -temp1[k], lastred, symnam(k) );
4719573Smckusick if( -temp1[k] > lastred ) temp1[k] = -lastred;
4819573Smckusick ++zzrrconf;
4919573Smckusick settab();
5019573Smckusick }
5119573Smckusick else { /* potential shift/reduce conflict */
5219573Smckusick switch( precftn( lastred, k ) ) {
5319573Smckusick
5419573Smckusick case 0: /* precedence does not apply */
5519573Smckusick
5619573Smckusick settty();
5719573Smckusick fprintf( cout , "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i,
5819573Smckusick temp1[k], lastred, symnam(k) );
5919573Smckusick ++zzsrconf;
6019573Smckusick settab();
6119573Smckusick /* resolve in favor of shifting, so remove from reduce set */
6219573Smckusick wsets[j].ws[k>>4] &=~ (1<<(k&017));
6319573Smckusick break;
6419573Smckusick
6519573Smckusick case 1: /* reduce */
6619573Smckusick
6719573Smckusick temp1[k] = -lastred;
6819573Smckusick break;
6919573Smckusick
7019573Smckusick case 2: /* error, binary operator */
7119573Smckusick
7219573Smckusick temp1[k] = ERRCODE;
7319573Smckusick break;
7419573Smckusick
7519573Smckusick case 3: /* shift ... leave the entry alone */
7619573Smckusick
7719573Smckusick break;
7819573Smckusick }
7919573Smckusick }
8019573Smckusick }
8119573Smckusick }
8219573Smckusick }
8319573Smckusick }
8419573Smckusick wract(i);
8519573Smckusick }
8619573Smckusick
8719573Smckusick settab();
8819573Smckusick arrdone();
8919573Smckusick
9019573Smckusick /* now, output the pointers to the action array */
9119573Smckusick /* also output the info about reductions */
9219573Smckusick prred();
9319573Smckusick }
9419573Smckusick
prred()9519573Smckusick prred(){ /* print the information about the actions and the reductions */
9619573Smckusick int index, i;
9719573Smckusick
9819573Smckusick arrset("yypact");
9919573Smckusick index = 1; /* position in the output table */
10019573Smckusick
10119573Smckusick for( i=0; i<nstate; ++i ){
10219573Smckusick if( tystate[i]>0 ){ /* the state is real */
10319573Smckusick temp1[i] = index;
10419573Smckusick arrval( index );
10519573Smckusick index += tystate[i];
10619573Smckusick }
10719573Smckusick else {
10819573Smckusick arrval( temp1[-tystate[i]] );
10919573Smckusick }
11019573Smckusick }
11119573Smckusick
11219573Smckusick arrdone();
11319573Smckusick
11419573Smckusick arrset("yyr1");
11519573Smckusick for( i=1; i<nprod; ++i ) arrval( *prdptr[i] - NTBASE );
11619573Smckusick arrdone();
11719573Smckusick
11819573Smckusick arrset("yyr2");
11919573Smckusick for( i=1; i<nprod; ++i ) arrval( ( prdptr[i+1]-prdptr[i]-2 ) );
12019573Smckusick arrdone();
12119573Smckusick
12219573Smckusick }
12319573Smckusick
go2(i,c)12419573Smckusick go2(i,c){ /* do a goto on the closure state, not worrying about lookaheads */
12519573Smckusick if( c<NTBASE ) return( amem[ apstate[i]+c ] );
12619573Smckusick else return( amem[ apstate[i] + c - NTBASE + nterms ] );
12719573Smckusick }
12819573Smckusick
12919573Smckusick int pkdebug = 0;
apack(p,n)13019573Smckusick apack(p, n ) int *p;{ /* pack state i from temp1 into amem */
13119573Smckusick _REGISTER k, l, off;
13219573Smckusick int j;
13319573Smckusick
13419573Smckusick /* find the spot */
13519573Smckusick
13619573Smckusick j = n;
13719573Smckusick for( off = 0; off <= j && p[off] == 0; ++off ) ;
13819573Smckusick if( off > j ){ /* no actions */
13919573Smckusick return(0);
14019573Smckusick }
14119573Smckusick j -= off;
14219573Smckusick for( k=0; k<actsiz; ++k ){
14319573Smckusick for( l=0; l<=j; ++l ){
14419573Smckusick if( p[off+l] != 0 ){
14519573Smckusick if( p[off+l] != amem[k+l] && amem[k+l] != 0 ) goto nextk;
14619573Smckusick }
14719573Smckusick }
14819573Smckusick if( pkdebug ){ settty(); fprintf( cout , "off = %d, k = %d\n", off, k ); }
14919573Smckusick /* we have found an acceptable k */
15019573Smckusick for( l=0; l<=j; ++l ){
15119573Smckusick if( p[off+l] ){
15219573Smckusick if( k+l >= actsiz ) error("action table overflow");
15319573Smckusick if( k+l >= memact ) memact = k+l;
15419573Smckusick amem[k+l] = p[off+l];
15519573Smckusick }
15619573Smckusick }
15719573Smckusick if( pkdebug ){
15819573Smckusick for( k=0; k<memact; k+=10){
15919573Smckusick fprintf( cout , "\t");
16019573Smckusick for( l=0; l<=9; ++l ) fprintf( cout , "%d ", amem[k+l] );
16119573Smckusick fprintf( cout , "\n");
16219573Smckusick }
16319573Smckusick }
16419573Smckusick return(k-off);
16519573Smckusick
16619573Smckusick nextk: ;
16719573Smckusick }
16819573Smckusick error("no space in action table");
16919573Smckusick }
17019573Smckusick
go2out()17119573Smckusick go2out(){ /* output the gotos for the nontermninals */
17219573Smckusick int i, j, k, best, offset, count, cbest, times;
17319573Smckusick
17419573Smckusick settab();
17519573Smckusick arrset("yygo");
17619573Smckusick offset = 1;
17719573Smckusick
17819573Smckusick for( i=1; i<=nnonter; ++i ) {
17919573Smckusick go2gen(i);
18019573Smckusick
18119573Smckusick /* find the best one to make default */
18219573Smckusick
18319573Smckusick temp2[i] = offset;
18419573Smckusick
18519573Smckusick best = -1;
18619573Smckusick times = 0;
18719573Smckusick
18819573Smckusick for( j=0; j<=nstate; ++j ){ /* is j the most frequent */
18919573Smckusick if( tystate[j] == 0 ) continue;
19019573Smckusick if( tystate[j] == best ) continue;
19119573Smckusick
19219573Smckusick /* is tystate[j] the most frequent */
19319573Smckusick
19419573Smckusick count = 0;
19519573Smckusick cbest = tystate[j];
19619573Smckusick
19719573Smckusick for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count;
19819573Smckusick
19919573Smckusick if( count > times ){
20019573Smckusick best = cbest;
20119573Smckusick times = count;
20219573Smckusick }
20319573Smckusick }
20419573Smckusick
20519573Smckusick /* best is now the default entry */
20619573Smckusick
20719573Smckusick zzgobest += (times-1)*2;
20819573Smckusick settab();
20919573Smckusick for( j=0; j<=nstate; ++j ){
21019573Smckusick if( tystate[j] != 0 && tystate[j]!=best ){
21119573Smckusick arrval( j );
21219573Smckusick arrval( tystate[j] );
21319573Smckusick offset += 2;
21419573Smckusick zzgoent += 2;
21519573Smckusick }
21619573Smckusick }
21719573Smckusick
21819573Smckusick /* now, the default */
21919573Smckusick
22019573Smckusick zzgoent += 2;
22119573Smckusick arrval( -1 );
22219573Smckusick arrval( best );
22319573Smckusick offset += 2;
22419573Smckusick
22519573Smckusick }
22619573Smckusick
22719573Smckusick arrdone();
22819573Smckusick
22919573Smckusick arrset("yypgo");
23019573Smckusick for( i=1; i<=nnonter; ++i ) arrval( temp2[i] );
23119573Smckusick arrdone();
23219573Smckusick
23319573Smckusick }
23419573Smckusick
23519573Smckusick int g2debug = 0;
go2gen(c)23619573Smckusick go2gen(c){ /* output the gotos for nonterminal c */
23719573Smckusick
23819573Smckusick int i, work, cc;
23919573Smckusick struct item *p, *q;
24019573Smckusick
24119573Smckusick /* first, find nonterminals with gotos on c */
24219573Smckusick
24319573Smckusick aryfil( temp1, nnonter+1, 0 );
24419573Smckusick temp1[c] = 1;
24519573Smckusick
24619573Smckusick work = 1;
24719573Smckusick while( work ){
24819573Smckusick work = 0;
24919573Smckusick for( i=0; i<nprod; ++i ){
25019573Smckusick if( (cc=prdptr[i][1]-NTBASE) >= 0 ){ /* cc is a nonterminal */
25119573Smckusick if( temp1[cc] != 0 ){ /* cc has a goto on c */
25219573Smckusick cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */
25319573Smckusick if( temp1[cc] == 0 ){
25419573Smckusick work = 1;
25519573Smckusick temp1[cc] = 1;
25619573Smckusick }
25719573Smckusick }
25819573Smckusick }
25919573Smckusick }
26019573Smckusick }
26119573Smckusick
26219573Smckusick /* now, we have temp1[c] = 1 if a goto on c in closure of cc */
26319573Smckusick
26419573Smckusick if( g2debug ){
26519573Smckusick settty();
26619573Smckusick fprintf( cout , "%s: gotos on ", nontrst[c].name );
26719573Smckusick for( i=0; i<=nnonter; ++i ) if( temp1[i]) fprintf( cout , "%s ", nontrst[i].name);
26819573Smckusick fprintf( cout , "\n");
26919573Smckusick }
27019573Smckusick
27119573Smckusick /* now, go through and put gotos into tystate */
27219573Smckusick
27319573Smckusick aryfil( tystate, nstate, 0 );
27419573Smckusick settty();
27519573Smckusick fprintf( cout , "\nnonterminal %s\n", nontrst[c].name );
27619573Smckusick for( i=0; i<nstate; ++i ){
27719573Smckusick q = pstate[i+1];
27819573Smckusick for( p=pstate[i]; p<q; ++p ){
27919573Smckusick if( (cc= *p->pitem) >= NTBASE ){
28019573Smckusick if( temp1[cc -= NTBASE] ){ /* goto on c is possible */
28119573Smckusick tystate[i] = amem[indgo[i]+c];
28219573Smckusick break;
28319573Smckusick }
28419573Smckusick }
28519573Smckusick }
28619573Smckusick if( tystate[i] ) fprintf( cout , "\t%d\t%d\n", i, tystate[i]);
28719573Smckusick }
28819573Smckusick }
28919573Smckusick
precftn(r,t)29019573Smckusick precftn(r,t){ /* decide a shift/reduce conflict by precedence.
29119573Smckusick Returns 0 if action is 'do nothing',1 if action is reduce,
29219573Smckusick 2 if the action is 'error,binary operator'
29319573Smckusick and 3 if the action is 'reduce'. */
29419573Smckusick
29519573Smckusick int lp,lt;
29619573Smckusick lp = levprd[r];
29719573Smckusick lt = trmlev[t];
29819573Smckusick if ((lt==0)||((lp&03)==0))return(0);
29919573Smckusick if((lt>>3) == (lp>>3)){
30019573Smckusick return(lt&03);
30119573Smckusick }
30219573Smckusick if((lt>>3) > (lp>>3)) return(3);
30319573Smckusick return(1);
30419573Smckusick }
30519573Smckusick
30619573Smckusick int cdebug = 0; /* debug for common states */
wract(i)30719573Smckusick wract(i){ /* output state i */
30819573Smckusick /* temp1 has the actions, lastred the default */
30919573Smckusick int p, p0, p1, size;
31019573Smckusick int ntimes, tred, count, j, k;
31119573Smckusick struct item *q0, *q1;
31219573Smckusick
31319573Smckusick /* find the best choice for lastred */
31419573Smckusick
31519573Smckusick lastred = 0;
31619573Smckusick ntimes = 0;
31719573Smckusick stateflags[i] = 0;
31819573Smckusick /***** UCB MOD - full state spec if shift on error *****/
31919573Smckusick if (temp1[2] > 0)
32019573Smckusick stateflags[i] |= NEEDSREDUCE;
32119573Smckusick else for( j=1; j<=nterms; ++j ){
32219573Smckusick /* find the entry on which the greatest number of reductions are done */
32319573Smckusick if( temp1[j] >= 0 ) continue;
32419573Smckusick if( temp1[j]+lastred == 0 ) continue;
32519573Smckusick /* count the number of appearances of temp1[j] */
32619573Smckusick count = 0;
32719573Smckusick tred = -temp1[j];
32819573Smckusick for( p=1; p<=nterms; ++p ){
32919573Smckusick if( temp1[p]+tred == 0 ) ++count;
33019573Smckusick }
33119573Smckusick if( count >ntimes ){
33219573Smckusick lastred = tred;
33319573Smckusick ntimes = count;
33419573Smckusick }
33519573Smckusick }
33619573Smckusick
33719573Smckusick /* clear out entries in temp1 which equal lastred */
33819573Smckusick /* ie, make the most frequent reduction into the default reduction */
33919573Smckusick for( p=1; p<= nterms; ++p ) if( temp1[p]+lastred == 0 )temp1[p]=0;
34019573Smckusick
34119573Smckusick /* write out the state */
34219573Smckusick
34319573Smckusick /* first, check for equality with another state */
34419573Smckusick /* see if there is a nonterminal with all dots before it, */
34519573Smckusick /* and no reductions in the state */
34619573Smckusick /* this is done by checking if all items are the same non-terminal */
34719573Smckusick p0 = 0;
34819573Smckusick q1 = pstate[i+1];
34919573Smckusick for( q0=pstate[i]; q0<q1; ++q0 ){
35019573Smckusick if( (p1= *(q0->pitem) ) < NTBASE ) goto standard;
35119573Smckusick if( p0 == 0 ) p0 = p1;
35219573Smckusick else if( p0 != p1 ) goto standard;
35319573Smckusick }
35419573Smckusick stateflags[i] |= SINGLE_NT | pempty[p0 - NTBASE];
35519573Smckusick
35619573Smckusick /* now, all items have dots before p0 */
35719573Smckusick if( cdebug ){
35819573Smckusick settty();
35919573Smckusick fprintf( cout , "state %d, pre-nonterminal %s\n",i,nontrst[p0-NTBASE].name);
36019573Smckusick }
36119573Smckusick
36219573Smckusick for( j=0; j<i; ++j ){
36319573Smckusick /*
36419573Smckusick * check that the states have the same shift lookaheads.
36519573Smckusick */
36619573Smckusick if( apstate[i] != apstate[j] )
36719573Smckusick continue;
36819573Smckusick if (cdebug)
36919573Smckusick fprintf(cout, "states %d and %d have same shift lookaheads\n",i,j);
37019573Smckusick
37119573Smckusick /*
37219573Smckusick * Check that state has one item, and that the item matches.
37319573Smckusick */
37419573Smckusick if ((stateflags[j] & SINGLE_NT) == 0 || *(pstate[j]->pitem) != p0)
37519573Smckusick continue;
37619573Smckusick
37719573Smckusick /*
37819573Smckusick * Check that enumeration and reduce lookaheads are the same.
37919573Smckusick */
38019573Smckusick if ((stateflags[i]&(GENLAMBDA|NEEDSREDUCE)) == (GENLAMBDA|NEEDSREDUCE)) {
38119573Smckusick /*
38219573Smckusick * p0 derives lambda.
38319573Smckusick * state[i] needs full reduce lookahead
38419573Smckusick * state[j] has full reduce lookahead
38519573Smckusick */
38619573Smckusick if ((stateflags[j] & NEEDSREDUCE) == 0)
38719573Smckusick error("state %d does not need full reduce", j);
38819573Smckusick if (lambdarule < 0)
38919573Smckusick error("missing lambda rule definition in state %d", i);
39019573Smckusick if (lookstate[j] == 0)
39119573Smckusick error("state %d lookahead was not saved", j);
39219573Smckusick /* must check lookaheads */
39319573Smckusick for (k = 0; k < tbitset; ++k)
39419573Smckusick if (lastate[lookstate[j]].lset[k] != wsets[lambdarule].ws[k])
39519573Smckusick /* cannot merge states */ goto nextj;
39619573Smckusick }
39719573Smckusick
39819573Smckusick /* we have a match with state j ! */
39919573Smckusick
40019573Smckusick if( cdebug ){
40119573Smckusick settty();
40219573Smckusick fprintf( cout , "state %d matches state %d\n", i, j);
40319573Smckusick }
40419573Smckusick tystate[i] = -j;
40519573Smckusick zzacsave += tystate[j];
40619573Smckusick zznsave++;
40719573Smckusick wrstate(i);
40819573Smckusick /* merged, so no need for future consideration */
40919573Smckusick stateflags[i] = 0;
41019573Smckusick return;
41119573Smckusick
41219573Smckusick nextj: ;
41319573Smckusick }
41419573Smckusick
41519573Smckusick
41619573Smckusick standard:
41719573Smckusick tystate[i] = 2;
41819573Smckusick wrstate(i);
41919573Smckusick if ((stateflags[i] & (SINGLE_NT|NEEDSREDUCE|GENLAMBDA)) ==
42019573Smckusick (SINGLE_NT|NEEDSREDUCE|GENLAMBDA)) {
42119573Smckusick if (savedlook + 1 >= maxlastate) {
42219573Smckusick settty();
42319573Smckusick fprintf(cout,
42419573Smckusick "Warning: _maxlastate too small (%d), state packing impared\n",
42519573Smckusick maxlastate);
42619573Smckusick /* cannot consider future merger with this state */
42719573Smckusick stateflags[i] = 0;
42819573Smckusick } else {
42919573Smckusick if( cdebug ){
43019573Smckusick settty();
43119573Smckusick fprintf( cout , "save lookahead for state %d\n", i);
43219573Smckusick }
43319573Smckusick lookstate[i] = savedlook;
43419573Smckusick for (k = 0; k < tbitset; ++k)
43519573Smckusick lastate[savedlook].lset[k] = wsets[lambdarule].ws[k];
43619573Smckusick savedlook++;
43719573Smckusick }
43819573Smckusick }
43919573Smckusick
44019573Smckusick size = 0;
44119573Smckusick for( p0=1; p0<=nterms; ++p0 )
44219573Smckusick if( (p1=temp1[p0])!=0 ) {
44319573Smckusick /***** UCB MOD - test actions are negative of symbol to be tested
44419573Smckusick this speeds up the parser as it is easy to check for
44519573Smckusick *****/
44619573Smckusick arrval( -trmset[p0].value );
44719573Smckusick if( p1 < 0 ) arrval( REDUCACT - p1 );
44819573Smckusick else if( p1 == ACCEPTCODE ) arrval( ACCEPTACT );
44919573Smckusick else if( p1 == ERRCODE ) arrval( ERRACT );
45019573Smckusick else arrval( SHIFTACT + p1 );
45119573Smckusick size += 2;
45219573Smckusick }
45319573Smckusick if( lastred ) arrval( REDUCACT + lastred );
45419573Smckusick else arrval( ERRACT );
45519573Smckusick tystate[i] = size+1; /* store entry size in tystate */
45619573Smckusick zzacent += (size+1);
45719573Smckusick return;
45819573Smckusick }
45919573Smckusick
wrstate(i)46019573Smckusick wrstate(i){ /* writes state i */
46119573Smckusick int j0,j1,s;
46219573Smckusick struct item *pp, *qq;
46319573Smckusick settty();
46419573Smckusick fprintf( cout , "\nstate %d\n",i);
46519573Smckusick qq = pstate[i+1];
46619573Smckusick for( pp=pstate[i]; pp<qq; ++pp) fprintf( cout , "\t%s\n", writem(pp));
46719573Smckusick
46819573Smckusick /* check for state equal to another */
46919573Smckusick
47019573Smckusick if( tystate[i] <= 0 ){
47119573Smckusick fprintf( cout , "\n\tsame as %d\n\n", -tystate[i] );
47219573Smckusick return;
47319573Smckusick }
47419573Smckusick
47519573Smckusick for( j0=1; j0<=nterms; ++j0 ) if( (j1=temp1[j0]) != 0 ){
47619573Smckusick fprintf( cout , "\n\t%s ", symnam(j0) );
47719573Smckusick if( j1>0 ){ /* shift, error, or accept */
47819573Smckusick if( j1 == ACCEPTCODE ) fprintf( cout , "accept" );
47919573Smckusick else if( j1 == ERRCODE ) fprintf( cout , "error" );
48019573Smckusick else fprintf( cout , "shift %d", j1 );
48119573Smckusick }
48219573Smckusick else fprintf( cout , "reduce %d",-j1 );
48319573Smckusick }
48419573Smckusick
48519573Smckusick /* output the final production */
48619573Smckusick
48719573Smckusick if( lastred ) fprintf( cout , "\n\t. reduce %d\n\n", lastred );
48819573Smckusick else fprintf( cout , "\n\t. error\n\n" );
48919573Smckusick
49019573Smckusick ret:
49119573Smckusick settab();
49219573Smckusick }
493