home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / eyacc / ey2.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  12KB  |  536 lines

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