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