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