# include # include "y.h" extern FILE *Fin; extern FILE *Fout; /* ** * * * * y a c c * * * * ** ** features to be fixed up ... ** ** Print estimate of total space needed for parser ** Either list inputs on y.output, or list empty prdn's in states ** Mention nonterms not used (or, rules. not reduced) as nonfatal error ** Output states where conflicts were found by default on y.output ** Engage in newspeak: production=>grammar rules, term=>token, etc. ** handle # define, #ifdef, etc., in yacc actions, %{ %} ** ** ** new features to be added ** ** reductions by single productions (by request) ** follow sets for start symbol ** option to only do slr(1) ** easily changed array names on output ** allocate core, rather than predefined ** input controlled by a grammar ** support multiple choices for conflicts ** better conflict diagnostics */ main(argc, argv) int argc; char *argv[]; { Fin = stdin; Fout = stdout; setup(argc, argv); /* initialize and read productions */ tbitset = (nterms + 16) / 16; cpres(); /* make table of which productions yield a given nonterminal */ cempty(); /* make a table of which nonterminals can match the empty string */ cpfir(); /* make a table of e free first lists */ stagen(); /* generate the states */ output(); /* write the states and the tables */ go2out(); summary(); windup(); } windup() { /* no errors */ cflush(stdout); cexit(0); } settty() { /* sets the output file to y.output */ cflush(Foutput); /* a bit of a cheat */ cout = Foutput; } settab() { /* sets the output file to y.tab.c */ cflush(ftable); cout = ftable; } char *chcopy(p, q) register char *p; register char *q; { /* copies string q into p, returning next free char ptr */ while(*p = *q++) ++p; return (p); } char *writem(pp) register struct item *pp; { /* creates output string for item pointed to by pp */ register int i; register int *p; register char *q; static char sarr[100]; extern char *symnam(); for(p = pp->pitem; *p > 0 ; ++p) ; p = prdptr[-*p]; q = chcopy(sarr, nontrst[*p-NTBASE].name); q = chcopy(q, " : "); for( ; ; ) { *q++ = ++p == (pp->pitem)? '_': ' '; if ((i = *p) <= 0) break; q = chcopy(q, symnam(i)); } *q = '\0' ; return (sarr); } char *symnam(i) register int i; { /* return a pointer to the name of symbol i */ register char *cp; cp = (i >= NTBASE)? nontrst[i-NTBASE].name: trmset[i].name ; if (*cp == ' ') ++cp; return (cp); } summary() { /* output the summary on the tty */ register int i; register int *pn; if (!sflag) { settab(); fprintf(Fout, "\nint\t\tnterms = %d;", nterms); fprintf(Fout, "\nint\t\tnnonter = %d;", nnonter); fprintf(Fout, "\nint\t\tnstate = %d;", nstate); fprintf(Fout, "\nchar\t\t*yysterm[] =\n{"); for (i = 1; i <= nterms; i++) if (trmset[i].value >= 0400) fprintf(Fout, "\n\t\"%s\",", symnam(i)); fprintf(Fout, "\n\t(char *) 0\n};\n"); fprintf(Fout, "\nchar\t\t*yysnter[] =\n{"); for (i = 0; i < nnonter; i++) fprintf(Fout, "\n\t\"%s\",", nontrst[i].name); fprintf(Fout, "\n\t\"%s\"\n};\n", nontrst[nnonter].name); } settty(); fprintf(Fout, "\n%d/%d terminals, %d/%d nonterminals\n", nterms, tlim, nnonter, ntlim); fprintf(Fout, "%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize); fprintf(Fout, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf); pn = (int *) pstate[nstate + 1]; fprintf(Fout, "%d/%d working sets used\n", zzcwset, wssize); fprintf(Fout, "memory: states, etc. %d/%d, parser %d/%d\n", pn - mem0, memsiz, memact, actsiz); fprintf(Fout, "%d/%d distinct lookahead sets\n", nlset, lsetsz); fprintf(Fout, "%d extra closures\n", zzclose - 2 * nstate); fprintf(Fout, "%d action entries\n", zzacent); fprintf(Fout, "%d action entries saved through merging %d states\n", zzacsave, zznsave); fprintf(Fout, "%d goto entries\n", zzgoent); fprintf(Fout, "%d entries saved by goto default\n", zzgobest); if (zzsrconf != 0 || zzrrconf != 0) { cflush(stderr); cout = stderr; fprintf(Fout, "\nconflicts: "); if (zzsrconf) fprintf(Fout, "%d shift/reduce" , zzsrconf); if (zzsrconf && zzrrconf) fprintf(Fout, ", "); if (zzrrconf) fprintf(Fout, "%d reduce/reduce" , zzrrconf); fprintf(Fout, "\n"); } } error(s, a1) register char *s; register char *a1; { /* write out error comment */ ++nerrors; cflush(stderr); cout = stderr; /* set output to tty */ fprintf(Fout, "\n fatal error: "); fprintf(Fout, s, a1); fprintf(Fout, ", line %d\n", lineno); if (!fatfl) return; summary(); cexit(1); } arrset(s) register char *s; { fprintf(Fout, "\nshort\t%s[] =\n{\n\t0", s); arrndx = 1; } arrval(n) register int n; { fprintf(Fout, ",\t%d", n); if ((++arrndx % 8) == 0) fprintf(Fout, "\n"); } arrdone() { fprintf(Fout, ",\t-1\n};\n"); } copy(v) register char *v; { /* copy ctokn to v */ register char *p; p = ctokn; while (*v++ = *p++) ; } compare(v) register char *v; { /* compare ctokn with v */ register char *p; for (p = ctokn; ; ++p) { if (*p != *v++) return (0); if (*p == 0) return (1); } } int *yalloc(n) register int n; { /* allocate n + 1 words from vector mem */ register int *omem; omem = mem; mem += n + 1; if (mem - mem0 >= memsiz) error("memory overflow"); return (omem); } aryfil(v, n, c) register int *v; register int n; register int c; { /* set elements 0 through n-1 to c */ register int i; for(i = 0; i < n; ++i) v[i] = c; } sunion(a, b, c) register int *a; register int *b; register int *c; { /* set a to the union of b and c */ /* a may equal b */ /* return 1 if c is not a subset of b, 0 otherwise */ register int i; register int x; register int sub; sub = 0; for(i = 0; i < tbitset; ++i) { x = b[i] | c[i]; if (x != b[i]) sub=1; a[i] = x; } return (sub); } prlook(pp) register int *pp; { register int j; pp = ((struct looksets *) pp)->lset; if (pp == (int *) 0) fprintf(Fout, "\tNULL"); else { fprintf(Fout, " { "); for(j = 1; j <= nterms; ++j) { if ((pp[j >> 4] >> (j & 017)) & 01 != 0) fprintf(Fout, "%s ", symnam(j)); } fprintf(Fout, "}"); } }