1: /* (c) 1979 Regents of the University of California */ 2: # include "ey.h" 3: /* * * * * e y a c c * * * * */ 4: 5: /**** NB ----- 6: * 7: * This version of yacc, known as "eyacc" has been slightly but 8: * importantly modified to allow error recovery in the UNIX Pascal 9: * translator "pi" and also in "pix". 10: * 11: * Changes here include: 12: * 13: * 1) Enumeration of test actions when "error" is an input token. 14: * 15: * 2) Change to the encoding of the action entries. Test entries 16: * are encoded as the arithmetic inverse of the symbol being tested 17: * for. This is an optimization that makes the parser run at the 18: * same speed even though, with error productions and enumerated 19: * lookaheads, it would normally be much slower. Of course the 20: * same thing could be done to the regular yacc... 21: * 22: * 3) Different table sizes 23: * 24: * 4) Recognizes form feeds 25: * 26: * 5) Also most of the numbers for the sizes of the tables have been 27: * increased, to an extent to allow for "eyacc"ing of the Pascal grammar 28: * and of a grammar which I have for "EUCLID". 29: * 30: * There seem to be subtle dependencies between the various magic 31: * numbers... I found some of them but to be safe most of the limits 32: * are very generous... for this reason "eyacc" will most likely 33: * have to run separate i/d... no matter. 34: * 35: * Bill Joy 36: * Computer Science Division 37: * EECS Department 38: * University of California, Berkeley 39: * Berkeley, California 94704 40: * 41: * Office: (415) 642-4948 42: * Home: (415) 524-4510 43: ****/ 44: 45: /* features to be fixed up ... 46: 47: *** Print estimate of total space needed for parser 48: *** Either list inputs on y.output, or list empty prdn's in states 49: *** Mention nonterms not used (or, rules. not reduced) as nonfatal error 50: *** Output states where conflicts were found by default on y.output 51: *** Engage in newspeak: production=>grammar rules, term=>token, etc. 52: *** handle # define, #ifdef, etc., in yacc actions, %{ %} 53: */ 54: 55: /* new features to be added 56: 57: *** reductions by single productions ( by request ) 58: *** follow sets for start symbol 59: *** option to only do slr(1) 60: *** easily changed array names on output 61: *** allocate core, rather than predefined 62: *** input controlled by a grammar 63: *** support multiple choices for conflicts 64: *** better conflict diagnostics 65: */ 66: 67: extern char *symnam(); 68: 69: main(argc,argv) int argc; char *argv[]; { 70: auto int n; 71: 72: whereami(); 73: setup(argc,argv); /* initialize and read productions */ 74: tbitset = (nterms+16)/16; 75: cpres(); /* make table of which productions yield a given nonterminal */ 76: cempty(); /* make a table of which nonterminals can match the empty string */ 77: cpfir(); /* make a table of e free first lists */ 78: stagen(); /* generate the states */ 79: output(); /* write the states and the tables */ 80: go2out(); 81: summary(); 82: windup(); 83: } 84: 85: whereami(){ /* sets the variable machine to UNIX, GCOS, or IBM */ 86: 87: int i; 88: 89: i = 1; 90: i = i << 30; 91: if( i == 0 ) { 92: machine = UNIX; 93: return; 94: } 95: i = i << 4; 96: if( i == 0 ){ 97: machine = IBM; 98: return; 99: } 100: machine = GCOS; 101: } 102: 103: windup(){ 104: /* no errors, do the optimization if appropriate */ 105: char *cp; 106: int i; 107: 108: if( !oflag ) cexit(0); 109: 110: switch( machine ){ 111: 112: case GCOS: 113: if( rflag ){ 114: if( foutput<0 ) system( "./yopt -r" ); 115: else system( "./yopt -rv" ); 116: } 117: else { 118: if( foutput<0 ) system( "./yopt" ); 119: else system( "./yopt -v" ); 120: } 121: cexit(0); /* terminate */ 122: 123: case UNIX: 124: cp = "/usr/nlib/yaccopt"; 125: if( rflag ) execl( cp, cp, (foutput<0)?"-r":"-rv", 0 ); 126: else if( foutput<0 ) execl( cp, cp, 0 ); 127: else execl( cp, cp, "-v", 0 ); 128: error( "optimization execl call fails" ); 129: 130: case IBM: 131: if( rflag ){ 132: if( foutput<0 ) system( "MH2019.yaccopt -r" ); 133: else system( "MH2019.yaccopt -rv" ); 134: } 135: else { 136: if( foutput<0 ) system( "MH2019.yaccopt" ); 137: else system( "MH2019.yaccopt -v" ); 138: } 139: cexit(0); 140: 141: } 142: 143: } 144: 145: settty() 146: /* sets the output file to y.output */ 147: { 148: cflush( foutput ); /* a bit of a cheat */ 149: cout = foutput; 150: } 151: 152: settab(){ /* sets the output file to y.tab.c */ 153: 154: cflush( ftable ); 155: cout = ftable; 156: } 157: 158: char *chcopy( p, q ) char *p, *q; { 159: /* copies string q into p, returning next free char ptr */ 160: while( *p = *q++ ) ++p; 161: return( p ); 162: } 163: 164: char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */ 165: int i,*p; 166: static char sarr[100]; 167: char *q; 168: 169: for( p=pp->pitem; *p>0 ; ++p ) ; 170: p = prdptr[-*p]; 171: q = chcopy( sarr, nontrst[*p-NTBASE].name ); 172: q = chcopy( q, " : " ); 173: 174: for(;;){ 175: *q++ = ++p==(pp->pitem) ? '_' : ' '; 176: if((i = *p) <= 0) break; 177: q = chcopy( q, symnam(i) ); 178: } 179: 180: *q = '\0' ; 181: return( sarr ); 182: } 183: 184: char *symnam(i){ /* return a pointer to the name of symbol i */ 185: char *cp; 186: 187: cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ; 188: if( *cp == ' ' ) ++cp; 189: return( cp ); 190: } 191: 192: summary(){ /* output the summary on the tty */ 193: 194: int i, s, *pn; 195: 196: 197: if( !rflag ){ 198: settab(); 199: fprintf( cout , "\nint nterms %d;",nterms); 200: fprintf( cout , "\nint nnonter %d;", nnonter); 201: fprintf( cout , "\nint nstate %d;", nstate); 202: fprintf( cout , "\nchar *yysterm[] {"); 203: for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) fprintf( cout , "\n\"%s\",",symnam(i)); 204: fprintf( cout , "\n0 };\n" ); 205: fprintf( cout , "\nchar *yysnter[] {"); 206: for (i=0;i<nnonter;i++) fprintf( cout , "\n\"%s\",",nontrst[i].name); 207: fprintf( cout , "\n\"%s\" };\n",nontrst[nnonter].name); 208: } 209: 210: settty(); 211: fprintf( cout , "\n%d/%d terminals, %d/%d nonterminals\n", nterms, tlim, 212: nnonter, ntlim ); 213: fprintf( cout , "%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize ); 214: fprintf( cout , "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf ); 215: pn = pstate[nstate+1]; 216: fprintf( cout , "%d/%d working sets used\n", zzcwset, wssize ); 217: fprintf( cout , "memory: states,etc. %d/%d, parser %d/%d\n", pn-mem0, memsiz, 218: memact, actsiz ); 219: fprintf( cout , "%d/%d distinct lookahead sets\n", nlset, lsetsz ); 220: fprintf( cout , "%d extra closures\n", zzclose - 2*nstate ); 221: fprintf( cout , "%d action entries\n", zzacent ); 222: fprintf( cout , "%d action entries saved through merging %d states\n",zzacsave,zznsave); 223: fprintf( cout , "%d goto entries\n", zzgoent ); 224: fprintf( cout , "%d entries saved by goto default\n", zzgobest ); 225: if( zzsrconf!=0 || zzrrconf!=0 ){ 226: cflush( errfileno ); 227: cout = errfileno; 228: fprintf( cout , "\nconflicts: "); 229: if( zzsrconf )fprintf( cout , "%d shift/reduce" , zzsrconf ); 230: if( zzsrconf && zzrrconf )fprintf( cout , ", " ); 231: if( zzrrconf )fprintf( cout , "%d reduce/reduce" , zzrrconf ); 232: fprintf( cout , "\n" ); 233: } 234: } 235: 236: error(s,a1){ /* write out error comment */ 237: 238: int c; 239: ++nerrors; 240: cflush( errfileno ); 241: cout = errfileno; /* set output to tty */ 242: fprintf( cout , "\n fatal error: "); 243: fprintf( cout , s,a1); 244: fprintf( cout , ", line %d\n", lineno ); 245: if( !fatfl ) return; 246: summary(); 247: cexit(1); 248: } 249: 250: arrset(s) char s[]; { 251: fprintf( cout , "\nint %s[] {0", s ); 252: arrndx = 1; 253: } 254: 255: arrval(n){ 256: fprintf( cout , ",%d",n); 257: if( (++arrndx%10) == 0 ) fprintf( cout , "\n"); 258: } 259: 260: arrdone(){ 261: fprintf( cout , ",-1};\n"); 262: } 263: 264: copy(v) char *v; { /* copy ctokn to v */ 265: char *p; 266: 267: p=ctokn; 268: while( *v++ = *p++ ); 269: } 270: 271: compare(v) char *v; { /* compare ctokn with v */ 272: char *p; 273: 274: for( p=ctokn; ; ++p ){ 275: if( *p != *v++ ) return( 0 ); 276: if( *p == 0 ) return(1); 277: } 278: } 279: 280: int *yalloc(n){ /* allocate n+1 words from vector mem */ 281: int *omem; 282: omem = mem; 283: mem += n+1; 284: if(mem-mem0 >= memsiz) error("memory overflow"); 285: return(omem); 286: } 287: 288: aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ 289: int i; 290: for( i=0; i<n; ++i ) v[i] = c; 291: } 292: 293: UNION( a, b, c ) int *a, *b, *c; { 294: /* set a to the UNION of b and c */ 295: /* a may equal b */ 296: /* return 1 if c is not a subset of b, 0 otherwise */ 297: 298: _REGISTER int i, x, sub; 299: 300: sub = 0; 301: for( i=0; i<tbitset; ++i ){ 302: x = b[i] | c[i]; 303: if( x != b[i] ) sub=1; 304: a[i] = x; 305: } 306: return( sub ); 307: } 308: 309: prlook( pp ) int *pp;{ 310: int j; 311: pp = pp->lset; 312: if( pp == 0 ) fprintf( cout , "\tNULL"); 313: else { 314: fprintf( cout , " { " ); 315: for( j=1; j<=nterms; ++j ){ 316: if( (pp[j>>4]>>(j&017) )&01 != 0 ) fprintf( cout , "%s ", symnam(j) ); 317: } 318: fprintf( cout , "}" ); 319: } 320: }