aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/yacc.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-21 22:49:15 +0000
committerrsc <devnull@localhost>2004-04-21 22:49:15 +0000
commita9df759c98d44d6c1c8c3f5665b19ac7c6d75060 (patch)
treeec402abae27ef03aee53e879a0bc6f455d6d84f6 /src/cmd/yacc.c
parentfb36ed82ec7470efe4e334ddc054bcb4fa06ae9e (diff)
downloadplan9port-a9df759c98d44d6c1c8c3f5665b19ac7c6d75060.tar.gz
plan9port-a9df759c98d44d6c1c8c3f5665b19ac7c6d75060.tar.bz2
plan9port-a9df759c98d44d6c1c8c3f5665b19ac7c6d75060.zip
new stuff.
Diffstat (limited to 'src/cmd/yacc.c')
-rw-r--r--src/cmd/yacc.c2939
1 files changed, 0 insertions, 2939 deletions
diff --git a/src/cmd/yacc.c b/src/cmd/yacc.c
deleted file mode 100644
index 6614414d..00000000
--- a/src/cmd/yacc.c
+++ /dev/null
@@ -1,2939 +0,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ctype.h>
-
-#define Bungetrune Bungetc /* ok for now. */
-
-/*
- * all these are 32 bit
- */
-#define TBITSET ((32+NTERMS)/32) /* BOTCH?? +31 */
-#define BIT(a,i) ((a)[(i)>>5] & (1<<((i)&037)))
-#define SETBIT(a,i) ((a)[(i)>>5] |= (1<<((i)&037)))
-#define NWORDS(n) (((n)+32)/32)
-
-#define PARSER "#9/lib/yaccpar"
-#define PARSERS "#9/lib/yaccpars"
-#define TEMPNAME "y.tmp.XXXXXX"
-#define ACTNAME "y.acts.XXXXXX"
-#define OFILE "tab.c"
-#define FILEU "output"
-#define FILED "tab.h"
-#define FILEDEBUG "debug"
-
-enum
-{
-/*
- * the following are adjustable
- * according to memory size
- */
- ACTSIZE = 40000,
- MEMSIZE = 40000,
- NSTATES = 2000,
- NTERMS = 511,
- NPROD = 1600,
- NNONTERM = 600,
- TEMPSIZE = 2000,
- CNAMSZ = 10000,
- LSETSIZE = 2400,
- WSETSIZE = 350,
-
- NAMESIZE = 50,
- NTYPES = 63,
- ISIZE = 400,
-
- PRIVATE = 0xE000, /* unicode private use */
-
- /* relationships which must hold:
- TBITSET ints must hold NTERMS+1 bits...
- WSETSIZE >= NNONTERM
- LSETSIZE >= NNONTERM
- TEMPSIZE >= NTERMS + NNONTERM + 1
- TEMPSIZE >= NSTATES
- */
-
- NTBASE = 010000,
- ERRCODE = 8190,
- ACCEPTCODE = 8191,
-
- NOASC = 0, /* no assoc. */
- LASC = 1, /* left assoc. */
- RASC = 2, /* right assoc. */
- BASC = 3, /* binary assoc. */
-
- /* flags for state generation */
-
- DONE = 0,
- MUSTDO = 1,
- MUSTLOOKAHEAD = 2,
-
- /* flags for a rule having an action, and being reduced */
-
- ACTFLAG = 04,
- REDFLAG = 010,
-
- /* output parser flags */
- YYFLAG1 = -1000,
-
- /* parse tokens */
- IDENTIFIER = PRIVATE,
- MARK,
- TERM,
- LEFT,
- RIGHT,
- BINARY,
- PREC,
- LCURLY,
- IDENTCOLON,
- NUMBER,
- START,
- TYPEDEF,
- TYPENAME,
- UNION,
-
- ENDFILE = 0,
-
- EMPTY = 1,
- WHOKNOWS = 0,
- OK = 1,
- NOMORE = -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) for(q=pstate[i+1], p=pstate[i]; p<q; p++)
-#define SETLOOP(i) for(i=0; i<tbitset; i++)
-
- /* command to clobber tempfiles after use */
-
-#define ZAPFILE(x) if(x) remove(x)
-
- /* I/O descriptors */
-
-Biobuf* faction; /* file for saving actions */
-Biobuf* fdefine; /* file for #defines */
-Biobuf* fdebug; /* y.debug for strings for debugging */
-Biobuf* ftable; /* y.tab.c file */
-Biobuf* ftemp; /* tempfile to pass 2 */
-Biobuf* finput; /* input file */
-Biobuf* foutput; /* y.output file */
-
- /* communication variables between various I/O routines */
-
-char* infile; /* input file name */
-int numbval; /* value of an input number */
-char tokname[NAMESIZE+4]; /* input token name, slop for runes and 0 */
-
- /* structure declarations */
-
-typedef
-struct
-{
- int lset[TBITSET];
-} Lkset;
-
-typedef
-struct
-{
- int* pitem;
- Lkset* look;
-} Item;
-
-typedef
-struct
-{
- char* name;
- int value;
-} Symb;
-
-typedef
-struct
-{
- int* pitem;
- int flag;
- Lkset ws;
-} Wset;
-
- /* 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 = 4; /* number of defined symbols output */
-char* tempname;
-char* actname;
-char ttempname[] = TEMPNAME;
-char tactname[] = ACTNAME;
-char* parser = PARSER;
-char* yydebug;
-
- /* storage of types */
-int ntypes; /* number of types defined */
-char* typeset[NTYPES]; /* pointers to type tags */
-
- /* token information */
-
-int ntokens = 0 ; /* number of tokens */
-Symb tokset[NTERMS];
-int toklev[NTERMS]; /* vector with the precedence of the terminals */
-
- /* nonterminal information */
-
-int nnonter = -1; /* the number of nonterminals */
-Symb nontrst[NNONTERM];
-int start; /* start symbol */
-
- /* assigned token type values */
-int extval = 0;
-
-char* ytabc = OFILE; /* name of y.tab.c */
-
- /* grammar rule information */
-
-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 */
-int rlines[NPROD]; /* line number for this rule */
-
- /* state information */
-
-int nstate = 0; /* number of states */
-Item* pstate[NSTATES+2]; /* pointers to the descriptions of the states */
-int tystate[NSTATES]; /* contains type information about the states */
-int defact[NSTATES]; /* the default actions of states */
-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 lastred; /* the number of the last reduction of a state */
-
- /* lookahead set information */
-
-Lkset lkst[LSETSIZE];
-int nolook; /* flag to turn off lookahead computations */
-int tbitset; /* size of lookahead sets */
-int nlset = 0; /* next lookahead set index */
-int nolook = 0; /* flag to suppress lookahead computations */
-Lkset clset; /* temporary storage for lookahead computations */
-
- /* working set information */
-
-Wset wsets[WSETSIZE];
-Wset* cwp;
-
- /* storage for action table */
-
-int amem[ACTSIZE]; /* action table storage */
-int* memp = amem; /* next free action table position */
-int indgo[NSTATES]; /* index to the stored goto table */
-
- /* temporary vector, indexable by states, terms, or ntokens */
-
-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 */
-
- /* statistics collection variables */
-
-int zzgoent;
-int zzgobest;
-int zzacent;
-int zzexcp;
-int zzclose;
-int zzrrconf;
-int zzsrconf;
-
-int* ggreed = lkst[0].lset;
-int* pgo = wsets[0].ws.lset;
-int* yypgo = &nontrst[0].value;
-
-int maxspr = 0; /* maximum spread of any entry */
-int maxoff = 0; /* maximum offset into a array */
-int* pmem = mem0;
-int* maxa;
-int nxdb = 0;
-int adb = 0;
-
-
- /* storage for information about the nonterminals */
-
-int** pres[NNONTERM+2]; /* vector of pointers to productions yielding each nonterminal */
-Lkset* pfirst[NNONTERM+2]; /* vector of pointers to first sets for each nonterminal */
-int pempty[NNONTERM+1]; /* vector of nonterminals nontrivially deriving e */
-
- /* random stuff picked out from between functions */
-
-int indebug = 0;
-Wset* zzcwp = wsets;
-int zzgoent = 0;
-int zzgobest = 0;
-int zzacent = 0;
-int zzexcp = 0;
-int zzclose = 0;
-int zzsrconf = 0;
-int* zzmemsz = mem0;
-int zzrrconf = 0;
-int pidebug = 0; /* debugging flag for putitem */
-int gsdebug = 0;
-int cldebug = 0; /* debugging flag for closure */
-int pkdebug = 0;
-int g2debug = 0;
-
-struct
-{
- char* name;
- long value;
-} resrv[] =
-{
- "binary", BINARY,
- "left", LEFT,
- "nonassoc", BINARY,
- "prec", PREC,
- "right", RIGHT,
- "start", START,
- "term", TERM,
- "token", TERM,
- "type", TYPEDEF,
- "union", UNION,
- 0,
-};
-
- /* define functions */
-
-void main(int, char**);
-void others(void);
-char* chcopy(char*, char*);
-char* writem(int*);
-char* symnam(int);
-void summary(void);
-void error(char*, ...);
-void aryfil(int*, int, int);
-int setunion(int*, int*);
-void prlook(Lkset*);
-void cpres(void);
-void cpfir(void);
-int state(int);
-void putitem(int*, Lkset*);
-void cempty(void);
-void stagen(void);
-void closure(int);
-Lkset* flset(Lkset*);
-void cleantmp(void);
-void intr(void);
-void setup(int, char**);
-void finact(void);
-int defin(int, char*);
-void defout(int);
-char* cstash(char*);
-long gettok(void);
-int fdtype(int);
-int chfind(int, char*);
-void cpyunion(void);
-void cpycode(void);
-int skipcom(void);
-void cpyact(int);
-void openup(char*, int, int, int, char*);
-void output(void);
-int apack(int*, int);
-void go2out(void);
-void go2gen(int);
-void precftn(int, int, int);
-void wract(int);
-void wrstate(int);
-void warray(char*, int*, int);
-void hideprod(void);
-void callopt(void);
-void gin(int);
-void stin(int);
-int nxti(void);
-void osummary(void);
-void aoutput(void);
-void arout(char*, int*, int);
-int gtnm(void);
-
-void
-main(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();
- exits(0);
-}
-
-/*
- * put out other arrays, copy the parsers
- */
-void
-others(void)
-{
- int c, i, j;
-
- finput = Bopen(unsharp(parser), OREAD);
- if(finput == 0)
- error("cannot open parser %s: %r", parser);
- 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, nstate, -1000);
- TLOOP(i)
- for(j=tstates[i]; j!=0; j=mstates[j])
- temp1[j] = i;
- NTLOOP(i)
- for(j=ntstates[i]; j!=0; j=mstates[j])
- temp1[j] = -i;
- warray("yychk", temp1, nstate);
- warray("yydef", defact, nstate);
-
- /* put out token translation tables */
- /* table 1 has 0-256 */
- aryfil(temp1, 256, 0);
- c = 0;
- TLOOP(i) {
- j = tokset[i].value;
- if(j >= 0 && j < 256) {
- if(temp1[j]) {
- print("yacc bug -- cant have 2 different Ts with same value\n");
- print(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name);
- nerrors++;
- }
- temp1[j] = i;
- if(j > c)
- c = j;
- }
- }
- warray("yytok1", temp1, c+1);
-
- /* table 2 has PRIVATE-PRIVATE+256 */
- aryfil(temp1, 256, 0);
- c = 0;
- TLOOP(i) {
- j = tokset[i].value - PRIVATE;
- if(j >= 0 && j < 256) {
- if(temp1[j]) {
- print("yacc bug -- cant have 2 different Ts with same value\n");
- print(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name);
- nerrors++;
- }
- temp1[j] = i;
- if(j > c)
- c = j;
- }
- }
- warray("yytok2", temp1, c+1);
-
- /* table 3 has everything else */
- Bprint(ftable, "long yytok3[] =\n{\n");
- c = 0;
- TLOOP(i) {
- j = tokset[i].value;
- if(j >= 0 && j < 256)
- continue;
- if(j >= PRIVATE && j < 256+PRIVATE)
- continue;
-
- Bprint(ftable, "%4d,%4d,", j, i);
- c++;
- if(c%5 == 0)
- Bprint(ftable, "\n");
- }
- Bprint(ftable, "%4d\n};\n", 0);
-
- /* copy parser text */
- while((c=Bgetrune(finput)) != Beof) {
- if(c == '$') {
- if((c = Bgetrune(finput)) != 'A')
- Bputrune(ftable, '$');
- else { /* copy actions */
- faction = Bopen(actname, OREAD);
- if(faction == 0)
- error("cannot reopen action tempfile");
- while((c=Bgetrune(faction)) != Beof)
- Bputrune(ftable, c);
- Bterm(faction);
- ZAPFILE(actname);
- c = Bgetrune(finput);
- }
- }
- Bputrune(ftable, c);
- }
- Bterm(ftable);
-}
-
-/*
- * copies string q into p, returning next free char ptr
- */
-char*
-chcopy(char* p, char* q)
-{
- int c;
-
- while(c = *q) {
- if(c == '"')
- *p++ = '\\';
- *p++ = c;
- q++;
- }
- *p = 0;
- return p;
-}
-
-/*
- * creates output string for item pointed to by pp
- */
-char*
-writem(int *pp)
-{
- int i,*p;
- static char sarr[ISIZE];
- char* q;
-
- for(p=pp; *p>0; p++)
- ;
- p = prdptr[-*p];
- q = chcopy(sarr, nontrst[*p-NTBASE].name);
- q = chcopy(q, ": ");
- for(;;) {
- *q = ' ';
- p++;
- if(p == pp)
- *q = '.';
- q++;
- *q = '\0';
- i = *p;
- if(i <= 0)
- break;
- q = chcopy(q, symnam(i));
- if(q > &sarr[ISIZE-30])
- error("item too big");
- }
-
- /* an item calling for a reduction */
- i = *pp;
- if(i < 0 ) {
- q = chcopy(q, " (");
- sprint(q, "%d)", -i);
- }
- return sarr;
-}
-
-/*
- * return a pointer to the name of symbol i
- */
-char*
-symnam(int i)
-{
- char* cp;
-
- cp = (i >= NTBASE)? nontrst[i-NTBASE].name: tokset[i].name;
- if(*cp == ' ')
- cp++;
- return cp;
-}
-
-/*
- * output the summary on y.output
- */
-void
-summary(void)
-{
-
- if(foutput != 0) {
- Bprint(foutput, "\n%d/%d terminals, %d/%d nonterminals\n",
- ntokens, NTERMS, nnonter, NNONTERM);
- Bprint(foutput, "%d/%d grammar rules, %d/%d states\n",
- nprod, NPROD, nstate, NSTATES);
- Bprint(foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n",
- zzsrconf, zzrrconf);
- Bprint(foutput, "%d/%d working sets used\n",
- (int)(zzcwp-wsets), WSETSIZE);
- Bprint(foutput, "memory: states,etc. %d/%d, parser %d/%d\n",
- (int)(zzmemsz-mem0), MEMSIZE, (int)(memp-amem), ACTSIZE);
- Bprint(foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE);
- Bprint(foutput, "%d extra closures\n", zzclose - 2*nstate);
- Bprint(foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp);
- Bprint(foutput, "%d goto entries\n", zzgoent);
- Bprint(foutput, "%d entries saved by goto default\n", zzgobest);
- }
- if(zzsrconf != 0 || zzrrconf != 0) {
- print("\nconflicts: ");
- if(zzsrconf)
- print("%d shift/reduce", zzsrconf);
- if(zzsrconf && zzrrconf)
- print(", ");
- if(zzrrconf)
- print("%d reduce/reduce", zzrrconf);
- print("\n");
- }
- if(ftemp != 0) {
- Bterm(ftemp);
- ftemp = 0;
- }
- if(fdefine != 0) {
- Bterm(fdefine);
- fdefine = 0;
- }
-}
-
-/*
- * write out error comment -- NEEDS WORK
- */
-void
-error(char *s, ...)
-{
-
- nerrors++;
- fprint(2, "\n fatal error:");
- fprint(2, s, (&s)[1]);
- fprint(2, ", %s:%d\n", infile, lineno);
- if(!fatfl)
- return;
- summary();
- cleantmp();
- exits("error");
-}
-
-/*
- * set elements 0 through n-1 to c
- */
-void
-aryfil(int *v, int n, int c)
-{
- int i;
-
- for(i=0; i<n; i++)
- v[i] = c;
-}
-
-/*
- * set a to the union of a and b
- * return 1 if b is not a subset of a, 0 otherwise
- */
-int
-setunion(int *a, int *b)
-{
- int i, x, sub;
-
- sub = 0;
- SETLOOP(i) {
- x = *a;
- *a |= *b;
- if(*a != x)
- sub = 1;
- a++;
- b++;
- }
- return sub;
-}
-
-void
-prlook(Lkset* p)
-{
- int j, *pp;
-
- pp = p->lset;
- if(pp == 0)
- Bprint(foutput, "\tNULL");
- else {
- Bprint(foutput, " { ");
- TLOOP(j)
- if(BIT(pp,j))
- Bprint(foutput, "%s ", symnam(j));
- Bprint(foutput, "}");
- }
-}
-
-/*
- * 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
- */
-void
-cpres(void)
-{
- int c, j, i, **pmem;
- static int *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();
- cleantmp();
- exits("error");
- }
- if(pmem != &pyield[nprod])
- error("internal Yacc error: pyield %d", pmem-&pyield[nprod]);
-}
-
-/*
- * compute an array with the first of nonterminals
- */
-void
-cpfir(void)
-{
- int *p, **s, i, **t, ch, changes;
-
- zzcwp = &wsets[nnonter];
- NTLOOP(i) {
- aryfil(wsets[i].ws.lset, tbitset, 0);
- t = pres[i+1];
- /* initially fill the sets */
- for(s=pres[i]; s<t; ++s)
- for(p = *s; (ch = *p) > 0; ++p) {
- if(ch < NTBASE) {
- SETBIT(wsets[i].ws.lset, ch);
- break;
- }
- if(!pempty[ch-NTBASE])
- break;
- }
- }
-
- /* now, reflect transitivity */
- 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;
- }
- }
- }
-
- NTLOOP(i)
- pfirst[i] = flset(&wsets[i].ws);
- if(!indebug)
- return;
- if(foutput != 0)
- NTLOOP(i) {
- Bprint(foutput, "\n%s: ", nontrst[i].name);
- prlook(pfirst[i]);
- Bprint(foutput, " %d\n", pempty[i]);
- }
-}
-
-/*
- * sorts last state,and sees if it equals earlier ones. returns state number
- */
-int
-state(int c)
-{
- Item *p1, *p2, *k, *l, *q1, *q2;
- int size1, size2, i;
-
- 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;
- Lkset *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++;
-}
-
-void
-putitem(int *ptr, Lkset *lptr)
-{
- Item *j;
-
- if(pidebug && foutput != 0)
- Bprint(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");
- }
-}
-
-/*
- * mark nonterminals which derive the empty string
- * also, look for nonterminals which don't derive any token strings
- */
-void
-cempty(void)
-{
-
- int i, *p;
-
- /* first, use the array pempty to detect productions that can never be reduced */
- /* set pempty to WHONOWS */
- aryfil(pempty, nnonter+1, WHOKNOWS);
-
- /* now, look at productions, marking nonterminals which derive something */
-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;
- /* production can be derived */
- if(*p < 0) {
- pempty[*prdptr[i]-NTBASE] = OK;
- goto more;
- }
- }
-
- /* now, look at the nonterminals, to see if they are all OK */
- 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);
- }
- }
-
- if(nerrors) {
- summary();
- cleantmp();
- exits("error");
- }
-
- /* now, compute the pempty array, to see which nonterminals derive the empty string */
- /* set pempty to WHOKNOWS */
- aryfil( pempty, nnonter+1, WHOKNOWS);
-
- /* loop as long as we keep finding empty nonterminals */
-
-again:
- PLOOP(1, i) {
- /* not known to be empty */
- if(pempty[*prdptr[i]-NTBASE] == WHOKNOWS) {
- for(p = prdptr[i]+1; *p >= NTBASE && pempty[*p-NTBASE] == EMPTY ; ++p)
- ;
- /* we have a nontrivially empty nonterminal */
- if(*p < 0) {
- pempty[*prdptr[i]-NTBASE] = EMPTY;
- /* got one ... try for another */
- goto again;
- }
- }
- }
-}
-
-/*
- * generate the states
- */
-void
-stagen(void)
-{
-
- int c, i, j, more;
- Wset *p, *q;
-
- /* initialize */
- 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...
- */
-
- pstate[0] = pstate[1] = (Item*)mem;
- aryfil(clset.lset, tbitset, 0);
- putitem(prdptr[0]+1, &clset);
- tystate[0] = MUSTDO;
- nstate = 1;
- pstate[2] = pstate[1];
-
- aryfil(amem, ACTSIZE, 0);
-
- /* now, the main state generation loop */
- for(more=1; more;) {
- more = 0;
- 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);
- /* generate goto's */
- WSLOOP(wsets, p) {
- 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)
- /* this item contributes to the goto */
- if(c == *(q->pitem)) {
- 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 != 0) {
- Bprint(foutput, "%d: ", i);
- NTLOOP(j)
- if(temp1[j])
- Bprint(foutput, "%s %d, ",
- nontrst[j].name, temp1[j]);
- Bprint(foutput, "\n");
- }
- indgo[i] = apack(&temp1[1], nnonter-1) - 1;
- /* do some more */
- more = 1;
- }
- }
-}
-
-/*
- * generate the closure of state i
- */
-void
-closure(int i)
-{
-
- Wset *u, *v;
- Item *p, *q;
- int c, ch, work, k, *pi, **s, **t;
-
- zzclose++;
-
- /* first, copy kernel of state i to wsets */
- 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);
- }
-
- /* now, go through the loop, closing each item */
- work = 1;
- while(work) {
- work = 0;
- WSLOOP(wsets, u) {
- if(u->flag == 0)
- continue;
- /* dot is before c */
- c = *(u->pitem);
- if(c < NTBASE) {
- u->flag = 0;
- /* only interesting case is where . is before nonterminal */
- continue;
- }
-
- /* compute the lookahead */
- aryfil(clset.lset, tbitset, 0);
-
- /* find items involving c */
- WSLOOP(u, v)
- if(v->flag == 1 && *(pi=v->pitem) == c) {
- v->flag = 0;
- if(nolook)
- continue;
- while((ch = *++pi) > 0) {
- /* terminal symbol */
- if(ch < NTBASE) {
- 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 is now nonterminal number
- */
- c -= NTBASE;
- t = pres[c+1];
- for(s = pres[c]; s < t; ++s) {
- /*
- * put these items into the closure
- * is the item there
- */
- WSLOOP(wsets, v)
- /* yes, it is there */
- if(v->pitem == *s) {
- 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 != 0) {
- Bprint(foutput, "\nState %d, nolook = %d\n", i, nolook);
- WSLOOP(wsets, u) {
- if(u->flag)
- Bprint(foutput, "flag set!\n");
- u->flag = 0;
- Bprint(foutput, "\t%s", writem(u->pitem));
- prlook(&u->ws);
- Bprint(foutput, "\n");
- }
- }
-}
-
-/*
- * decide if the lookahead set pointed to by p is known
- * return pointer to a perminent location for the set
- */
-Lkset*
-flset(Lkset *p)
-{
- Lkset *q;
- int *u, *v, *w, j;
-
- 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;
-}
-
-void
-cleantmp(void)
-{
- ZAPFILE(actname);
- ZAPFILE(tempname);
-}
-
-void
-intr(void)
-{
- cleantmp();
- exits("interrupted");
-}
-
-void
-setup(int argc, char *argv[])
-{
- long c, t;
- int i, j, fd, lev, ty, ytab, *p;
- int vflag, dflag, stem;
- char actnm[8], *stemc, *s, dirbuf[128];
-
- ytab = 0;
- vflag = 0;
- dflag = 0;
- stem = 0;
- stemc = "y";
- foutput = 0;
- fdefine = 0;
- fdebug = 0;
- ARGBEGIN{
- case 'v':
- case 'V':
- vflag++;
- break;
- case 'D':
- yydebug = ARGF();
- break;
- case 'd':
- dflag++;
- break;
- case 'o':
- ytab++;
- ytabc = ARGF();
- break;
- case 's':
- stem++;
- stemc = ARGF();
- break;
- case 'S':
- parser = PARSERS;
- break;
- default:
- error("illegal option: %c", ARGC());
- }ARGEND
- openup(stemc, dflag, vflag, ytab, ytabc);
-
- if((fd = mkstemp(ttempname)) >= 0){
- tempname = ttempname;
- ftemp = Bfdopen(fd, OWRITE);
- }
- if((fd = mkstemp(tactname)) >= 0){
- actname = tactname;
- faction = Bfdopen(fd, OWRITE);
- }
- if(ftemp == 0 || faction == 0)
- error("cannot open temp file");
- if(argc < 1)
- error("no input file");
- infile = argv[0];
- if(infile[0] != '/' && getwd(dirbuf, sizeof dirbuf)!=nil){
- i = strlen(infile)+1+strlen(dirbuf)+1+10;
- s = malloc(i);
- if(s != nil){
- snprint(s, i, "%s/%s", dirbuf, infile);
- cleanname(s);
- infile = s;
- }
- }
- finput = Bopen(infile, OREAD);
- if(finput == 0)
- error("cannot open '%s'", argv[0]);
- cnamp = cnames;
-
- defin(0, "$end");
- extval = PRIVATE; /* tokens start in unicode 'private use' */
- defin(0, "error");
- defin(1, "$accept");
- defin(0, "$unk");
- mem = mem0;
- i = 0;
-
- for(t = gettok(); t != MARK && t != ENDFILE;)
- switch(t) {
- case ';':
- t = gettok();
- break;
-
- case START:
- if(gettok() != IDENTIFIER)
- error("bad %%start construction");
- start = chfind(1, tokname);
- t = gettok();
- continue;
-
- case TYPEDEF:
- if(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].value;
- if(j != 0 && j != ty)
- error("type redeclaration of nonterminal %s",
- nontrst[t-NTBASE].name );
- else
- nontrst[t-NTBASE].value = ty;
- }
- case ',':
- continue;
- case ';':
- t = gettok();
- 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:
- /* nonzero means new prec. and assoc. */
- lev = t-TERM;
- ty = 0;
-
- /* get identifiers so defined */
- t = gettok();
-
- /* there is a type defined */
- if(t == TYPENAME) {
- ty = numbval;
- t = gettok();
- }
- for(;;) {
- switch(t) {
- case ',':
- t = gettok();
- continue;
-
- case ';':
- break;
-
- case IDENTIFIER:
- j = chfind(0, tokname);
- if(j >= NTBASE)
- error("%s defined earlier as nonterminal", 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);
- }
- t = gettok();
- if(t == NUMBER) {
- tokset[j].value = numbval;
- if(j < ndefout && j > 3)
- error("please define type number of %s earlier",
- tokset[j].name);
- t = gettok();
- }
- continue;
- }
- break;
- }
- continue;
-
- case LCURLY:
- defout(0);
- cpycode();
- t = gettok();
- continue;
-
- default:
- error("syntax error");
- }
- if(t == ENDFILE)
- error("unexpected EOF before %%");
-
- /* t is MARK */
- Bprint(ftable, "extern int yyerrflag;\n");
- Bprint(ftable, "#ifndef YYMAXDEPTH\n");
- Bprint(ftable, "#define YYMAXDEPTH 150\n");
- Bprint(ftable, "#endif\n" );
- if(!ntypes) {
- Bprint(ftable, "#ifndef YYSTYPE\n");
- Bprint(ftable, "#define YYSTYPE int\n");
- Bprint(ftable, "#endif\n");
- }
- Bprint(ftable, "YYSTYPE yylval;\n");
- Bprint(ftable, "YYSTYPE yyval;\n");
-
- prdptr[0] = mem;
-
- /* added production */
- *mem++ = NTBASE;
-
- /* if start is 0, we will overwrite with the lhs of the first rule */
- *mem++ = start;
- *mem++ = 1;
- *mem++ = 0;
- prdptr[1] = mem;
- while((t=gettok()) == LCURLY)
- cpycode();
- if(t != IDENTCOLON)
- error("bad syntax on first rule");
-
- if(!start)
- prdptr[0][1] = chfind(1, tokname);
-
- /* read rules */
- while(t != MARK && t != ENDFILE) {
- /* process a rule */
- rlines[nprod] = lineno;
- if(t == '|')
- *mem++ = *prdptr[nprod-1];
- else
- if(t == IDENTCOLON) {
- *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;
- Bprint(faction, "\ncase %d:", nprod);
- cpyact(mem-prdptr[nprod]-1);
- Bprint(faction, " break;");
- if((t=gettok()) == IDENTIFIER) {
-
- /* action within rule... */
- sprint(actnm, "$$%d", nprod);
-
- /* make it a nonterminal */
- j = chfind(1, actnm);
-
- /*
- * 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].value) {
-
- /* no explicit action, LHS has value */
- int 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].value;
- else
- tempty = TYPE(toklev[tempty]);
- if(tempty != nontrst[*prdptr[nprod]-NTBASE].value)
- error("default action causes potential type clash");
- }
- nprod++;
- if(nprod >= NPROD)
- error("more than %d rules", NPROD);
- prdptr[nprod] = mem;
- levprd[nprod] = 0;
- }
-
- /* end of all rules */
- defout(1);
-
- finact();
- if(t == MARK) {
- Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- while((c=Bgetrune(finput)) != Beof)
- Bputrune(ftable, c);
- }
- Bterm(finput);
-}
-
-/*
- * finish action routine
- */
-void
-finact(void)
-{
-
- Bterm(faction);
- Bprint(ftable, "#define YYEOFCODE %d\n", 1);
- Bprint(ftable, "#define YYERRCODE %d\n", 2);
-}
-
-/*
- * define s to be a terminal if t=0
- * or a nonterminal if t=1
- */
-int
-defin(int nt, char *s)
-{
- int val;
- Rune rune;
-
- val = 0;
- if(nt) {
- nnonter++;
- if(nnonter >= NNONTERM)
- error("too many nonterminals, limit %d",NNONTERM);
- nontrst[nnonter].name = cstash(s);
- return NTBASE + nnonter;
- }
-
- /* must be a token */
- ntokens++;
- if(ntokens >= NTERMS)
- error("too many terminals, limit %d", NTERMS);
- tokset[ntokens].name = cstash(s);
-
- /* establish value for token */
- /* single character literal */
- if(s[0] == ' ') {
- val = chartorune(&rune, &s[1]);
- if(s[val+1] == 0) {
- val = rune;
- goto out;
- }
- }
-
- /* escape sequence */
- if(s[0] == ' ' && s[1] == '\\') {
- if(s[3] == 0) {
- /* single character escape sequence */
- switch(s[2]) {
- 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");
- }
- goto out;
- }
-
- /* \nnn sequence */
- if(s[2] >= '0' && s[2] <= '7') {
- 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");
- goto out;
- }
- error("unknown escape");
- }
- val = extval++;
-
-out:
- tokset[ntokens].value = val;
- toklev[ntokens] = 0;
- return ntokens;
-}
-
-/*
- * write out the defines (at the end of the declaration section)
- */
-void
-defout(int last)
-{
- int i, c;
- char sar[NAMESIZE+10];
-
- for(i=ndefout; i<=ntokens; i++) {
- /* non-literals */
- c = tokset[i].name[0];
- if(c != ' ' && c != '$') {
- Bprint(ftable, "#define %s %d\n",
- tokset[i].name, tokset[i].value);
- if(fdefine)
- Bprint(fdefine, "#define\t%s\t%d\n",
- tokset[i].name, tokset[i].value);
- }
- }
- ndefout = ntokens+1;
- if(last && fdebug) {
- Bprint(fdebug, "char* yytoknames[] =\n{\n");
- TLOOP(i) {
- if(tokset[i].name) {
- chcopy(sar, tokset[i].name);
- Bprint(fdebug, "\t\"%s\",\n", sar);
- continue;
- }
- Bprint(fdebug, "\t0,\n");
- }
- Bprint(fdebug, "};\n");
- }
-}
-
-char*
-cstash(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;
-}
-
-long
-gettok(void)
-{
- long c;
- Rune rune;
- int i, base, match, reserve;
- static int peekline;
-
-begin:
- reserve = 0;
- lineno += peekline;
- peekline = 0;
- c = Bgetrune(finput);
- while(c == ' ' || c == '\n' || c == '\t' || c == '\f') {
- if(c == '\n')
- lineno++;
- c = Bgetrune(finput);
- }
-
- /* skip comment */
- if(c == '/') {
- lineno += skipcom();
- goto begin;
- }
- switch(c) {
- case Beof:
- return ENDFILE;
-
- case '{':
- Bungetrune(finput);
- return '=';
-
- case '<':
- /* get, and look up, a type name (union member name) */
- i = 0;
- while((c=Bgetrune(finput)) != '>' && c >= 0 && c != '\n') {
- rune = c;
- c = runetochar(&tokname[i], &rune);
- if(i < NAMESIZE)
- i += c;
- }
- if(c != '>')
- error("unterminated < ... > clause");
- tokname[i] = 0;
- for(i=1; i<=ntypes; i++)
- if(!strcmp(typeset[i], tokname)) {
- numbval = i;
- return TYPENAME;
- }
- ntypes++;
- numbval = ntypes;
- typeset[numbval] = cstash(tokname);
- return TYPENAME;
-
- case '"':
- case '\'':
- match = c;
- tokname[0] = ' ';
- i = 1;
- for(;;) {
- c = Bgetrune(finput);
- if(c == '\n' || c <= 0)
- error("illegal or missing ' or \"" );
- if(c == '\\') {
- tokname[i] = '\\';
- if(i < NAMESIZE)
- i++;
- c = Bgetrune(finput);
- } else
- if(c == match)
- break;
- rune = c;
- c = runetochar(&tokname[i], &rune);
- if(i < NAMESIZE)
- i += c;
- }
- break;
-
- case '%':
- case '\\':
- switch(c = Bgetrune(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:
- /* number */
- if(isdigit(c)) {
- numbval = c-'0';
- base = (c=='0')? 8: 10;
- for(c = Bgetrune(finput); isdigit(c); c = Bgetrune(finput))
- numbval = numbval*base + (c-'0');
- Bungetrune(finput);
- return NUMBER;
- }
- if(islower(c) || isupper(c) || c=='_' || c=='.' || c=='$') {
- i = 0;
- while(islower(c) || isupper(c) || isdigit(c) ||
- c == '-' || c=='_' || c=='.' || c=='$') {
- if(reserve && isupper(c))
- c += 'a'-'A';
- rune = c;
- c = runetochar(&tokname[i], &rune);
- if(i < NAMESIZE)
- i += c;
- c = Bgetrune(finput);
- }
- } else
- return c;
- Bungetrune(finput);
- }
- tokname[i] = 0;
-
- /* find a reserved word */
- if(reserve) {
- for(c=0; resrv[c].name; c++)
- if(strcmp(tokname, resrv[c].name) == 0)
- return resrv[c].value;
- error("invalid escape, or illegal reserved word: %s", tokname);
- }
-
- /* look ahead to distinguish IDENTIFIER from IDENTCOLON */
- c = Bgetrune(finput);
- while(c == ' ' || c == '\t'|| c == '\n' || c == '\f' || c == '/') {
- if(c == '\n')
- peekline++;
- /* look for comments */
- if(c == '/')
- peekline += skipcom();
- c = Bgetrune(finput);
- }
- if(c == ':')
- return IDENTCOLON;
- Bungetrune(finput);
- return IDENTIFIER;
-}
-
-/*
- * determine the type of a symbol
- */
-int
-fdtype(int t)
-{
- int v;
-
- if(t >= NTBASE)
- v = nontrst[t-NTBASE].value;
- 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;
-}
-
-int
-chfind(int t, 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 NTBASE+i;
-
- /* cannot find name */
- if(t > 1)
- error("%s should have been defined earlier", s);
- return defin(t, s);
-}
-
-/*
- * copy the union declaration to the output, and the define file if present
- */
-void
-cpyunion(void)
-{
- long c;
- int level;
-
- Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- Bprint(ftable, "typedef union ");
- if(fdefine != 0)
- Bprint(fdefine, "\ntypedef union ");
-
- level = 0;
- for(;;) {
- if((c=Bgetrune(finput)) == Beof)
- error("EOF encountered while processing %%union");
- Bputrune(ftable, c);
- if(fdefine != 0)
- Bputrune(fdefine, c);
- switch(c) {
- case '\n':
- lineno++;
- break;
- case '{':
- level++;
- break;
- case '}':
- level--;
-
- /* we are finished copying */
- if(level == 0) {
- Bprint(ftable, " YYSTYPE;\n");
- if(fdefine != 0)
- Bprint(fdefine, "\tYYSTYPE;\nextern\tYYSTYPE\tyylval;\n");
- return;
- }
- }
- }
-}
-
-/*
- * copies code between \{ and \}
- */
-void
-cpycode(void)
-{
-
- long c;
-
- c = Bgetrune(finput);
- if(c == '\n') {
- c = Bgetrune(finput);
- lineno++;
- }
- Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- while(c != Beof) {
- if(c == '\\') {
- if((c=Bgetrune(finput)) == '}')
- return;
- Bputc(ftable, '\\');
- }
- if(c == '%') {
- if((c=Bgetrune(finput)) == '}')
- return;
- Bputc(ftable, '%');
- }
- Bputrune(ftable, c);
- if(c == '\n')
- lineno++;
- c = Bgetrune(finput);
- }
- error("eof before %%}");
-}
-
-/*
- * skip over comments
- * skipcom is called after reading a '/'
- */
-int
-skipcom(void)
-{
- long c;
- int i;
-
- /* i is the number of lines skipped */
- i = 0;
- if(Bgetrune(finput) != '*')
- error("illegal comment");
- c = Bgetrune(finput);
- while(c != Beof) {
- while(c == '*')
- if((c=Bgetrune(finput)) == '/')
- return i;
- if(c == '\n')
- i++;
- c = Bgetrune(finput);
- }
- error("EOF inside comment");
- return 0;
-}
-
-/*
- * copy C action to the next ; or closing }
- */
-void
-cpyact(int offset)
-{
- long c;
- int brac, match, j, s, fnd, tok;
-
- Bprint(faction, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- brac = 0;
-
-loop:
- c = Bgetrune(finput);
-swt:
- switch(c) {
- case ';':
- if(brac == 0) {
- Bputrune(faction, c);
- return;
- }
- goto lcopy;
-
- case '{':
- brac++;
- goto lcopy;
-
- case '$':
- s = 1;
- tok = -1;
- c = Bgetrune(finput);
-
- /* type description */
- if(c == '<') {
- Bungetrune(finput);
- if(gettok() != TYPENAME)
- error("bad syntax on $<ident> clause");
- tok = numbval;
- c = Bgetrune(finput);
- }
- if(c == '$') {
- Bprint(faction, "yyval");
-
- /* put out the proper tag... */
- if(ntypes) {
- if(tok < 0)
- tok = fdtype(*prdptr[nprod]);
- Bprint(faction, ".%s", typeset[tok]);
- }
- goto loop;
- }
- if(c == '-') {
- s = -s;
- c = Bgetrune(finput);
- }
- if(isdigit(c)) {
- j = 0;
- while(isdigit(c)) {
- j = j*10 + (c-'0');
- c = Bgetrune(finput);
- }
- Bungetrune(finput);
- j = j*s - offset;
- if(j > 0)
- error("Illegal use of $%d", j+offset);
-
- dollar:
- Bprint(faction, "yypt[-%d].yyv", -j);
-
- /* put out the proper tag */
- if(ntypes) {
- if(j+offset <= 0 && tok < 0)
- error("must specify type of $%d", j+offset);
- if(tok < 0)
- tok = fdtype(prdptr[nprod][j+offset]);
- Bprint(faction, ".%s", typeset[tok]);
- }
- goto loop;
- }
- if(isupper(c) || islower(c) || c == '_' || c == '.') {
- int tok; /* tok used oustide for type info */
-
- /* look for $name */
- Bungetrune(finput);
- if(gettok() != IDENTIFIER)
- error("$ must be followed by an identifier");
- tok = chfind(2, tokname);
- if((c = Bgetrune(finput)) != '#') {
- Bungetrune(finput);
- fnd = -1;
- } else
- if(gettok() != NUMBER) {
- error("# must be followed by number");
- fnd = -1;
- } else
- fnd = numbval;
- for(j=1; j<=offset; ++j)
- if(tok == prdptr[nprod][j]) {
- if(--fnd <= 0) {
- j -= offset;
- goto dollar;
- }
- }
- error("$name or $name#number not found");
- }
- Bputc(faction, '$');
- if(s < 0 )
- Bputc(faction, '-');
- goto swt;
-
- case '}':
- brac--;
- if(brac)
- goto lcopy;
- Bputrune(faction, c);
- return;
-
- case '/':
- /* look for comments */
- Bputrune(faction, c);
- c = Bgetrune(finput);
- if(c != '*')
- goto swt;
-
- /* it really is a comment */
- Bputrune(faction, c);
- c = Bgetrune(finput);
- while(c >= 0) {
- while(c == '*') {
- Bputrune(faction, c);
- if((c=Bgetrune(finput)) == '/')
- goto lcopy;
- }
- Bputrune(faction, c);
- if(c == '\n')
- lineno++;
- c = Bgetrune(finput);
- }
- error("EOF inside comment");
-
- case '\'':
- /* character constant */
- match = '\'';
- goto string;
-
- case '"':
- /* character string */
- match = '"';
-
- string:
- Bputrune(faction, c);
- while(c = Bgetrune(finput)) {
- if(c == '\\') {
- Bputrune(faction, c);
- c = Bgetrune(finput);
- if(c == '\n')
- lineno++;
- } else
- if(c == match)
- goto lcopy;
- if(c == '\n')
- error("newline in string or char. const.");
- Bputrune(faction, c);
- }
- error("EOF in string or character constant");
-
- case Beof:
- error("action does not terminate");
-
- case '\n':
- lineno++;
- goto lcopy;
- }
-
-lcopy:
- Bputrune(faction, c);
- goto loop;
-}
-
-void
-openup(char *stem, int dflag, int vflag, int ytab, char *ytabc)
-{
- char buf[256];
-
- if(vflag) {
- sprint(buf, "%s.%s", stem, FILEU);
- foutput = Bopen(buf, OWRITE);
- if(foutput == 0)
- error("cannot open %s", buf);
- }
- if(yydebug) {
- sprint(buf, "%s.%s", stem, FILEDEBUG);
- if((fdebug = Bopen(buf, OWRITE)) == 0)
- error("can't open %s", buf);
- }
- if(dflag) {
- sprint(buf, "%s.%s", stem, FILED);
- fdefine = Bopen(buf, OWRITE);
- if(fdefine == 0)
- error("can't create %s", buf);
- }
- if(ytab == 0)
- sprint(buf, "%s.%s", stem, OFILE);
- else
- strcpy(buf, ytabc);
- ftable = Bopen(buf, OWRITE);
- if(ftable == 0)
- error("cannot open table file %s", buf);
-}
-
-/*
- * print the output for the states
- */
-void
-output(void)
-{
- int i, k, c;
- Wset *u, *v;
-
- Bprint(ftable, "short yyexca[] =\n{");
- if(fdebug)
- Bprint(fdebug, "char* yystates[] =\n{\n");
-
- /* output the stuff for state i */
- SLOOP(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, (Lkset*)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;
-
- /* now, we have the shifts; look at the reductions */
- lastred = 0;
- WSLOOP(wsets, u) {
- c = *u->pitem;
-
- /* reduction */
- if(c <= 0) {
- 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)
- Bprint(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);
- }
-
- if(fdebug)
- Bprint(fdebug, "};\n");
- Bprint(ftable, "};\n");
- Bprint(ftable, "#define YYNPROD %d\n", nprod);
- Bprint(ftable, "#define YYPRIVATE %d\n", PRIVATE);
- if(yydebug)
- Bprint(ftable, "#define yydebug %s\n", yydebug);
-}
-
-/*
- * pack state i from temp1 into amem
- */
-int
-apack(int *p, int n)
-{
- int *pp, *qq, *rr, off, *q, *r;
-
- /* we don't need to worry about checking because
- * we will only look at entries known to be there...
- * eliminate leading and trailing 0's
- */
-
- q = p+n;
- for(pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off)
- ;
- /* no actions */
- if(pp > q)
- return 0;
- p = pp;
-
- /* now, find a place for the elements from p to q, inclusive */
- r = &amem[ACTSIZE-1];
- for(rr = amem; rr <= r; rr++, off++) {
- 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 */
- if(pkdebug && foutput != 0)
- Bprint(foutput, "off = %d, k = %d\n", off, (int)(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 != 0)
- for(pp = amem; pp <= memp; pp += 10) {
- Bprint(foutput, "\t");
- for(qq = pp; qq <= pp+9; qq++)
- Bprint(foutput, "%d ", *qq);
- Bprint(foutput, "\n");
- }
- return(off);
- nextk:;
- }
- error("no space in action table");
- return 0;
-}
-
-/*
- * output the gotos for the nontermninals
- */
-void
-go2out(void)
-{
- int i, j, k, best, count, cbest, times;
-
- /* mark begining of gotos */
- Bprint(ftemp, "$\n");
- for(i = 1; i <= nnonter; i++) {
- go2gen(i);
-
- /* find the best one to make default */
- best = -1;
- times = 0;
-
- /* is j the most frequent */
- for(j = 0; j <= nstate; j++) {
- if(tystate[j] == 0)
- continue;
- if(tystate[j] == best)
- continue;
-
- /* is tystate[j] the most frequent */
- count = 0;
- cbest = tystate[j];
- for(k = j; k <= nstate; k++)
- if(tystate[k] == cbest)
- count++;
- if(count > times) {
- best = cbest;
- times = count;
- }
- }
-
- /* best is now the default entry */
- zzgobest += times-1;
- for(j = 0; j <= nstate; j++)
- if(tystate[j] != 0 && tystate[j] != best) {
- Bprint(ftemp, "%d,%d,", j, tystate[j]);
- zzgoent++;
- }
-
- /* now, the default */
- if(best == -1)
- best = 0;
- zzgoent++;
- Bprint(ftemp, "%d\n", best);
- }
-}
-
-/*
- * output the gotos for nonterminal c
- */
-void
-go2gen(int c)
-{
- int i, work, cc;
- Item *p, *q;
-
-
- /* first, find nonterminals with gotos on c */
- aryfil(temp1, nnonter+1, 0);
- temp1[c] = 1;
- work = 1;
- while(work) {
- work = 0;
- PLOOP(0, i)
-
- /* cc is a nonterminal */
- if((cc=prdptr[i][1]-NTBASE) >= 0)
- /* cc has a goto on c */
- if(temp1[cc] != 0) {
-
- /* thus, the left side of production i does too */
- cc = *prdptr[i]-NTBASE;
- if(temp1[cc] == 0) {
- work = 1;
- temp1[cc] = 1;
- }
- }
- }
-
- /* now, we have temp1[c] = 1 if a goto on c in closure of cc */
- if(g2debug && foutput != 0) {
- Bprint(foutput, "%s: gotos on ", nontrst[c].name);
- NTLOOP(i)
- if(temp1[i])
- Bprint(foutput, "%s ", nontrst[i].name);
- Bprint(foutput, "\n");
- }
-
- /* now, go through and put gotos into tystate */
- aryfil(tystate, nstate, 0);
- SLOOP(i)
- ITMLOOP(i, p, q)
- if((cc = *p->pitem) >= NTBASE)
- /* goto on c is possible */
- if(temp1[cc-NTBASE]) {
- tystate[i] = amem[indgo[i]+c];
- break;
- }
-}
-
-/*
- * 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
- */
-void
-precftn(int r, int t, int s)
-{
- int lp, lt, action;
-
- lp = levprd[r];
- lt = toklev[t];
- if(PLEVEL(lt) == 0 || PLEVEL(lp) == 0) {
-
- /* conflict */
- if(foutput != 0)
- Bprint(foutput,
- "\n%d: shift/reduce conflict (shift %d(%d), red'n %d(%d)) on %s",
- s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), 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;
- break;
- case LASC: /* reduce */
- temp1[t] = -r;
- break;
- }
-}
-
-/*
- * output state i
- * temp1 has the actions, lastred the default
- */
-void
-wract(int i)
-{
- int p, p0, p1, ntimes, tred, count, j, flag;
-
- /* 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;
- }
- }
-
- /*
- * 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[2] > 0)
- lastred = 0;
-
- /* clear out entries in temp1 which equal lastred */
- TLOOP(p)
- if(temp1[p]+lastred == 0)
- temp1[p] = 0;
-
- wrstate(i);
- defact[i] = lastred;
- flag = 0;
- TLOOP(p0)
- if((p1=temp1[p0]) != 0) {
- if(p1 < 0) {
- p1 = -p1;
- goto exc;
- }
- if(p1 == ACCEPTCODE) {
- p1 = -1;
- goto exc;
- }
- if(p1 == ERRCODE) {
- p1 = 0;
- exc:
- if(flag++ == 0)
- Bprint(ftable, "-1, %d,\n", i);
- Bprint(ftable, "\t%d, %d,\n", p0, p1);
- zzexcp++;
- continue;
- }
- Bprint(ftemp, "%d,%d,", p0, p1);
- zzacent++;
- }
- if(flag) {
- defact[i] = -2;
- Bprint(ftable, "\t-2, %d,\n", lastred);
- }
- Bprint(ftemp, "\n");
-}
-
-/*
- * writes state i
- */
-void
-wrstate(int i)
-{
- int j0, j1;
- Item *pp, *qq;
- Wset *u;
-
- if(fdebug) {
- if(lastred) {
- Bprint(fdebug, " 0, /*%d*/\n", i);
- } else {
- Bprint(fdebug, " \"");
- ITMLOOP(i, pp, qq)
- Bprint(fdebug, "%s\\n", writem(pp->pitem));
- if(tystate[i] == MUSTLOOKAHEAD)
- WSLOOP(wsets + (pstate[i+1] - pstate[i]), u)
- if(*u->pitem < 0)
- Bprint(fdebug, "%s\\n", writem(u->pitem));
- Bprint(fdebug, "\", /*%d*/\n", i);
- }
- }
- if(foutput == 0)
- return;
- Bprint(foutput, "\nstate %d\n", i);
- ITMLOOP(i, pp, qq)
- Bprint(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)
- Bprint(foutput, "\t%s\n", writem(u->pitem));
-
- /* check for state equal to another */
- TLOOP(j0)
- if((j1=temp1[j0]) != 0) {
- Bprint(foutput, "\n\t%s ", symnam(j0));
- /* shift, error, or accept */
- if(j1 > 0) {
- if(j1 == ACCEPTCODE)
- Bprint(foutput, "accept");
- else
- if(j1 == ERRCODE)
- Bprint(foutput, "error");
- else
- Bprint(foutput, "shift %d", j1);
- } else
- Bprint(foutput, "reduce %d (src line %d)", -j1, rlines[-j1]);
- }
-
- /* output the final production */
- if(lastred)
- Bprint(foutput, "\n\t. reduce %d (src line %d)\n\n",
- lastred, rlines[lastred]);
- else
- Bprint(foutput, "\n\t. error\n\n");
-
- /* now, output nonterminal actions */
- j1 = ntokens;
- for(j0 = 1; j0 <= nnonter; j0++) {
- j1++;
- if(temp1[j1])
- Bprint(foutput, "\t%s goto %d\n", symnam(j0+NTBASE), temp1[j1]);
- }
-}
-
-void
-warray(char *s, int *v, int n)
-{
- int i;
-
- Bprint(ftable, "short %s[] =\n{", s);
- for(i=0;;) {
- if(i%10 == 0)
- Bprint(ftable, "\n");
- Bprint(ftable, "%4d", v[i]);
- i++;
- if(i >= n) {
- Bprint(ftable, "\n};\n");
- break;
- }
- Bprint(ftable, ",");
- }
-}
-
-/*
- * 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.
- */
-
-void
-hideprod(void)
-{
- int i, j;
-
- j = 0;
- levprd[0] = 0;
- PLOOP(1, i) {
- if(!(levprd[i] & REDFLAG)) {
- j++;
- if(foutput != 0)
- Bprint(foutput, "Rule not reduced: %s\n", writem(prdptr[i]));
- }
- levprd[i] = *prdptr[i] - NTBASE;
- }
- if(j)
- print("%d rules never reduced\n", j);
-}
-
-void
-callopt(void)
-{
- int i, *p, j, k, *q;
-
- /* read the arrays from tempfile and set parameters */
- finput = Bopen(tempname, OREAD);
- if(finput == 0)
- error("optimizer cannot open tempfile");
-
- pgo[0] = 0;
- temp1[0] = 0;
- nstate = 0;
- nnonter = 0;
- for(;;) {
- switch(gtnm()) {
- case '\n':
- nstate++;
- pmem--;
- temp1[nstate] = pmem - mem0;
- case ',':
- continue;
- case '$':
- break;
- default:
- error("bad tempfile");
- }
- break;
- }
-
- pmem--;
- temp1[nstate] = yypgo[0] = pmem - mem0;
- for(;;) {
- switch(gtnm()) {
- case '\n':
- nnonter++;
- yypgo[nnonter] = pmem-mem0;
- case ',':
- continue;
- case -1:
- break;
- default:
- error("bad tempfile");
- }
- break;
- }
- pmem--;
- yypgo[nnonter--] = pmem - mem0;
- for(i = 0; i < nstate; i++) {
- k = 32000;
- j = 0;
- q = mem0 + temp1[i+1];
- for(p = mem0 + temp1[i]; p < q ; p += 2) {
- if(*p > j)
- j = *p;
- if(*p < k)
- k = *p;
- }
- /* nontrivial situation */
- if(k <= j) {
- /* j is now the range */
-/* j -= k; *//* call scj */
- if(k > maxoff)
- maxoff = k;
- }
- tystate[i] = (temp1[i+1]-temp1[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 = mem0 + yypgo[i+1] - 1;
- for(p = mem0+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 amem array */
- for(i = 0; i < ACTSIZE; i++)
- amem[i] = 0;
- maxa = amem;
- for(i = 0; i < nstate; i++) {
- if(tystate[i] == 0 && adb > 1)
- Bprint(ftable, "State %d: null\n", i);
- indgo[i] = YYFLAG1;
- }
- while((i = nxti()) != NOMORE)
- if(i >= 0)
- stin(i);
- else
- gin(-i);
-
- /* print amem array */
- if(adb > 2 )
- for(p = amem; p <= maxa; p += 10) {
- Bprint(ftable, "%4d ", (int)(p-amem));
- for(i = 0; i < 10; ++i)
- Bprint(ftable, "%4d ", p[i]);
- Bprint(ftable, "\n");
- }
-
- /* write out the output appropriate to the language */
- aoutput();
- osummary();
- ZAPFILE(tempname);
-}
-
-void
-gin(int i)
-{
- int *p, *r, *s, *q1, *q2;
-
- /* enter gotos on nonterminal i into array amem */
- ggreed[i] = 0;
-
- q2 = mem0+ yypgo[i+1] - 1;
- q1 = mem0 + yypgo[i];
-
- /* now, find amem place for it */
- for(p = amem; p < &amem[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) > &amem[ACTSIZE])
- error("a array overflow");
- }
- /* we have found amem spot */
- *p = *q2;
- if(p > maxa)
- if((maxa = p) > &amem[ACTSIZE])
- error("a array overflow");
- for(r = q1; r < q2; r += 2) {
- s = p + *r + 1;
- *s = r[1];
- }
- pgo[i] = p-amem;
- if(adb > 1)
- Bprint(ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]);
- return;
-
- nextgp:;
- }
- error("cannot place goto %d\n", i);
-}
-
-void
-stin(int i)
-{
- int *r, *s, n, flag, j, *q1, *q2;
-
- tystate[i] = 0;
-
- /* enter state i into the amem array */
- q2 = mem0+temp1[i+1];
- q1 = mem0+temp1[i];
- /* find an acceptable place */
- for(n = -maxoff; n < ACTSIZE; n++) {
- flag = 0;
- for(r = q1; r < q2; r += 2) {
- if((s = *r + n + amem) < amem)
- 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(indgo[j] == n) {
-
- /* we have some disagreement */
- if(flag)
- goto nextn;
- if(temp1[j+1]+temp1[i] == temp1[j]+temp1[i+1]) {
-
- /* states are equal */
- indgo[i] = n;
- if(adb > 1)
- Bprint(ftable,
- "State %d: entry at %d equals state %d\n",
- i, n, j);
- return;
- }
-
- /* we have some disagreement */
- goto nextn;
- }
- }
-
- for(r = q1; r < q2; r += 2) {
- if((s = *r+n+amem) >= &amem[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-amem, r[1]);
- *s = r[1];
- }
- indgo[i] = n;
- if(adb > 1)
- Bprint(ftable, "State %d: entry at %d\n", i, indgo[i]);
- return;
- nextn:;
- }
- error("Error; failure to place state %d\n", i);
-}
-
-/*
- * finds the next i
- */
-int
-nxti(void)
-{
- int i, max, maxi;
-
- max = 0;
- maxi = 0;
- for(i = 1; i <= nnonter; i++)
- if(ggreed[i] >= max) {
- max = ggreed[i];
- maxi = -i;
- }
- for(i = 0; i < nstate; ++i)
- if(tystate[i] >= max) {
- max = tystate[i];
- maxi = i;
- }
- if(nxdb)
- Bprint(ftable, "nxti = %d, max = %d\n", maxi, max);
- if(max == 0)
- return NOMORE;
- return maxi;
-}
-
-/*
- * write summary
- */
-void
-osummary(void)
-{
-
- int i, *p;
-
- if(foutput == 0)
- return;
- i = 0;
- for(p = maxa; p >= amem; p--)
- if(*p == 0)
- i++;
-
- Bprint(foutput, "Optimizer space used: input %d/%d, output %d/%d\n",
- (int)(pmem-mem0+1), MEMSIZE, (int)(maxa-amem+1), ACTSIZE);
- Bprint(foutput, "%d table entries, %d zero\n", (int)(maxa-amem+1), i);
- Bprint(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff);
-}
-
-/*
- * this version is for C
- * write out the optimized parser
- */
-void
-aoutput(void)
-{
- Bprint(ftable, "#define\tYYLAST\t%d\n", (int)(maxa-amem+1));
- arout("yyact", amem, (maxa-amem)+1);
- arout("yypact", indgo, nstate);
- arout("yypgo", pgo, nnonter+1);
-}
-
-void
-arout(char *s, int *v, int n)
-{
- int i;
-
- Bprint(ftable, "short %s[] =\n{", s);
- for(i = 0; i < n;) {
- if(i%10 == 0)
- Bprint(ftable, "\n");
- Bprint(ftable, "%4d", v[i]);
- i++;
- if(i == n)
- Bprint(ftable, "\n};\n");
- else
- Bprint(ftable, ",");
- }
-}
-
-/*
- * read and convert an integer from the standard input
- * return the terminating character
- * blanks, tabs, and newlines are ignored
- */
-int
-gtnm(void)
-{
- int sign, val, c;
-
- sign = 0;
- val = 0;
- while((c=Bgetrune(finput)) != Beof) {
- if(isdigit(c)) {
- val = val*10 + c-'0';
- continue;
- }
- if(c == '-') {
- sign = 1;
- continue;
- }
- break;
- }
- if(sign)
- val = -val;
- *pmem++ = val;
- if(pmem >= &mem0[MEMSIZE])
- error("out of space");
- return c;
-}