1*47968Sbostic /*- 2*47968Sbostic * Copyright (c) 1979 The Regents of the University of California. 3*47968Sbostic * All rights reserved. 4*47968Sbostic * 5*47968Sbostic * %sccs.include.proprietary.c% 619573Smckusick */ 719573Smckusick 819573Smckusick #ifndef lint 9*47968Sbostic static char sccsid[] = "@(#)ey4.c 5.2 (Berkeley) 04/12/91"; 10*47968Sbostic #endif /* not lint */ 1119573Smckusick 1219573Smckusick # include "ey.h" 1319573Smckusick 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 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 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; 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 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; 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 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 */ 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 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