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