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