|
|
1.1 root 1: /*
2: * LALR-1 parser generator
3: * generation of lookahead sets
4: * the algorithm is thanks to Frank D. Remer & Thomas J Pennello,
5: * "Efficient computation of LALR(1) lookahead sets",
6: * SIGPLAN conference 1979.
7: */
8:
9: #include "yacc.h"
10: #include <assert.h>
11:
12: /* the size of SMAX must be related to the amount of space available
13: on the runtime stack for recursive calls to traverse.
14: (on systems which do not dynamically allocate the stack like RSX)
15: on RSX traverse takes up about 18 bytes per call which means that
16: with a 1024 byte stack we can probably make 50-55 levels of recursion
17: */
18: #define SMAX 100
19:
20: #define INFINITY 10000 /* infinity is small for a mathematician */
21: #define INITCODE 1
22: #define COPYCODE 2
23: #define UNIONCODE 3
24: #define EOFCODE 4
25: static struct
26: {
27: int s_last;
28: int s_vals[SMAX];
29: } stk; /* stack for digraph */
30:
31: static struct trans *transp; /* temporary vector for traverse */
32: static struct lset *lsetp, *fsetp;
33: static int nttrans;
34: int rread(), rincl();
35: struct lset *getset();
36:
37: genlook()
38: {
39: int code = EOFCODE;
40: rewopt();
41: cttrans();
42: transp = (struct trans *)yalloc(nttrans, sizeof *transp);
43: cdread();
44: rread(0);
45: rread(1);
46: digraph();
47: free(transp->t_trans->ng_rel);
48: rincl(0);
49: rincl(1);
50: digraph();
51: free(transp->t_trans->ng_rel);
52: free(transp);
53: fwrite(&code, sizeof code, 1, optout);
54: execute();
55: lookback();
56: }
57:
58: cdread()
59: {
60: register i, j, k;
61: struct state *stp, *stp1;
62: struct ntgo *ntp;
63: struct lset lset;
64: int code = INITCODE;
65:
66: for(i=0; i<nstates; i++) {
67: stp = &states[i];
68: for(j=0; j<stp->s_ntgo; j++) {
69: zerolset(&lset);
70: ntp = &stp->s_ntgos[j];
71: stp1 = &states[ntp->ng_st];
72: for(k=0; k<stp1->s_tgo; k++)
73: setbit(&lset, stp1->s_tgos[k].tg_trm);
74: fwrite(&code, sizeof code, 1, optout);
75: fwrite(&ntp, sizeof ntp, 1, optout);
76: fwrite(lset.l_bits, sizeof lset.l_bits, 1, optout);
77: }
78: }
79: }
80:
81:
82:
83: cttrans()
84: {
85: /* count number of nonterminal transations in automaton */
86: register i;
87:
88: nttrans = 0;
89: for(i=0; i<nstates; i++)
90: nttrans += states[i].s_ntgo;
91: }
92:
93: digraph()
94: {
95: register i;
96: stk.s_last = 0;
97: zerolev();
98: for(i=0; i<nttrans; i++)
99: if( transp[i].t_level==0 )
100: traverse(i);
101: }
102:
103: traverse(x)
104: register int x;
105: {
106: register i, y;
107: int k;
108: struct ntgo *ntp;
109: int code = UNIONCODE;
110:
111: if( stk.s_last>= (SMAX-1) )
112: yyerror(FATAL|NLNO, "internal stack overflow - SMAX");
113: stk.s_vals[++stk.s_last] = x;
114: k = stk.s_last;
115: transp[x].t_level = k;
116: ntp = transp[x].t_trans;
117:
118: for(i=0; i<ntp->ng_rel->r_count; i++) {
119: y = ntp->ng_rel->r_list[i];
120: if( transp[y].t_level==0 )
121: traverse(y);
122: if( transp[y].t_level < transp[x].t_level )
123: transp[x].t_level = transp[y].t_level;
124: fwrite(&code, sizeof code, 1, optout);
125: fwrite(&ntp, sizeof ntp, 1, optout);
126: fwrite(&transp[y].t_trans, sizeof ntp, 1, optout);
127: }
128:
129: code = COPYCODE;
130: if( transp[x].t_level == k ) {
131: transp[x].t_level = INFINITY;
132: while( (y = stk.s_vals[stk.s_last--]) != x ) {
133: transp[y].t_level = INFINITY;
134: fwrite(&code, sizeof code, 1, optout);
135: fwrite(&transp[y].t_trans, sizeof ntp, 1, optout);
136: fwrite(&ntp, sizeof ntp, 1, optout);
137: }
138: }
139: }
140:
141: /*
142: * form the set unions of the read sets and the follow sets, following
143: * the codes left in temp file by digraph
144: */
145: execute()
146: {
147: int code;
148: struct ntgo *ntp1, *ntp2;
149: register struct lset *csetp;
150:
151: rewopt();
152: csetp = lsetp = (struct lset *)yalloc(nttrans, sizeof *lsetp);
153: fsetp = NULL;
154: for(;;) {
155: if( fread(&code, sizeof code, 1, optout) != 1 )
156: yyerror(NLNO|FATAL, "eof on tempfile in execute");
157: switch( code ) {
158: case INITCODE:
159: fread(&ntp1, sizeof ntp1, 1, optout);
160: assert( csetp < &lsetp[nttrans] );
161: fread(csetp->l_bits, sizeof csetp->l_bits, 1, optout);
162: /*
163: fprintf(listout, "init: "); ptrans(ntp1);
164: prlset(csetp); fprintf(listout,"\n");
165: */
166: ntp1->ng_lset = csetp++;
167: break;
168:
169: case UNIONCODE:
170: fread(&ntp1, sizeof ntp1, 1, optout);
171: fread(&ntp2, sizeof ntp2, 1, optout);
172: /*
173: fprintf(listout, "union "); ptrans(ntp1); fprintf(listout," |=");
174: ptrans(ntp2);
175: */
176: setunion(ntp1->ng_lset, ntp2->ng_lset);
177: /*
178: prlset(ntp1->ng_lset); fprintf(listout, "\n");
179: */
180: break;
181:
182: case COPYCODE:
183: fread(&ntp1, sizeof ntp1, 1, optout);
184: fread(&ntp2, sizeof ntp2, 1, optout);
185: xxx("copy", ntp1, ntp2);
186: freeset(ntp1->ng_lset);
187: ntp1->ng_lset = getset();
188: copylset(ntp1->ng_lset, ntp2->ng_lset);
189: break;
190:
191: case EOFCODE:
192: return;
193: default:
194: yyerror(NLNO|FATAL, "bad temp file; code %o\n", code);
195: }
196: }
197: }
198:
199: lookback()
200: {
201: register i;
202:
203: for(i=0; i<nprod; i++)
204: reduce(prdptr[i]);
205:
206: }
207:
208: reduce(pp)
209: register struct prod *pp;
210: {
211: register nt, i;
212: struct sym *sp;
213: struct redn *rdp;
214: struct state *stp, *stp1;
215: int j, sno, sno1;
216: struct ntgo *ntp;
217:
218: nt = -pp->p_left;
219: sp = ntrmptr[nt-NTBASE];
220: for(j=0; j<sp->s_nstates; j++) {
221: stp = &states[sno = sp->s_states[j]];
222: for(i=0; i<stp->s_ntgo; i++) {
223: ntp = &stp->s_ntgos[i];
224: if( ntp->ng_nt == nt )
225: break;
226: }
227: assert(pp->p_prodno==0 || i<stp->s_ntgo);
228: sno1 = go2star(sno, pp->p_right, pp->p_right+prodl(pp));
229: stp1 = &states[sno1];
230: if( stp1->s_reds == (struct redn *)NULL ) { /* MWC DSC */
231: stp1->s_reds = (struct redn *)yalloc(stp1->s_nred, sizeof *stp1->s_reds);
232: stp1->s_nred = 0;
233: }
234: rdp = stp1->s_reds;
235: for(i=0; i<stp1->s_nred; i++,rdp++)
236: if( rdp->rd_prod==pp )
237: break;
238: if( yydebug ) {
239: fprintf(listout, "(%d, pdn %d) ", sno1, pp->p_prodno);
240: prlset(ntp->ng_lset);
241: fprintf(listout, "\n");
242: }
243: if( i==stp1->s_nred ) {
244: rdp->rd_prod = pp;
245: rdp->rd_lset = getset();
246: if( pp->p_prodno!=0 ) {
247: copylset(rdp->rd_lset, ntp->ng_lset);
248: } else {
249: zerolset(rdp->rd_lset);
250: setbit(rdp->rd_lset, EOFNO);
251: }
252: stp1->s_nred++;
253: } else {
254: setunion(rdp->rd_lset, ntp->ng_lset);
255: }
256: }
257: }
258:
259: go2star(sno, ip, fin)
260: register *ip;
261: int *fin;
262: {
263: register i;
264: register struct state *stp;
265:
266: while( ip!=fin ) {
267: stp = &states[sno];
268: if( *ip>=NTBASE ) {
269: for(i=0; i<stp->s_ntgo; i++)
270: if( stp->s_ntgos[i].ng_nt == *ip )
271: break;
272: assert(i<stp->s_ntgo);
273: sno = stp->s_ntgos[i].ng_st;
274: } else {
275: for(i=0; i<stp->s_tgo; i++)
276: if( stp->s_tgos[i].tg_trm == *ip )
277: break;
278: assert(i<stp->s_tgo);
279: sno = stp->s_tgos[i].tg_st;
280: }
281: ip++;
282: }
283: return(sno);
284: }
285:
286: rread(todo)
287: {
288: struct state *stp;
289: register struct sym *sp;
290: register i, j;
291: int p;
292: struct ntgo *ntp;
293:
294: if( todo )
295: zerolev();
296: else
297: startcount();
298:
299: for(i=0; i<nttrans; i++) {
300: stp = &states[transp[i].t_trans->ng_st];
301: for(j=0; j<stp->s_ntgo; j++) {
302: ntp = &stp->s_ntgos[j];
303: sp = ntrmptr[ntp->ng_nt-NTBASE];
304: if( sp->s_flags&DERIV ) {
305: p = transp[i].t_level++;
306: if( todo ) {
307: transp[i].t_trans->ng_rel->r_list[p] =
308: rsearch(ntp);
309: xxx("reads",transp[i].t_trans,ntp);
310: }
311: break;
312: }
313: }
314: }
315: if( !todo )
316: endcount();
317: }
318:
319: rincl(todo)
320: {
321: register i, j;
322: int *pb, *pe, k, p, sno, sno1, ind, nt;
323: struct state *stp;
324: struct prod *pp;
325: struct ntgo *ntp;
326: struct sym *sp;
327:
328: if( todo )
329: zerolev();
330: else
331: startcount();
332: for(i=0; i<nttrans; i++) {
333: sno = ssearch(transp[i].t_trans);
334: sp = ntrmptr[transp[i].t_trans->ng_nt-NTBASE];
335: for(j=0; j<sp->s_nprods; j++) {
336: pp = sp->s_prods[j];
337: pb = pp->p_right;
338: pe = pb + prodl(pp);
339: while( pb <= --pe && (nt = *pe) >= NTBASE ) {
340: sno1 = go2star(sno, pb, pe);
341: stp = &states[sno1];
342: for(k=0; k<stp->s_ntgo; k++)
343: if( stp->s_ntgos[k].ng_nt==nt )
344: break;
345: assert(k<stp->s_ntgo);
346: ind = rsearch(&stp->s_ntgos[k]);
347: p = transp[ind].t_level++;
348: if( todo ) {
349: ntp = transp[ind].t_trans;
350: xxx("includes", ntp, transp[i].t_trans);
351: ntp->ng_rel->r_list[p] = i;
352: }
353: if( (ntrmptr[nt-NTBASE]->s_flags&DERIV)==0 )
354: break;
355: }
356: }
357: }
358: if( !todo )
359: endcount();
360: }
361:
362: endcount()
363: {
364: register i, k, *relp; /* relp must be integer pointer */
365: struct ntgo *ntp;
366: k = 0;
367: for(i=0; i<nttrans; i++)
368: {
369: k += transp[i].t_level+1; /* include 1 for count */
370: }
371: relp = (int *)yalloc(k, sizeof *relp);
372: for(i=0; i<nttrans; i++) {
373: ntp = transp[i].t_trans;
374: ntp->ng_rel = relp;
375: ntp->ng_rel->r_count = transp[i].t_level;
376: relp += transp[i].t_level+1;
377: }
378: }
379:
380: startcount()
381: {
382: register i, j, k;
383: struct state *stp;
384:
385: k = 0;
386: for(i=0; i<nstates; i++) {
387: stp = &states[i];
388: for(j=0; j<stp->s_ntgo; j++) {
389: transp[k].t_trans = &stp->s_ntgos[j];
390: transp[k].t_level = 0;
391: k++;
392: }
393: }
394: }
395:
396: zerolev()
397: {
398: register i;
399: for(i=0; i<nttrans; i++)
400: transp[i].t_level = 0;
401: }
402:
403: rsearch(ntp)
404: struct ntgo *ntp;
405: {
406: register lb, nb;
407: register struct ntgo *el;
408: int ub;
409:
410: lb = 0;
411: ub = nttrans-1;
412: do {
413: nb = (ub+lb)/2;
414: if( (el = transp[nb].t_trans) < ntp )
415: lb = nb+1;
416: else if( el > ntp )
417: ub = nb-1;
418: else
419: return(nb);
420: } while( lb<=ub );
421: yyerror(NLNO|FATAL, "oops in rsearch");
422: }
423:
424: ssearch(ntp)
425: struct ntgo *ntp;
426: {
427: register lb, nb;
428: register struct ntgo *el;
429: int ub;
430:
431: lb = 0;
432: ub = nstates-1;
433:
434: do {
435: nb = (ub+lb) / 2;
436: el = states[nb].s_ntgos;
437: if( ntp < el )
438: ub = nb-1;
439: else if( ntp >= &el[states[nb].s_ntgo] )
440: lb = nb+1;
441: else
442: return(nb);
443: } while( lb<=ub );
444: yyerror(NLNO|FATAL, "oops in ssearch");
445: }
446:
447: prodl(pp)
448: register struct prod *pp;
449: {
450: register *ip;
451:
452: ip = pp->p_right;
453: while( *ip++ != -1 );
454: return( ip-pp->p_right-1 ); /* BONZO OR NO??? */
455: }
456:
457: struct lset *
458: getset()
459: {
460: register struct lset *lp;
461: if( fsetp ) {
462: lp = fsetp;
463: fsetp = fsetp->l_next;
464: return(lp);
465: }
466: lp = (struct lset *)yalloc(1, sizeof *lp);
467: return(lp);
468: }
469:
470: freeset(lp)
471: struct lset *lp;
472: {
473: lp->l_next = fsetp;
474: fsetp = lp;
475: }
476:
477: frlset()
478: {
479: register struct state *stp;
480: register i, j;
481: struct lset *lp, *lp1;
482:
483: free(states[0].s_tgos);
484: free(states[0].s_ntgos);
485: for(i=0; i<nstates; i++) {
486: stp = &states[i];
487: for(j=0; j<stp->s_nred; j++)
488: freeset(stp->s_reds[j].rd_lset);
489: if( stp->s_reds != (struct redn *)NULL ) /* MWC DSC */
490: free(stp->s_reds);
491: for(j=0; j<stp->s_ntgo; j++)
492: freeset(stp->s_ntgos[j].ng_lset);
493: }
494: lp = fsetp;
495: while( lp ) {
496: lp1 = lp->l_next;
497: if( lp<&lsetp[0] || lp>=&lsetp[nttrans] )
498: free(lp);
499: lp = lp1;
500: }
501: free(lsetp);
502: }
503:
504: xxx(s, ntp1, ntp2)
505: char *s;
506: struct ntgo *ntp1, *ntp2;
507: {
508: if( !yydebug )
509: return;
510: ptrans(ntp1); fprintf(listout, " %s ", s); ptrans(ntp2);
511: fprintf(listout, "\n");
512: }
513: ptrans(ntp)
514: struct ntgo *ntp;
515: {
516: int sno;
517: sno = ssearch(ntp);
518: fprintf(listout, "(%d, %s)", sno, ptosym(ntp->ng_nt));
519: }
520:
521: prlset(ls)
522: struct lset *ls;
523: {
524: register i, once;
525: fprintf(listout, "[");
526: once = 0;
527: for(i=first(ls); i>=0; i=next(ls,i)) {
528: if( once++ ) fprintf(listout, ",");
529: fprintf(listout, "%s", trmptr[i]->s_name);
530: }
531: fprintf(listout, "]");
532: }
533:
534:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.