# include "dextern" # include "files" /* * * * * y a c c * * * * */ /* features to be fixed up ... *** provide the ability to change table sizes dynamically *** Make the output line numbers agree with the input line numbers *** Engage in newspeak: production=>grammar rules, term=>token, etc. *** handle # define, #ifdef, etc., in yacc actions, %{ %} *** say ACCEPT, not "shift 8191", in S/R message */ /* 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 *** input controlled by a grammar *** support multiple choices for conflicts *** better conflict diagnostics */ main(argc,argv) int argc; char *argv[]; { setup(argc,argv); /* initialize and read productions */ tbitset = NWORDS(nterms); 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 firsts of nonterminals */ stagen(); /* generate the states */ output(); /* write the states and the tables */ go2out(); hideprod(); summary(); callopt(); others(); exit(0); } others(){ /* put out other arrays, copy the parsers */ register c, i, j; /* this outputs the other arrays, after the /* size of the action array is known (this is needed for /* ratfor... */ /* this routine uses prdptr, trmset, tstates, mstates, ntstates, defact, levprd, cnames /* the other space can have been clobbered for use of the optimizer */ finput = fopen( parser[lflag], "r" ); if( finput == NULL ) error( "cannot find parser %s", parser[lflag] ); (*warray[lflag])( "yyr1", levprd, nprod ); aryfil( temp1, nprod, 0 ); PLOOP(1,i)temp1[i] = prdptr[i+1]-prdptr[i]-2; (*warray[lflag])( "yyr2", temp1, nprod ); aryfil( temp1, nstate, -1000 ); TLOOP(i){ for( j=tstates[i]; j!=0; j=mstates[j] ){ temp1[j] = trmset[i].value; } } NTLOOP(i){ for( j=ntstates[i]; j!=0; j=mstates[j] ){ temp1[j] = -i; } } (*warray[lflag])( "yychk", temp1, nstate ); (*warray[lflag])( "yydef", defact, nstate ); /* copy parser text */ while( (c=getc(finput) ) != EOF ){ if( c == '$' ){ if( (c=getc(finput)) != 'A' ) putc( '$', ftable ); else { /* copy actions */ faction = fopen( ACTNAME, "r" ); if( faction == NULL ) error( "cannot reopen action tempfile" ); while( (c=getc(faction) ) != EOF ) putc( c, ftable ); fclose(faction); ZAPFILE(ACTNAME); c = getc(finput); } } putc( c, ftable ); } fclose( ftable ); } char *chcopy( p, q ) char *p, *q; { /* copies string q into p, returning next free char ptr */ while( *p = *q++ ) ++p; return( p ); } # define ISIZE 400 char *writem(pp) int *pp; { /* creates output string for item pointed to by pp */ int i,*p; static char sarr[ISIZE]; char *q; for( p=pp; *p>0 ; ++p ) ; p = prdptr[-*p]; q = chcopy( sarr, nontrst[*p-NTBASE].name ); q = chcopy( q, " : " ); for(;;){ *q++ = ++p==pp ? '_' : ' '; *q = '\0'; if((i = *p) <= 0) break; q = chcopy( q, symnam(i) ); if( q> &sarr[ISIZE-30] ) error( "item too big" ); } if( (i = *pp) < 0 ){ /* an item calling for a reduction */ q = chcopy( q, " (" ); sprintf( q, "%d)", -i ); } 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 */ if( foutput!=NULL ){ fprintf( foutput, "\n%d/%d terminals, %d/%d nonterminals\n", nterms, tlim, nnonter, ntlim ); fprintf( foutput, "%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize ); fprintf( foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf ); fprintf( foutput, "%d/%d working sets used\n", zzcwp-wsets, wssize ); fprintf( foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz, memsiz, memp-amem, actsiz ); fprintf( foutput, "%d/%d distinct lookahead sets\n", nlset, lsetsz ); fprintf( foutput, "%d extra closures\n", zzclose - 2*nstate ); fprintf( foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp ); fprintf( foutput, "%d goto entries\n", zzgoent ); fprintf( foutput, "%d entries saved by goto default\n", zzgobest ); } if( zzsrconf!=0 || zzrrconf!=0 ){ fprintf( stdout,"\nconflicts: "); if( zzsrconf )fprintf( stdout, "%d shift/reduce" , zzsrconf ); if( zzsrconf && zzrrconf )fprintf( stdout, ", " ); if( zzrrconf )fprintf( stdout, "%d reduce/reduce" , zzrrconf ); fprintf( stdout, "\n" ); } fclose( ftemp ); if( fdefine != NULL ) fclose( fdefine ); } /* VARARGS */ error(s,a1){ /* write out error comment */ ++nerrors; fprintf( stderr, "\n fatal error: "); fprintf( stderr, s,a1); fprintf( stderr, ", line %d\n", lineno ); if( !fatfl ) return; summary(); exit(1); } int *yalloc(n){ /* allocate n+1 words from vector mem */ int *omem; omem = mem; mem =+ n+1; if(mem-mem0 >= 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; i<n; ++i ) v[i] = c; } setunion( a, b ) register *a, *b; { /* set a to the union of a and b */ /* return 1 if b is not a subset of a, 0 otherwise */ register i, x, sub; sub = 0; SETLOOP(i){ *a = (x = *a)|*b++; if( *a++ != x ) sub = 1; } return( sub ); } prlook( pp ) int *pp;{ int j; pp = pp->lset; if( pp == 0 ) fprintf( foutput, "\tNULL"); else { fprintf( foutput, " { " ); TLOOP(j) { if( BIT(pp,j) ) fprintf( foutput, "%s ", symnam(j) ); } fprintf( foutput, "}" ); } } concat( s, t, u ) char *s, *t, *u; { /* copies the concatenation of t and u into s */ while( *t ) *s++ = *t++; while( *s++ = *u++ ); }