Annotation of 43BSD/ucb/pascal/eyacc/ey2.c, revision 1.1.1.1

1.1       root        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:        }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.