1: # include <stdio.h> 2: # include "dextern" 3: 4: extern FILE *Fout, *Fin; 5: 6: # define IDENTIFIER 257 7: # define MARK 258 8: # define TERM 259 9: # define LEFT 260 10: # define BINARY 261 11: # define RIGHT 262 12: # define PREC 263 13: # define LCURLY 264 14: # define C_IDENTIFIER 265 /* name followed by colon */ 15: # define NUMBER 266 16: 17: setup(argc,argv) int argc; char *argv[]; 18: { int i,j,lev,t; 19: int c; 20: 21: Foutput = NULL; 22: i = 1; 23: while( argc >= 2 && argv[1][0] == '-' ) { 24: while( *++(argv[1]) ){ 25: switch( *argv[1] ){ 26: case 'v': 27: case 'V': 28: Foutput = copen("y.output", 'w' ); 29: if( Foutput == 0 ) error( "cannot open y.output"); 30: continue; 31: case 'o': 32: case 'O': 33: oflag = 1; 34: continue; 35: case 'r': 36: case 'R': 37: rflag = 1; 38: oflag = 1; 39: continue; 40: case 's': 41: case 'S': 42: sflag = 1; 43: continue; 44: default: error( "illegal option: %c", *argv[1]); 45: } 46: } 47: argv++; 48: argc--; 49: } 50: 51: if (Foutput == 0) 52: Foutput = copen("/dev/null", 'w'); 53: ftable = copen( oflag ? "yacc.tmp" : "y.tab.c" , 'w' ); 54: if( ftable<0 ) error( "cannot open table file" ); 55: if( argc > 1 ) cin = copen( argv[1], 'r' ); 56: if( cin < 0 ) error( "cannot open input" ); 57: settab(); 58: fprintf(Fout, "#\n"); 59: ctokn = "$end"; 60: defin(0); /* eof */ 61: extval = 0400; /* beginning of assigned values */ 62: ctokn = "error"; 63: defin(0); 64: ctokn = "$accept"; 65: defin(1); 66: mem=mem0; 67: cnamp = cnames; 68: lev=0; 69: i=0; 70: 71: while( t = gettok() ){ 72: switch( t ){ 73: case IDENTIFIER: j = chFind(0); 74: trmlev[j] = lev; 75: continue; 76: case ',': 77: case ';': continue; 78: case TERM: lev=0; continue; 79: case LEFT: lev=(++i<<3)|01; continue; 80: case BINARY: lev=(++i<<3)|02; continue; 81: case RIGHT: lev=(++i<<3)|03; continue; 82: case MARK: 83: deFout(); 84: if( rflag ){ /* RATFOR */ 85: fprintf(Fout, "define yyerrok yyerrf = 0\n" ); 86: fprintf(Fout, "define yyclearin yychar = -1\n" ); 87: fprintf(Fout, "subroutine yyactr(yyprdn)\n"); 88: fprintf(Fout, "common/yycomn/yylval,yyval,yypv,yyvalv(150)\n" ); 89: fprintf(Fout, "common/yylcom/yychar,yyerrf,yydebu\n" ); 90: fprintf(Fout, "integer yychar, yyerrf, yydebu\n" ); 91: fprintf(Fout, "integer yyprdn,yyval,yylval,yypv,yyvalv\n" ); 92: } 93: else { 94: fprintf(Fout, "#define yyclearin yychar = -1\n" ); 95: fprintf(Fout, "#define yyerrok yyerrflag = 0\n" ); 96: fprintf(Fout, "extern int yychar, yyerrflag;\n" ); 97: fprintf(Fout, "\nint yyval = 0;\nint *yypv;\nint yylval = 0;"); 98: fprintf(Fout, "\nyyactr(__np__){\n"); 99: } 100: break; 101: case LCURLY: deFout(); 102: cpycode(); 103: continue; 104: case NUMBER: 105: trmset[j].value = numbval; 106: if( j < ndeFout && j>2 ) 107: error("please define type # of %s earlier", trmset[j].name ); 108: continue; 109: default: error("bad precedence syntax, input %d", t ); 110: } 111: break; 112: } 113: prdptr[0]=mem; 114: /* added production */ 115: *mem++ = NTBASE; 116: *mem++ = NTBASE+1; 117: *mem++ = 1; 118: *mem++ = 0; 119: prdptr[1]=mem; 120: i=0; 121: 122: /* i is 0 when a rule can begin, 1 otherwise */ 123: 124: for(;;) switch( t=gettok() ) { 125: case C_IDENTIFIER: if( mem == prdptr[1] ) { /* first time */ 126: if( rflag ){ 127: fprintf(Fout, "goto 1000\n" ); 128: } 129: else fprintf(Fout, "\nswitch(__np__){\n"); 130: } 131: if( i != 0 ) error( "previous rule not terminated" ); 132: *mem = chFind(1); 133: if( *mem < NTBASE )error( "token illegal on lhs of grammar rule" ); 134: i=1; 135: ++mem; 136: continue; 137: case IDENTIFIER: 138: *mem=chFind(1); 139: if(*mem < NTBASE)levprd[nprod]=trmlev[*mem]; 140: mem++; 141: if(i==0) error("missing :"); 142: continue; 143: case '=': levprd[nprod] |= 04; 144: if( i==0 ) error("semicolon preceeds action"); 145: fprintf(Fout, rflag?"\n%d ":"\ncase %d:", nprod ); 146: cpyact(); 147: fprintf(Fout, rflag ? " return" : " break;" ); 148: case '|': 149: case ';': if(i){ 150: *mem++ = -nprod; 151: prdptr[++nprod] = mem; 152: levprd[nprod]=0; 153: i=0;} 154: if (t=='|'){i=1;*mem++ = *prdptr[nprod-1];} 155: continue; 156: case 0: /* End Of File */ 157: case MARK: if( i != 0 ) error( "rule not terminated before %%%% or EOF" ); 158: settab(); 159: Finact(); 160: /* copy the programs which follow the rules */ 161: if( t == MARK ){ 162: while ((c=getc(Fin)) > 0) putc(c, Fout); 163: } 164: return; 165: case PREC: 166: if( i==0 ) error( "%%prec must appear inside rule" ); 167: if( gettok()!=IDENTIFIER)error("illegal %%prec syntax" ); 168: j=chFind(2); 169: if(j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name); 170: levprd[nprod]=trmlev[j]; 171: continue; 172: case LCURLY: 173: if( i!=0 ) error( "%%{ appears within a rule" ); 174: cpycode(); 175: continue; 176: default: error( "syntax error, input %d", t ); 177: } 178: } 179: 180: Finact(){ 181: /* Finish action routine */ 182: register i; 183: 184: if( rflag ){ 185: 186: fprintf(Fout, "\n1000 goto(" ); 187: for( i=1; i<nprod; ++i ){ 188: fprintf(Fout, "%d,", (levprd[i]&04)==0?999:i ); 189: } 190: fprintf(Fout, "999),yyprdn\n" ); 191: fprintf(Fout, "999 return\nend\n" ); 192: fprintf(Fout, "define YYERRCODE %d\n", trmset[2].value ); 193: } 194: else { 195: /* ------- The next line is an INGRES customization ------- */ 196: fprintf(Fout, "\n}\nreturn(0);\n}\n" ); 197: fprintf(Fout, "int yyerrval = %d;\n", trmset[2].value ); 198: } 199: } 200: defin(t) { 201: /* define ctokn to be a terminal if t=0 202: or a nonterminal if t=1 */ 203: char *cp,*p; 204: int c; 205: 206: 207: if (t) { 208: if( ++nnonter >= ntlim ) error("too many nonterminals, limit %d",ntlim); 209: nontrst[nnonter].name = ctokn; 210: return( NTBASE + nnonter ); 211: } 212: else { 213: if( ++nterms >= tlim ) error("too many terminals, limit %d",tlim ); 214: trmset[nterms].name = ctokn; 215: if( ctokn[0]==' ' && ctokn[2]=='\0' ) /* single character literal */ 216: trmset[nterms].value = ctokn[1]; 217: else if ( ctokn[0]==' ' && ctokn[1]=='\\' ) { /* escape sequence */ 218: if( ctokn[3] == '\0' ){ /* single character escape sequence */ 219: switch ( ctokn[2] ){ 220: /* character which is escaped */ 221: case 'n': trmset[nterms].value = '\n'; break; 222: case 'r': trmset[nterms].value = '\r'; break; 223: case 'b': trmset[nterms].value = '\b'; break; 224: case 't': trmset[nterms].value = '\t'; break; 225: case '\'': trmset[nterms].value = '\''; break; 226: case '"': trmset[nterms].value = '"'; break; 227: case '\\': trmset[nterms].value = '\\'; break; 228: default: error( "invalid escape" ); 229: } 230: } 231: else if( ctokn[2] <= '7' && ctokn[2]>='0' ){ /* \nnn sequence */ 232: if( ctokn[3]<'0' || ctokn[3] > '7' || ctokn[4]<'0' || 233: ctokn[4]>'7' || ctokn[5] != '\0' ) error("illegal \\nnn construction" ); 234: trmset[nterms].value = 64*(ctokn[2]-'0')+8*(ctokn[3]-'0')+ctokn[4]-'0'; 235: if( trmset[nterms].value == 0 ) error( "'\\000' is illegal" ); 236: } 237: } 238: else { 239: trmset[nterms].value = extval++; 240: 241: } 242: trmlev[nterms] = 0; 243: return( nterms ); 244: } 245: } 246: 247: deFout(){ /* write out the defines (at the end of the declaration section) */ 248: 249: _REGISTER int i, c; 250: _REGISTER char *cp; 251: 252: for( i=ndeFout; i<=nterms; ++i ){ 253: 254: cp = trmset[i].name; 255: if( *cp == ' ' ) ++cp; /* literals */ 256: 257: for( ; (c= *cp)!='\0'; ++cp ){ 258: 259: if( c>='a' && c<='z' || 260: c>='A' && c<='Z' || 261: c>='0' && c<='9' || 262: c=='_' ) ; /* VOID */ 263: else goto nodef; 264: } 265: 266: /* define it */ 267: 268: fprintf(Fout, "%c define %s %d\n", rflag?' ':'#', trmset[i].name, trmset[i].value ); 269: 270: nodef: ; 271: } 272: 273: ndeFout = nterms+1; 274: 275: } 276: 277: chstash( c ){ 278: /* put character away into cnames */ 279: if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); 280: else *cnamp++ = c; 281: } 282: 283: int gettok() { 284: int j, base; 285: static int peekline; /* number of '\n' seen in lookahead */ 286: auto int c, match, reserve; 287: 288: begin: 289: reserve = 0; 290: if( peekc>=0 ) { 291: c = peekc; 292: lineno += peekline; 293: peekc = -1; 294: peekline = 0; 295: } 296: else c = getc(Fin); 297: while( c==' ' || c=='\n' || c=='\t' ){ 298: if( c == '\n' ) ++lineno; 299: c=getc(Fin); 300: } 301: if (c=='/') 302: {if (getc(Fin)!='*')error("illegal /"); 303: c=getc(Fin); 304: while(c) { 305: if( c == '\n' ) ++lineno; 306: if (c=='*') 307: {if((c=getc(Fin))=='/')break;} 308: else c=getc(Fin);} 309: if (!c) return(0); 310: goto begin;} 311: j=0; 312: switch(c){ 313: case '"': 314: case '\'': match = c; 315: ctokn = cnamp; 316: chstash( ' ' ); 317: while(1){ 318: c = getc(Fin); 319: if( c == '\n' || c == '\0' ) 320: error("illegal or missing ' or \""); 321: if( c == '\\' ){ 322: c = getc(Fin); 323: chstash( '\\' ); 324: } 325: else if( c == match ) break; 326: chstash( c ); 327: } 328: break; 329: case '%': 330: case '\\': switch(c=getc(Fin)) 331: {case '0': return(TERM); 332: case '<': return(LEFT); 333: case '2': return(BINARY); 334: case '>': return(RIGHT); 335: case '%': 336: case '\\': return(MARK); 337: case '=': return(PREC); 338: case '{': return(LCURLY); 339: default: reserve = 1; 340: } 341: default: if( c >= '0' && c <= '9' ){ /* number */ 342: numbval = c-'0' ; 343: base = (c=='0') ? 8 : 10 ; 344: for( c=getc(Fin); c>='0' && c<='9'; c=getc(Fin) ){ 345: numbval = numbval*base + c - '0'; 346: } 347: peekc = c; 348: return(NUMBER); 349: } 350: else if( (c>='a'&&c<='z')||(c>='A'&&c<='Z')||c=='_'||c=='.'||c=='$'){ 351: ctokn = cnamp; 352: while( (c>='a'&&c<='z') || 353: (c>='A'&&c<='Z') || 354: (c>='0'&&c<='9') || 355: c=='_' || c=='.' || c=='$' ) { 356: chstash( c ); 357: if( peekc>=0 ) { c = peekc; peekc = -1; } 358: else c = getc(Fin); 359: } 360: } 361: else return(c); 362: 363: peekc=c; 364: } 365: chstash( '\0' ); 366: 367: if( reserve ){ /* Find a reserved word */ 368: if( compare("term")) return( TERM ); 369: if( compare("TERM")) return( TERM ); 370: if( compare("token")) return( TERM ); 371: if( compare("TOKEN")) return( TERM ); 372: if( compare("left")) return( LEFT ); 373: if( compare("LEFT")) return( LEFT ); 374: if( compare("nonassoc")) return( BINARY ); 375: if( compare("NONASSOC")) return( BINARY ); 376: if( compare("binary")) return( BINARY ); 377: if( compare("BINARY")) return( BINARY ); 378: if( compare("right")) return( RIGHT ); 379: if( compare("RIGHT")) return( RIGHT ); 380: if( compare("prec")) return( PREC ); 381: if( compare("PREC")) return( PREC ); 382: error("invalid escape, or illegal reserved word: %s", ctokn ); 383: } 384: 385: /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ 386: 387: look: 388: while( peekc==' ' || peekc=='\t' || peekc == '\n' ) { 389: if( peekc == '\n' ) ++peekline; 390: peekc = getc(Fin); 391: } 392: 393: if( peekc != ':' ) return( IDENTIFIER ); 394: peekc = -1; 395: lineno += peekline; 396: peekline = 0; 397: return( C_IDENTIFIER ); 398: } 399: chFind(t) 400: 401: { int i,j; 402: 403: if (ctokn[0]==' ')t=0; 404: for(i=1;i<=nterms;i++) 405: if(compare(trmset[i].name)){ 406: cnamp = ctokn; 407: return( i ); 408: } 409: for(i=1;i<=nnonter;i++) 410: if(compare(nontrst[i].name)) { 411: cnamp = ctokn; 412: return( i+NTBASE ); 413: } 414: /* cannot Find name */ 415: if( t>1 && ctokn[0] != ' ' ) 416: error( "%s should have been defined earlier", ctokn ); 417: return( defin( t ) ); 418: } 419: 420: cpycode(){ /* copies code between \{ and \} */ 421: 422: int c; 423: c = getc(Fin); 424: if( c == '\n' ) { 425: c = getc(Fin); 426: lineno++; 427: } 428: while( c ){ 429: if( c=='\\' ) 430: if( (c=getc(Fin)) == '}' ) return; 431: else putc('\\', Fout); 432: if( c=='%' ) 433: if( (c=getc(Fin)) == '}' ) return; 434: else putc('%', Fout); 435: putc( c , Fout); 436: if( c == '\n' ) ++lineno; 437: c = getc(Fin); 438: } 439: error("eof before %%}"); 440: } 441: 442: cpyact(){ /* copy C action to the next ; or closing } */ 443: int brac, c, match, *i, j, s; 444: 445: brac = 0; 446: 447: loop: 448: c = getc(Fin); 449: swt: 450: switch( c ){ 451: 452: case ';': 453: if( brac == 0 ){ 454: putc( c , Fout); 455: return; 456: } 457: goto lcopy; 458: 459: case '{': 460: brac++; 461: goto lcopy; 462: 463: case '$': 464: s = 1; 465: c = getc(Fin); 466: if( c == '$' ){ 467: fprintf(Fout, "yyval"); 468: goto loop; 469: } 470: if( c == '-' ){ 471: s = -s; 472: c = getc(Fin); 473: } 474: if( c>='0' && c <= '9' ){ 475: j=0; 476: while( c>='0' && c<= '9' ){ 477: j= j*10+c-'0'; 478: c = getc(Fin); 479: } 480: if( rflag ) fprintf(Fout, "yyvalv(yypv%c%d)", s==1?'+':'-', j ); 481: else fprintf(Fout, "yypv[%d]", s*j ); 482: goto swt; 483: } 484: putc( '$' , Fout); 485: if( s<0 ) putc('-', Fout); 486: goto swt; 487: 488: case '}': 489: brac--; 490: if( brac == 0 ){ 491: putc( c , Fout); 492: return; 493: } 494: goto lcopy; 495: 496: case '/': /* look for comments */ 497: putc( c , Fout); 498: c = getc(Fin); 499: if( c != '*' ) goto swt; 500: 501: /* it really is a comment */ 502: 503: putc( c , Fout); 504: while( (c=getc(Fin)) > 0 ){ 505: if( c=='*' ){ 506: putc( c , Fout); 507: if( (c=getc(Fin)) == '/' ) goto lcopy; 508: } 509: putc( c , Fout); 510: } 511: error( "EOF inside comment" ); 512: 513: case '\'': /* character constant */ 514: match = '\''; 515: goto string; 516: 517: case '"': /* character string */ 518: match = '"'; 519: 520: string: 521: 522: putc( c , Fout); 523: while( (c=getc(Fin)) > 0 ){ 524: 525: if( c=='\\' ){ 526: putc( c , Fout); 527: c=getc(Fin); 528: } 529: else if( c==match ) goto lcopy; 530: putc( c , Fout); 531: } 532: error( "EOF in string or character constant" ); 533: 534: case '\0': 535: error("action does not terminate"); 536: case '\n': ++lineno; 537: goto lcopy; 538: 539: } 540: 541: lcopy: 542: putc( c , Fout); 543: goto loop; 544: }