home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OS2-YACC.ZIP / YSETUP.2C < prev    next >
Text File  |  1989-10-07  |  14KB  |  476 lines

  1. /*
  2.   HEADER: CUG     nnn.nn;
  3.   TITLE:     YACC - Yet Another Compilier-Compilier
  4.   VERSION:     1.0 for IBM-PC
  5.   DATE:      JAN 28, 1985
  6.   DESCRIPTION:     LALR(1) Parser Generator. From UNIX
  7.   KEYWORDS:     Parser Generator Compilier-Compilier YACC
  8.   SYSTEM:     IBM-PC and Compatiables
  9.   FILENAME:      YSETUP.2C
  10.   WARNINGS:     This program is not for the casual user. It will
  11.          be useful primarily to expert developers.
  12.   CRC:         N/A
  13.   SEE-ALSO:     LEX and PREP
  14.   AUTHORS:     Scott Guthery 11100 leafwood lane Austin, TX 78750
  15.   COMPILERS:     DESMET-C
  16.   REFERENCES:     UNIX Systems Manuals
  17. */
  18.  
  19. #include <string.h>
  20. #include "y1.h"
  21. #include "y2.h"
  22. /*
  23.  * YSETUP.C  -- Modified for use with DECUS LEX
  24.  *              Variable "yylval" resides in yylex(), not in yypars();
  25.  *              Therefore, is defined "extern" here.
  26.  *
  27.  *              Also, the command line processing for the Decus version
  28.  *              has been changed.  A new switch has been added to allow
  29.  *              specification of the "table" file name(s), and unused
  30.  *              switch processing removed.
  31.  *
  32.  *                               NOTE
  33.  *              This probably won't run on UNIX any more.
  34.  *
  35.  * Bob Denny 27-Aug-81
  36.  * Bob Denny 22-Mar-82 (01) Added header line, changes for 'new' DECUS library
  37.  * Bob Denny 12-Apr-83 (02) Make filename[] size per #define'd FNAMESIZE so
  38.  *                          VAX filenames won't blow out.  Conditionalize
  39.  *                          time handling for banner.  Make filespec buffer
  40.  *                          static for safety, since global "infile" is
  41.  *                          pointed to it.
  42.  * Scott Guthery 15-May-83  (03) Fixed up option flag handling for RT-11
  43.  *                 23-Dec-83  Adapted for IBM PC/XT & DeSmet C compiler
  44.  */
  45.  
  46. static char filename[FNAMESIZE];
  47.  
  48. int i,j,lev,t, ty;
  49. int c;
  50. int tempty;
  51. int *p;
  52. int defsw, infsw;
  53. char actname[8];
  54. char *cp;
  55.  
  56. void setup(int argc, char *argv[])
  57.    {
  58.    char finsave[FNAMESIZE];
  59.  
  60.    defsw = infsw = 0;
  61.    foutput = NULL;
  62.    fdefine = NULL;
  63.    ftemp = NULL;
  64.    i = 1;                                               /*(03)*/
  65.    while( argc > 1 && argv[i][0] == '-' )               /*(03)*/
  66.       {
  67.       while( *++(argv[i]) )
  68.          {
  69.          switch( *argv[i] )
  70.             {
  71.          case 'i':
  72.          case 'I':
  73.             infsw++;
  74.             continue;
  75.          case 'h':
  76.          case 'H':
  77.  
  78.             defsw++;
  79.             continue;
  80.          default:
  81.             fprintf(stderr, "Illegal option: %c\n", *argv[i]);
  82.             usage();
  83.             }
  84.          }
  85.       i++;                                              /*(03)*/
  86.       argc--;
  87.       }
  88.  
  89.    if(argc < 2) usage();               /* Catch no filename given */
  90.  
  91. /*
  92.  * Now open the input file with a default extension of ".Y",
  93.  * then replace the period in argv[1] with a null, so argv[1]
  94.  * can be used to form the table, defs and info filenames.
  95.  */
  96.  
  97.    cp = argv[i];
  98.    while(*cp++ != '.' && *cp != '\0'); /* Scan past '.' or to null */
  99.    if(*cp == '\0') {
  100.       strcpy(filename, argv[i]); strcat(filename, ".Y");
  101.    } else
  102.       {
  103.       strcpy(filename, argv[i]);
  104.       *(argv[i]-1) = '\0';             /* Null the period */
  105.       }
  106.  
  107.    strcpy(finsave, filename);
  108.    if((finput=fopen( filename, "r" )) == NULL )
  109.       error( "cannot open input file \"%s\"", filename );
  110.  
  111. /*
  112.  * Now open the .H and .I files if requested.
  113.  */
  114.  
  115.    if(defsw)
  116.       {
  117.       strcpy(filename, argv[i]); strcat(filename, ".H");
  118.       fdefine = fopen(filename, "w");
  119.       if(fdefine == NULL) error("cannot open defs file\"%s\"", filename);
  120.       }
  121.  
  122.    if(infsw)
  123.       {
  124.       strcpy(filename, argv[i]); strcat(filename, ".I");
  125.       foutput = fopen(filename, "w");
  126.       if(foutput == NULL) error("cannot open info file\"%s\"", filename);
  127.       }
  128. /*
  129.  * Now the "table" output C file.
  130.  */
  131.    strcpy(filename, argv[i]); strcat(filename, ".C");
  132.    ftable = fopen(filename, "w");
  133.    if( ftable == NULL ) error( "cannot open table file\"%s\"", filename);
  134. /*
  135.  * Finally, the temp files.
  136.  */
  137.    ftemp = fopen( TEMPNAME, "w" );
  138.    if( ftemp==NULL ) error( "cannot open temp file" );
  139.    faction = fopen( ACTNAME, "w" );
  140.    if( faction==NULL ) error( "cannot open action file" );
  141.  
  142. /*
  143.  * Now put the full filename of the input file into
  144.  * the "filename" buffer for cpyact(), and point the
  145.  * global cell "infile" at it.
  146.  */
  147.    strcpy(filename, finsave);
  148.    infile = filename;
  149. /*
  150.  * Put out a header line at the beginning of the 'table' file.
  151.  */
  152. fprintf(ftable, "/*\n * Created by CSD YACC (IBM PC) from \"%s\" */\n",
  153.         infile);
  154. /*
  155.  * Complete  initialization.
  156.  */
  157.    cnamp = cnames;
  158.    defin(0,"$end");
  159.    extval = 0400;
  160.    defin(0,"error");
  161.    defin(1,"$accept");
  162.    mem=mem0;
  163.    lev = 0;
  164.    ty = 0;
  165.    i=0;
  166.  
  167.    yyparse();
  168.    }
  169.  
  170. void yyparse( void )
  171.    {
  172.    /* sorry -- no yacc parser here.....
  173.                 we must bootstrap somehow... */
  174.  
  175.    for( t=gettok();  t!=MARK && t!= ENDFILE; )
  176.       {
  177.       switch( t )
  178.          {
  179.  
  180.       case ';':
  181.          t = gettok();
  182.          break;
  183.  
  184.       case START:
  185.          if( (t=gettok()) != IDENTIFIER )
  186.             {
  187.             error( "bad %%start construction" );
  188.             }
  189.          start = chfind(1,tokname);
  190.          t = gettok();
  191.          continue;
  192.  
  193.       case TYPEDEF:
  194.          if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" );
  195.          ty = numbval;
  196.          for(;;)
  197.  
  198.             {
  199.             t = gettok();
  200.             switch( t )
  201.                {
  202.  
  203.             case IDENTIFIER:
  204.                if( (t=chfind( 1, tokname ) ) < NTBASE )
  205.                   {
  206.                   j = TYPE( toklev[t] );
  207.                   if( j!= 0 && j != ty )
  208.                      {
  209.                      error( "type redeclaration of token %s",
  210.                      tokset[t].name );
  211.                      }
  212.                   else SETTYPE( toklev[t],ty);
  213.                   }
  214.                else
  215.                   {
  216.                   j = nontrst[t-NTBASE].tvalue;
  217.                   if( j != 0 && j != ty )
  218.                      {
  219.                      error( "type redeclaration of nonterminal %s",
  220.                      nontrst[t-NTBASE].name );
  221.                      }
  222.                   else nontrst[t-NTBASE].tvalue = ty;
  223.                   }
  224.             case ',':
  225.                continue;
  226.  
  227.             case ';':
  228.                t = gettok();
  229.                break;
  230.             default:
  231.                break;
  232.                }
  233.             break;
  234.             }
  235.          continue;
  236.  
  237.       case UNION:
  238.          /* copy the union declaration to the output */
  239.          cpyunion();
  240.          t = gettok();
  241.          continue;
  242.  
  243.       case LEFT:
  244.       case BINARY:
  245.       case RIGHT:
  246.          ++i;
  247.       case TERM:
  248.          lev = t-TERM;  /* nonzero means new prec. and assoc. */
  249.          ty = 0;
  250.  
  251.          /* get identifiers so defined */
  252.  
  253.          t = gettok();
  254.          if( t == TYPENAME )
  255.             {
  256.             /* there is a type defined */
  257.             ty = numbval;
  258.             t = gettok();
  259.             }
  260.  
  261.          for(;;)
  262.             {
  263.             switch( t )
  264.                {
  265.  
  266.             case ',':
  267.                t = gettok();
  268.                continue;
  269.  
  270.             case ';':
  271.                break;
  272.  
  273.             case IDENTIFIER:
  274.                j = chfind(0,tokname);
  275.                if( lev )
  276.                   {
  277.                   if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of%s", tokname );
  278.                   SETASC(toklev[j],lev);
  279.                   SETPLEV(toklev[j],i);
  280.                   }
  281.                if( ty )
  282.                   {
  283.                   if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname );
  284.                   SETTYPE(toklev[j],ty);
  285.                   }
  286.                if( (t=gettok()) == NUMBER )
  287.                   {
  288.                   tokset[j].value = numbval;
  289.                   if( j < ndefout && j>2 )
  290.                      {
  291.                      error( "please define type number of %s earlier",
  292.                      tokset[j].name );
  293.                      }
  294.                   t=gettok();
  295.                   }
  296.                continue;
  297.  
  298.                }
  299.  
  300.             break;
  301.             }
  302.  
  303.          continue;
  304.  
  305.       case LCURLY:
  306.          defout();
  307.          cpycode();
  308.          t = gettok();
  309.          continue;
  310.  
  311.       default:
  312.          printf("Unrecognized character: %o\n", t);
  313.          error( "syntax error" );
  314.  
  315.          }
  316.  
  317.       }
  318.  
  319.    if( t == ENDFILE )
  320.       {
  321.       error( "unexpected EOF before %%" );
  322.       }
  323.  
  324.    /* t is MARK */
  325.  
  326.    defout();
  327.  
  328.    fprintf( ftable,"#define yyclearin yychar = -1\n" );
  329.    fprintf( ftable,"#define yyerrok yyerrflag = 0\n" );
  330. /*
  331.    fprintf( ftable,"extern int yychar;\nextern short yyerrflag;\n" );
  332. */
  333.    fprintf( ftable,"#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" );
  334.    if(!ntypes)
  335.       fprintf( ftable,  "#ifndef YYSTYPE\n#define YYSTYPE char *\n#endif\n" );
  336. #ifdef unix
  337.    fprintf( ftable,  "YYSTYPE yylval, yyval;\n" );
  338. #else
  339.    fprintf( ftable, "extern YYSTYPE yylval;  /*CSD & DECUS LEX */\n");
  340.    fprintf( ftable, "YYSTYPE yyval;          /*CSD & DECUS LEX */\n");
  341. #endif
  342.    prdptr[0]=mem;
  343.    /* added production */
  344.    *mem++ = NTBASE;
  345.    *mem++ = start;  /* if start is 0, we will overwrite with the lhs of the firstrule */
  346.    *mem++ = 1;
  347.    *mem++ = 0;
  348.    prdptr[1]=mem;
  349.    while( (t=gettok()) == LCURLY ) cpycode();
  350.    if( t != C_IDENTIFIER ) error( "bad syntax on first rule" );
  351.    if( !start ) prdptr[0][1] = chfind(1,tokname);
  352.  
  353.    /* read rules */
  354.  
  355.    while( t!=MARK && t!=ENDFILE )
  356.       {
  357.  
  358.       /* process a rule */
  359.  
  360.       if( t == '|' )
  361.          {
  362.          *mem++ = *prdptr[nprod-1];
  363.          }
  364.       else if( t == C_IDENTIFIER )
  365.          {
  366.          *mem = chfind(1,tokname);
  367.          if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" );
  368.          ++mem;
  369.          }
  370.       else error( "illegal rule: missing semicolon or | ?" );
  371.  
  372.       /* read rule body */
  373.       t = gettok();
  374. more_rule:
  375.       while( t == IDENTIFIER )
  376.          {
  377.          *mem = chfind(1,tokname);
  378.          if( *mem<NTBASE ) levprd[nprod] = toklev[*mem];
  379.          ++mem;
  380.          t = gettok();
  381.          }
  382.       if( t == PREC )
  383.  
  384.          {
  385.          if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" );
  386.          j = chfind(2,tokname);
  387.          if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
  388.          levprd[nprod]=toklev[j];
  389.          t = gettok();
  390.          }
  391.       if( t == '=' )
  392.          {
  393.          levprd[nprod] |= ACTFLAG;
  394.          fprintf( faction, "\ncase %d:", nprod );
  395.          cpyact( mem-prdptr[nprod]-1 );
  396.          fprintf( faction, " break;" );
  397.          if( (t=gettok()) == IDENTIFIER )
  398.             {
  399.             /* action within rule... */
  400.             sprintf( actname, "$$%d", nprod );
  401.             j = chfind(1,actname);  /* make it a nonterminal */
  402.             /* the current rule will become rule number nprod+1 */
  403.             /* move the contents down, and make room for the null */
  404.             for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p;
  405.             mem += 2;
  406.             /* enter null production for action */
  407.             p = prdptr[nprod];
  408.             *p++ = j;
  409.             *p++ = -nprod;
  410.  
  411.             /* update the production information */
  412.             levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
  413.             levprd[nprod] = ACTFLAG;
  414.  
  415.             if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
  416.             prdptr[nprod] = p;
  417.  
  418.             /* make the action appear in the original rule */
  419.             *mem++ = j;
  420.  
  421.             /* get some more of the rule */
  422.  
  423.             goto more_rule;
  424.             }
  425.  
  426.          }
  427.  
  428.       while( t == ';' ) t = gettok();
  429.  
  430.       *mem++ = -nprod;
  431.  
  432.       /* check that default action is reasonable */
  433.  
  434.       if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue )
  435.          {
  436.          /* no explicit action, LHS has value */
  437.          /*01*/
  438.          tempty = prdptr[nprod][1];
  439.          if( tempty < 0 ) error( "must return a value, since LHS has a type" );
  440.          else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue;
  441.          else tempty = TYPE( toklev[tempty] );
  442.          if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue )
  443.             {
  444.             error( "default action causes potential type clash" );
  445.             }
  446.  
  447.          }
  448.       if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
  449.       prdptr[nprod] = mem;
  450.       levprd[nprod]=0;
  451.       }
  452.    /* end of all rules */
  453.    fprintf(faction, "/* End of actions */"); /* Properly terminate the last line */
  454.    finact();
  455.    if( t == MARK )
  456.       {
  457.       fprintf( ftable, "\n#line %d\n", lineno );
  458.       while( (c=unix_getc(finput)) != EOF ) putc( c, ftable );
  459.       }
  460.    fclose( finput );
  461.    }
  462.  
  463. void usage( void )
  464.  
  465.    {
  466.    fprintf(stderr,"UNIX YACC (CSD Variant):\n");
  467.    fprintf(stderr,"   yacc -hi infile\n\n");
  468.    fprintf(stderr,"Switches:\n");
  469.    fprintf(stderr,"   -h   Create definitions header file\n");
  470.    fprintf(stderr,"   -i   Create parser description file\n\n");
  471.    fprintf(stderr,"Default input file extension is \".Y\"\n");
  472.    fprintf(stderr,"Defs file same name, \".H\" extension.\n");
  473.    fprintf(stderr,"Info file same name, \".I\" extension.\n");
  474.    exit(EX_ERR);
  475.    }
  476.