|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)y1.c 4.2 (Berkeley) 5/10/89";
3: #endif not lint
4:
5: # include "dextern"
6: # include "pathnames.h"
7:
8: /* variables used locally */
9:
10: /* lookahead computations */
11:
12: int tbitset; /* size of lookahead sets */
13: struct looksets lkst [ LSETSIZE ];
14: int nlset = 0; /* next lookahead set index */
15: int nolook = 0; /* flag to suppress lookahead computations */
16: struct looksets clset; /* temporary storage for lookahead computations */
17:
18: /* working set computations */
19:
20: struct wset wsets[ WSETSIZE ];
21: struct wset *cwp;
22:
23: /* state information */
24:
25: int nstate = 0; /* number of states */
26: struct item *pstate[NSTATES+2]; /* pointers to the descriptions of the states */
27: int tystate[NSTATES]; /* contains type information about the states */
28: int indgo[NSTATES]; /* index to the stored goto table */
29: int tstates[ NTERMS ]; /* states generated by terminal gotos */
30: int ntstates[ NNONTERM ]; /* states generated by nonterminal gotos */
31: int mstates[ NSTATES ]; /* chain of overflows of term/nonterm generation lists */
32:
33: /* storage for the actions in the parser */
34:
35: int amem[ACTSIZE]; /* action table storage */
36: int *memp = amem; /* next free action table position */
37:
38: /* other storage areas */
39:
40: int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or states */
41: int lineno= 1; /* current input line number */
42: int fatfl = 1; /* if on, error is fatal */
43: int nerrors = 0; /* number of errors */
44:
45: /* storage for information about the nonterminals */
46:
47: int **pres[NNONTERM+2]; /* vector of pointers to productions yielding each nonterminal */
48: struct looksets *pfirst[NNONTERM+2]; /* vector of pointers to first sets for each nonterminal */
49: int pempty[NNONTERM+1]; /* vector of nonterminals nontrivially deriving e */
50:
51: main(argc,argv) int argc; char *argv[]; {
52:
53: setup(argc,argv); /* initialize and read productions */
54: tbitset = NWORDS(ntokens);
55: cpres(); /* make table of which productions yield a given nonterminal */
56: cempty(); /* make a table of which nonterminals can match the empty string */
57: cpfir(); /* make a table of firsts of nonterminals */
58: stagen(); /* generate the states */
59: output(); /* write the states and the tables */
60: go2out();
61: hideprod();
62: summary();
63: callopt();
64: others();
65: exit(0);
66: }
67:
68: others(){ /* put out other arrays, copy the parsers */
69: register c, i, j;
70:
71: finput = fopen( _PATH_PARSER, "r" );
72: if( finput == NULL ) error( "cannot find parser %s", _PATH_PARSER);
73:
74: warray( "yyr1", levprd, nprod );
75:
76: aryfil( temp1, nprod, 0 );
77: PLOOP(1,i)temp1[i] = prdptr[i+1]-prdptr[i]-2;
78: warray( "yyr2", temp1, nprod );
79:
80: aryfil( temp1, nstate, -1000 );
81: TLOOP(i){
82: for( j=tstates[i]; j!=0; j=mstates[j] ){
83: temp1[j] = tokset[i].value;
84: }
85: }
86: NTLOOP(i){
87: for( j=ntstates[i]; j!=0; j=mstates[j] ){
88: temp1[j] = -i;
89: }
90: }
91: warray( "yychk", temp1, nstate );
92:
93: warray( "yydef", defact, nstate );
94:
95: /* copy parser text */
96:
97: while( (c=getc(finput) ) != EOF ){
98: if( c == '$' ){
99: if( (c=getc(finput)) != 'A' ) putc( '$', ftable );
100: else { /* copy actions */
101: faction = fopen( ACTNAME, "r" );
102: if( faction == NULL ) error( "cannot reopen action tempfile" );
103: while( (c=getc(faction) ) != EOF ) putc( c, ftable );
104: fclose(faction);
105: ZAPFILE(ACTNAME);
106: c = getc(finput);
107: }
108: }
109: putc( c, ftable );
110: }
111:
112: fclose( ftable );
113: }
114:
115: char *chcopy( p, q ) char *p, *q; {
116: /* copies string q into p, returning next free char ptr */
117: while( *p = *q++ ) ++p;
118: return( p );
119: }
120:
121: # define ISIZE 400
122: char *writem(pp) int *pp; { /* creates output string for item pointed to by pp */
123: int i,*p;
124: static char sarr[ISIZE];
125: char *q;
126:
127: for( p=pp; *p>0 ; ++p ) ;
128: p = prdptr[-*p];
129: q = chcopy( sarr, nontrst[*p-NTBASE].name );
130: q = chcopy( q, " : " );
131:
132: for(;;){
133: *q++ = ++p==pp ? '_' : ' ';
134: *q = '\0';
135: if((i = *p) <= 0) break;
136: q = chcopy( q, symnam(i) );
137: if( q> &sarr[ISIZE-30] ) error( "item too big" );
138: }
139:
140: if( (i = *pp) < 0 ){ /* an item calling for a reduction */
141: q = chcopy( q, " (" );
142: sprintf( q, "%d)", -i );
143: }
144:
145: return( sarr );
146: }
147:
148: char *symnam(i){ /* return a pointer to the name of symbol i */
149: char *cp;
150:
151: cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : tokset[i].name ;
152: if( *cp == ' ' ) ++cp;
153: return( cp );
154: }
155:
156: struct wset *zzcwp = wsets;
157: int zzgoent = 0;
158: int zzgobest = 0;
159: int zzacent = 0;
160: int zzexcp = 0;
161: int zzclose = 0;
162: int zzsrconf = 0;
163: int * zzmemsz = mem0;
164: int zzrrconf = 0;
165:
166: summary(){ /* output the summary on the tty */
167:
168: if( foutput!=NULL ){
169: fprintf( foutput, "\n%d/%d terminals, %d/%d nonterminals\n", ntokens, NTERMS,
170: nnonter, NNONTERM );
171: fprintf( foutput, "%d/%d grammar rules, %d/%d states\n", nprod, NPROD, nstate, NSTATES );
172: fprintf( foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf );
173: fprintf( foutput, "%d/%d working sets used\n", zzcwp-wsets, WSETSIZE );
174: fprintf( foutput, "memory: states,etc. %d/%d, parser %d/%d\n", zzmemsz-mem0, MEMSIZE,
175: memp-amem, ACTSIZE );
176: fprintf( foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE );
177: fprintf( foutput, "%d extra closures\n", zzclose - 2*nstate );
178: fprintf( foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp );
179: fprintf( foutput, "%d goto entries\n", zzgoent );
180: fprintf( foutput, "%d entries saved by goto default\n", zzgobest );
181: }
182: if( zzsrconf!=0 || zzrrconf!=0 ){
183: fprintf( stdout,"\nconflicts: ");
184: if( zzsrconf )fprintf( stdout, "%d shift/reduce" , zzsrconf );
185: if( zzsrconf && zzrrconf )fprintf( stdout, ", " );
186: if( zzrrconf )fprintf( stdout, "%d reduce/reduce" , zzrrconf );
187: fprintf( stdout, "\n" );
188: }
189:
190: fclose( ftemp );
191: if( fdefine != NULL ) fclose( fdefine );
192: }
193:
194: /* VARARGS1 */
195: error(s,a1) char *s; { /* write out error comment */
196:
197: ++nerrors;
198: fprintf( stderr, "\n fatal error: ");
199: fprintf( stderr, s,a1);
200: fprintf( stderr, ", line %d\n", lineno );
201: if( !fatfl ) return;
202: summary();
203: exit(1);
204: }
205:
206: aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */
207: int i;
208: for( i=0; i<n; ++i ) v[i] = c;
209: }
210:
211: setunion( a, b ) register *a, *b; {
212: /* set a to the union of a and b */
213: /* return 1 if b is not a subset of a, 0 otherwise */
214: register i, x, sub;
215:
216: sub = 0;
217: SETLOOP(i){
218: *a = (x = *a)|*b++;
219: if( *a++ != x ) sub = 1;
220: }
221: return( sub );
222: }
223:
224: prlook( p ) struct looksets *p;{
225: register j, *pp;
226: pp = p->lset;
227: if( pp == 0 ) fprintf( foutput, "\tNULL");
228: else {
229: fprintf( foutput, " { " );
230: TLOOP(j) {
231: if( BIT(pp,j) ) fprintf( foutput, "%s ", symnam(j) );
232: }
233: fprintf( foutput, "}" );
234: }
235: }
236:
237: cpres(){ /* compute an array with the beginnings of productions yielding given nonterminals
238: The array pres points to these lists */
239: /* the array pyield has the lists: the total size is only NPROD+1 */
240: register **pmem;
241: register c, j, i;
242: static int * pyield[NPROD];
243:
244: pmem = pyield;
245:
246: NTLOOP(i){
247: c = i+NTBASE;
248: pres[i] = pmem;
249: fatfl = 0; /* make undefined symbols nonfatal */
250: PLOOP(0,j){
251: if (*prdptr[j] == c) *pmem++ = prdptr[j]+1;
252: }
253: if(pres[i] == pmem){
254: error("nonterminal %s not defined!", nontrst[i].name);
255: }
256: }
257: pres[i] = pmem;
258: fatfl = 1;
259: if( nerrors ){
260: summary();
261: exit(1);
262: }
263: if( pmem != &pyield[nprod] ) error( "internal Yacc error: pyield %d", pmem-&pyield[nprod] );
264: }
265:
266: int indebug = 0;
267: cpfir() {
268: /* compute an array with the first of nonterminals */
269: register *p, **s, i, **t, ch, changes;
270:
271: zzcwp = &wsets[nnonter];
272: NTLOOP(i){
273: aryfil( wsets[i].ws.lset, tbitset, 0 );
274: t = pres[i+1];
275: for( s=pres[i]; s<t; ++s ){ /* initially fill the sets */
276: for( p = *s; (ch = *p) > 0 ; ++p ) {
277: if( ch < NTBASE ) {
278: SETBIT( wsets[i].ws.lset, ch );
279: break;
280: }
281: else if( !pempty[ch-NTBASE] ) break;
282: }
283: }
284: }
285:
286: /* now, reflect transitivity */
287:
288: changes = 1;
289: while( changes ){
290: changes = 0;
291: NTLOOP(i){
292: t = pres[i+1];
293: for( s=pres[i]; s<t; ++s ){
294: for( p = *s; ( ch = (*p-NTBASE) ) >= 0; ++p ) {
295: changes |= setunion( wsets[i].ws.lset, wsets[ch].ws.lset );
296: if( !pempty[ch] ) break;
297: }
298: }
299: }
300: }
301:
302: NTLOOP(i) pfirst[i] = flset( &wsets[i].ws );
303: if( !indebug ) return;
304: if( (foutput!=NULL) ){
305: NTLOOP(i) {
306: fprintf( foutput, "\n%s: ", nontrst[i].name );
307: prlook( pfirst[i] );
308: fprintf( foutput, " %d\n", pempty[i] );
309: }
310: }
311: }
312:
313: state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */
314: int size1,size2;
315: register i;
316: struct item *p1, *p2, *k, *l, *q1, *q2;
317: p1 = pstate[nstate];
318: p2 = pstate[nstate+1];
319: if(p1==p2) return(0); /* null state */
320: /* sort the items */
321: for(k=p2-1;k>p1;k--) { /* make k the biggest */
322: for(l=k-1;l>=p1;--l)if( l->pitem > k->pitem ){
323: int *s;
324: struct looksets *ss;
325: s = k->pitem;
326: k->pitem = l->pitem;
327: l->pitem = s;
328: ss = k->look;
329: k->look = l->look;
330: l->look = ss;
331: }
332: }
333: size1 = p2 - p1; /* size of state */
334:
335: for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) {
336: /* get ith state */
337: q1 = pstate[i];
338: q2 = pstate[i+1];
339: size2 = q2 - q1;
340: if (size1 != size2) continue;
341: k=p1;
342: for(l=q1;l<q2;l++) {
343: if( l->pitem != k->pitem ) break;
344: ++k;
345: }
346: if (l != q2) continue;
347: /* found it */
348: pstate[nstate+1] = pstate[nstate]; /* delete last state */
349: /* fix up lookaheads */
350: if( nolook ) return(i);
351: for( l=q1,k=p1; l<q2; ++l,++k ){
352: int s;
353: SETLOOP(s) clset.lset[s] = l->look->lset[s];
354: if( setunion( clset.lset, k->look->lset ) ) {
355: tystate[i] = MUSTDO;
356: /* register the new set */
357: l->look = flset( &clset );
358: }
359: }
360: return (i);
361: }
362: /* state is new */
363: if( nolook ) error( "yacc state/nolook error" );
364: pstate[nstate+2] = p2;
365: if(nstate+1 >= NSTATES) error("too many states" );
366: if( c >= NTBASE ){
367: mstates[ nstate ] = ntstates[ c-NTBASE ];
368: ntstates[ c-NTBASE ] = nstate;
369: }
370: else {
371: mstates[ nstate ] = tstates[ c ];
372: tstates[ c ] = nstate;
373: }
374: tystate[nstate]=MUSTDO;
375: return(nstate++);
376: }
377:
378: int pidebug = 0; /* debugging flag for putitem */
379: putitem( ptr, lptr ) int *ptr; struct looksets *lptr; {
380: register struct item *j;
381:
382: if( pidebug && (foutput!=NULL) ) {
383: fprintf( foutput, "putitem(%s), state %d\n", writem(ptr), nstate );
384: }
385: j = pstate[nstate+1];
386: j->pitem = ptr;
387: if( !nolook ) j->look = flset( lptr );
388: pstate[nstate+1] = ++j;
389: if( (int *)j > zzmemsz ){
390: zzmemsz = (int *)j;
391: if( zzmemsz >= &mem0[MEMSIZE] ) error( "out of state space" );
392: }
393: }
394:
395: cempty(){ /* mark nonterminals which derive the empty string */
396: /* also, look for nonterminals which don't derive any token strings */
397:
398: # define EMPTY 1
399: # define WHOKNOWS 0
400: # define OK 1
401:
402: register i, *p;
403:
404: /* first, use the array pempty to detect productions that can never be reduced */
405: /* set pempty to WHONOWS */
406: aryfil( pempty, nnonter+1, WHOKNOWS );
407:
408: /* now, look at productions, marking nonterminals which derive something */
409:
410: more:
411: PLOOP(0,i){
412: if( pempty[ *prdptr[i] - NTBASE ] ) continue;
413: for( p=prdptr[i]+1; *p>=0; ++p ){
414: if( *p>=NTBASE && pempty[ *p-NTBASE ] == WHOKNOWS ) break;
415: }
416: if( *p < 0 ){ /* production can be derived */
417: pempty[ *prdptr[i]-NTBASE ] = OK;
418: goto more;
419: }
420: }
421:
422: /* now, look at the nonterminals, to see if they are all OK */
423:
424: NTLOOP(i){
425: /* the added production rises or falls as the start symbol ... */
426: if( i == 0 ) continue;
427: if( pempty[ i ] != OK ) {
428: fatfl = 0;
429: error( "nonterminal %s never derives any token string", nontrst[i].name );
430: }
431: }
432:
433: if( nerrors ){
434: summary();
435: exit(1);
436: }
437:
438: /* now, compute the pempty array, to see which nonterminals derive the empty string */
439:
440: /* set pempty to WHOKNOWS */
441:
442: aryfil( pempty, nnonter+1, WHOKNOWS );
443:
444: /* loop as long as we keep finding empty nonterminals */
445:
446: again:
447: PLOOP(1,i){
448: if( pempty[ *prdptr[i]-NTBASE ]==WHOKNOWS ){ /* not known to be empty */
449: for( p=prdptr[i]+1; *p>=NTBASE && pempty[*p-NTBASE]==EMPTY ; ++p ) ;
450: if( *p < 0 ){ /* we have a nontrivially empty nonterminal */
451: pempty[*prdptr[i]-NTBASE] = EMPTY;
452: goto again; /* got one ... try for another */
453: }
454: }
455: }
456:
457: }
458:
459: int gsdebug = 0;
460: stagen(){ /* generate the states */
461:
462: int i, j;
463: register c;
464: register struct wset *p, *q;
465:
466: /* initialize */
467:
468: nstate = 0;
469: /* THIS IS FUNNY from the standpoint of portability */
470: /* it represents the magic moment when the mem0 array, which has
471: /* been holding the productions, starts to hold item pointers, of a
472: /* different type... */
473: /* someday, alloc should be used to allocate all this stuff... for now, we
474: /* accept that if pointers don't fit in integers, there is a problem... */
475:
476: pstate[0] = pstate[1] = (struct item *)mem;
477: aryfil( clset.lset, tbitset, 0 );
478: putitem( prdptr[0]+1, &clset );
479: tystate[0] = MUSTDO;
480: nstate = 1;
481: pstate[2] = pstate[1];
482:
483: aryfil( amem, ACTSIZE, 0 );
484:
485: /* now, the main state generation loop */
486:
487: more:
488: SLOOP(i){
489: if( tystate[i] != MUSTDO ) continue;
490: tystate[i] = DONE;
491: aryfil( temp1, nnonter+1, 0 );
492: /* take state i, close it, and do gotos */
493: closure(i);
494: WSLOOP(wsets,p){ /* generate goto's */
495: if( p->flag ) continue;
496: p->flag = 1;
497: c = *(p->pitem);
498: if( c <= 1 ) {
499: if( pstate[i+1]-pstate[i] <= p-wsets ) tystate[i] = MUSTLOOKAHEAD;
500: continue;
501: }
502: /* do a goto on c */
503: WSLOOP(p,q){
504: if( c == *(q->pitem) ){ /* this item contributes to the goto */
505: putitem( q->pitem + 1, &q->ws );
506: q->flag = 1;
507: }
508: }
509: if( c < NTBASE ) {
510: state(c); /* register new state */
511: }
512: else {
513: temp1[c-NTBASE] = state(c);
514: }
515: }
516: if( gsdebug && (foutput!=NULL) ){
517: fprintf( foutput, "%d: ", i );
518: NTLOOP(j) {
519: if( temp1[j] ) fprintf( foutput, "%s %d, ", nontrst[j].name, temp1[j] );
520: }
521: fprintf( foutput, "\n");
522: }
523: indgo[i] = apack( &temp1[1], nnonter-1 ) - 1;
524: goto more; /* we have done one goto; do some more */
525: }
526: /* no more to do... stop */
527: }
528:
529: int cldebug = 0; /* debugging flag for closure */
530: closure(i){ /* generate the closure of state i */
531:
532: int c, ch, work, k;
533: register struct wset *u, *v;
534: int *pi;
535: int **s, **t;
536: struct item *q;
537: register struct item *p;
538:
539: ++zzclose;
540:
541: /* first, copy kernel of state i to wsets */
542:
543: cwp = wsets;
544: ITMLOOP(i,p,q){
545: cwp->pitem = p->pitem;
546: cwp->flag = 1; /* this item must get closed */
547: SETLOOP(k) cwp->ws.lset[k] = p->look->lset[k];
548: WSBUMP(cwp);
549: }
550:
551: /* now, go through the loop, closing each item */
552:
553: work = 1;
554: while( work ){
555: work = 0;
556: WSLOOP(wsets,u){
557:
558: if( u->flag == 0 ) continue;
559: c = *(u->pitem); /* dot is before c */
560:
561: if( c < NTBASE ){
562: u->flag = 0;
563: continue; /* only interesting case is where . is before nonterminal */
564: }
565:
566: /* compute the lookahead */
567: aryfil( clset.lset, tbitset, 0 );
568:
569: /* find items involving c */
570:
571: WSLOOP(u,v){
572: if( v->flag == 1 && *(pi=v->pitem) == c ){
573: v->flag = 0;
574: if( nolook ) continue;
575: while( (ch= *++pi)>0 ){
576: if( ch < NTBASE ){ /* terminal symbol */
577: SETBIT( clset.lset, ch );
578: break;
579: }
580: /* nonterminal symbol */
581: setunion( clset.lset, pfirst[ch-NTBASE]->lset );
582: if( !pempty[ch-NTBASE] ) break;
583: }
584: if( ch<=0 ) setunion( clset.lset, v->ws.lset );
585: }
586: }
587:
588: /* now loop over productions derived from c */
589:
590: c -= NTBASE; /* c is now nonterminal number */
591:
592: t = pres[c+1];
593: for( s=pres[c]; s<t; ++s ){
594: /* put these items into the closure */
595: WSLOOP(wsets,v){ /* is the item there */
596: if( v->pitem == *s ){ /* yes, it is there */
597: if( nolook ) goto nexts;
598: if( setunion( v->ws.lset, clset.lset ) ) v->flag = work = 1;
599: goto nexts;
600: }
601: }
602:
603: /* not there; make a new entry */
604: if( cwp-wsets+1 >= WSETSIZE ) error( "working set overflow" );
605: cwp->pitem = *s;
606: cwp->flag = 1;
607: if( !nolook ){
608: work = 1;
609: SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
610: }
611: WSBUMP(cwp);
612:
613: nexts: ;
614: }
615:
616: }
617: }
618:
619: /* have computed closure; flags are reset; return */
620:
621: if( cwp > zzcwp ) zzcwp = cwp;
622: if( cldebug && (foutput!=NULL) ){
623: fprintf( foutput, "\nState %d, nolook = %d\n", i, nolook );
624: WSLOOP(wsets,u){
625: if( u->flag ) fprintf( foutput, "flag set!\n");
626: u->flag = 0;
627: fprintf( foutput, "\t%s", writem(u->pitem));
628: prlook( &u->ws );
629: fprintf( foutput, "\n" );
630: }
631: }
632: }
633:
634: struct looksets *flset( p ) struct looksets *p; {
635: /* decide if the lookahead set pointed to by p is known */
636: /* return pointer to a perminent location for the set */
637:
638: register struct looksets *q;
639: int j, *w;
640: register *u, *v;
641:
642: for( q = &lkst[nlset]; q-- > lkst; ){
643: u = p->lset;
644: v = q->lset;
645: w = & v[tbitset];
646: while( v<w) if( *u++ != *v++ ) goto more;
647: /* we have matched */
648: return( q );
649: more: ;
650: }
651: /* add a new one */
652: q = &lkst[nlset++];
653: if( nlset >= LSETSIZE )error("too many lookahead sets" );
654: SETLOOP(j){
655: q->lset[j] = p->lset[j];
656: }
657: return( q );
658: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.