# include # include "dextern" extern FILE *Fout, *Fin; /* * * * * y a c c * * * * */ /* features to be fixed up ... *** Print estimate of total space needed for parser *** Either list inputs on y.output, or list empty prdn's in states *** Mention nonterms not used (or, rules. not reduced) as nonfatal error *** Output states where conflicts were found by default on y.output *** Engage in newspeak: production=>grammar rules, term=>token, etc. *** handle # define, #ifdef, etc., in yacc actions, %{ %} */ /* new features to be added *** reductions by single productions ( by request ) *** follow sets for start symbol *** option to only do slr(1) *** easily changed array names on output *** allocate core, rather than predefined *** input controlled by a grammar *** support multiple choices for conflicts *** better conflict diagnostics */ main(argc,argv) int argc; char *argv[]; { auto int n; Fin = stdin; Fout = stdout; whereami(); setup(argc,argv); /* initialize and read productions */ tbitset = (nterms+16)/16; cpres(); /* make table of which productions yield a given nonterminal */ cempty(); /* make a table of which nonterminals can match the empty string */ cpfir(); /* make a table of e free first lists */ stagen(); /* generate the states */ output(); /* write the states and the tables */ go2out(); summary(); windup(); } whereami(){ /* sets the variable machine to UNIX, GCOS, or IBM */ int i; i = 1; i = i << 30; if( i == 0 ) { machine = UNIX; return; } i = i << 4; if( i == 0 ){ machine = IBM; return; } machine = GCOS; } windup(){ /* no errors, do the optimization if appropriate */ char *cp; int i; cflush(stdout); if( !oflag ) cexit(0); for( i=3; i<10; ++i ) cclose(i); switch( machine ){ case GCOS: if( rflag ){ if( Foutput==0 ) system( "./yopt -r" ); else system( "./yopt -rv" ); } else { if( Foutput==0 ) system( "./yopt" ); else system( "./yopt -v" ); } cexit(0); /* terminate */ case UNIX: cp = "/usr/yacc/yopti"; if( rflag ) execl( cp, cp, (Foutput==0)?"-r":"-rv", 0 ); else if( Foutput==0 ) execl( cp, cp, 0 ); else execl( cp, cp, "-v", 0 ); error( "optimization execl call fails" ); case IBM: if( rflag ){ if( Foutput==0 ) system( "MH2019.yaccopt -r" ); else system( "MH2019.yaccopt -rv" ); } else { if( Foutput==0 ) system( "MH2019.yaccopt" ); else system( "MH2019.yaccopt -v" ); } cexit(0); } } settty() /* sets the output file to y.output */ { cflush( Foutput ); /* a bit of a cheat */ cout = Foutput; } settab(){ /* sets the output file to y.tab.c */ cflush( ftable ); cout = ftable; } char *chcopy( p, q ) char *p, *q; { /* copies string q into p, returning next free char ptr */ while( *p = *q++ ) ++p; return( p ); } char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */ int i,*p; static char sarr[100]; char *q; for( p=pp->pitem; *p>0 ; ++p ) ; p = prdptr[-*p]; q = chcopy( sarr, nontrst[*p-NTBASE].name ); q = chcopy( q, " : " ); for(;;){ *q++ = ++p==(pp->pitem) ? '_' : ' '; if((i = *p) <= 0) break; q = chcopy( q, symnam(i) ); } *q = '\0' ; return( sarr ); } char *symnam(i){ /* return a pointer to the name of symbol i */ char *cp; cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ; if( *cp == ' ' ) ++cp; return( cp ); } summary(){ /* output the summary on the tty */ int i, s, *pn; if (!rflag && !sflag) { settab(); fprintf(Fout, "\nint nterms = %d;",nterms); fprintf(Fout, "\nint nnonter = %d;", nnonter); fprintf(Fout, "\nint nstate = %d;", nstate); fprintf(Fout, "\nchar *yysterm[] = {"); for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) fprintf(Fout, "\n\"%s\",",symnam(i)); fprintf(Fout, "\n0 };\n" ); fprintf(Fout, "\nchar *yysnter[] = {"); for (i=0;i= memsiz) error("memory overflow"); return(omem); } aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ int i; for( i=0; ilset; if( pp == 0 ) fprintf(Fout, "\tNULL"); else { fprintf(Fout, " { " ); for( j=1; j<=nterms; ++j ){ if( (pp[j>>4]>>(j&017) )&01 != 0 ) fprintf(Fout, "%s ", symnam(j) ); } fprintf(Fout, "}" ); } }