diff --git a/src/cmd/yacc/Makefile b/src/cmd/yacc/Makefile index 6c6fb77..2d1d07a 100644 --- a/src/cmd/yacc/Makefile +++ b/src/cmd/yacc/Makefile @@ -25,7 +25,7 @@ clean: install: all install yacc $(DESTDIR)/bin/ -y1.o: y1.c dextern -y2.o: y2.c dextern -y3.o: y3.c dextern -y4.o: y4.c dextern +y1.o: y1.c dextern.h +y2.o: y2.c dextern.h +y3.o: y3.c dextern.h +y4.o: y4.c dextern.h diff --git a/src/cmd/yacc/dextern b/src/cmd/yacc/dextern deleted file mode 100644 index 60be484..0000000 --- a/src/cmd/yacc/dextern +++ /dev/null @@ -1,275 +0,0 @@ -/* - * @(#)dextern 4.2 (Berkeley) 3/21/86 - */ -# include -# include -# include "files" - - /* MANIFEST CONSTANT DEFINITIONS */ - - /* base of nonterminal internal numbers */ -# define NTBASE 010000 - - /* internal codes for error and accept actions */ - -# define ERRCODE 8190 -# define ACCEPTCODE 8191 - - /* sizes and limits */ - -# ifdef HUGE -# define ACTSIZE 12000 -# define MEMSIZE 24000 -# define NSTATES 750 -# define NTERMS 300 -# define NPROD 600 -# define NNONTERM 300 -# define TEMPSIZE 1200 -# define CNAMSZ 5000 -# define LSETSIZE 600 -# define WSETSIZE 350 -# endif - -# ifdef MEDIUM -# define ACTSIZE 4000 -# define MEMSIZE 5200 -# define NSTATES 750 -# define NTERMS 127 -# define NPROD 400 -# define NNONTERM 200 -# define TEMPSIZE 800 -# define CNAMSZ 4000 -# define LSETSIZE 450 -# define WSETSIZE 250 -# endif - -# ifdef TINY -# define ACTSIZE 1000 -# define MEMSIZE 1300 -# define NSTATES 750 -# define NTERMS 127 -# define NPROD 200 -# define NNONTERM 50 -# define TEMPSIZE 200 -# define CNAMSZ 1000 -# define LSETSIZE 250 -# define WSETSIZE 100 -# endif - -# define NAMESIZE 50 -# define NTYPES 63 - -# ifdef WORD32 -# define TBITSET ((32+NTERMS)/32) - - /* bit packing macros (may be machine dependent) */ -# define BIT(a,i) ((a)[(i)>>5] & (1<<((i)&037))) -# define SETBIT(a,i) ((a)[(i)>>5] |= (1<<((i)&037))) - - /* number of words needed to hold n+1 bits */ -# define NWORDS(n) (((n)+32)/32) - -# else - -# define TBITSET ((16+NTERMS)/16) - - /* bit packing macros (may be machine dependent) */ -# define BIT(a,i) ((a)[(i)>>4] & (1<<((i)&017))) -# define SETBIT(a,i) ((a)[(i)>>4] |= (1<<((i)&017))) - - /* number of words needed to hold n+1 bits */ -# define NWORDS(n) (((n)+16)/16) -# endif - - /* relationships which must hold: - TBITSET ints must hold NTERMS+1 bits... - WSETSIZE >= NNONTERM - LSETSIZE >= NNONTERM - TEMPSIZE >= NTERMS + NNONTERMs + 1 - TEMPSIZE >= NSTATES - */ - - /* associativities */ - -# define NOASC 0 /* no assoc. */ -# define LASC 1 /* left assoc. */ -# define RASC 2 /* right assoc. */ -# define BASC 3 /* binary assoc. */ - - /* flags for state generation */ - -# define DONE 0 -# define MUSTDO 1 -# define MUSTLOOKAHEAD 2 - - /* flags for a rule having an action, and being reduced */ - -# define ACTFLAG 04 -# define REDFLAG 010 - - /* output parser flags */ -# define YYFLAG1 (-1000) - - /* macros for getting associativity and precedence levels */ - -# define ASSOC(i) ((i)&03) -# define PLEVEL(i) (((i)>>4)&077) -# define TYPE(i) ((i>>10)&077) - - /* macros for setting associativity and precedence levels */ - -# define SETASC(i,j) i|=j -# define SETPLEV(i,j) i |= (j<<4) -# define SETTYPE(i,j) i |= (j<<10) - - /* looping macros */ - -# define TLOOP(i) for(i=1;i<=ntokens;++i) -# define NTLOOP(i) for(i=0;i<=nnonter;++i) -# define PLOOP(s,i) for(i=s;i +#include + +#include "files.h" + +/* MANIFEST CONSTANT DEFINITIONS */ + +/* base of nonterminal internal numbers */ +#define NTBASE 010000 + +/* internal codes for error and accept actions */ + +#define ERRCODE 8190 +#define ACCEPTCODE 8191 + +/* sizes and limits */ + +#ifdef HUGE +#define ACTSIZE 12000 +#define MEMSIZE 24000 +#define NSTATES 750 +#define NTERMS 300 +#define NPROD 600 +#define NNONTERM 300 +#define TEMPSIZE 1200 +#define CNAMSZ 5000 +#define LSETSIZE 600 +#define WSETSIZE 350 +#endif + +#ifdef MEDIUM +#define ACTSIZE 4000 +#define MEMSIZE 5200 +#define NSTATES 750 +#define NTERMS 127 +#define NPROD 400 +#define NNONTERM 200 +#define TEMPSIZE 800 +#define CNAMSZ 4000 +#define LSETSIZE 450 +#define WSETSIZE 250 +#endif + +#ifdef TINY +#define ACTSIZE 1000 +#define MEMSIZE 1300 +#define NSTATES 750 +#define NTERMS 127 +#define NPROD 200 +#define NNONTERM 50 +#define TEMPSIZE 200 +#define CNAMSZ 1000 +#define LSETSIZE 250 +#define WSETSIZE 100 +#endif + +#define NAMESIZE 50 +#define NTYPES 63 + +#ifdef WORD32 +#define TBITSET ((32 + NTERMS) / 32) + +/* bit packing macros (may be machine dependent) */ +#define BIT(a, i) ((a)[(i) >> 5] & (1 << ((i)&037))) +#define SETBIT(a, i) ((a)[(i) >> 5] |= (1 << ((i)&037))) + +/* number of words needed to hold n+1 bits */ +#define NWORDS(n) (((n) + 32) / 32) + +#else + +#define TBITSET ((16 + NTERMS) / 16) + +/* bit packing macros (may be machine dependent) */ +#define BIT(a, i) ((a)[(i) >> 4] & (1 << ((i)&017))) +#define SETBIT(a, i) ((a)[(i) >> 4] |= (1 << ((i)&017))) + +/* number of words needed to hold n+1 bits */ +#define NWORDS(n) (((n) + 16) / 16) +#endif + +/* relationships which must hold: +TBITSET ints must hold NTERMS+1 bits... +WSETSIZE >= NNONTERM +LSETSIZE >= NNONTERM +TEMPSIZE >= NTERMS + NNONTERMs + 1 +TEMPSIZE >= NSTATES +*/ + +/* associativities */ + +#define NOASC 0 /* no assoc. */ +#define LASC 1 /* left assoc. */ +#define RASC 2 /* right assoc. */ +#define BASC 3 /* binary assoc. */ + +/* flags for state generation */ + +#define DONE 0 +#define MUSTDO 1 +#define MUSTLOOKAHEAD 2 + +/* flags for a rule having an action, and being reduced */ + +#define ACTFLAG 04 +#define REDFLAG 010 + +/* output parser flags */ +#define YYFLAG1 (-1000) + +/* macros for getting associativity and precedence levels */ + +#define ASSOC(i) ((i)&03) +#define PLEVEL(i) (((i) >> 4) & 077) +#define TYPE(i) ((i >> 10) & 077) + +/* macros for setting associativity and precedence levels */ + +#define SETASC(i, j) i |= j +#define SETPLEV(i, j) i |= (j << 4) +#define SETTYPE(i, j) i |= (j << 10) + +/* looping macros */ + +#define TLOOP(i) for (i = 1; i <= ntokens; ++i) +#define NTLOOP(i) for (i = 0; i <= nnonter; ++i) +#define PLOOP(s, i) for (i = s; i < nprod; ++i) +#define SLOOP(i) for (i = 0; i < nstate; ++i) +#define WSBUMP(x) ++x +#define WSLOOP(s, j) for (j = s; j < cwp; ++j) +#define ITMLOOP(i, p, q) \ + q = pstate[i + 1]; \ + for (p = pstate[i]; p < q; ++p) +#define SETLOOP(i) for (i = 0; i < tbitset; ++i) + +/* I/O descriptors */ + +extern FILE *finput; /* input file */ +extern FILE *faction; /* file for saving actions */ +extern FILE *fdefine; /* file for # defines */ +extern FILE *ftable; /* y.tab.c file */ +extern FILE *ftemp; /* tempfile to pass 2 */ +extern FILE *foutput; /* y.output file */ + +/* structure declarations */ + +struct looksets { + int lset[TBITSET]; +}; + +struct item { + int *pitem; + struct looksets *look; +}; + +struct toksymb { + char *name; + int value; +}; + +struct ntsymb { + char *name; + int tvalue; +}; + +struct wset { + int *pitem; + int flag; + struct looksets ws; +}; + +/* token information */ + +extern int ntokens; /* number of tokens */ +extern struct toksymb tokset[]; +extern int toklev[]; /* vector with the precedence of the terminals */ + +/* nonterminal information */ + +extern int nnonter; /* the number of nonterminals */ +extern struct ntsymb nontrst[]; + +/* grammar rule information */ + +extern int nprod; /* number of productions */ +extern int *prdptr[]; /* pointers to descriptions of productions */ +extern int levprd[]; /* contains production levels to break conflicts */ + +/* state information */ + +extern int nstate; /* number of states */ +extern struct item *pstate[]; /* pointers to the descriptions of the states */ +extern int tystate[]; /* contains type information about the states */ +extern int defact[]; /* the default action of the state */ +extern int tstates[]; /* the states deriving each token */ +extern int ntstates[]; /* the states deriving each nonterminal */ +extern int mstates[]; /* the continuation of the chains begun in tstates and ntstates */ + +/* lookahead set information */ + +extern struct looksets lkst[]; +extern int nolook; /* flag to turn off lookahead computations */ + +/* working set information */ + +extern struct wset wsets[]; +extern struct wset *cwp; + +/* storage for productions */ + +extern int mem0[]; +extern int *mem; + +/* storage for action table */ + +extern int amem[]; /* action table storage */ +extern int *memp; /* next free action table position */ +extern int indgo[]; /* index to the stored goto table */ + +/* temporary vector, indexable by states, terms, or ntokens */ + +extern int temp1[]; +extern int lineno; /* current line number */ + +/* statistics collection variables */ + +extern int zzgoent; +extern int zzgobest; +extern int zzacent; +extern int zzexcp; +extern int zzclose; +extern int zzrrconf; +extern int zzsrconf; +/* define functions with strange types... */ + +extern char *cstash(); +extern struct looksets *flset(); +extern char *symnam(); +extern char *writem(); + +/* default settings for a number of macros */ + +/* name of yacc tempfiles */ + +#ifndef TEMPNAME +#define TEMPNAME "yacc.tmp" +#endif + +#ifndef ACTNAME +#define ACTNAME "yacc.acts" +#endif + +/* output file name */ + +#ifndef OFILE +#define OFILE "y.tab.c" +#endif + +/* user output file name */ + +#ifndef FILEU +#define FILEU "y.output" +#endif + +/* output file for # defines */ + +#ifndef FILED +#define FILED "y.tab.h" +#endif + +/* command to clobber tempfiles after use */ + +#ifndef ZAPFILE +#define ZAPFILE(x) unlink(x) +#endif diff --git a/src/cmd/yacc/files b/src/cmd/yacc/files deleted file mode 100644 index 9eeb349..0000000 --- a/src/cmd/yacc/files +++ /dev/null @@ -1,21 +0,0 @@ -/* - * @(#)files 4.1.1 (2.11BSD) 1996/10/24 - */ - /* this file has the location of the parser, and the size of the progam desired */ - /* It may also contain definitions to override various defaults: for example, - /* WORD32 tells yacc that there are at least 32 bits per int */ - /* on some systems, notably IBM, the names for the output files and tempfiles must - /* also be changed */ - -/* - * #ifndef WORD32 - * #define WORD32 - * #endif - */ - /* location of the parser text file */ -# define PARSER "/usr/share/misc/yaccpar" - - /* basic size of the Yacc implementation */ -/* # define HUGE */ -/* #define MEDIUM */ -#define TINY diff --git a/src/cmd/yacc/files.h b/src/cmd/yacc/files.h new file mode 100644 index 0000000..7d4215c --- /dev/null +++ b/src/cmd/yacc/files.h @@ -0,0 +1,21 @@ +/* + * @(#)files 4.1.1 (2.11BSD) 1996/10/24 + */ +/* this file has the location of the parser, and the size of the progam desired */ +/* It may also contain definitions to override various defaults: for example, + * WORD32 tells yacc that there are at least 32 bits per int */ +/* on some systems, notably IBM, the names for the output files and tempfiles must + * also be changed */ + +/* + * #ifndef WORD32 + * #define WORD32 + * #endif + */ +/* location of the parser text file */ +#define PARSER "/usr/share/misc/yaccpar.c" + +/* basic size of the Yacc implementation */ +/* # define HUGE */ +/* #define MEDIUM */ +#define TINY diff --git a/src/cmd/yacc/y1.c b/src/cmd/yacc/y1.c index 45d4c9b..36101f0 100644 --- a/src/cmd/yacc/y1.c +++ b/src/cmd/yacc/y1.c @@ -1,157 +1,173 @@ -#if !defined(lint) && defined(DOSCCS) -static char sccsid[] = "@(#)y1.c 4.1.1 (2.11BSD) 1995/05/11"; -#endif - -# include "dextern" #include - /* variables used locally */ +#include "dextern.h" - /* lookahead computations */ +/* variables used locally */ -int tbitset; /* size of lookahead sets */ -struct looksets lkst [ LSETSIZE ]; -int nlset = 0; /* next lookahead set index */ -int nolook = 0; /* flag to suppress lookahead computations */ -struct looksets clset; /* temporary storage for lookahead computations */ +/* lookahead computations */ - /* working set computations */ +int tbitset; /* size of lookahead sets */ +struct looksets lkst[LSETSIZE]; +int nlset = 0; /* next lookahead set index */ +int nolook = 0; /* flag to suppress lookahead computations */ +struct looksets clset; /* temporary storage for lookahead computations */ -struct wset wsets[ WSETSIZE ]; +/* working set computations */ + +struct wset wsets[WSETSIZE]; struct wset *cwp; - /* state information */ +/* state information */ -int nstate = 0; /* number of states */ -struct item *pstate[NSTATES+2]; /* pointers to the descriptions of the states */ -int tystate[NSTATES]; /* contains type information about the states */ -int indgo[NSTATES]; /* index to the stored goto table */ -int tstates[ NTERMS ]; /* states generated by terminal gotos */ -int ntstates[ NNONTERM ]; /* states generated by nonterminal gotos */ -int mstates[ NSTATES ]; /* chain of overflows of term/nonterm generation lists */ +int nstate = 0; /* number of states */ +struct item *pstate[NSTATES + 2]; /* pointers to the descriptions of the states */ +int tystate[NSTATES]; /* contains type information about the states */ +int indgo[NSTATES]; /* index to the stored goto table */ +int tstates[NTERMS]; /* states generated by terminal gotos */ +int ntstates[NNONTERM]; /* states generated by nonterminal gotos */ +int mstates[NSTATES]; /* chain of overflows of term/nonterm generation lists */ - /* storage for the actions in the parser */ +/* storage for the actions in the parser */ -int amem[ACTSIZE]; /* action table storage */ -int *memp = amem; /* next free action table position */ +int amem[ACTSIZE]; /* action table storage */ +int *memp = amem; /* next free action table position */ - /* other storage areas */ +/* other storage areas */ int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or states */ -int lineno= 1; /* current input line number */ -int fatfl = 1; /* if on, error is fatal */ -int nerrors = 0; /* number of errors */ +int lineno = 1; /* current input line number */ +int fatfl = 1; /* if on, error is fatal */ +int nerrors = 0; /* number of errors */ - /* storage for information about the nonterminals */ +/* storage for information about the nonterminals */ -int **pres[NNONTERM+2]; /* vector of pointers to productions yielding each nonterminal */ -struct looksets *pfirst[NNONTERM+2]; /* vector of pointers to first sets for each nonterminal */ -int pempty[NNONTERM+1]; /* vector of nonterminals nontrivially deriving e */ +int **pres[NNONTERM + 2]; /* vector of pointers to productions yielding each nonterminal */ +struct looksets *pfirst[NNONTERM + 2]; /* vector of pointers to first sets for each nonterminal */ +int pempty[NNONTERM + 1]; /* vector of nonterminals nontrivially deriving e */ -main(argc,argv) int argc; char *argv[]; { +int main(argc, argv) +int argc; +char *argv[]; +{ + setup(argc, argv); /* initialize and read productions */ + tbitset = NWORDS(ntokens); + 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); +} - setup(argc,argv); /* initialize and read productions */ - tbitset = NWORDS(ntokens); - 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); - } +void others() +{ /* put out other arrays, copy the parsers */ + register c, i, j; -others(){ /* put out other arrays, copy the parsers */ - register c, i, j; + finput = fopen(PARSER, "r"); + if (finput == NULL) + error("cannot find parser %s", PARSER); - finput = fopen( PARSER, "r" ); - if( finput == NULL ) error( "cannot find parser %s", PARSER ); + warray("yyr1", levprd, nprod); - warray( "yyr1", levprd, nprod ); + aryfil(temp1, nprod, 0); + PLOOP(1, i) temp1[i] = prdptr[i + 1] - prdptr[i] - 2; + warray("yyr2", temp1, nprod); - aryfil( temp1, nprod, 0 ); - PLOOP(1,i)temp1[i] = prdptr[i+1]-prdptr[i]-2; - warray( "yyr2", temp1, nprod ); + aryfil(temp1, nstate, -1000); + TLOOP(i) + { + for (j = tstates[i]; j != 0; j = mstates[j]) { + temp1[j] = tokset[i].value; + } + } + NTLOOP(i) + { + for (j = ntstates[i]; j != 0; j = mstates[j]) { + temp1[j] = -i; + } + } + warray("yychk", temp1, nstate); - aryfil( temp1, nstate, -1000 ); - TLOOP(i){ - for( j=tstates[i]; j!=0; j=mstates[j] ){ - temp1[j] = tokset[i].value; - } - } - NTLOOP(i){ - for( j=ntstates[i]; j!=0; j=mstates[j] ){ - temp1[j] = -i; - } - } - warray( "yychk", temp1, nstate ); + warray("yydef", defact, nstate); - warray( "yydef", defact, nstate ); + /* copy parser text */ - /* 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); + } - 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); +} - fclose( ftable ); - } +char *chcopy(p, q) +register char *p, *q; +{ + /* copies string q into p, returning next free char ptr */ + while (*p = *q++) + ++p; + return (p); +} -char *chcopy( p, q ) register 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 */ + register int i, *p; + static char sarr[ISIZE]; + register char *q; -# define ISIZE 400 -char *writem(pp) int *pp; { /* creates output string for item pointed to by pp */ - register int i,*p; - static char sarr[ISIZE]; - register char *q; + for (p = pp; *p > 0; ++p) + ; + p = prdptr[-*p]; + q = chcopy(sarr, nontrst[*p - NTBASE].name); + q = chcopy(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"); + } - 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); + } - if( (i = *pp) < 0 ){ /* an item calling for a reduction */ - q = chcopy( q, " (" ); - sprintf( q, "%d)", -i ); - } + return (sarr); +} - return( sarr ); - } +char *symnam(i) +{ /* return a pointer to the name of symbol i */ + register char *cp; -char *symnam(i){ /* return a pointer to the name of symbol i */ - register char *cp; - - cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : tokset[i].name ; - if( *cp == ' ' ) ++cp; - return( cp ); - } + cp = (i >= NTBASE) ? nontrst[i - NTBASE].name : tokset[i].name; + if (*cp == ' ') + ++cp; + return (cp); +} struct wset *zzcwp = wsets; int zzgoent = 0; @@ -160,500 +176,579 @@ int zzacent = 0; int zzexcp = 0; int zzclose = 0; int zzsrconf = 0; -int * zzmemsz = mem0; +int *zzmemsz = mem0; int zzrrconf = 0; -summary(){ /* output the summary on the tty */ +void summary() +{ /* output the summary on the tty */ - if( foutput!=NULL ){ - fprintf( foutput, "\n%d/%d terminals, %d/%d nonterminals\n", ntokens, NTERMS, - nnonter, NNONTERM ); - fprintf( foutput, "%d/%d grammar rules, %d/%d states\n", nprod, NPROD, nstate, NSTATES ); - fprintf( foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf ); - fprintf( foutput, "%d/%d working sets used\n", zzcwp-wsets, WSETSIZE ); - fprintf( foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz-mem0, MEMSIZE, - memp-amem, ACTSIZE ); - fprintf( foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE ); - 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" ); - } + if (foutput != NULL) { + fprintf(foutput, "\n%d/%d terminals, %d/%d nonterminals\n", ntokens, NTERMS, nnonter, + NNONTERM); + fprintf(foutput, "%d/%d grammar rules, %d/%d states\n", nprod, NPROD, nstate, NSTATES); + fprintf(foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, + zzrrconf); + fprintf(foutput, "%d/%d working sets used\n", zzcwp - wsets, WSETSIZE); + fprintf(foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz - mem0, MEMSIZE, + memp - amem, ACTSIZE); + fprintf(foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE); + 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 ); - } + fclose(ftemp); + if (fdefine != NULL) + fclose(fdefine); +} /* VARARGS1 */ -error(s,a1) char *s; { /* 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); - } +void error(s, a1) char *s; +{ /* write out error comment */ -aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ - register int i; - for( i=0; ilset; - if( pp == 0 ) fprintf( foutput, "\tNULL"); - else { - fprintf( foutput, " { " ); - TLOOP(j) { - if( BIT(pp,j) ) fprintf( foutput, "%s ", symnam(j) ); - } - fprintf( foutput, "}" ); - } - } +void prlook(p) struct looksets *p; +{ + register j, *pp; -cpres(){ /* compute an array with the beginnings of productions yielding given nonterminals - The array pres points to these lists */ - /* the array pyield has the lists: the total size is only NPROD+1 */ - int **pmem; - register c, j, i; - static int * pyield[NPROD]; + pp = p->lset; + if (pp == 0) + fprintf(foutput, "\tNULL"); + else { + fprintf(foutput, " { "); + TLOOP(j) + { + if (BIT(pp, j)) + fprintf(foutput, "%s ", symnam(j)); + } + fprintf(foutput, "}"); + } +} - pmem = pyield; +void cpres() +{ /* compute an array with the beginnings of productions yielding given nonterminals +The array pres points to these lists */ + /* the array pyield has the lists: the total size is only NPROD+1 */ + int **pmem; + register c, j, i; + static int *pyield[NPROD]; - NTLOOP(i){ - c = i+NTBASE; - pres[i] = pmem; - fatfl = 0; /* make undefined symbols nonfatal */ - PLOOP(0,j){ - if (*prdptr[j] == c) *pmem++ = prdptr[j]+1; - } - if(pres[i] == pmem){ - error("nonterminal %s not defined!", nontrst[i].name); - } - } - pres[i] = pmem; - fatfl = 1; - if( nerrors ){ - summary(); - exit(1); - } - if( pmem != &pyield[nprod] ) error( "internal Yacc error: pyield %d", pmem-&pyield[nprod] ); - } + pmem = pyield; + + NTLOOP(i) + { + c = i + NTBASE; + pres[i] = pmem; + fatfl = 0; /* make undefined symbols nonfatal */ + PLOOP(0, j) + { + if (*prdptr[j] == c) + *pmem++ = prdptr[j] + 1; + } + if (pres[i] == pmem) { + error("nonterminal %s not defined!", nontrst[i].name); + } + } + pres[i] = pmem; + fatfl = 1; + if (nerrors) { + summary(); + exit(1); + } + if (pmem != &pyield[nprod]) + error("internal Yacc error: pyield %d", pmem - &pyield[nprod]); +} int indebug = 0; -cpfir() { - /* compute an array with the first of nonterminals */ - register *p, **s, i, **t, ch, changes; - zzcwp = &wsets[nnonter]; - NTLOOP(i){ - aryfil( wsets[i].ws.lset, tbitset, 0 ); - t = pres[i+1]; - for( s=pres[i]; s 0 ; ++p ) { - if( ch < NTBASE ) { - SETBIT( wsets[i].ws.lset, ch ); - break; - } - else if( !pempty[ch-NTBASE] ) break; - } - } - } +void cpfir() +{ + /* compute an array with the first of nonterminals */ + register *p, **s, i, **t, ch, changes; - /* now, reflect transitivity */ + zzcwp = &wsets[nnonter]; + NTLOOP(i) + { + aryfil(wsets[i].ws.lset, tbitset, 0); + t = pres[i + 1]; + for (s = pres[i]; s < t; ++s) { /* initially fill the sets */ + for (p = *s; (ch = *p) > 0; ++p) { + if (ch < NTBASE) { + SETBIT(wsets[i].ws.lset, ch); + break; + } else if (!pempty[ch - NTBASE]) + break; + } + } + } - changes = 1; - while( changes ){ - changes = 0; - NTLOOP(i){ - t = pres[i+1]; - for( s=pres[i]; s= 0; ++p ) { - changes |= setunion( wsets[i].ws.lset, wsets[ch].ws.lset ); - if( !pempty[ch] ) break; - } - } - } - } + /* now, reflect transitivity */ - NTLOOP(i) pfirst[i] = flset( &wsets[i].ws ); - if( !indebug ) return; - if( (foutput!=NULL) ){ - NTLOOP(i) { - fprintf( foutput, "\n%s: ", nontrst[i].name ); - prlook( pfirst[i] ); - fprintf( foutput, " %d\n", pempty[i] ); - } - } - } + changes = 1; + while (changes) { + changes = 0; + NTLOOP(i) + { + t = pres[i + 1]; + for (s = pres[i]; s < t; ++s) { + for (p = *s; (ch = (*p - NTBASE)) >= 0; ++p) { + changes |= setunion(wsets[i].ws.lset, wsets[ch].ws.lset); + if (!pempty[ch]) + break; + } + } + } + } -state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */ - int size1,size2; - register i; - struct item *p1, *p2, *k, *l, *q1, *q2; - p1 = pstate[nstate]; - p2 = pstate[nstate+1]; - if(p1==p2) return(0); /* null state */ - /* sort the items */ - for(k=p2-1;k>p1;k--) { /* make k the biggest */ - for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){ - int *s; - struct looksets *ss; - s = k->pitem; - k->pitem = l->pitem; - l->pitem = s; - ss = k->look; - k->look = l->look; - l->look = ss; - } - } - size1 = p2 - p1; /* size of state */ + NTLOOP(i) pfirst[i] = flset(&wsets[i].ws); + if (!indebug) + return; + if ((foutput != NULL)) { + NTLOOP(i) + { + fprintf(foutput, "\n%s: ", nontrst[i].name); + prlook(pfirst[i]); + fprintf(foutput, " %d\n", pempty[i]); + } + } +} - for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) { - /* get ith state */ - q1 = pstate[i]; - q2 = pstate[i+1]; - size2 = q2 - q1; - if (size1 != size2) continue; - k=p1; - for(l=q1;lpitem != k->pitem ) break; - ++k; - } - if (l != q2) continue; - /* found it */ - pstate[nstate+1] = pstate[nstate]; /* delete last state */ - /* fix up lookaheads */ - if( nolook ) return(i); - for( l=q1,k=p1; llook->lset[s]; - if( setunion( clset.lset, k->look->lset ) ) { - tystate[i] = MUSTDO; - /* register the new set */ - l->look = flset( &clset ); - } - } - return (i); - } - /* state is new */ - if( nolook ) error( "yacc state/nolook error" ); - pstate[nstate+2] = p2; - if(nstate+1 >= NSTATES) error("too many states" ); - if( c >= NTBASE ){ - mstates[ nstate ] = ntstates[ c-NTBASE ]; - ntstates[ c-NTBASE ] = nstate; - } - else { - mstates[ nstate ] = tstates[ c ]; - tstates[ c ] = nstate; - } - tystate[nstate]=MUSTDO; - return(nstate++); - } +int state(c) +{ /* sorts last state,and sees if it equals earlier ones. returns state number */ + int size1, size2; + register i; + struct item *p1, *p2, *k, *l, *q1, *q2; + p1 = pstate[nstate]; + p2 = pstate[nstate + 1]; + if (p1 == p2) + return (0); /* null state */ + /* sort the items */ + for (k = p2 - 1; k > p1; k--) { /* make k the biggest */ + for (l = k - 1; l >= p1; --l) + if (l->pitem > k->pitem) { + int *s; + struct looksets *ss; + s = k->pitem; + k->pitem = l->pitem; + l->pitem = s; + ss = k->look; + k->look = l->look; + l->look = ss; + } + } + size1 = p2 - p1; /* size of state */ + + for (i = (c >= NTBASE) ? ntstates[c - NTBASE] : tstates[c]; i != 0; i = mstates[i]) { + /* get ith state */ + q1 = pstate[i]; + q2 = pstate[i + 1]; + size2 = q2 - q1; + if (size1 != size2) + continue; + k = p1; + for (l = q1; l < q2; l++) { + if (l->pitem != k->pitem) + break; + ++k; + } + if (l != q2) + continue; + /* found it */ + pstate[nstate + 1] = pstate[nstate]; /* delete last state */ + /* fix up lookaheads */ + if (nolook) + return (i); + for (l = q1, k = p1; l < q2; ++l, ++k) { + int s; + SETLOOP(s) clset.lset[s] = l->look->lset[s]; + if (setunion(clset.lset, k->look->lset)) { + tystate[i] = MUSTDO; + /* register the new set */ + l->look = flset(&clset); + } + } + return (i); + } + /* state is new */ + if (nolook) + error("yacc state/nolook error"); + pstate[nstate + 2] = p2; + if (nstate + 1 >= NSTATES) + error("too many states"); + if (c >= NTBASE) { + mstates[nstate] = ntstates[c - NTBASE]; + ntstates[c - NTBASE] = nstate; + } else { + mstates[nstate] = tstates[c]; + tstates[c] = nstate; + } + tystate[nstate] = MUSTDO; + return (nstate++); +} int pidebug = 0; /* debugging flag for putitem */ -putitem( ptr, lptr ) int *ptr; struct looksets *lptr; { - register struct item *j; - if( pidebug && (foutput!=NULL) ) { - fprintf( foutput, "putitem(%s), state %d\n", writem(ptr), nstate ); - } - j = pstate[nstate+1]; - j->pitem = ptr; - if( !nolook ) j->look = flset( lptr ); - pstate[nstate+1] = ++j; - if( (int *)j > zzmemsz ){ - zzmemsz = (int *)j; - if( zzmemsz >= &mem0[MEMSIZE] ) error( "out of state space" ); - } - } +void putitem(ptr, lptr) int *ptr; +struct looksets *lptr; +{ + register struct item *j; -cempty(){ /* mark nonterminals which derive the empty string */ - /* also, look for nonterminals which don't derive any token strings */ + if (pidebug && (foutput != NULL)) { + fprintf(foutput, "putitem(%s), state %d\n", writem(ptr), nstate); + } + j = pstate[nstate + 1]; + j->pitem = ptr; + if (!nolook) + j->look = flset(lptr); + pstate[nstate + 1] = ++j; + if ((int *)j > zzmemsz) { + zzmemsz = (int *)j; + if (zzmemsz >= &mem0[MEMSIZE]) + error("out of state space"); + } +} -# define EMPTY 1 -# define WHOKNOWS 0 -# define OK 1 +void cempty() +{ /* mark nonterminals which derive the empty string */ + /* also, look for nonterminals which don't derive any token strings */ - register i, *p; +#define EMPTY 1 +#define WHOKNOWS 0 +#define OK 1 - /* first, use the array pempty to detect productions that can never be reduced */ - /* set pempty to WHONOWS */ - aryfil( pempty, nnonter+1, WHOKNOWS ); + register i, *p; - /* now, look at productions, marking nonterminals which derive something */ + /* first, use the array pempty to detect productions that can never be reduced */ + /* set pempty to WHONOWS */ + aryfil(pempty, nnonter + 1, WHOKNOWS); - more: - PLOOP(0,i){ - if( pempty[ *prdptr[i] - NTBASE ] ) continue; - for( p=prdptr[i]+1; *p>=0; ++p ){ - if( *p>=NTBASE && pempty[ *p-NTBASE ] == WHOKNOWS ) break; - } - if( *p < 0 ){ /* production can be derived */ - pempty[ *prdptr[i]-NTBASE ] = OK; - goto more; - } - } + /* now, look at productions, marking nonterminals which derive something */ - /* now, look at the nonterminals, to see if they are all OK */ +more: + PLOOP(0, i) + { + if (pempty[*prdptr[i] - NTBASE]) + continue; + for (p = prdptr[i] + 1; *p >= 0; ++p) { + if (*p >= NTBASE && pempty[*p - NTBASE] == WHOKNOWS) + break; + } + if (*p < 0) { /* production can be derived */ + pempty[*prdptr[i] - NTBASE] = OK; + goto more; + } + } - NTLOOP(i){ - /* the added production rises or falls as the start symbol ... */ - if( i == 0 ) continue; - if( pempty[ i ] != OK ) { - fatfl = 0; - error( "nonterminal %s never derives any token string", nontrst[i].name ); - } - } + /* now, look at the nonterminals, to see if they are all OK */ - if( nerrors ){ - summary(); - exit(1); - } + NTLOOP(i) + { + /* the added production rises or falls as the start symbol ... */ + if (i == 0) + continue; + if (pempty[i] != OK) { + fatfl = 0; + error("nonterminal %s never derives any token string", nontrst[i].name); + } + } - /* now, compute the pempty array, to see which nonterminals derive the empty string */ + if (nerrors) { + summary(); + exit(1); + } - /* set pempty to WHOKNOWS */ + /* now, compute the pempty array, to see which nonterminals derive the empty string */ - aryfil( pempty, nnonter+1, WHOKNOWS ); + /* set pempty to WHOKNOWS */ - /* loop as long as we keep finding empty nonterminals */ + aryfil(pempty, nnonter + 1, WHOKNOWS); + + /* loop as long as we keep finding empty nonterminals */ again: - PLOOP(1,i){ - if( pempty[ *prdptr[i]-NTBASE ]==WHOKNOWS ){ /* not known to be empty */ - for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]==EMPTY ; ++p ) ; - if( *p < 0 ){ /* we have a nontrivially empty nonterminal */ - pempty[*prdptr[i]-NTBASE] = EMPTY; - goto again; /* got one ... try for another */ - } - } - } - - } + PLOOP(1, i) + { + if (pempty[*prdptr[i] - NTBASE] == WHOKNOWS) { /* not known to be empty */ + for (p = prdptr[i] + 1; *p >= NTBASE && pempty[*p - NTBASE] == EMPTY; ++p) + ; + if (*p < 0) { /* we have a nontrivially empty nonterminal */ + pempty[*prdptr[i] - NTBASE] = EMPTY; + goto again; /* got one ... try for another */ + } + } + } +} int gsdebug = 0; -stagen(){ /* generate the states */ - int i, j; - register c; - register struct wset *p, *q; +void stagen() +{ /* generate the states */ - /* initialize */ + int i, j; + register c; + register struct wset *p, *q; - nstate = 0; - /* THIS IS FUNNY from the standpoint of portability */ - /* it represents the magic moment when the mem0 array, which has - /* been holding the productions, starts to hold item pointers, of a - /* different type... */ - /* someday, alloc should be used to allocate all this stuff... for now, we - /* accept that if pointers don't fit in integers, there is a problem... */ + /* initialize */ - pstate[0] = pstate[1] = (struct item *)mem; - aryfil( clset.lset, tbitset, 0 ); - putitem( prdptr[0]+1, &clset ); - tystate[0] = MUSTDO; - nstate = 1; - pstate[2] = pstate[1]; + nstate = 0; + /* THIS IS FUNNY from the standpoint of portability */ + /* it represents the magic moment when the mem0 array, which has + /* been holding the productions, starts to hold item pointers, of a + /* different type... */ + /* someday, alloc should be used to allocate all this stuff... for now, we + /* accept that if pointers don't fit in integers, there is a problem... */ - aryfil( amem, ACTSIZE, 0 ); + pstate[0] = pstate[1] = (struct item *)mem; + aryfil(clset.lset, tbitset, 0); + putitem(prdptr[0] + 1, &clset); + tystate[0] = MUSTDO; + nstate = 1; + pstate[2] = pstate[1]; - /* now, the main state generation loop */ + aryfil(amem, ACTSIZE, 0); - more: - SLOOP(i){ - if( tystate[i] != MUSTDO ) continue; - tystate[i] = DONE; - aryfil( temp1, nnonter+1, 0 ); - /* take state i, close it, and do gotos */ - closure(i); - WSLOOP(wsets,p){ /* generate goto's */ - if( p->flag ) continue; - p->flag = 1; - c = *(p->pitem); - if( c <= 1 ) { - if( pstate[i+1]-pstate[i] <= p-wsets ) tystate[i] = MUSTLOOKAHEAD; - continue; - } - /* do a goto on c */ - WSLOOP(p,q){ - if( c == *(q->pitem) ){ /* this item contributes to the goto */ - putitem( q->pitem + 1, &q->ws ); - q->flag = 1; - } - } - if( c < NTBASE ) { - state(c); /* register new state */ - } - else { - temp1[c-NTBASE] = state(c); - } - } - if( gsdebug && (foutput!=NULL) ){ - fprintf( foutput, "%d: ", i ); - NTLOOP(j) { - if( temp1[j] ) fprintf( foutput, "%s %d, ", nontrst[j].name, temp1[j] ); - } - fprintf( foutput, "\n"); - } - indgo[i] = apack( &temp1[1], nnonter-1 ) - 1; - goto more; /* we have done one goto; do some more */ - } - /* no more to do... stop */ - } + /* now, the main state generation loop */ + +more: + SLOOP(i) + { + if (tystate[i] != MUSTDO) + continue; + tystate[i] = DONE; + aryfil(temp1, nnonter + 1, 0); + /* take state i, close it, and do gotos */ + closure(i); + WSLOOP(wsets, p) + { /* generate goto's */ + if (p->flag) + continue; + p->flag = 1; + c = *(p->pitem); + if (c <= 1) { + if (pstate[i + 1] - pstate[i] <= p - wsets) + tystate[i] = MUSTLOOKAHEAD; + continue; + } + /* do a goto on c */ + WSLOOP(p, q) + { + if (c == *(q->pitem)) { /* this item contributes to the goto */ + putitem(q->pitem + 1, &q->ws); + q->flag = 1; + } + } + if (c < NTBASE) { + state(c); /* register new state */ + } else { + temp1[c - NTBASE] = state(c); + } + } + if (gsdebug && (foutput != NULL)) { + fprintf(foutput, "%d: ", i); + NTLOOP(j) + { + if (temp1[j]) + fprintf(foutput, "%s %d, ", nontrst[j].name, temp1[j]); + } + fprintf(foutput, "\n"); + } + indgo[i] = apack(&temp1[1], nnonter - 1) - 1; + goto more; /* we have done one goto; do some more */ + } + /* no more to do... stop */ +} int cldebug = 0; /* debugging flag for closure */ -closure(i){ /* generate the closure of state i */ - int c, ch, work, k; - register struct wset *u, *v; - int *pi; - int **s, **t; - struct item *q; - register struct item *p; +void closure(i) +{ /* generate the closure of state i */ - ++zzclose; + int c, ch, work, k; + register struct wset *u, *v; + int *pi; + int **s, **t; + struct item *q; + register struct item *p; - /* first, copy kernel of state i to wsets */ + ++zzclose; - cwp = wsets; - ITMLOOP(i,p,q){ - cwp->pitem = p->pitem; - cwp->flag = 1; /* this item must get closed */ - SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k]; - WSBUMP(cwp); - } + /* first, copy kernel of state i to wsets */ - /* now, go through the loop, closing each item */ + cwp = wsets; + ITMLOOP(i, p, q) + { + cwp->pitem = p->pitem; + cwp->flag = 1; /* this item must get closed */ + SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k]; + WSBUMP(cwp); + } - work = 1; - while( work ){ - work = 0; - WSLOOP(wsets,u){ - - if( u->flag == 0 ) continue; - c = *(u->pitem); /* dot is before c */ - - if( c < NTBASE ){ - u->flag = 0; - continue; /* only interesting case is where . is before nonterminal */ - } - - /* compute the lookahead */ - aryfil( clset.lset, tbitset, 0 ); + /* now, go through the loop, closing each item */ - /* find items involving c */ + work = 1; + while (work) { + work = 0; + WSLOOP(wsets, u) + { + if (u->flag == 0) + continue; + c = *(u->pitem); /* dot is before c */ - WSLOOP(u,v){ - if( v->flag == 1 && *(pi=v->pitem) == c ){ - v->flag = 0; - if( nolook ) continue; - while( (ch= *++pi)>0 ){ - if( ch < NTBASE ){ /* terminal symbol */ - SETBIT( clset.lset, ch ); - break; - } - /* nonterminal symbol */ - setunion( clset.lset, pfirst[ch-NTBASE]->lset ); - if( !pempty[ch-NTBASE] ) break; - } - if( ch<=0 ) setunion( clset.lset, v->ws.lset ); - } - } - - /* now loop over productions derived from c */ - - c -= NTBASE; /* c is now nonterminal number */ - - t = pres[c+1]; - for( s=pres[c]; spitem == *s ){ /* yes, it is there */ - if( nolook ) goto nexts; - if( setunion( v->ws.lset, clset.lset ) ) v->flag = work = 1; - goto nexts; - } - } - - /* not there; make a new entry */ - if( cwp-wsets+1 >= WSETSIZE ) error( "working set overflow" ); - cwp->pitem = *s; - cwp->flag = 1; - if( !nolook ){ - work = 1; - SETLOOP(k) cwp->ws.lset[k] = clset.lset[k]; - } - WSBUMP(cwp); - - nexts: ; - } - - } - } + if (c < NTBASE) { + u->flag = 0; + continue; /* only interesting case is where . is before nonterminal */ + } - /* have computed closure; flags are reset; return */ + /* compute the lookahead */ + aryfil(clset.lset, tbitset, 0); - if( cwp > zzcwp ) zzcwp = cwp; - if( cldebug && (foutput!=NULL) ){ - fprintf( foutput, "\nState %d, nolook = %d\n", i, nolook ); - WSLOOP(wsets,u){ - if( u->flag ) fprintf( foutput, "flag set!\n"); - u->flag = 0; - fprintf( foutput, "\t%s", writem(u->pitem)); - prlook( &u->ws ); - fprintf( foutput, "\n" ); - } - } - } + /* find items involving c */ -struct looksets *flset( p ) struct looksets *p; { - /* decide if the lookahead set pointed to by p is known */ - /* return pointer to a perminent location for the set */ + WSLOOP(u, v) + { + if (v->flag == 1 && *(pi = v->pitem) == c) { + v->flag = 0; + if (nolook) + continue; + while ((ch = *++pi) > 0) { + if (ch < NTBASE) { /* terminal symbol */ + SETBIT(clset.lset, ch); + break; + } + /* nonterminal symbol */ + setunion(clset.lset, pfirst[ch - NTBASE]->lset); + if (!pempty[ch - NTBASE]) + break; + } + if (ch <= 0) + setunion(clset.lset, v->ws.lset); + } + } - register struct looksets *q; - int j, *w; - register *u, *v; + /* now loop over productions derived from c */ - for( q = &lkst[nlset]; q-- > lkst; ){ - u = p->lset; - v = q->lset; - w = & v[tbitset]; - while( v= LSETSIZE )error("too many lookahead sets" ); - SETLOOP(j){ - q->lset[j] = p->lset[j]; - } - return( q ); - } + c -= NTBASE; /* c is now nonterminal number */ + + t = pres[c + 1]; + for (s = pres[c]; s < t; ++s) { + /* put these items into the closure */ + WSLOOP(wsets, v) + { /* is the item there */ + if (v->pitem == *s) { /* yes, it is there */ + if (nolook) + goto nexts; + if (setunion(v->ws.lset, clset.lset)) + v->flag = work = 1; + goto nexts; + } + } + + /* not there; make a new entry */ + if (cwp - wsets + 1 >= WSETSIZE) + error("working set overflow"); + cwp->pitem = *s; + cwp->flag = 1; + if (!nolook) { + work = 1; + SETLOOP(k) cwp->ws.lset[k] = clset.lset[k]; + } + WSBUMP(cwp); + + nexts:; + } + } + } + + /* have computed closure; flags are reset; return */ + + if (cwp > zzcwp) + zzcwp = cwp; + if (cldebug && (foutput != NULL)) { + fprintf(foutput, "\nState %d, nolook = %d\n", i, nolook); + WSLOOP(wsets, u) + { + if (u->flag) + fprintf(foutput, "flag set!\n"); + u->flag = 0; + fprintf(foutput, "\t%s", writem(u->pitem)); + prlook(&u->ws); + fprintf(foutput, "\n"); + } + } +} + +struct looksets *flset(p) +struct looksets *p; +{ + /* decide if the lookahead set pointed to by p is known */ + /* return pointer to a perminent location for the set */ + + register struct looksets *q; + int j, *w; + register *u, *v; + + for (q = &lkst[nlset]; q-- > lkst;) { + u = p->lset; + v = q->lset; + w = &v[tbitset]; + while (v < w) + if (*u++ != *v++) + goto more; + /* we have matched */ + return (q); + more:; + } + /* add a new one */ + q = &lkst[nlset++]; + if (nlset >= LSETSIZE) + error("too many lookahead sets"); + SETLOOP(j) + { + q->lset[j] = p->lset[j]; + } + return (q); +} diff --git a/src/cmd/yacc/y2.c b/src/cmd/yacc/y2.c index 2b58153..636451a 100644 --- a/src/cmd/yacc/y2.c +++ b/src/cmd/yacc/y2.c @@ -1,866 +1,950 @@ -#if !defined(lint) && defined(DOSCCS) -static char sccsid[] = "@(#)y2.c 4.1.1 (2.11BSD) 1995/05/11"; -#endif +#include "dextern.h" -# include "dextern" -# define IDENTIFIER 257 -# define MARK 258 -# define TERM 259 -# define LEFT 260 -# define RIGHT 261 -# define BINARY 262 -# define PREC 263 -# define LCURLY 264 -# define C_IDENTIFIER 265 /* name followed by colon */ -# define NUMBER 266 -# define START 267 -# define TYPEDEF 268 -# define TYPENAME 269 -# define UNION 270 -# define ENDFILE 0 +#define IDENTIFIER 257 +#define MARK 258 +#define TERM 259 +#define LEFT 260 +#define RIGHT 261 +#define BINARY 262 +#define PREC 263 +#define LCURLY 264 +#define C_IDENTIFIER 265 /* name followed by colon */ +#define NUMBER 266 +#define START 267 +#define TYPEDEF 268 +#define TYPENAME 269 +#define UNION 270 +#define ENDFILE 0 - /* communication variables between various I/O routines */ +/* communication variables between various I/O routines */ -char *infile; /* input file name */ -int numbval; /* value of an input number */ -char tokname[NAMESIZE]; /* input token name */ +char *infile; /* input file name */ +int numbval; /* value of an input number */ +char tokname[NAMESIZE]; /* input token name */ - /* storage of names */ +/* storage of names */ -char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */ -int cnamsz = CNAMSZ; /* size of cnames */ -char * cnamp = cnames; /* place where next name is to be put in */ -int ndefout = 3; /* number of defined symbols output */ +char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */ +int cnamsz = CNAMSZ; /* size of cnames */ +char *cnamp = cnames; /* place where next name is to be put in */ +int ndefout = 3; /* number of defined symbols output */ - /* storage of types */ -int ntypes; /* number of types defined */ -char * typeset[NTYPES]; /* pointers to type tags */ +/* storage of types */ +int ntypes; /* number of types defined */ +char *typeset[NTYPES]; /* pointers to type tags */ - /* symbol tables for tokens and nonterminals */ +/* symbol tables for tokens and nonterminals */ int ntokens = 0; struct toksymb tokset[NTERMS]; int toklev[NTERMS]; int nnonter = -1; struct ntsymb nontrst[NNONTERM]; -int start; /* start symbol */ +int start; /* start symbol */ - /* assigned token type values */ +/* assigned token type values */ int extval = 0; - /* input and output file descriptors */ +/* input and output file descriptors */ -FILE * finput; /* yacc input file */ -FILE * faction; /* file for saving actions */ -FILE * fdefine; /* file for # defines */ -FILE * ftable; /* y.tab.c file */ -FILE * ftemp; /* tempfile to pass 2 */ -FILE * foutput; /* y.output file */ +FILE *finput; /* yacc input file */ +FILE *faction; /* file for saving actions */ +FILE *fdefine; /* file for # defines */ +FILE *ftable; /* y.tab.c file */ +FILE *ftemp; /* tempfile to pass 2 */ +FILE *foutput; /* y.output file */ - /* storage for grammar rules */ +/* storage for grammar rules */ -int mem0[MEMSIZE] ; /* production storage */ +int mem0[MEMSIZE]; /* production storage */ int *mem = mem0; -int nprod= 1; /* number of productions */ -int *prdptr[NPROD]; /* pointers to descriptions of productions */ -int levprd[NPROD] ; /* precedence levels for the productions */ - - -setup(argc,argv) int argc; char *argv[]; -{ int i,lev, ty; - register int t, j; - int c; - int *p; - char actname[8]; - - foutput = NULL; - fdefine = NULL; - i = 1; - while( argc >= 2 && argv[1][0] == '-' ) { - while( *++(argv[1]) ){ - switch( *argv[1] ){ - case 'v': - case 'V': - foutput = fopen(FILEU, "w" ); - if( foutput == NULL ) error( "cannot open y.output" ); - continue; - case 'D': - case 'd': - fdefine = fopen( FILED, "w" ); - continue; - case 'o': - case 'O': - fprintf( stderr, "`o' flag now default in yacc\n" ); - continue; - - case 'r': - case 'R': - error( "Ratfor Yacc is dead: sorry...\n" ); - - default: - error( "illegal option: %c", *argv[1]); - } - } - argv++; - argc--; - } - - ftable = fopen( OFILE, "w" ); - if( ftable == NULL ) error( "cannot open table file" ); - - ftemp = fopen( TEMPNAME, "w" ); - faction = fopen( ACTNAME, "w" ); - if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" ); - - if( argc < 2 || ((finput=fopen( infile=argv[1], "r" )) == NULL ) ){ - error( "cannot open input file" ); - } - - cnamp = cnames; - defin(0,"$end"); - extval = 0400; - defin(0,"error"); - defin(1,"$accept"); - mem=mem0; - lev = 0; - ty = 0; - i=0; - - /* 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: - 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 int\n#endif\n" ); - fprintf( ftable, "YYSTYPE yylval, yyval;\n" ); - - prdptr[0]=mem; - /* added production */ - *mem++ = NTBASE; - *mem++ = start; /* if start is 0, we will overwrite with the lhs of the first rule */ - *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)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 */ - register tempty; - 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 */ - - finact(); - if( t == MARK ){ - fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); - while( (c=getc(finput)) != EOF ) putc( c, ftable ); - } - fclose( finput ); - } - -finact(){ - /* finish action routine */ - - fclose(faction); - - fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value ); - - } - -defin( t, s ) register char *s; { -/* define s to be a terminal if t=0 - or a nonterminal if t=1 */ - - register val; - - if (t) { - if( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d",NNONTERM); - nontrst[nnonter].name = cstash(s); - return( NTBASE + nnonter ); - } - /* must be a token */ - if( ++ntokens >= NTERMS ) error("too many terminals, limit %d",NTERMS ); - tokset[ntokens].name = cstash(s); - - /* establish value for token */ - - if( s[0]==' ' && s[2]=='\0' ) /* single character literal */ - val = s[1]; - else if ( s[0]==' ' && s[1]=='\\' ) { /* escape sequence */ - if( s[3] == '\0' ){ /* single character escape sequence */ - switch ( s[2] ){ - /* character which is escaped */ - case 'n': val = '\n'; break; - case 'r': val = '\r'; break; - case 'b': val = '\b'; break; - case 't': val = '\t'; break; - case 'f': val = '\f'; break; - case '\'': val = '\''; break; - case '"': val = '"'; break; - case '\\': val = '\\'; break; - default: error( "invalid escape" ); - } - } - else if( s[2] <= '7' && s[2]>='0' ){ /* \nnn sequence */ - if( s[3]<'0' || s[3] > '7' || s[4]<'0' || - s[4]>'7' || s[5] != '\0' ) error("illegal \\nnn construction" ); - val = 64*s[2] + 8*s[3] + s[4] - 73*'0'; - if( val == 0 ) error( "'\\000' is illegal" ); - } - } - else { - val = extval++; - } - tokset[ntokens].value = val; - toklev[ntokens] = 0; - return( ntokens ); - } - -defout(){ /* write out the defines (at the end of the declaration section) */ - - register int i, c; - register char *cp; - - for( i=ndefout; i<=ntokens; ++i ){ - - cp = tokset[i].name; - if( *cp == ' ' ) ++cp; /* literals */ - - for( ; (c= *cp)!='\0'; ++cp ){ - - if( islower(c) || isupper(c) || isdigit(c) || c=='_' ); /* VOID */ - else goto nodef; - } - - fprintf( ftable, "# define %s %d\n", tokset[i].name, tokset[i].value ); - if( fdefine != NULL ) fprintf( fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value ); - - nodef: ; - } - - ndefout = ntokens+1; - - } - -char * -cstash( s ) register char *s; { - char *temp; - - temp = cnamp; - do { - if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); - else *cnamp++ = *s; - } while ( *s++ ); - return( temp ); - } - -gettok() { - register i, base; - static int peekline; /* number of '\n' seen in lookahead */ - register c, match, reserve; - -begin: - reserve = 0; - lineno += peekline; - peekline = 0; - c = getc(finput); - while( c==' ' || c=='\n' || c=='\t' || c=='\f' ){ - if( c == '\n' ) ++lineno; - c=getc(finput); - } - if( c == '/' ){ /* skip comment */ - lineno += skipcom(); - goto begin; - } - - switch(c){ - - case EOF: - return(ENDFILE); - case '{': - ungetc( c, finput ); - return( '=' ); /* action ... */ - case '<': /* get, and look up, a type name (union member name) */ - i = 0; - while( (c=getc(finput)) != '>' && c>=0 && c!= '\n' ){ - tokname[i] = c; - if( ++i >= NAMESIZE ) --i; - } - if( c != '>' ) error( "unterminated < ... > clause" ); - tokname[i] = '\0'; - for( i=1; i<=ntypes; ++i ){ - if( !strcmp( typeset[i], tokname ) ){ - numbval = i; - return( TYPENAME ); - } - } - typeset[numbval = ++ntypes] = cstash( tokname ); - return( TYPENAME ); - - case '"': - case '\'': - match = c; - tokname[0] = ' '; - i = 1; - for(;;){ - c = getc(finput); - if( c == '\n' || c == EOF ) - error("illegal or missing ' or \"" ); - if( c == '\\' ){ - c = getc(finput); - tokname[i] = '\\'; - if( ++i >= NAMESIZE ) --i; - } - else if( c == match ) break; - tokname[i] = c; - if( ++i >= NAMESIZE ) --i; - } - break; - - case '%': - case '\\': - - switch(c=getc(finput)) { - - case '0': return(TERM); - case '<': return(LEFT); - case '2': return(BINARY); - case '>': return(RIGHT); - case '%': - case '\\': return(MARK); - case '=': return(PREC); - case '{': return(LCURLY); - default: reserve = 1; - } - - default: - - if( isdigit(c) ){ /* number */ - numbval = c-'0' ; - base = (c=='0') ? 8 : 10 ; - for( c=getc(finput); isdigit(c) ; c=getc(finput) ){ - numbval = numbval*base + c - '0'; - } - ungetc( c, finput ); - return(NUMBER); - } - else if( islower(c) || isupper(c) || c=='_' || c=='.' || c=='$' ){ - i = 0; - while( islower(c) || isupper(c) || isdigit(c) || c=='_' || c=='.' || c=='$' ){ - tokname[i] = c; - if( reserve && isupper(c) ) tokname[i] += 'a'-'A'; - if( ++i >= NAMESIZE ) --i; - c = getc(finput); - } - } - else return(c); - - ungetc( c, finput ); - } - - tokname[i] = '\0'; - - if( reserve ){ /* find a reserved word */ - if( !strcmp(tokname,"term")) return( TERM ); - if( !strcmp(tokname,"token")) return( TERM ); - if( !strcmp(tokname,"left")) return( LEFT ); - if( !strcmp(tokname,"nonassoc")) return( BINARY ); - if( !strcmp(tokname,"binary")) return( BINARY ); - if( !strcmp(tokname,"right")) return( RIGHT ); - if( !strcmp(tokname,"prec")) return( PREC ); - if( !strcmp(tokname,"start")) return( START ); - if( !strcmp(tokname,"type")) return( TYPEDEF ); - if( !strcmp(tokname,"union")) return( UNION ); - error("invalid escape, or illegal reserved word: %s", tokname ); - } - - /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ - - c = getc(finput); - while( c==' ' || c=='\t'|| c=='\n' || c=='\f' || c== '/' ) { - if( c == '\n' ) ++peekline; - else if( c == '/' ){ /* look for comments */ - peekline += skipcom(); - } - c = getc(finput); - } - if( c == ':' ) return( C_IDENTIFIER ); - ungetc( c, finput ); - return( IDENTIFIER ); +int nprod = 1; /* number of productions */ +int *prdptr[NPROD]; /* pointers to descriptions of productions */ +int levprd[NPROD]; /* precedence levels for the productions */ + +setup(argc, argv) int argc; +char *argv[]; +{ + int i, lev, ty; + register int t, j; + int c; + int *p; + char actname[8]; + + foutput = NULL; + fdefine = NULL; + i = 1; + while (argc >= 2 && argv[1][0] == '-') { + while (*++(argv[1])) { + switch (*argv[1]) { + case 'v': + case 'V': + foutput = fopen(FILEU, "w"); + if (foutput == NULL) + error("cannot open y.output"); + continue; + case 'D': + case 'd': + fdefine = fopen(FILED, "w"); + continue; + case 'o': + case 'O': + fprintf(stderr, "`o' flag now default in yacc\n"); + continue; + + case 'r': + case 'R': + error("Ratfor Yacc is dead: sorry...\n"); + + default: + error("illegal option: %c", *argv[1]); + } + } + argv++; + argc--; + } + + ftable = fopen(OFILE, "w"); + if (ftable == NULL) + error("cannot open table file"); + + ftemp = fopen(TEMPNAME, "w"); + faction = fopen(ACTNAME, "w"); + if (ftemp == NULL || faction == NULL) + error("cannot open temp file"); + + if (argc < 2 || ((finput = fopen(infile = argv[1], "r")) == NULL)) { + error("cannot open input file"); + } + + cnamp = cnames; + defin(0, "$end"); + extval = 0400; + defin(0, "error"); + defin(1, "$accept"); + mem = mem0; + lev = 0; + ty = 0; + i = 0; + + /* 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: + 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 int\n#endif\n"); + fprintf(ftable, "YYSTYPE yylval, yyval;\n"); + + prdptr[0] = mem; + /* added production */ + *mem++ = NTBASE; + *mem++ = start; /* if start is 0, we will overwrite with the lhs of the first rule */ + *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 */ + register tempty; + 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 */ + + finact(); + if (t == MARK) { + fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile); + while ((c = getc(finput)) != EOF) + putc(c, ftable); + } + fclose(finput); } -fdtype( t ){ /* determine the type of a symbol */ - register v; +finact() +{ + /* finish action routine */ - if( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue; - else v = TYPE( toklev[t] ); - if( v <= 0 ) error( "must specify type for %s", (t>=NTBASE)?nontrst[t-NTBASE].name: - tokset[t].name ); - return( v ); - } + fclose(faction); -chfind( t, s ) register char *s; { - int i; + fprintf(ftable, "# define YYERRCODE %d\n", tokset[2].value); +} - if (s[0]==' ')t=0; - TLOOP(i){ - if(!strcmp(s,tokset[i].name)){ - return( i ); - } - } - NTLOOP(i){ - if(!strcmp(s,nontrst[i].name)) { - return( i+NTBASE ); - } - } - /* cannot find name */ - if( t>1 ) - error( "%s should have been defined earlier", s ); - return( defin( t, s ) ); - } +defin(t, s) register char *s; +{ + /* define s to be a terminal if t=0 + or a nonterminal if t=1 */ -cpyunion(){ - /* copy the union declaration to the output, and the define file if present */ + register val; - int level, c; - fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); - fprintf( ftable, "typedef union " ); - if( fdefine ) fprintf( fdefine, "\ntypedef union " ); + if (t) { + if (++nnonter >= NNONTERM) + error("too many nonterminals, limit %d", NNONTERM); + nontrst[nnonter].name = cstash(s); + return (NTBASE + nnonter); + } + /* must be a token */ + if (++ntokens >= NTERMS) + error("too many terminals, limit %d", NTERMS); + tokset[ntokens].name = cstash(s); - level = 0; - for(;;){ - if( (c=getc(finput)) < 0 ) error( "EOF encountered while processing %%union" ); - putc( c, ftable ); - if( fdefine ) putc( c, fdefine ); + /* establish value for token */ - switch( c ){ + if (s[0] == ' ' && s[2] == '\0') /* single character literal */ + val = s[1]; + else if (s[0] == ' ' && s[1] == '\\') { /* escape sequence */ + if (s[3] == '\0') { /* single character escape sequence */ + switch (s[2]) { + /* character which is escaped */ + case 'n': + val = '\n'; + break; + case 'r': + val = '\r'; + break; + case 'b': + val = '\b'; + break; + case 't': + val = '\t'; + break; + case 'f': + val = '\f'; + break; + case '\'': + val = '\''; + break; + case '"': + val = '"'; + break; + case '\\': + val = '\\'; + break; + default: + error("invalid escape"); + } + } else if (s[2] <= '7' && s[2] >= '0') { /* \nnn sequence */ + if (s[3] < '0' || s[3] > '7' || s[4] < '0' || s[4] > '7' || s[5] != '\0') + error("illegal \\nnn construction"); + val = 64 * s[2] + 8 * s[3] + s[4] - 73 * '0'; + if (val == 0) + error("'\\000' is illegal"); + } + } else { + val = extval++; + } + tokset[ntokens].value = val; + toklev[ntokens] = 0; + return (ntokens); +} - case '\n': - ++lineno; - break; +defout() +{ /* write out the defines (at the end of the declaration section) */ - case '{': - ++level; - break; + register int i, c; + register char *cp; - case '}': - --level; - if( level == 0 ) { /* we are finished copying */ - fprintf( ftable, " YYSTYPE;\n" ); - if( fdefine ) fprintf( fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n" ); - return; - } - } - } - } + for (i = ndefout; i <= ntokens; ++i) { + cp = tokset[i].name; + if (*cp == ' ') + ++cp; /* literals */ -cpycode(){ /* copies code between \{ and \} */ - register int c; + for (; (c = *cp) != '\0'; ++cp) { + if (islower(c) || isupper(c) || isdigit(c) || c == '_') + ; /* VOID */ + else + goto nodef; + } - c = getc(finput); - if( c == '\n' ) { - c = getc(finput); - lineno++; - } - fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); - while( c>=0 ){ - if( c=='\\' ) - if( (c=getc(finput)) == '}' ) return; - else putc('\\', ftable ); - if( c=='%' ) - if( (c=getc(finput)) == '}' ) return; - else putc('%', ftable ); - putc( c , ftable ); - if( c == '\n' ) ++lineno; - c = getc(finput); - } - error("eof before %%}" ); - } + fprintf(ftable, "# define %s %d\n", tokset[i].name, tokset[i].value); + if (fdefine != NULL) + fprintf(fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value); -skipcom(){ /* skip over comments */ - register int c, i=0; /* i is the number of lines skipped */ + nodef:; + } - /* skipcom is called after reading a / */ + ndefout = ntokens + 1; +} - if( getc(finput) != '*' ) error( "illegal comment" ); - c = getc(finput); - while( c != EOF ){ - while( c == '*' ){ - if( (c=getc(finput)) == '/' ) return( i ); - } - if( c == '\n' ) ++i; - c = getc(finput); - } - error( "EOF inside comment" ); - /* NOTREACHED */ - } +char *cstash(s) +register char *s; +{ + char *temp; -cpyact(offset){ /* copy C action to the next ; or closing } */ - register int c; - int brac, match, j, s, tok; + temp = cnamp; + do { + if (cnamp >= &cnames[cnamsz]) + error("too many characters in id's and literals"); + else + *cnamp++ = *s; + } while (*s++); + return (temp); +} - fprintf( faction, "\n# line %d \"%s\"\n", lineno, infile ); +gettok() +{ + register i, base; + static int peekline; /* number of '\n' seen in lookahead */ + register c, match, reserve; - brac = 0; +begin: + reserve = 0; + lineno += peekline; + peekline = 0; + c = getc(finput); + while (c == ' ' || c == '\n' || c == '\t' || c == '\f') { + if (c == '\n') + ++lineno; + c = getc(finput); + } + if (c == '/') { /* skip comment */ + lineno += skipcom(); + goto begin; + } + + switch (c) { + case EOF: + return (ENDFILE); + case '{': + ungetc(c, finput); + return ('='); /* action ... */ + case '<': /* get, and look up, a type name (union member name) */ + i = 0; + while ((c = getc(finput)) != '>' && c >= 0 && c != '\n') { + tokname[i] = c; + if (++i >= NAMESIZE) + --i; + } + if (c != '>') + error("unterminated < ... > clause"); + tokname[i] = '\0'; + for (i = 1; i <= ntypes; ++i) { + if (!strcmp(typeset[i], tokname)) { + numbval = i; + return (TYPENAME); + } + } + typeset[numbval = ++ntypes] = cstash(tokname); + return (TYPENAME); + + case '"': + case '\'': + match = c; + tokname[0] = ' '; + i = 1; + for (;;) { + c = getc(finput); + if (c == '\n' || c == EOF) + error("illegal or missing ' or \""); + if (c == '\\') { + c = getc(finput); + tokname[i] = '\\'; + if (++i >= NAMESIZE) + --i; + } else if (c == match) + break; + tokname[i] = c; + if (++i >= NAMESIZE) + --i; + } + break; + + case '%': + case '\\': + + switch (c = getc(finput)) { + case '0': + return (TERM); + case '<': + return (LEFT); + case '2': + return (BINARY); + case '>': + return (RIGHT); + case '%': + case '\\': + return (MARK); + case '=': + return (PREC); + case '{': + return (LCURLY); + default: + reserve = 1; + } + + default: + + if (isdigit(c)) { /* number */ + numbval = c - '0'; + base = (c == '0') ? 8 : 10; + for (c = getc(finput); isdigit(c); c = getc(finput)) { + numbval = numbval * base + c - '0'; + } + ungetc(c, finput); + return (NUMBER); + } else if (islower(c) || isupper(c) || c == '_' || c == '.' || c == '$') { + i = 0; + while (islower(c) || isupper(c) || isdigit(c) || c == '_' || c == '.' || c == '$') { + tokname[i] = c; + if (reserve && isupper(c)) + tokname[i] += 'a' - 'A'; + if (++i >= NAMESIZE) + --i; + c = getc(finput); + } + } else + return (c); + + ungetc(c, finput); + } + + tokname[i] = '\0'; + + if (reserve) { /* find a reserved word */ + if (!strcmp(tokname, "term")) + return (TERM); + if (!strcmp(tokname, "token")) + return (TERM); + if (!strcmp(tokname, "left")) + return (LEFT); + if (!strcmp(tokname, "nonassoc")) + return (BINARY); + if (!strcmp(tokname, "binary")) + return (BINARY); + if (!strcmp(tokname, "right")) + return (RIGHT); + if (!strcmp(tokname, "prec")) + return (PREC); + if (!strcmp(tokname, "start")) + return (START); + if (!strcmp(tokname, "type")) + return (TYPEDEF); + if (!strcmp(tokname, "union")) + return (UNION); + error("invalid escape, or illegal reserved word: %s", tokname); + } + + /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ + + c = getc(finput); + while (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '/') { + if (c == '\n') + ++peekline; + else if (c == '/') { /* look for comments */ + peekline += skipcom(); + } + c = getc(finput); + } + if (c == ':') + return (C_IDENTIFIER); + ungetc(c, finput); + return (IDENTIFIER); +} + +fdtype(t) +{ /* determine the type of a symbol */ + register v; + + if (t >= NTBASE) + v = nontrst[t - NTBASE].tvalue; + else + v = TYPE(toklev[t]); + if (v <= 0) + error("must specify type for %s", + (t >= NTBASE) ? nontrst[t - NTBASE].name : tokset[t].name); + return (v); +} + +chfind(t, s) register char *s; +{ + int i; + + if (s[0] == ' ') + t = 0; + TLOOP(i) + { + if (!strcmp(s, tokset[i].name)) { + return (i); + } + } + NTLOOP(i) + { + if (!strcmp(s, nontrst[i].name)) { + return (i + NTBASE); + } + } + /* cannot find name */ + if (t > 1) + error("%s should have been defined earlier", s); + return (defin(t, s)); +} + +cpyunion() +{ + /* copy the union declaration to the output, and the define file if present */ + + int level, c; + fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile); + fprintf(ftable, "typedef union "); + if (fdefine) + fprintf(fdefine, "\ntypedef union "); + + level = 0; + for (;;) { + if ((c = getc(finput)) < 0) + error("EOF encountered while processing %%union"); + putc(c, ftable); + if (fdefine) + putc(c, fdefine); + + switch (c) { + case '\n': + ++lineno; + break; + + case '{': + ++level; + break; + + case '}': + --level; + if (level == 0) { /* we are finished copying */ + fprintf(ftable, " YYSTYPE;\n"); + if (fdefine) + fprintf(fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n"); + return; + } + } + } +} + +cpycode() +{ /* copies code between \{ and \} */ + register int c; + + c = getc(finput); + if (c == '\n') { + c = getc(finput); + lineno++; + } + fprintf(ftable, "\n# line %d \"%s\"\n", lineno, infile); + while (c >= 0) { + if (c == '\\') + if ((c = getc(finput)) == '}') + return; + else + putc('\\', ftable); + if (c == '%') + if ((c = getc(finput)) == '}') + return; + else + putc('%', ftable); + putc(c, ftable); + if (c == '\n') + ++lineno; + c = getc(finput); + } + error("eof before %%}"); +} + +skipcom() +{ /* skip over comments */ + register int c, i = 0; /* i is the number of lines skipped */ + + /* skipcom is called after reading a / */ + + if (getc(finput) != '*') + error("illegal comment"); + c = getc(finput); + while (c != EOF) { + while (c == '*') { + if ((c = getc(finput)) == '/') + return (i); + } + if (c == '\n') + ++i; + c = getc(finput); + } + error("EOF inside comment"); + /* NOTREACHED */ +} + +cpyact(offset) +{ /* copy C action to the next ; or closing } */ + register int c; + int brac, match, j, s, tok; + + fprintf(faction, "\n# line %d \"%s\"\n", lineno, infile); + + brac = 0; loop: - c = getc(finput); + c = getc(finput); swt: - switch( c ){ + switch (c) { + case ';': + if (brac == 0) { + putc(c, faction); + return; + } + goto lcopy; -case ';': - if( brac == 0 ){ - putc( c , faction ); - return; - } - goto lcopy; + case '{': + brac++; + goto lcopy; -case '{': - brac++; - goto lcopy; + case '$': + s = 1; + tok = -1; + c = getc(finput); + if (c == '<') { /* type description */ + ungetc(c, finput); + if (gettok() != TYPENAME) + error("bad syntax on $ clause"); + tok = numbval; + c = getc(finput); + } + if (c == '$') { + fprintf(faction, "yyval"); + if (ntypes) { /* put out the proper tag... */ + if (tok < 0) + tok = fdtype(*prdptr[nprod]); + fprintf(faction, ".%s", typeset[tok]); + } + goto loop; + } + if (c == '-') { + s = -s; + c = getc(finput); + } + if (isdigit(c)) { + j = 0; + while (isdigit(c)) { + j = j * 10 + c - '0'; + c = getc(finput); + } -case '$': - s = 1; - tok = -1; - c = getc(finput); - if( c == '<' ){ /* type description */ - ungetc( c, finput ); - if( gettok() != TYPENAME ) error( "bad syntax on $ clause" ); - tok = numbval; - c = getc(finput); - } - if( c == '$' ){ - fprintf( faction, "yyval"); - if( ntypes ){ /* put out the proper tag... */ - if( tok < 0 ) tok = fdtype( *prdptr[nprod] ); - fprintf( faction, ".%s", typeset[tok] ); - } - goto loop; - } - if( c == '-' ){ - s = -s; - c = getc(finput); - } - if( isdigit(c) ){ - j=0; - while( isdigit(c) ){ - j= j*10+c-'0'; - c = getc(finput); - } + j = j * s - offset; + if (j > 0) { + error("Illegal use of $%d", j + offset); + } - j = j*s - offset; - if( j > 0 ){ - error( "Illegal use of $%d", j+offset ); - } + fprintf(faction, "yypvt[-%d]", -j); + if (ntypes) { /* put out the proper tag */ + if (j + offset <= 0 && tok < 0) + error("must specify type of $%d", j + offset); + if (tok < 0) + tok = fdtype(prdptr[nprod][j + offset]); + fprintf(faction, ".%s", typeset[tok]); + } + goto swt; + } + putc('$', faction); + if (s < 0) + putc('-', faction); + goto swt; - fprintf( faction, "yypvt[-%d]", -j ); - if( ntypes ){ /* put out the proper tag */ - if( j+offset <= 0 && tok < 0 ) error( "must specify type of $%d", j+offset ); - if( tok < 0 ) tok = fdtype( prdptr[nprod][j+offset] ); - fprintf( faction, ".%s", typeset[tok] ); - } - goto swt; - } - putc( '$' , faction ); - if( s<0 ) putc('-', faction ); - goto swt; + case '}': + if (--brac) + goto lcopy; + putc(c, faction); + return; -case '}': - if( --brac ) goto lcopy; - putc( c, faction ); - return; + case '/': /* look for comments */ + putc(c, faction); + c = getc(finput); + if (c != '*') + goto swt; + /* it really is a comment */ -case '/': /* look for comments */ - putc( c , faction ); - c = getc(finput); - if( c != '*' ) goto swt; + putc(c, faction); + c = getc(finput); + while (c != EOF) { + while (c == '*') { + putc(c, faction); + if ((c = getc(finput)) == '/') + goto lcopy; + } + putc(c, faction); + if (c == '\n') + ++lineno; + c = getc(finput); + } + error("EOF inside comment"); - /* it really is a comment */ + case '\'': /* character constant */ + match = '\''; + goto string; - putc( c , faction ); - c = getc(finput); - while( c != EOF ){ - while( c=='*' ){ - putc( c , faction ); - if( (c=getc(finput)) == '/' ) goto lcopy; - } - putc( c , faction ); - if( c == '\n' )++lineno; - c = getc(finput); - } - error( "EOF inside comment" ); + case '"': /* character string */ + match = '"'; -case '\'': /* character constant */ - match = '\''; - goto string; + string: -case '"': /* character string */ - match = '"'; + putc(c, faction); + while (c = getc(finput)) { + if (c == '\\') { + putc(c, faction); + c = getc(finput); + if (c == '\n') + ++lineno; + } else if (c == match) + goto lcopy; + else if (c == '\n') + error("newline in string or char. const."); + putc(c, faction); + } + error("EOF in string or character constant"); - string: + case EOF: + error("action does not terminate"); - putc( c , faction ); - while( c=getc(finput) ){ - - if( c=='\\' ){ - putc( c , faction ); - c=getc(finput); - if( c == '\n' ) ++lineno; - } - else if( c==match ) goto lcopy; - else if( c=='\n' ) error( "newline in string or char. const." ); - putc( c , faction ); - } - error( "EOF in string or character constant" ); - -case EOF: - error("action does not terminate" ); - -case '\n': ++lineno; - goto lcopy; - - } + case '\n': + ++lineno; + goto lcopy; + } lcopy: - putc( c , faction ); - goto loop; - } + putc(c, faction); + goto loop; +} diff --git a/src/cmd/yacc/y3.c b/src/cmd/yacc/y3.c index 4375231..84ff043 100644 --- a/src/cmd/yacc/y3.c +++ b/src/cmd/yacc/y3.c @@ -1,413 +1,454 @@ -#if !defined(lint) && defined(DOSCCS) -static char sccsid[] = "@(#)y3.c 4.1.1 (2.11BSD) 1995/05/11"; -#endif +#include "dextern.h" -# include "dextern" +/* important local variables */ +int lastred; /* the number of the last reduction of a state */ +int defact[NSTATES]; /* the default actions of states */ - /* important local variables */ -int lastred; /* the number of the last reduction of a state */ -int defact[NSTATES]; /* the default actions of states */ +output() +{ /* print the output for the states */ -output(){ /* print the output for the states */ + int i, k; + register int c; + register struct wset *u, *v; - int i, k; - register int c; - register struct wset *u, *v; + fprintf(ftable, "short yyexca[] ={\n"); - fprintf( ftable, "short yyexca[] ={\n" ); + SLOOP(i) + { /* output the stuff for state i */ + nolook = !(tystate[i] == MUSTLOOKAHEAD); + closure(i); + /* output actions */ + nolook = 1; + aryfil(temp1, ntokens + nnonter + 1, 0); + WSLOOP(wsets, u) + { + c = *(u->pitem); + if (c > 1 && c < NTBASE && temp1[c] == 0) { + WSLOOP(u, v) + { + if (c == *(v->pitem)) + putitem(v->pitem + 1, (struct looksets *)0); + } + temp1[c] = state(c); + } else if (c > NTBASE && temp1[(c -= NTBASE) + ntokens] == 0) { + temp1[c + ntokens] = amem[indgo[i] + c]; + } + } - SLOOP(i) { /* output the stuff for state i */ - nolook = !(tystate[i]==MUSTLOOKAHEAD); - closure(i); - /* output actions */ - nolook = 1; - aryfil( temp1, ntokens+nnonter+1, 0 ); - WSLOOP(wsets,u){ - c = *( u->pitem ); - if( c>1 && cpitem) ) putitem( v->pitem+1, (struct looksets *)0 ); - } - temp1[c] = state(c); - } - else if( c > NTBASE && temp1[ (c -= NTBASE) + ntokens ] == 0 ){ - temp1[ c+ntokens ] = amem[indgo[i]+c]; - } - } + if (i == 1) + temp1[1] = ACCEPTCODE; - if( i == 1 ) temp1[1] = ACCEPTCODE; + /* now, we have the shifts; look at the reductions */ - /* now, we have the shifts; look at the reductions */ + lastred = 0; + WSLOOP(wsets, u) + { + c = *(u->pitem); + if (c <= 0) { /* reduction */ + lastred = -c; + TLOOP(k) + { + if (BIT(u->ws.lset, k)) { + if (temp1[k] == 0) + temp1[k] = c; + else if (temp1[k] < 0) { /* reduce/reduce conflict */ + if (foutput != NULL) + fprintf(foutput, + "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s", i, + -temp1[k], lastred, symnam(k)); + if (-temp1[k] > lastred) + temp1[k] = -lastred; + ++zzrrconf; + } else { /* potential shift/reduce conflict */ + precftn(lastred, k, i); + } + } + } + } + } + wract(i); + } - lastred = 0; - WSLOOP(wsets,u){ - c = *( u->pitem ); - if( c<=0 ){ /* reduction */ - lastred = -c; - TLOOP(k){ - if( BIT(u->ws.lset,k) ){ - if( temp1[k] == 0 ) temp1[k] = c; - else if( temp1[k]<0 ){ /* reduce/reduce conflict */ - if( foutput!=NULL ) - fprintf( foutput, - "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s", - i, -temp1[k], lastred, symnam(k) ); - if( -temp1[k] > lastred ) temp1[k] = -lastred; - ++zzrrconf; - } - else { /* potential shift/reduce conflict */ - precftn( lastred, k, i ); - } - } - } - } - } - wract(i); - } + fprintf(ftable, "\t};\n"); - fprintf( ftable, "\t};\n" ); - - wdef( "YYNPROD", nprod ); - - } + wdef("YYNPROD", nprod); +} int pkdebug = 0; -apack(p, n ) int *p;{ /* pack state i from temp1 into amem */ - int off; - register *pp, *qq, *rr; - int *q, *r; +apack(p, n) int *p; +{ /* pack state i from temp1 into amem */ + int off; + register *pp, *qq, *rr; + int *q, *r; - /* we don't need to worry about checking because we - we will only look entries known to be there... */ + /* we don't need to worry about checking because we + we will only look entries known to be there... */ - /* eliminate leading and trailing 0's */ + /* eliminate leading and trailing 0's */ - q = p+n; - for( pp=p,off=0 ; *pp==0 && pp<=q; ++pp,--off ) /* VOID */ ; - if( pp > q ) return(0); /* no actions */ - p = pp; + q = p + n; + for (pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off) /* VOID */ + ; + if (pp > q) + return (0); /* no actions */ + p = pp; - /* now, find a place for the elements from p to q, inclusive */ + /* now, find a place for the elements from p to q, inclusive */ - r = &amem[ACTSIZE-1]; - for( rr=amem; rr<=r; ++rr,++off ){ /* try rr */ - for( qq=rr,pp=p ; pp<=q ; ++pp,++qq){ - if( *pp != 0 ){ - if( *pp != *qq && *qq != 0 ) goto nextk; - } - } + r = &amem[ACTSIZE - 1]; + for (rr = amem; rr <= r; ++rr, ++off) { /* try rr */ + for (qq = rr, pp = p; pp <= q; ++pp, ++qq) { + if (*pp != 0) { + if (*pp != *qq && *qq != 0) + goto nextk; + } + } - /* we have found an acceptable k */ + /* we have found an acceptable k */ - if( pkdebug && foutput!=NULL ) fprintf( foutput, "off = %d, k = %d\n", off, rr-amem ); + if (pkdebug && foutput != NULL) + fprintf(foutput, "off = %d, k = %d\n", off, rr - amem); - for( qq=rr,pp=p; pp<=q; ++pp,++qq ){ - if( *pp ){ - if( qq > r ) error( "action table overflow" ); - if( qq>memp ) memp = qq; - *qq = *pp; - } - } - if( pkdebug && foutput!=NULL ){ - for( pp=amem; pp<= memp; pp+=10 ){ - fprintf( foutput, "\t"); - for( qq=pp; qq<=pp+9; ++qq ) fprintf( foutput, "%d ", *qq ); - fprintf( foutput, "\n"); - } - } - return( off ); + for (qq = rr, pp = p; pp <= q; ++pp, ++qq) { + if (*pp) { + if (qq > r) + error("action table overflow"); + if (qq > memp) + memp = qq; + *qq = *pp; + } + } + if (pkdebug && foutput != NULL) { + for (pp = amem; pp <= memp; pp += 10) { + fprintf(foutput, "\t"); + for (qq = pp; qq <= pp + 9; ++qq) + fprintf(foutput, "%d ", *qq); + fprintf(foutput, "\n"); + } + } + return (off); - nextk: ; - } - error("no space in action table" ); - /* NOTREACHED */ - } + nextk:; + } + error("no space in action table"); + /* NOTREACHED */ +} -go2out(){ /* output the gotos for the nontermninals */ - register int i, j, k; - int best, count, cbest, times; +go2out() +{ /* output the gotos for the nontermninals */ + register int i, j, k; + int best, count, cbest, times; - fprintf( ftemp, "$\n" ); /* mark begining of gotos */ + fprintf(ftemp, "$\n"); /* mark begining of gotos */ - for( i=1; i<=nnonter; ++i ) { - go2gen(i); + for (i = 1; i <= nnonter; ++i) { + go2gen(i); - /* find the best one to make default */ + /* find the best one to make default */ - best = -1; - times = 0; + best = -1; + times = 0; - for( j=0; j<=nstate; ++j ){ /* is j the most frequent */ - if( tystate[j] == 0 ) continue; - if( tystate[j] == best ) continue; + for (j = 0; j <= nstate; ++j) { /* is j the most frequent */ + if (tystate[j] == 0) + continue; + if (tystate[j] == best) + continue; - /* is tystate[j] the most frequent */ + /* is tystate[j] the most frequent */ - count = 0; - cbest = tystate[j]; + count = 0; + cbest = tystate[j]; - for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count; + for (k = j; k <= nstate; ++k) + if (tystate[k] == cbest) + ++count; - if( count > times ){ - best = cbest; - times = count; - } - } + if (count > times) { + best = cbest; + times = count; + } + } - /* best is now the default entry */ + /* best is now the default entry */ - zzgobest += (times-1); - for( j=0; j<=nstate; ++j ){ - if( tystate[j] != 0 && tystate[j]!=best ){ - fprintf( ftemp, "%d,%d,", j, tystate[j] ); - zzgoent += 1; - } - } + zzgobest += (times - 1); + for (j = 0; j <= nstate; ++j) { + if (tystate[j] != 0 && tystate[j] != best) { + fprintf(ftemp, "%d,%d,", j, tystate[j]); + zzgoent += 1; + } + } - /* now, the default */ + /* now, the default */ - zzgoent += 1; - fprintf( ftemp, "%d\n", best ); - - } - - - - } + zzgoent += 1; + fprintf(ftemp, "%d\n", best); + } +} int g2debug = 0; -go2gen(c){ /* output the gotos for nonterminal c */ +go2gen(c) +{ /* output the gotos for nonterminal c */ - register int i, cc; - int work; - struct item *p, *q; + register int i, cc; + int work; + struct item *p, *q; + /* first, find nonterminals with gotos on c */ - /* first, find nonterminals with gotos on c */ + aryfil(temp1, nnonter + 1, 0); + temp1[c] = 1; - aryfil( temp1, nnonter+1, 0 ); - temp1[c] = 1; + work = 1; + while (work) { + work = 0; + PLOOP(0, i) + { + if ((cc = prdptr[i][1] - NTBASE) >= 0) { /* cc is a nonterminal */ + if (temp1[cc] != 0) { /* cc has a goto on c */ + cc = *prdptr[i] - NTBASE; /* thus, the left side of production i does too */ + if (temp1[cc] == 0) { + work = 1; + temp1[cc] = 1; + } + } + } + } + } - work = 1; - while( work ){ - work = 0; - PLOOP(0,i){ - if( (cc=prdptr[i][1]-NTBASE) >= 0 ){ /* cc is a nonterminal */ - if( temp1[cc] != 0 ){ /* cc has a goto on c */ - cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */ - if( temp1[cc] == 0 ){ - work = 1; - temp1[cc] = 1; - } - } - } - } - } + /* now, we have temp1[c] = 1 if a goto on c in closure of cc */ - /* now, we have temp1[c] = 1 if a goto on c in closure of cc */ + if (g2debug && foutput != NULL) { + fprintf(foutput, "%s: gotos on ", nontrst[c].name); + NTLOOP(i) if (temp1[i]) fprintf(foutput, "%s ", nontrst[i].name); + fprintf(foutput, "\n"); + } - if( g2debug && foutput!=NULL ){ - fprintf( foutput, "%s: gotos on ", nontrst[c].name ); - NTLOOP(i) if( temp1[i] ) fprintf( foutput, "%s ", nontrst[i].name); - fprintf( foutput, "\n"); - } + /* now, go through and put gotos into tystate */ - /* now, go through and put gotos into tystate */ + aryfil(tystate, nstate, 0); + SLOOP(i) + { + ITMLOOP(i, p, q) + { + if ((cc = *p->pitem) >= NTBASE) { + if (temp1[cc -= NTBASE]) { /* goto on c is possible */ + tystate[i] = amem[indgo[i] + c]; + break; + } + } + } + } +} - aryfil( tystate, nstate, 0 ); - SLOOP(i){ - ITMLOOP(i,p,q){ - if( (cc= *p->pitem) >= NTBASE ){ - if( temp1[cc -= NTBASE] ){ /* goto on c is possible */ - tystate[i] = amem[indgo[i]+c]; - break; - } - } - } - } - } +precftn(r, t, s) register int t; +{ /* decide a shift/reduce conflict by precedence. +/* r is a rule number, t a token number */ + /* the conflict is in state s */ + /* temp1[t] is changed to reflect the action */ -precftn(r,t,s) register int t; - { /* decide a shift/reduce conflict by precedence. - /* r is a rule number, t a token number */ - /* the conflict is in state s */ - /* temp1[t] is changed to reflect the action */ + int lp, lt, action; - int lp,lt, action; + lp = levprd[r]; + lt = toklev[t]; + if (PLEVEL(lt) == 0 || PLEVEL(lp) == 0) { + /* conflict */ + if (foutput != NULL) + fprintf(foutput, "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", s, temp1[t], + r, symnam(t)); + ++zzsrconf; + return; + } + if (PLEVEL(lt) == PLEVEL(lp)) + action = ASSOC(lt); + else if (PLEVEL(lt) > PLEVEL(lp)) + action = RASC; /* shift */ + else + action = LASC; /* reduce */ - lp = levprd[r]; - lt = toklev[t]; - if( PLEVEL(lt) == 0 || PLEVEL(lp) == 0 ) { - /* conflict */ - if( foutput != NULL ) fprintf( foutput, "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", - s, temp1[t], r, symnam(t) ); - ++zzsrconf; - return; - } - if( PLEVEL(lt) == PLEVEL(lp) ) action = ASSOC(lt); - else if( PLEVEL(lt) > PLEVEL(lp) ) action = RASC; /* shift */ - else action = LASC; /* reduce */ + switch (action) { + case BASC: /* error action */ + temp1[t] = ERRCODE; + return; - switch( action ){ + case LASC: /* reduce */ + temp1[t] = -r; + return; + } +} - case BASC: /* error action */ - temp1[t] = ERRCODE; - return; +wract(i) register int i; +{ /* output state i */ + /* temp1 has the actions, lastred the default */ + int p, p0, p1; + int ntimes, tred, count; + register int j; + int flag; - case LASC: /* reduce */ - temp1[t] = -r; - return; + /* find the best choice for lastred */ - } - } + lastred = 0; + ntimes = 0; + TLOOP(j) + { + if (temp1[j] >= 0) + continue; + if (temp1[j] + lastred == 0) + continue; + /* count the number of appearances of temp1[j] */ + count = 0; + tred = -temp1[j]; + levprd[tred] |= REDFLAG; + TLOOP(p) + { + if (temp1[p] + tred == 0) + ++count; + } + if (count > ntimes) { + lastred = tred; + ntimes = count; + } + } -wract(i) register int i; { /* output state i */ - /* temp1 has the actions, lastred the default */ - int p, p0, p1; - int ntimes, tred, count; - register int j; - int flag; + /* for error recovery, arrange that, if there is a shift on the + /* error recovery token, `error', that the default be the error action */ + if (temp1[1] > 0) + lastred = 0; - /* find the best choice for lastred */ + /* clear out entries in temp1 which equal lastred */ + TLOOP(p) if (temp1[p] + lastred == 0) temp1[p] = 0; - lastred = 0; - ntimes = 0; - TLOOP(j){ - if( temp1[j] >= 0 ) continue; - if( temp1[j]+lastred == 0 ) continue; - /* count the number of appearances of temp1[j] */ - count = 0; - tred = -temp1[j]; - levprd[tred] |= REDFLAG; - TLOOP(p){ - if( temp1[p]+tred == 0 ) ++count; - } - if( count >ntimes ){ - lastred = tred; - ntimes = count; - } - } + wrstate(i); + defact[i] = lastred; - /* for error recovery, arrange that, if there is a shift on the - /* error recovery token, `error', that the default be the error action */ - if( temp1[1] > 0 ) lastred = 0; + flag = 0; + TLOOP(p0) + { + if ((p1 = temp1[p0]) != 0) { + if (p1 < 0) { + p1 = -p1; + goto exc; + } else if (p1 == ACCEPTCODE) { + p1 = -1; + goto exc; + } else if (p1 == ERRCODE) { + p1 = 0; + goto exc; + exc: + if (flag++ == 0) + fprintf(ftable, "-1, %d,\n", i); + fprintf(ftable, "\t%d, %d,\n", tokset[p0].value, p1); + ++zzexcp; + } else { + fprintf(ftemp, "%d,%d,", tokset[p0].value, p1); + ++zzacent; + } + } + } + if (flag) { + defact[i] = -2; + fprintf(ftable, "\t-2, %d,\n", lastred); + } + fprintf(ftemp, "\n"); + return; +} - /* clear out entries in temp1 which equal lastred */ - TLOOP(p) if( temp1[p]+lastred == 0 )temp1[p]=0; +wrstate(i) +{ /* writes state i */ + register j0, j1; + register struct item *pp, *qq; + register struct wset *u; - wrstate(i); - defact[i] = lastred; + if (foutput == NULL) + return; + fprintf(foutput, "\nstate %d\n", i); + ITMLOOP(i, pp, qq) fprintf(foutput, "\t%s\n", writem(pp->pitem)); + if (tystate[i] == MUSTLOOKAHEAD) { + /* print out empty productions in closure */ + WSLOOP(wsets + (pstate[i + 1] - pstate[i]), u) + { + if (*(u->pitem) < 0) + fprintf(foutput, "\t%s\n", writem(u->pitem)); + } + } - flag = 0; - TLOOP(p0){ - if( (p1=temp1[p0])!=0 ) { - if( p1 < 0 ){ - p1 = -p1; - goto exc; - } - else if( p1 == ACCEPTCODE ) { - p1 = -1; - goto exc; - } - else if( p1 == ERRCODE ) { - p1 = 0; - goto exc; - exc: - if( flag++ == 0 ) fprintf( ftable, "-1, %d,\n", i ); - fprintf( ftable, "\t%d, %d,\n", tokset[p0].value, p1 ); - ++zzexcp; - } - else { - fprintf( ftemp, "%d,%d,", tokset[p0].value, p1 ); - ++zzacent; - } - } - } - if( flag ) { - defact[i] = -2; - fprintf( ftable, "\t-2, %d,\n", lastred ); - } - fprintf( ftemp, "\n" ); - return; - } + /* check for state equal to another */ -wrstate(i){ /* writes state i */ - register j0,j1; - register struct item *pp, *qq; - register struct wset *u; + TLOOP(j0) if ((j1 = temp1[j0]) != 0) + { + fprintf(foutput, "\n\t%s ", symnam(j0)); + if (j1 > 0) { /* shift, error, or accept */ + if (j1 == ACCEPTCODE) + fprintf(foutput, "accept"); + else if (j1 == ERRCODE) + fprintf(foutput, "error"); + else + fprintf(foutput, "shift %d", j1); + } else + fprintf(foutput, "reduce %d", -j1); + } - if( foutput == NULL ) return; - fprintf( foutput, "\nstate %d\n",i); - ITMLOOP(i,pp,qq) fprintf( foutput, "\t%s\n", writem(pp->pitem)); - if( tystate[i] == MUSTLOOKAHEAD ){ - /* print out empty productions in closure */ - WSLOOP( wsets+(pstate[i+1]-pstate[i]), u ){ - if( *(u->pitem) < 0 ) fprintf( foutput, "\t%s\n", writem(u->pitem) ); - } - } + /* output the final production */ - /* check for state equal to another */ + if (lastred) + fprintf(foutput, "\n\t. reduce %d\n\n", lastred); + else + fprintf(foutput, "\n\t. error\n\n"); - TLOOP(j0) if( (j1=temp1[j0]) != 0 ){ - fprintf( foutput, "\n\t%s ", symnam(j0) ); - if( j1>0 ){ /* shift, error, or accept */ - if( j1 == ACCEPTCODE ) fprintf( foutput, "accept" ); - else if( j1 == ERRCODE ) fprintf( foutput, "error" ); - else fprintf( foutput, "shift %d", j1 ); - } - else fprintf( foutput, "reduce %d",-j1 ); - } + /* now, output nonterminal actions */ - /* output the final production */ + j1 = ntokens; + for (j0 = 1; j0 <= nnonter; ++j0) { + if (temp1[++j1]) + fprintf(foutput, "\t%s goto %d\n", symnam(j0 + NTBASE), temp1[j1]); + } +} - if( lastred ) fprintf( foutput, "\n\t. reduce %d\n\n", lastred ); - else fprintf( foutput, "\n\t. error\n\n" ); +wdef(s, n) char *s; +{ /* output a definition of s to the value n */ + fprintf(ftable, "# define %s %d\n", s, n); +} - /* now, output nonterminal actions */ +warray(s, v, n) char *s; +int *v, n; +{ + register i; - j1 = ntokens; - for( j0 = 1; j0 <= nnonter; ++j0 ){ - if( temp1[++j1] ) fprintf( foutput, "\t%s goto %d\n", symnam( j0+NTBASE), temp1[j1] ); - } + fprintf(ftable, "short %s[]={\n", s); + for (i = 0; i < n;) { + if (i % 10 == 0) + fprintf(ftable, "\n"); + fprintf(ftable, "%4d", v[i]); + if (++i == n) + fprintf(ftable, " };\n"); + else + fprintf(ftable, ","); + } +} - } +hideprod() +{ + /* in order to free up the mem and amem arrays for the optimizer, + /* and still be able to output yyr1, etc., after the sizes of + /* the action array is known, we hide the nonterminals + /* derived by productions in levprd. + */ -wdef( s, n ) char *s; { /* output a definition of s to the value n */ - fprintf( ftable, "# define %s %d\n", s, n ); - } + register i, j; -warray( s, v, n ) char *s; int *v, n; { - - register i; - - fprintf( ftable, "short %s[]={\n", s ); - for( i=0; i j ) j = *p; - if( *p < k ) k = *p; - } - if( k <= j ){ /* nontrivial situation */ - /* temporarily, kill this for compatibility - j -= k; /* j is now the range */ - if( k > maxoff ) maxoff = k; - } - greed[i] = (yypact[i+1]-yypact[i]) + 2*j; - if( j > maxspr ) maxspr = j; - } - - /* initialize ggreed table */ - - for( i=1; i<=nnonter; ++i ){ - ggreed[i] = 1; - j = 0; - /* minimum entry index is always 0 */ - q = mem + yypgo[i+1] -1; - for( p = mem+yypgo[i]; p j ) j = *p; - } - ggreed[i] = ggreed[i] + 2*j; - if( j > maxoff ) maxoff = j; - } - - - /* now, prepare to put the shift actions into the a array */ - - for( i=0; i1 ) fprintf( ftable, "State %d: null\n", i ); - pa[i] = YYFLAG1; - } - - while( (i = nxti()) != NOMORE ) { - if( i >= 0 ) stin(i); - else gin(-i); - - } - - if( adb>2 ){ /* print a array */ - for( p=a; p <= maxa; p += 10){ - fprintf( ftable, "%4d ", p-a ); - for( i=0; i<10; ++i ) fprintf( ftable, "%4d ", p[i] ); - fprintf( ftable, "\n" ); - } - } - /* write out the output appropriate to the language */ - - aoutput(); - - osummary(); - ZAPFILE(TEMPNAME); - } - -gin(i){ - - register *p, *r, *s, *q1, *q2; - - /* enter gotos on nonterminal i into array a */ - - ggreed[i] = 0; - - q2 = mem+ yypgo[i+1] - 1; - q1 = mem + yypgo[i]; - - /* now, find a place for it */ - - for( p=a; p < &a[ACTSIZE]; ++p ){ - if( *p ) continue; - for( r=q1; r maxa ){ - if( (maxa=s) > &a[ACTSIZE] ) error( "a array overflow" ); - } - } - /* we have found a spot */ - - *p = *q2; - if( p > maxa ){ - if( (maxa=p) > &a[ACTSIZE] ) error( "a array overflow" ); - } - for( r=q1; r1 ) fprintf( ftable, "Nonterminal %d, entry at %d\n" , i, pgo[i] ); - goto nextgi; - - nextgp: ; - } - - error( "cannot place goto %d\n", i ); - - nextgi: ; - } - -stin(i){ - register *r, *s, n, flag, j, *q1, *q2; - - greed[i] = 0; - - /* enter state i into the a array */ - - q2 = mem+yypact[i+1]; - q1 = mem+yypact[i]; - /* find an acceptable place */ - - for( n= -maxoff; n1 ) fprintf( ftable, "State %d: entry at %d equals state %d\n", - i, n, j ); - return; - } - goto nextn; /* we have some disagreement */ - } - } - - for( r = q1; r < q2; r += 2 ){ - if( (s = *r + n + a ) >= &a[ACTSIZE] ) error( "out of space in optimizer a array" ); - if( s > maxa ) maxa = s; - if( *s != 0 && *s != r[1] ) error( "clobber of a array, pos'n %d, by %d", s-a, r[1] ); - *s = r[1]; - } - pa[i] = n; - if( adb>1 ) fprintf( ftable, "State %d: entry at %d\n", i, pa[i] ); - return; - - nextn: ; - } - - error( "Error; failure to place state %d\n", i ); - - } - -nxti(){ /* finds the next i */ - register i, max, maxi; - - max = 0; - - for( i=1; i<= nnonter; ++i ) if( ggreed[i] >= max ){ - max = ggreed[i]; - maxi = -i; - } - - for( i=0; i= max ){ - max = greed[i]; - maxi = i; - } - - if( nxdb ) fprintf( ftable, "nxti = %d, max = %d\n", maxi, max ); - if( max==0 ) return( NOMORE ); - else return( maxi ); - } - -osummary(){ - /* write summary */ - - register i, *p; - - if( foutput == NULL ) return; - i=0; - for( p=maxa; p>=a; --p ) { - if( *p == 0 ) ++i; - } - - fprintf( foutput, "Optimizer space used: input %d/%d, output %d/%d\n", - pmem-mem+1, MEMSIZE, maxa-a+1, ACTSIZE ); - fprintf( foutput, "%d table entries, %d zero\n", (maxa-a)+1, i ); - fprintf( foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff ); - - } - -aoutput(){ /* this version is for C */ - - - /* write out the optimized parser */ - - fprintf( ftable, "# define YYLAST %d\n", maxa-a+1 ); - - arout( "yyact", a, (maxa-a)+1 ); - arout( "yypact", pa, nstate ); - arout( "yypgo", pgo, nnonter+1 ); - - } - -arout( s, v, n ) char *s; int *v, n; { - - register i; - - fprintf( ftable, "short %s[]={\n", s ); - for( i=0; i &mem[MEMSIZE] ) error( "out of space" ); - return( c ); - - } +callopt() +{ + register i, *p, j, k, *q; + + /* read the arrays from tempfile and set parameters */ + + if ((finput = fopen(TEMPNAME, "r")) == NULL) + error("optimizer cannot open tempfile"); + + pgo[0] = 0; + yypact[0] = 0; + nstate = 0; + nnonter = 0; + for (;;) { + switch (gtnm()) { + case '\n': + yypact[++nstate] = (--pmem) - mem; + case ',': + continue; + + case '$': + break; + + default: + error("bad tempfile"); + } + break; + } + + yypact[nstate] = yypgo[0] = (--pmem) - mem; + + for (;;) { + switch (gtnm()) { + case '\n': + yypgo[++nnonter] = pmem - mem; + case ',': + continue; + + case EOF: + break; + + default: + error("bad tempfile"); + } + break; + } + + yypgo[nnonter--] = (--pmem) - mem; + + for (i = 0; i < nstate; ++i) { + k = 32000; + j = 0; + q = mem + yypact[i + 1]; + for (p = mem + yypact[i]; p < q; p += 2) { + if (*p > j) + j = *p; + if (*p < k) + k = *p; + } + if (k <= j) { /* nontrivial situation */ + /* temporarily, kill this for compatibility + j -= k; /* j is now the range */ + if (k > maxoff) + maxoff = k; + } + greed[i] = (yypact[i + 1] - yypact[i]) + 2 * j; + if (j > maxspr) + maxspr = j; + } + + /* initialize ggreed table */ + + for (i = 1; i <= nnonter; ++i) { + ggreed[i] = 1; + j = 0; + /* minimum entry index is always 0 */ + q = mem + yypgo[i + 1] - 1; + for (p = mem + yypgo[i]; p < q; p += 2) { + ggreed[i] += 2; + if (*p > j) + j = *p; + } + ggreed[i] = ggreed[i] + 2 * j; + if (j > maxoff) + maxoff = j; + } + + /* now, prepare to put the shift actions into the a array */ + + for (i = 0; i < ACTSIZE; ++i) + a[i] = 0; + maxa = a; + + for (i = 0; i < nstate; ++i) { + if (greed[i] == 0 && adb > 1) + fprintf(ftable, "State %d: null\n", i); + pa[i] = YYFLAG1; + } + + while ((i = nxti()) != NOMORE) { + if (i >= 0) + stin(i); + else + gin(-i); + } + + if (adb > 2) { /* print a array */ + for (p = a; p <= maxa; p += 10) { + fprintf(ftable, "%4d ", p - a); + for (i = 0; i < 10; ++i) + fprintf(ftable, "%4d ", p[i]); + fprintf(ftable, "\n"); + } + } + /* write out the output appropriate to the language */ + + aoutput(); + + osummary(); + ZAPFILE(TEMPNAME); +} + +gin(i) +{ + register *p, *r, *s, *q1, *q2; + + /* enter gotos on nonterminal i into array a */ + + ggreed[i] = 0; + + q2 = mem + yypgo[i + 1] - 1; + q1 = mem + yypgo[i]; + + /* now, find a place for it */ + + for (p = a; p < &a[ACTSIZE]; ++p) { + if (*p) + continue; + for (r = q1; r < q2; r += 2) { + s = p + *r + 1; + if (*s) + goto nextgp; + if (s > maxa) { + if ((maxa = s) > &a[ACTSIZE]) + error("a array overflow"); + } + } + /* we have found a spot */ + + *p = *q2; + if (p > maxa) { + if ((maxa = p) > &a[ACTSIZE]) + error("a array overflow"); + } + for (r = q1; r < q2; r += 2) { + s = p + *r + 1; + *s = r[1]; + } + + pgo[i] = p - a; + if (adb > 1) + fprintf(ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]); + goto nextgi; + + nextgp:; + } + + error("cannot place goto %d\n", i); + +nextgi:; +} + +stin(i) +{ + register *r, *s, n, flag, j, *q1, *q2; + + greed[i] = 0; + + /* enter state i into the a array */ + + q2 = mem + yypact[i + 1]; + q1 = mem + yypact[i]; + /* find an acceptable place */ + + for (n = -maxoff; n < ACTSIZE; ++n) { + flag = 0; + for (r = q1; r < q2; r += 2) { + if ((s = *r + n + a) < a) + goto nextn; + if (*s == 0) + ++flag; + else if (*s != r[1]) + goto nextn; + } + + /* check that the position equals another only if the states are identical */ + + for (j = 0; j < nstate; ++j) { + if (pa[j] == n) { + if (flag) + goto nextn; /* we have some disagreement */ + if (yypact[j + 1] + yypact[i] == yypact[j] + yypact[i + 1]) { + /* states are equal */ + pa[i] = n; + if (adb > 1) + fprintf(ftable, "State %d: entry at %d equals state %d\n", i, n, j); + return; + } + goto nextn; /* we have some disagreement */ + } + } + + for (r = q1; r < q2; r += 2) { + if ((s = *r + n + a) >= &a[ACTSIZE]) + error("out of space in optimizer a array"); + if (s > maxa) + maxa = s; + if (*s != 0 && *s != r[1]) + error("clobber of a array, pos'n %d, by %d", s - a, r[1]); + *s = r[1]; + } + pa[i] = n; + if (adb > 1) + fprintf(ftable, "State %d: entry at %d\n", i, pa[i]); + return; + + nextn:; + } + + error("Error; failure to place state %d\n", i); +} + +nxti() +{ /* finds the next i */ + register i, max, maxi; + + max = 0; + + for (i = 1; i <= nnonter; ++i) + if (ggreed[i] >= max) { + max = ggreed[i]; + maxi = -i; + } + + for (i = 0; i < nstate; ++i) + if (greed[i] >= max) { + max = greed[i]; + maxi = i; + } + + if (nxdb) + fprintf(ftable, "nxti = %d, max = %d\n", maxi, max); + if (max == 0) + return (NOMORE); + else + return (maxi); +} + +osummary() +{ + /* write summary */ + + register i, *p; + + if (foutput == NULL) + return; + i = 0; + for (p = maxa; p >= a; --p) { + if (*p == 0) + ++i; + } + + fprintf(foutput, "Optimizer space used: input %d/%d, output %d/%d\n", pmem - mem + 1, MEMSIZE, + maxa - a + 1, ACTSIZE); + fprintf(foutput, "%d table entries, %d zero\n", (maxa - a) + 1, i); + fprintf(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff); +} + +aoutput() +{ /* this version is for C */ + + /* write out the optimized parser */ + + fprintf(ftable, "# define YYLAST %d\n", maxa - a + 1); + + arout("yyact", a, (maxa - a) + 1); + arout("yypact", pa, nstate); + arout("yypgo", pgo, nnonter + 1); +} + +arout(s, v, n) char *s; +int *v, n; +{ + register i; + + fprintf(ftable, "short %s[]={\n", s); + for (i = 0; i < n;) { + if (i % 10 == 0) + fprintf(ftable, "\n"); + fprintf(ftable, "%4d", v[i]); + if (++i == n) + fprintf(ftable, " };\n"); + else + fprintf(ftable, ","); + } +} + +gtnm() +{ + register s, val, c; + + /* read and convert an integer from the standard input */ + /* return the terminating character */ + /* blanks, tabs, and newlines are ignored */ + + s = 1; + val = 0; + + while ((c = getc(finput)) != EOF) { + if (isdigit(c)) { + val = val * 10 + c - '0'; + } else if (c == '-') + s = -1; + else + break; + } + + *pmem++ = s * val; + if (pmem > &mem[MEMSIZE]) + error("out of space"); + return (c); +} diff --git a/src/cmd/yacc/yaccpar b/src/cmd/yacc/yaccpar deleted file mode 100644 index a37c24f..0000000 --- a/src/cmd/yacc/yaccpar +++ /dev/null @@ -1,153 +0,0 @@ -#if !defined(lint) && defined(DOSCCS) -static char yaccpar_sccsid[] = "@(#)yaccpar 4.1 (Berkeley) 2/11/83"; -#endif - -# -# define YYFLAG -1000 -# define YYERROR goto yyerrlab -# define YYACCEPT return(0) -# define YYABORT return(1) - -/* parser for yacc output */ - -#ifdef YYDEBUG -int yydebug = 0; /* 1 for debugging */ -#endif -YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ -int yychar = -1; /* current input token number */ -int yynerrs = 0; /* number of errors */ -short yyerrflag = 0; /* error recovery flag */ - -yyparse() { - - short yys[YYMAXDEPTH]; - short yyj, yym; - register YYSTYPE *yypvt; - register short yystate, *yyps, yyn; - register YYSTYPE *yypv; - register short *yyxi; - - yystate = 0; - yychar = -1; - yynerrs = 0; - yyerrflag = 0; - yyps= &yys[-1]; - yypv= &yyv[-1]; - - yystack: /* put a state and value onto the stack */ - -#ifdef YYDEBUG - if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar ); -#endif - if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } - *yyps = yystate; - ++yypv; - *yypv = yyval; - - yynewstate: - - yyn = yypact[yystate]; - - if( yyn<= YYFLAG ) goto yydefault; /* simple state */ - - if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; - if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; - - if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ - yychar = -1; - yyval = yylval; - yystate = yyn; - if( yyerrflag > 0 ) --yyerrflag; - goto yystack; - } - - yydefault: - /* default state action */ - - if( (yyn=yydef[yystate]) == -2 ) { - if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; - /* look through exception table */ - - for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ - - while( *(yyxi+=2) >= 0 ){ - if( *yyxi == yychar ) break; - } - if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ - } - - if( yyn == 0 ){ /* error */ - /* error ... attempt to resume parsing */ - - switch( yyerrflag ){ - - case 0: /* brand new error */ - - yyerror( "syntax error" ); - yyerrlab: - ++yynerrs; - - case 1: - case 2: /* incompletely recovered error ... try again */ - - yyerrflag = 3; - - /* find a state where "error" is a legal shift action */ - - while ( yyps >= yys ) { - yyn = yypact[*yyps] + YYERRCODE; - if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ - yystate = yyact[yyn]; /* simulate a shift of "error" */ - goto yystack; - } - yyn = yypact[*yyps]; - - /* the current yyps has no shift onn "error", pop stack */ - -#ifdef YYDEBUG - if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); -#endif - --yyps; - --yypv; - } - - /* there is no state on the stack with an error shift ... abort */ - - yyabort: - return(1); - - - case 3: /* no shift yet; clobber input char */ - -#ifdef YYDEBUG - if( yydebug ) printf( "error recovery discards char %d\n", yychar ); -#endif - - if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ - yychar = -1; - goto yynewstate; /* try again in the same state */ - - } - - } - - /* reduction by production yyn */ - -#ifdef YYDEBUG - if( yydebug ) printf("reduce %d\n",yyn); -#endif - yyps -= yyr2[yyn]; - yypvt = yypv; - yypv -= yyr2[yyn]; - yyval = yypv[1]; - yym=yyn; - /* consult goto table to find next state */ - yyn = yyr1[yyn]; - yyj = yypgo[yyn] + *yyps + 1; - if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; - switch(yym){ - $A - } - goto yystack; /* stack new state and value */ - - } diff --git a/src/cmd/yacc/yaccpar.c b/src/cmd/yacc/yaccpar.c new file mode 100644 index 0000000..d16a783 --- /dev/null +++ b/src/cmd/yacc/yaccpar.c @@ -0,0 +1,163 @@ +/* parser for yacc output */ + +#define YYFLAG -1000 +#define YYERROR goto yyerrlab +#define YYACCEPT return (0) +#define YYABORT return (1) + +#ifdef YYDEBUG +int yydebug = 0; /* 1 for debugging */ +#endif + +YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ +int yychar = -1; /* current input token number */ +int yynerrs = 0; /* number of errors */ +short yyerrflag = 0; /* error recovery flag */ + +yyparse() +{ + short yys[YYMAXDEPTH]; + short yyj, yym; + register YYSTYPE *yypvt; + register short yystate, *yyps, yyn; + register YYSTYPE *yypv; + register short *yyxi; + + yystate = 0; + yychar = -1; + yynerrs = 0; + yyerrflag = 0; + yyps = &yys[-1]; + yypv = &yyv[-1]; + +yystack: /* put a state and value onto the stack */ + +#ifdef YYDEBUG + if (yydebug) + printf("state %d, char 0%o\n", yystate, yychar); +#endif + if (++yyps > &yys[YYMAXDEPTH]) { + yyerror("yacc stack overflow"); + return (1); + } + *yyps = yystate; + ++yypv; + *yypv = yyval; + +yynewstate: + + yyn = yypact[yystate]; + + if (yyn <= YYFLAG) + goto yydefault; /* simple state */ + + if (yychar < 0) + if ((yychar = yylex()) < 0) + yychar = 0; + if ((yyn += yychar) < 0 || yyn >= YYLAST) + goto yydefault; + + if (yychk[yyn = yyact[yyn]] == yychar) { /* valid shift */ + yychar = -1; + yyval = yylval; + yystate = yyn; + if (yyerrflag > 0) + --yyerrflag; + goto yystack; + } + +yydefault: + /* default state action */ + + if ((yyn = yydef[yystate]) == -2) { + if (yychar < 0) + if ((yychar = yylex()) < 0) + yychar = 0; + /* look through exception table */ + + for (yyxi = yyexca; (*yyxi != (-1)) || (yyxi[1] != yystate); yyxi += 2) + ; /* VOID */ + + while (*(yyxi += 2) >= 0) { + if (*yyxi == yychar) + break; + } + if ((yyn = yyxi[1]) < 0) + return (0); /* accept */ + } + + if (yyn == 0) { /* error */ + /* error ... attempt to resume parsing */ + + switch (yyerrflag) { + case 0: /* brand new error */ + + yyerror("syntax error"); + yyerrlab: + ++yynerrs; + + case 1: + case 2: /* incompletely recovered error ... try again */ + + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + + while (yyps >= yys) { + yyn = yypact[*yyps] + YYERRCODE; + if (yyn >= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE) { + yystate = yyact[yyn]; /* simulate a shift of "error" */ + goto yystack; + } + yyn = yypact[*yyps]; + + /* the current yyps has no shift onn "error", pop stack */ + +#ifdef YYDEBUG + if (yydebug) + printf("error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1]); +#endif + --yyps; + --yypv; + } + + /* there is no state on the stack with an error shift ... abort */ + + yyabort: + return (1); + + case 3: /* no shift yet; clobber input char */ + +#ifdef YYDEBUG + if (yydebug) + printf("error recovery discards char %d\n", yychar); +#endif + + if (yychar == 0) + goto yyabort; /* don't discard EOF, quit */ + yychar = -1; + goto yynewstate; /* try again in the same state */ + } + } + + /* reduction by production yyn */ + +#ifdef YYDEBUG + if (yydebug) + printf("reduce %d\n", yyn); +#endif + yyps -= yyr2[yyn]; + yypvt = yypv; + yypv -= yyr2[yyn]; + yyval = yypv[1]; + yym = yyn; + /* consult goto table to find next state */ + yyn = yyr1[yyn]; + yyj = yypgo[yyn] + *yyps + 1; + if (yyj >= YYLAST || yychk[yystate = yyact[yyj]] != -yyn) + yystate = yyact[yypgo[yyn]]; + switch (yym) { + $A + } + goto yystack; /* stack new state and value */ +}