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

Defined functions

chfind defined in line 403; used 4 times
chstash defined in line 280; used 5 times
cpyact defined in line 446; used 1 times
cpycode defined in line 424; used 2 times
defin defined in line 203; used 4 times
defout defined in line 250; used 2 times
finact defined in line 184; used 1 times
gettok defined in line 286; used 3 times
setup defined in line 25; used 1 times

Defined variables

sccsid defined in line 8; never used

Defined macros

BINARY defined in line 16; used 5 times
C_IDENTIFIER defined in line 20; used 1 times
IDENTIFIER defined in line 12; used 2 times
LCURLY defined in line 19; used 1 times
LEFT defined in line 15; used 3 times
MARK defined in line 13; used 2 times
NUMBER defined in line 21; used 1 times
PREC defined in line 18; used 3 times
RIGHT defined in line 17; used 3 times
TERM defined in line 14; used 5 times
Last modified: 1985-04-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4264
Valid CSS Valid XHTML 1.0 Strict