1: #if !defined(lint) && defined(DOSCCS) 2: static char sccsid[] = "@(#)y1.c 4.1.1 (2.11BSD) 1995/05/11"; 3: #endif 4: 5: # include "dextern" 6: 7: /* variables used locally */ 8: 9: /* lookahead computations */ 10: 11: int tbitset; /* size of lookahead sets */ 12: struct looksets lkst [ LSETSIZE ]; 13: int nlset = 0; /* next lookahead set index */ 14: int nolook = 0; /* flag to suppress lookahead computations */ 15: struct looksets clset; /* temporary storage for lookahead computations */ 16: 17: /* working set computations */ 18: 19: struct wset wsets[ WSETSIZE ]; 20: struct wset *cwp; 21: 22: /* state information */ 23: 24: int nstate = 0; /* number of states */ 25: struct item *pstate[NSTATES+2]; /* pointers to the descriptions of the states */ 26: int tystate[NSTATES]; /* contains type information about the states */ 27: int indgo[NSTATES]; /* index to the stored goto table */ 28: int tstates[ NTERMS ]; /* states generated by terminal gotos */ 29: int ntstates[ NNONTERM ]; /* states generated by nonterminal gotos */ 30: int mstates[ NSTATES ]; /* chain of overflows of term/nonterm generation lists */ 31: 32: /* storage for the actions in the parser */ 33: 34: int amem[ACTSIZE]; /* action table storage */ 35: int *memp = amem; /* next free action table position */ 36: 37: /* other storage areas */ 38: 39: int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or states */ 40: int lineno= 1; /* current input line number */ 41: int fatfl = 1; /* if on, error is fatal */ 42: int nerrors = 0; /* number of errors */ 43: 44: /* storage for information about the nonterminals */ 45: 46: int **pres[NNONTERM+2]; /* vector of pointers to productions yielding each nonterminal */ 47: struct looksets *pfirst[NNONTERM+2]; /* vector of pointers to first sets for each nonterminal */ 48: int pempty[NNONTERM+1]; /* vector of nonterminals nontrivially deriving e */ 49: 50: main(argc,argv) int argc; char *argv[]; { 51: 52: setup(argc,argv); /* initialize and read productions */ 53: tbitset = NWORDS(ntokens); 54: cpres(); /* make table of which productions yield a given nonterminal */ 55: cempty(); /* make a table of which nonterminals can match the empty string */ 56: cpfir(); /* make a table of firsts of nonterminals */ 57: stagen(); /* generate the states */ 58: output(); /* write the states and the tables */ 59: go2out(); 60: hideprod(); 61: summary(); 62: callopt(); 63: others(); 64: exit(0); 65: } 66: 67: others(){ /* put out other arrays, copy the parsers */ 68: register c, i, j; 69: 70: finput = fopen( PARSER, "r" ); 71: if( finput == NULL ) error( "cannot find parser %s", PARSER ); 72: 73: warray( "yyr1", levprd, nprod ); 74: 75: aryfil( temp1, nprod, 0 ); 76: PLOOP(1,i)temp1[i] = prdptr[i+1]-prdptr[i]-2; 77: warray( "yyr2", temp1, nprod ); 78: 79: aryfil( temp1, nstate, -1000 ); 80: TLOOP(i){ 81: for( j=tstates[i]; j!=0; j=mstates[j] ){ 82: temp1[j] = tokset[i].value; 83: } 84: } 85: NTLOOP(i){ 86: for( j=ntstates[i]; j!=0; j=mstates[j] ){ 87: temp1[j] = -i; 88: } 89: } 90: warray( "yychk", temp1, nstate ); 91: 92: warray( "yydef", defact, nstate ); 93: 94: /* copy parser text */ 95: 96: while( (c=getc(finput) ) != EOF ){ 97: if( c == '$' ){ 98: if( (c=getc(finput)) != 'A' ) putc( '$', ftable ); 99: else { /* copy actions */ 100: faction = fopen( ACTNAME, "r" ); 101: if( faction == NULL ) error( "cannot reopen action tempfile" ); 102: while( (c=getc(faction) ) != EOF ) putc( c, ftable ); 103: fclose(faction); 104: ZAPFILE(ACTNAME); 105: c = getc(finput); 106: } 107: } 108: putc( c, ftable ); 109: } 110: 111: fclose( ftable ); 112: } 113: 114: char *chcopy( p, q ) register char *p, *q; { 115: /* copies string q into p, returning next free char ptr */ 116: while( *p = *q++ ) ++p; 117: return( p ); 118: } 119: 120: # define ISIZE 400 121: char *writem(pp) int *pp; { /* creates output string for item pointed to by pp */ 122: register int i,*p; 123: static char sarr[ISIZE]; 124: register char *q; 125: 126: for( p=pp; *p>0 ; ++p ) ; 127: p = prdptr[-*p]; 128: q = chcopy( sarr, nontrst[*p-NTBASE].name ); 129: q = chcopy( q, " : " ); 130: 131: for(;;){ 132: *q++ = ++p==pp ? '_' : ' '; 133: *q = '\0'; 134: if((i = *p) <= 0) break; 135: q = chcopy( q, symnam(i) ); 136: if( q> &sarr[ISIZE-30] ) error( "item too big" ); 137: } 138: 139: if( (i = *pp) < 0 ){ /* an item calling for a reduction */ 140: q = chcopy( q, " (" ); 141: sprintf( q, "%d)", -i ); 142: } 143: 144: return( sarr ); 145: } 146: 147: char *symnam(i){ /* return a pointer to the name of symbol i */ 148: register char *cp; 149: 150: cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : tokset[i].name ; 151: if( *cp == ' ' ) ++cp; 152: return( cp ); 153: } 154: 155: struct wset *zzcwp = wsets; 156: int zzgoent = 0; 157: int zzgobest = 0; 158: int zzacent = 0; 159: int zzexcp = 0; 160: int zzclose = 0; 161: int zzsrconf = 0; 162: int * zzmemsz = mem0; 163: int zzrrconf = 0; 164: 165: summary(){ /* output the summary on the tty */ 166: 167: if( foutput!=NULL ){ 168: fprintf( foutput, "\n%d/%d terminals, %d/%d nonterminals\n", ntokens, NTERMS, 169: nnonter, NNONTERM ); 170: fprintf( foutput, "%d/%d grammar rules, %d/%d states\n", nprod, NPROD, nstate, NSTATES ); 171: fprintf( foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf ); 172: fprintf( foutput, "%d/%d working sets used\n", zzcwp-wsets, WSETSIZE ); 173: fprintf( foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz-mem0, MEMSIZE, 174: memp-amem, ACTSIZE ); 175: fprintf( foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE ); 176: fprintf( foutput, "%d extra closures\n", zzclose - 2*nstate ); 177: fprintf( foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp ); 178: fprintf( foutput, "%d goto entries\n", zzgoent ); 179: fprintf( foutput, "%d entries saved by goto default\n", zzgobest ); 180: } 181: if( zzsrconf!=0 || zzrrconf!=0 ){ 182: fprintf( stdout,"\nconflicts: "); 183: if( zzsrconf )fprintf( stdout, "%d shift/reduce" , zzsrconf ); 184: if( zzsrconf && zzrrconf )fprintf( stdout, ", " ); 185: if( zzrrconf )fprintf( stdout, "%d reduce/reduce" , zzrrconf ); 186: fprintf( stdout, "\n" ); 187: } 188: 189: fclose( ftemp ); 190: if( fdefine != NULL ) fclose( fdefine ); 191: } 192: 193: /* VARARGS1 */ 194: error(s,a1) char *s; { /* write out error comment */ 195: 196: ++nerrors; 197: fprintf( stderr, "\n fatal error: "); 198: fprintf( stderr, s,a1); 199: fprintf( stderr, ", line %d\n", lineno ); 200: if( !fatfl ) return; 201: summary(); 202: exit(1); 203: } 204: 205: aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ 206: register int i; 207: for( i=0; i<n; ++i ) v[i] = c; 208: } 209: 210: setunion( a, b ) register *a, *b; { 211: /* set a to the union of a and b */ 212: /* return 1 if b is not a subset of a, 0 otherwise */ 213: register i, x, sub; 214: 215: sub = 0; 216: SETLOOP(i){ 217: *a = (x = *a)|*b++; 218: if( *a++ != x ) sub = 1; 219: } 220: return( sub ); 221: } 222: 223: prlook( p ) struct looksets *p;{ 224: register j, *pp; 225: 226: pp = p->lset; 227: if( pp == 0 ) fprintf( foutput, "\tNULL"); 228: else { 229: fprintf( foutput, " { " ); 230: TLOOP(j) { 231: if( BIT(pp,j) ) fprintf( foutput, "%s ", symnam(j) ); 232: } 233: fprintf( foutput, "}" ); 234: } 235: } 236: 237: cpres(){ /* compute an array with the beginnings of productions yielding given nonterminals 238: The array pres points to these lists */ 239: /* the array pyield has the lists: the total size is only NPROD+1 */ 240: int **pmem; 241: register c, j, i; 242: static int * pyield[NPROD]; 243: 244: pmem = pyield; 245: 246: NTLOOP(i){ 247: c = i+NTBASE; 248: pres[i] = pmem; 249: fatfl = 0; /* make undefined symbols nonfatal */ 250: PLOOP(0,j){ 251: if (*prdptr[j] == c) *pmem++ = prdptr[j]+1; 252: } 253: if(pres[i] == pmem){ 254: error("nonterminal %s not defined!", nontrst[i].name); 255: } 256: } 257: pres[i] = pmem; 258: fatfl = 1; 259: if( nerrors ){ 260: summary(); 261: exit(1); 262: } 263: if( pmem != &pyield[nprod] ) error( "internal Yacc error: pyield %d", pmem-&pyield[nprod] ); 264: } 265: 266: int indebug = 0; 267: cpfir() { 268: /* compute an array with the first of nonterminals */ 269: register *p, **s, i, **t, ch, changes; 270: 271: zzcwp = &wsets[nnonter]; 272: NTLOOP(i){ 273: aryfil( wsets[i].ws.lset, tbitset, 0 ); 274: t = pres[i+1]; 275: for( s=pres[i]; s<t; ++s ){ /* initially fill the sets */ 276: for( p = *s; (ch = *p) > 0 ; ++p ) { 277: if( ch < NTBASE ) { 278: SETBIT( wsets[i].ws.lset, ch ); 279: break; 280: } 281: else if( !pempty[ch-NTBASE] ) break; 282: } 283: } 284: } 285: 286: /* now, reflect transitivity */ 287: 288: changes = 1; 289: while( changes ){ 290: changes = 0; 291: NTLOOP(i){ 292: t = pres[i+1]; 293: for( s=pres[i]; s<t; ++s ){ 294: for( p = *s; ( ch = (*p-NTBASE) ) >= 0; ++p ) { 295: changes |= setunion( wsets[i].ws.lset, wsets[ch].ws.lset ); 296: if( !pempty[ch] ) break; 297: } 298: } 299: } 300: } 301: 302: NTLOOP(i) pfirst[i] = flset( &wsets[i].ws ); 303: if( !indebug ) return; 304: if( (foutput!=NULL) ){ 305: NTLOOP(i) { 306: fprintf( foutput, "\n%s: ", nontrst[i].name ); 307: prlook( pfirst[i] ); 308: fprintf( foutput, " %d\n", pempty[i] ); 309: } 310: } 311: } 312: 313: state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */ 314: int size1,size2; 315: register i; 316: struct item *p1, *p2, *k, *l, *q1, *q2; 317: p1 = pstate[nstate]; 318: p2 = pstate[nstate+1]; 319: if(p1==p2) return(0); /* null state */ 320: /* sort the items */ 321: for(k=p2-1;k>p1;k--) { /* make k the biggest */ 322: for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){ 323: int *s; 324: struct looksets *ss; 325: s = k->pitem; 326: k->pitem = l->pitem; 327: l->pitem = s; 328: ss = k->look; 329: k->look = l->look; 330: l->look = ss; 331: } 332: } 333: size1 = p2 - p1; /* size of state */ 334: 335: for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) { 336: /* get ith state */ 337: q1 = pstate[i]; 338: q2 = pstate[i+1]; 339: size2 = q2 - q1; 340: if (size1 != size2) continue; 341: k=p1; 342: for(l=q1;l<q2;l++) { 343: if( l->pitem != k->pitem ) break; 344: ++k; 345: } 346: if (l != q2) continue; 347: /* found it */ 348: pstate[nstate+1] = pstate[nstate]; /* delete last state */ 349: /* fix up lookaheads */ 350: if( nolook ) return(i); 351: for( l=q1,k=p1; l<q2; ++l,++k ){ 352: int s; 353: SETLOOP(s) clset.lset[s] = l->look->lset[s]; 354: if( setunion( clset.lset, k->look->lset ) ) { 355: tystate[i] = MUSTDO; 356: /* register the new set */ 357: l->look = flset( &clset ); 358: } 359: } 360: return (i); 361: } 362: /* state is new */ 363: if( nolook ) error( "yacc state/nolook error" ); 364: pstate[nstate+2] = p2; 365: if(nstate+1 >= NSTATES) error("too many states" ); 366: if( c >= NTBASE ){ 367: mstates[ nstate ] = ntstates[ c-NTBASE ]; 368: ntstates[ c-NTBASE ] = nstate; 369: } 370: else { 371: mstates[ nstate ] = tstates[ c ]; 372: tstates[ c ] = nstate; 373: } 374: tystate[nstate]=MUSTDO; 375: return(nstate++); 376: } 377: 378: int pidebug = 0; /* debugging flag for putitem */ 379: putitem( ptr, lptr ) int *ptr; struct looksets *lptr; { 380: register struct item *j; 381: 382: if( pidebug && (foutput!=NULL) ) { 383: fprintf( foutput, "putitem(%s), state %d\n", writem(ptr), nstate ); 384: } 385: j = pstate[nstate+1]; 386: j->pitem = ptr; 387: if( !nolook ) j->look = flset( lptr ); 388: pstate[nstate+1] = ++j; 389: if( (int *)j > zzmemsz ){ 390: zzmemsz = (int *)j; 391: if( zzmemsz >= &mem0[MEMSIZE] ) error( "out of state space" ); 392: } 393: } 394: 395: cempty(){ /* mark nonterminals which derive the empty string */ 396: /* also, look for nonterminals which don't derive any token strings */ 397: 398: # define EMPTY 1 399: # define WHOKNOWS 0 400: # define OK 1 401: 402: register i, *p; 403: 404: /* first, use the array pempty to detect productions that can never be reduced */ 405: /* set pempty to WHONOWS */ 406: aryfil( pempty, nnonter+1, WHOKNOWS ); 407: 408: /* now, look at productions, marking nonterminals which derive something */ 409: 410: more: 411: PLOOP(0,i){ 412: if( pempty[ *prdptr[i] - NTBASE ] ) continue; 413: for( p=prdptr[i]+1; *p>=0; ++p ){ 414: if( *p>=NTBASE && pempty[ *p-NTBASE ] == WHOKNOWS ) break; 415: } 416: if( *p < 0 ){ /* production can be derived */ 417: pempty[ *prdptr[i]-NTBASE ] = OK; 418: goto more; 419: } 420: } 421: 422: /* now, look at the nonterminals, to see if they are all OK */ 423: 424: NTLOOP(i){ 425: /* the added production rises or falls as the start symbol ... */ 426: if( i == 0 ) continue; 427: if( pempty[ i ] != OK ) { 428: fatfl = 0; 429: error( "nonterminal %s never derives any token string", nontrst[i].name ); 430: } 431: } 432: 433: if( nerrors ){ 434: summary(); 435: exit(1); 436: } 437: 438: /* now, compute the pempty array, to see which nonterminals derive the empty string */ 439: 440: /* set pempty to WHOKNOWS */ 441: 442: aryfil( pempty, nnonter+1, WHOKNOWS ); 443: 444: /* loop as long as we keep finding empty nonterminals */ 445: 446: again: 447: PLOOP(1,i){ 448: if( pempty[ *prdptr[i]-NTBASE ]==WHOKNOWS ){ /* not known to be empty */ 449: for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]==EMPTY ; ++p ) ; 450: if( *p < 0 ){ /* we have a nontrivially empty nonterminal */ 451: pempty[*prdptr[i]-NTBASE] = EMPTY; 452: goto again; /* got one ... try for another */ 453: } 454: } 455: } 456: 457: } 458: 459: int gsdebug = 0; 460: stagen(){ /* generate the states */ 461: 462: int i, j; 463: register c; 464: register struct wset *p, *q; 465: 466: /* initialize */ 467: 468: nstate = 0; 469: /* THIS IS FUNNY from the standpoint of portability */ 470: /* it represents the magic moment when the mem0 array, which has 471: /* been holding the productions, starts to hold item pointers, of a 472: /* different type... */ 473: /* someday, alloc should be used to allocate all this stuff... for now, we 474: /* accept that if pointers don't fit in integers, there is a problem... */ 475: 476: pstate[0] = pstate[1] = (struct item *)mem; 477: aryfil( clset.lset, tbitset, 0 ); 478: putitem( prdptr[0]+1, &clset ); 479: tystate[0] = MUSTDO; 480: nstate = 1; 481: pstate[2] = pstate[1]; 482: 483: aryfil( amem, ACTSIZE, 0 ); 484: 485: /* now, the main state generation loop */ 486: 487: more: 488: SLOOP(i){ 489: if( tystate[i] != MUSTDO ) continue; 490: tystate[i] = DONE; 491: aryfil( temp1, nnonter+1, 0 ); 492: /* take state i, close it, and do gotos */ 493: closure(i); 494: WSLOOP(wsets,p){ /* generate goto's */ 495: if( p->flag ) continue; 496: p->flag = 1; 497: c = *(p->pitem); 498: if( c <= 1 ) { 499: if( pstate[i+1]-pstate[i] <= p-wsets ) tystate[i] = MUSTLOOKAHEAD; 500: continue; 501: } 502: /* do a goto on c */ 503: WSLOOP(p,q){ 504: if( c == *(q->pitem) ){ /* this item contributes to the goto */ 505: putitem( q->pitem + 1, &q->ws ); 506: q->flag = 1; 507: } 508: } 509: if( c < NTBASE ) { 510: state(c); /* register new state */ 511: } 512: else { 513: temp1[c-NTBASE] = state(c); 514: } 515: } 516: if( gsdebug && (foutput!=NULL) ){ 517: fprintf( foutput, "%d: ", i ); 518: NTLOOP(j) { 519: if( temp1[j] ) fprintf( foutput, "%s %d, ", nontrst[j].name, temp1[j] ); 520: } 521: fprintf( foutput, "\n"); 522: } 523: indgo[i] = apack( &temp1[1], nnonter-1 ) - 1; 524: goto more; /* we have done one goto; do some more */ 525: } 526: /* no more to do... stop */ 527: } 528: 529: int cldebug = 0; /* debugging flag for closure */ 530: closure(i){ /* generate the closure of state i */ 531: 532: int c, ch, work, k; 533: register struct wset *u, *v; 534: int *pi; 535: int **s, **t; 536: struct item *q; 537: register struct item *p; 538: 539: ++zzclose; 540: 541: /* first, copy kernel of state i to wsets */ 542: 543: cwp = wsets; 544: ITMLOOP(i,p,q){ 545: cwp->pitem = p->pitem; 546: cwp->flag = 1; /* this item must get closed */ 547: SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k]; 548: WSBUMP(cwp); 549: } 550: 551: /* now, go through the loop, closing each item */ 552: 553: work = 1; 554: while( work ){ 555: work = 0; 556: WSLOOP(wsets,u){ 557: 558: if( u->flag == 0 ) continue; 559: c = *(u->pitem); /* dot is before c */ 560: 561: if( c < NTBASE ){ 562: u->flag = 0; 563: continue; /* only interesting case is where . is before nonterminal */ 564: } 565: 566: /* compute the lookahead */ 567: aryfil( clset.lset, tbitset, 0 ); 568: 569: /* find items involving c */ 570: 571: WSLOOP(u,v){ 572: if( v->flag == 1 && *(pi=v->pitem) == c ){ 573: v->flag = 0; 574: if( nolook ) continue; 575: while( (ch= *++pi)>0 ){ 576: if( ch < NTBASE ){ /* terminal symbol */ 577: SETBIT( clset.lset, ch ); 578: break; 579: } 580: /* nonterminal symbol */ 581: setunion( clset.lset, pfirst[ch-NTBASE]->lset ); 582: if( !pempty[ch-NTBASE] ) break; 583: } 584: if( ch<=0 ) setunion( clset.lset, v->ws.lset ); 585: } 586: } 587: 588: /* now loop over productions derived from c */ 589: 590: c -= NTBASE; /* c is now nonterminal number */ 591: 592: t = pres[c+1]; 593: for( s=pres[c]; s<t; ++s ){ 594: /* put these items into the closure */ 595: WSLOOP(wsets,v){ /* is the item there */ 596: if( v->pitem == *s ){ /* yes, it is there */ 597: if( nolook ) goto nexts; 598: if( setunion( v->ws.lset, clset.lset ) ) v->flag = work = 1; 599: goto nexts; 600: } 601: } 602: 603: /* not there; make a new entry */ 604: if( cwp-wsets+1 >= WSETSIZE ) error( "working set overflow" ); 605: cwp->pitem = *s; 606: cwp->flag = 1; 607: if( !nolook ){ 608: work = 1; 609: SETLOOP(k) cwp->ws.lset[k] = clset.lset[k]; 610: } 611: WSBUMP(cwp); 612: 613: nexts: ; 614: } 615: 616: } 617: } 618: 619: /* have computed closure; flags are reset; return */ 620: 621: if( cwp > zzcwp ) zzcwp = cwp; 622: if( cldebug && (foutput!=NULL) ){ 623: fprintf( foutput, "\nState %d, nolook = %d\n", i, nolook ); 624: WSLOOP(wsets,u){ 625: if( u->flag ) fprintf( foutput, "flag set!\n"); 626: u->flag = 0; 627: fprintf( foutput, "\t%s", writem(u->pitem)); 628: prlook( &u->ws ); 629: fprintf( foutput, "\n" ); 630: } 631: } 632: } 633: 634: struct looksets *flset( p ) struct looksets *p; { 635: /* decide if the lookahead set pointed to by p is known */ 636: /* return pointer to a perminent location for the set */ 637: 638: register struct looksets *q; 639: int j, *w; 640: register *u, *v; 641: 642: for( q = &lkst[nlset]; q-- > lkst; ){ 643: u = p->lset; 644: v = q->lset; 645: w = & v[tbitset]; 646: while( v<w) if( *u++ != *v++ ) goto more; 647: /* we have matched */ 648: return( q ); 649: more: ; 650: } 651: /* add a new one */ 652: q = &lkst[nlset++]; 653: if( nlset >= LSETSIZE )error("too many lookahead sets" ); 654: SETLOOP(j){ 655: q->lset[j] = p->lset[j]; 656: } 657: return( q ); 658: }