home *** CD-ROM | disk | FTP | other *** search
- /*
- HEADER: CUG nnn.nn;
- TITLE: YACC - Yet Another Compilier-Compilier
- VERSION: 1.0 for IBM-PC
- DATE: JAN 28, 1985
- DESCRIPTION: LALR(1) Parser Generator. From UNIX
- KEYWORDS: Parser Generator Compilier-Compilier YACC
- SYSTEM: IBM-PC and Compatiables
- FILENAME: YSETUP.2C
- WARNINGS: This program is not for the casual user. It will
- be useful primarily to expert developers.
- CRC: N/A
- SEE-ALSO: LEX and PREP
- AUTHORS: Scott Guthery 11100 leafwood lane Austin, TX 78750
- COMPILERS: DESMET-C
- REFERENCES: UNIX Systems Manuals
- */
-
- #include <string.h>
- #include "y1.h"
- #include "y2.h"
- /*
- * YSETUP.C -- Modified for use with DECUS LEX
- * Variable "yylval" resides in yylex(), not in yypars();
- * Therefore, is defined "extern" here.
- *
- * Also, the command line processing for the Decus version
- * has been changed. A new switch has been added to allow
- * specification of the "table" file name(s), and unused
- * switch processing removed.
- *
- * NOTE
- * This probably won't run on UNIX any more.
- *
- * Bob Denny 27-Aug-81
- * Bob Denny 22-Mar-82 (01) Added header line, changes for 'new' DECUS library
- * Bob Denny 12-Apr-83 (02) Make filename[] size per #define'd FNAMESIZE so
- * VAX filenames won't blow out. Conditionalize
- * time handling for banner. Make filespec buffer
- * static for safety, since global "infile" is
- * pointed to it.
- * Scott Guthery 15-May-83 (03) Fixed up option flag handling for RT-11
- * 23-Dec-83 Adapted for IBM PC/XT & DeSmet C compiler
- */
-
- static char filename[FNAMESIZE];
-
- int i,j,lev,t, ty;
- int c;
- int tempty;
- int *p;
- int defsw, infsw;
- char actname[8];
- char *cp;
-
- void setup(int argc, char *argv[])
- {
- char finsave[FNAMESIZE];
-
- defsw = infsw = 0;
- foutput = NULL;
- fdefine = NULL;
- ftemp = NULL;
- i = 1; /*(03)*/
- while( argc > 1 && argv[i][0] == '-' ) /*(03)*/
- {
- while( *++(argv[i]) )
- {
- switch( *argv[i] )
- {
- case 'i':
- case 'I':
- infsw++;
- continue;
- case 'h':
- case 'H':
-
- defsw++;
- continue;
- default:
- fprintf(stderr, "Illegal option: %c\n", *argv[i]);
- usage();
- }
- }
- i++; /*(03)*/
- argc--;
- }
-
- if(argc < 2) usage(); /* Catch no filename given */
-
- /*
- * Now open the input file with a default extension of ".Y",
- * then replace the period in argv[1] with a null, so argv[1]
- * can be used to form the table, defs and info filenames.
- */
-
- cp = argv[i];
- while(*cp++ != '.' && *cp != '\0'); /* Scan past '.' or to null */
- if(*cp == '\0') {
- strcpy(filename, argv[i]); strcat(filename, ".Y");
- } else
- {
- strcpy(filename, argv[i]);
- *(argv[i]-1) = '\0'; /* Null the period */
- }
-
- strcpy(finsave, filename);
- if((finput=fopen( filename, "r" )) == NULL )
- error( "cannot open input file \"%s\"", filename );
-
- /*
- * Now open the .H and .I files if requested.
- */
-
- if(defsw)
- {
- strcpy(filename, argv[i]); strcat(filename, ".H");
- fdefine = fopen(filename, "w");
- if(fdefine == NULL) error("cannot open defs file\"%s\"", filename);
- }
-
- if(infsw)
- {
- strcpy(filename, argv[i]); strcat(filename, ".I");
- foutput = fopen(filename, "w");
- if(foutput == NULL) error("cannot open info file\"%s\"", filename);
- }
- /*
- * Now the "table" output C file.
- */
- strcpy(filename, argv[i]); strcat(filename, ".C");
- ftable = fopen(filename, "w");
- if( ftable == NULL ) error( "cannot open table file\"%s\"", filename);
- /*
- * Finally, the temp files.
- */
- ftemp = fopen( TEMPNAME, "w" );
- if( ftemp==NULL ) error( "cannot open temp file" );
- faction = fopen( ACTNAME, "w" );
- if( faction==NULL ) error( "cannot open action file" );
-
- /*
- * Now put the full filename of the input file into
- * the "filename" buffer for cpyact(), and point the
- * global cell "infile" at it.
- */
- strcpy(filename, finsave);
- infile = filename;
- /*
- * Put out a header line at the beginning of the 'table' file.
- */
- fprintf(ftable, "/*\n * Created by CSD YACC (IBM PC) from \"%s\" */\n",
- infile);
- /*
- * Complete initialization.
- */
- cnamp = cnames;
- defin(0,"$end");
- extval = 0400;
- defin(0,"error");
- defin(1,"$accept");
- mem=mem0;
- lev = 0;
- ty = 0;
- i=0;
-
- yyparse();
- }
-
- void yyparse( void )
- {
- /* sorry -- no yacc parser here.....
- we must bootstrap somehow... */
-
- for( t=gettok(); t!=MARK && t!= ENDFILE; )
- {
- switch( t )
- {
-
- case ';':
- t = gettok();
- break;
-
- case START:
- if( (t=gettok()) != IDENTIFIER )
- {
- error( "bad %%start construction" );
- }
- start = chfind(1,tokname);
- t = gettok();
- continue;
-
- case TYPEDEF:
- if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" );
- ty = numbval;
- for(;;)
-
- {
- t = gettok();
- switch( t )
- {
-
- case IDENTIFIER:
- if( (t=chfind( 1, tokname ) ) < NTBASE )
- {
- j = TYPE( toklev[t] );
- if( j!= 0 && j != ty )
- {
- error( "type redeclaration of token %s",
- tokset[t].name );
- }
- else SETTYPE( toklev[t],ty);
- }
- else
- {
- j = nontrst[t-NTBASE].tvalue;
- if( j != 0 && j != ty )
- {
- error( "type redeclaration of nonterminal %s",
- nontrst[t-NTBASE].name );
- }
- else nontrst[t-NTBASE].tvalue = ty;
- }
- case ',':
- continue;
-
- case ';':
- t = gettok();
- break;
- default:
- break;
- }
- break;
- }
- continue;
-
- case UNION:
- /* copy the union declaration to the output */
- cpyunion();
- t = gettok();
- continue;
-
- case LEFT:
- case BINARY:
- case RIGHT:
- ++i;
- case TERM:
- lev = t-TERM; /* nonzero means new prec. and assoc. */
- ty = 0;
-
- /* get identifiers so defined */
-
- t = gettok();
- if( t == TYPENAME )
- {
- /* there is a type defined */
- ty = numbval;
- t = gettok();
- }
-
- for(;;)
- {
- switch( t )
- {
-
- case ',':
- t = gettok();
- continue;
-
- case ';':
- break;
-
- case IDENTIFIER:
- j = chfind(0,tokname);
- if( lev )
- {
- if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of%s", tokname );
- SETASC(toklev[j],lev);
- SETPLEV(toklev[j],i);
- }
- if( ty )
- {
- if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname );
- SETTYPE(toklev[j],ty);
- }
- if( (t=gettok()) == NUMBER )
- {
- tokset[j].value = numbval;
- if( j < ndefout && j>2 )
- {
- error( "please define type number of %s earlier",
- tokset[j].name );
- }
- t=gettok();
- }
- continue;
-
- }
-
- break;
- }
-
- continue;
-
- case LCURLY:
- defout();
- cpycode();
- t = gettok();
- continue;
-
- default:
- printf("Unrecognized character: %o\n", t);
- error( "syntax error" );
-
- }
-
- }
-
- if( t == ENDFILE )
- {
- error( "unexpected EOF before %%" );
- }
-
- /* t is MARK */
-
- defout();
-
- fprintf( ftable,"#define yyclearin yychar = -1\n" );
- fprintf( ftable,"#define yyerrok yyerrflag = 0\n" );
- /*
- fprintf( ftable,"extern int yychar;\nextern short yyerrflag;\n" );
- */
- fprintf( ftable,"#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" );
- if(!ntypes)
- fprintf( ftable, "#ifndef YYSTYPE\n#define YYSTYPE char *\n#endif\n" );
- #ifdef unix
- fprintf( ftable, "YYSTYPE yylval, yyval;\n" );
- #else
- fprintf( ftable, "extern YYSTYPE yylval; /*CSD & DECUS LEX */\n");
- fprintf( ftable, "YYSTYPE yyval; /*CSD & DECUS LEX */\n");
- #endif
- prdptr[0]=mem;
- /* added production */
- *mem++ = NTBASE;
- *mem++ = start; /* if start is 0, we will overwrite with the lhs of the firstrule */
- *mem++ = 1;
- *mem++ = 0;
- prdptr[1]=mem;
- while( (t=gettok()) == LCURLY ) cpycode();
- if( t != C_IDENTIFIER ) error( "bad syntax on first rule" );
- if( !start ) prdptr[0][1] = chfind(1,tokname);
-
- /* read rules */
-
- while( t!=MARK && t!=ENDFILE )
- {
-
- /* process a rule */
-
- if( t == '|' )
- {
- *mem++ = *prdptr[nprod-1];
- }
- else if( t == C_IDENTIFIER )
- {
- *mem = chfind(1,tokname);
- if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" );
- ++mem;
- }
- else error( "illegal rule: missing semicolon or | ?" );
-
- /* read rule body */
- t = gettok();
- more_rule:
- while( t == IDENTIFIER )
- {
- *mem = chfind(1,tokname);
- if( *mem<NTBASE ) levprd[nprod] = toklev[*mem];
- ++mem;
- t = gettok();
- }
- if( t == PREC )
-
- {
- if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" );
- j = chfind(2,tokname);
- if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name);
- levprd[nprod]=toklev[j];
- t = gettok();
- }
- if( t == '=' )
- {
- levprd[nprod] |= ACTFLAG;
- fprintf( faction, "\ncase %d:", nprod );
- cpyact( mem-prdptr[nprod]-1 );
- fprintf( faction, " break;" );
- if( (t=gettok()) == IDENTIFIER )
- {
- /* action within rule... */
- sprintf( actname, "$$%d", nprod );
- j = chfind(1,actname); /* make it a nonterminal */
- /* the current rule will become rule number nprod+1 */
- /* move the contents down, and make room for the null */
- for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p;
- mem += 2;
- /* enter null production for action */
- p = prdptr[nprod];
- *p++ = j;
- *p++ = -nprod;
-
- /* update the production information */
- levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
- levprd[nprod] = ACTFLAG;
-
- if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
- prdptr[nprod] = p;
-
- /* make the action appear in the original rule */
- *mem++ = j;
-
- /* get some more of the rule */
-
- goto more_rule;
- }
-
- }
-
- while( t == ';' ) t = gettok();
-
- *mem++ = -nprod;
-
- /* check that default action is reasonable */
-
- if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue )
- {
- /* no explicit action, LHS has value */
- /*01*/
- tempty = prdptr[nprod][1];
- if( tempty < 0 ) error( "must return a value, since LHS has a type" );
- else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue;
- else tempty = TYPE( toklev[tempty] );
- if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue )
- {
- error( "default action causes potential type clash" );
- }
-
- }
- if( ++nprod >= NPROD ) error( "more than %d rules", NPROD );
- prdptr[nprod] = mem;
- levprd[nprod]=0;
- }
- /* end of all rules */
- fprintf(faction, "/* End of actions */"); /* Properly terminate the last line */
- finact();
- if( t == MARK )
- {
- fprintf( ftable, "\n#line %d\n", lineno );
- while( (c=unix_getc(finput)) != EOF ) putc( c, ftable );
- }
- fclose( finput );
- }
-
- void usage( void )
-
- {
- fprintf(stderr,"UNIX YACC (CSD Variant):\n");
- fprintf(stderr," yacc -hi infile\n\n");
- fprintf(stderr,"Switches:\n");
- fprintf(stderr," -h Create definitions header file\n");
- fprintf(stderr," -i Create parser description file\n\n");
- fprintf(stderr,"Default input file extension is \".Y\"\n");
- fprintf(stderr,"Defs file same name, \".H\" extension.\n");
- fprintf(stderr,"Info file same name, \".I\" extension.\n");
- exit(EX_ERR);
- }
-