new template
[unix-history] / usr / src / usr.bin / pascal / eyacc / ey4.c
CommitLineData
15308f90
KM
1/*
2 * Copyright (c) 1979 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8static char sccsid[] = "@(#)ey4.c 5.1 (Berkeley) %G%";
9#endif not lint
10
11# include "ey.h"
12
13output(){ /* print the output for the states */
14
15 int i, j, k, c;
16
17 settab();
18 arrset("yyact");
19
20 for( i=0; i<nstate; ++i ){ /* output the stuff for state i */
21 nolook = (tystate[i]==0);
22 closure(i);
23 /* output actions */
24 aryfil( temp1, nterms+1, 0 );
25 for( j=0; j<cwset; ++j ){ /* look at the items */
26 c = *( wsets[j].pitem );
27 if( c>0 && c<NTBASE && temp1[c]==0 ) temp1[c] = go2(i,c);
28 }
29
30 if( i == 1 ) temp1[1] = ACCEPTCODE;
31
32 /* now, we have the shifts; look at the reductions */
33
34 lastred = 0;
35 for( j=0; j<cwset; ++j ){
36 c = *( wsets[j].pitem );
37 if( c<=0 ){ /* reduction */
38 lastred = -c;
39 for( k=1; k<=nterms; ++k ){
40 if( ((wsets[j].ws[k>>4])&(1<<(k&017))) != 0 ) {
41 if( temp1[k] == 0 ) temp1[k] = c;
42 else if( temp1[k]<0 ){ /* reduce/reduce conflict */
43 settty();
44 fprintf( cout , "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s",
45 i, -temp1[k], lastred, symnam(k) );
46 if( -temp1[k] > lastred ) temp1[k] = -lastred;
47 ++zzrrconf;
48 settab();
49 }
50 else { /* potential shift/reduce conflict */
51 switch( precftn( lastred, k ) ) {
52
53 case 0: /* precedence does not apply */
54
55 settty();
56 fprintf( cout , "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i,
57 temp1[k], lastred, symnam(k) );
58 ++zzsrconf;
59 settab();
60 /* resolve in favor of shifting, so remove from reduce set */
61 wsets[j].ws[k>>4] &=~ (1<<(k&017));
62 break;
63
64 case 1: /* reduce */
65
66 temp1[k] = -lastred;
67 break;
68
69 case 2: /* error, binary operator */
70
71 temp1[k] = ERRCODE;
72 break;
73
74 case 3: /* shift ... leave the entry alone */
75
76 break;
77 }
78 }
79 }
80 }
81 }
82 }
83 wract(i);
84 }
85
86 settab();
87 arrdone();
88
89 /* now, output the pointers to the action array */
90 /* also output the info about reductions */
91 prred();
92 }
93
94prred(){ /* print the information about the actions and the reductions */
95 int index, i;
96
97 arrset("yypact");
98 index = 1; /* position in the output table */
99
100 for( i=0; i<nstate; ++i ){
101 if( tystate[i]>0 ){ /* the state is real */
102 temp1[i] = index;
103 arrval( index );
104 index += tystate[i];
105 }
106 else {
107 arrval( temp1[-tystate[i]] );
108 }
109 }
110
111 arrdone();
112
113 arrset("yyr1");
114 for( i=1; i<nprod; ++i ) arrval( *prdptr[i] - NTBASE );
115 arrdone();
116
117 arrset("yyr2");
118 for( i=1; i<nprod; ++i ) arrval( ( prdptr[i+1]-prdptr[i]-2 ) );
119 arrdone();
120
121 }
122
123go2(i,c){ /* do a goto on the closure state, not worrying about lookaheads */
124 if( c<NTBASE ) return( amem[ apstate[i]+c ] );
125 else return( amem[ apstate[i] + c - NTBASE + nterms ] );
126 }
127
128int pkdebug = 0;
129apack(p, n ) int *p;{ /* pack state i from temp1 into amem */
130 _REGISTER k, l, off;
131 int j;
132
133 /* find the spot */
134
135 j = n;
136 for( off = 0; off <= j && p[off] == 0; ++off ) ;
137 if( off > j ){ /* no actions */
138 return(0);
139 }
140 j -= off;
141 for( k=0; k<actsiz; ++k ){
142 for( l=0; l<=j; ++l ){
143 if( p[off+l] != 0 ){
144 if( p[off+l] != amem[k+l] && amem[k+l] != 0 ) goto nextk;
145 }
146 }
147 if( pkdebug ){ settty(); fprintf( cout , "off = %d, k = %d\n", off, k ); }
148 /* we have found an acceptable k */
149 for( l=0; l<=j; ++l ){
150 if( p[off+l] ){
151 if( k+l >= actsiz ) error("action table overflow");
152 if( k+l >= memact ) memact = k+l;
153 amem[k+l] = p[off+l];
154 }
155 }
156 if( pkdebug ){
157 for( k=0; k<memact; k+=10){
158 fprintf( cout , "\t");
159 for( l=0; l<=9; ++l ) fprintf( cout , "%d ", amem[k+l] );
160 fprintf( cout , "\n");
161 }
162 }
163 return(k-off);
164
165 nextk: ;
166 }
167 error("no space in action table");
168 }
169
170go2out(){ /* output the gotos for the nontermninals */
171 int i, j, k, best, offset, count, cbest, times;
172
173 settab();
174 arrset("yygo");
175 offset = 1;
176
177 for( i=1; i<=nnonter; ++i ) {
178 go2gen(i);
179
180 /* find the best one to make default */
181
182 temp2[i] = offset;
183
184 best = -1;
185 times = 0;
186
187 for( j=0; j<=nstate; ++j ){ /* is j the most frequent */
188 if( tystate[j] == 0 ) continue;
189 if( tystate[j] == best ) continue;
190
191 /* is tystate[j] the most frequent */
192
193 count = 0;
194 cbest = tystate[j];
195
196 for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count;
197
198 if( count > times ){
199 best = cbest;
200 times = count;
201 }
202 }
203
204 /* best is now the default entry */
205
206 zzgobest += (times-1)*2;
207 settab();
208 for( j=0; j<=nstate; ++j ){
209 if( tystate[j] != 0 && tystate[j]!=best ){
210 arrval( j );
211 arrval( tystate[j] );
212 offset += 2;
213 zzgoent += 2;
214 }
215 }
216
217 /* now, the default */
218
219 zzgoent += 2;
220 arrval( -1 );
221 arrval( best );
222 offset += 2;
223
224 }
225
226 arrdone();
227
228 arrset("yypgo");
229 for( i=1; i<=nnonter; ++i ) arrval( temp2[i] );
230 arrdone();
231
232 }
233
234int g2debug = 0;
235go2gen(c){ /* output the gotos for nonterminal c */
236
237 int i, work, cc;
238 struct item *p, *q;
239
240 /* first, find nonterminals with gotos on c */
241
242 aryfil( temp1, nnonter+1, 0 );
243 temp1[c] = 1;
244
245 work = 1;
246 while( work ){
247 work = 0;
248 for( i=0; i<nprod; ++i ){
249 if( (cc=prdptr[i][1]-NTBASE) >= 0 ){ /* cc is a nonterminal */
250 if( temp1[cc] != 0 ){ /* cc has a goto on c */
251 cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */
252 if( temp1[cc] == 0 ){
253 work = 1;
254 temp1[cc] = 1;
255 }
256 }
257 }
258 }
259 }
260
261 /* now, we have temp1[c] = 1 if a goto on c in closure of cc */
262
263 if( g2debug ){
264 settty();
265 fprintf( cout , "%s: gotos on ", nontrst[c].name );
266 for( i=0; i<=nnonter; ++i ) if( temp1[i]) fprintf( cout , "%s ", nontrst[i].name);
267 fprintf( cout , "\n");
268 }
269
270 /* now, go through and put gotos into tystate */
271
272 aryfil( tystate, nstate, 0 );
273 settty();
274 fprintf( cout , "\nnonterminal %s\n", nontrst[c].name );
275 for( i=0; i<nstate; ++i ){
276 q = pstate[i+1];
277 for( p=pstate[i]; p<q; ++p ){
278 if( (cc= *p->pitem) >= NTBASE ){
279 if( temp1[cc -= NTBASE] ){ /* goto on c is possible */
280 tystate[i] = amem[indgo[i]+c];
281 break;
282 }
283 }
284 }
285 if( tystate[i] ) fprintf( cout , "\t%d\t%d\n", i, tystate[i]);
286 }
287 }
288
289precftn(r,t){ /* decide a shift/reduce conflict by precedence.
290 Returns 0 if action is 'do nothing',1 if action is reduce,
291 2 if the action is 'error,binary operator'
292 and 3 if the action is 'reduce'. */
293
294 int lp,lt;
295 lp = levprd[r];
296 lt = trmlev[t];
297 if ((lt==0)||((lp&03)==0))return(0);
298 if((lt>>3) == (lp>>3)){
299 return(lt&03);
300 }
301 if((lt>>3) > (lp>>3)) return(3);
302 return(1);
303 }
304
305int cdebug = 0; /* debug for common states */
306wract(i){ /* output state i */
307 /* temp1 has the actions, lastred the default */
308 int p, p0, p1, size;
309 int ntimes, tred, count, j, k;
310 struct item *q0, *q1;
311
312 /* find the best choice for lastred */
313
314 lastred = 0;
315 ntimes = 0;
316 stateflags[i] = 0;
317 /***** UCB MOD - full state spec if shift on error *****/
318 if (temp1[2] > 0)
319 stateflags[i] |= NEEDSREDUCE;
320 else for( j=1; j<=nterms; ++j ){
321 /* find the entry on which the greatest number of reductions are done */
322 if( temp1[j] >= 0 ) continue;
323 if( temp1[j]+lastred == 0 ) continue;
324 /* count the number of appearances of temp1[j] */
325 count = 0;
326 tred = -temp1[j];
327 for( p=1; p<=nterms; ++p ){
328 if( temp1[p]+tred == 0 ) ++count;
329 }
330 if( count >ntimes ){
331 lastred = tred;
332 ntimes = count;
333 }
334 }
335
336 /* clear out entries in temp1 which equal lastred */
337 /* ie, make the most frequent reduction into the default reduction */
338 for( p=1; p<= nterms; ++p ) if( temp1[p]+lastred == 0 )temp1[p]=0;
339
340 /* write out the state */
341
342 /* first, check for equality with another state */
343 /* see if there is a nonterminal with all dots before it, */
344 /* and no reductions in the state */
345 /* this is done by checking if all items are the same non-terminal */
346 p0 = 0;
347 q1 = pstate[i+1];
348 for( q0=pstate[i]; q0<q1; ++q0 ){
349 if( (p1= *(q0->pitem) ) < NTBASE ) goto standard;
350 if( p0 == 0 ) p0 = p1;
351 else if( p0 != p1 ) goto standard;
352 }
353 stateflags[i] |= SINGLE_NT | pempty[p0 - NTBASE];
354
355 /* now, all items have dots before p0 */
356 if( cdebug ){
357 settty();
358 fprintf( cout , "state %d, pre-nonterminal %s\n",i,nontrst[p0-NTBASE].name);
359 }
360
361 for( j=0; j<i; ++j ){
362 /*
363 * check that the states have the same shift lookaheads.
364 */
365 if( apstate[i] != apstate[j] )
366 continue;
367 if (cdebug)
368 fprintf(cout, "states %d and %d have same shift lookaheads\n",i,j);
369
370 /*
371 * Check that state has one item, and that the item matches.
372 */
373 if ((stateflags[j] & SINGLE_NT) == 0 || *(pstate[j]->pitem) != p0)
374 continue;
375
376 /*
377 * Check that enumeration and reduce lookaheads are the same.
378 */
379 if ((stateflags[i]&(GENLAMBDA|NEEDSREDUCE)) == (GENLAMBDA|NEEDSREDUCE)) {
380 /*
381 * p0 derives lambda.
382 * state[i] needs full reduce lookahead
383 * state[j] has full reduce lookahead
384 */
385 if ((stateflags[j] & NEEDSREDUCE) == 0)
386 error("state %d does not need full reduce", j);
387 if (lambdarule < 0)
388 error("missing lambda rule definition in state %d", i);
389 if (lookstate[j] == 0)
390 error("state %d lookahead was not saved", j);
391 /* must check lookaheads */
392 for (k = 0; k < tbitset; ++k)
393 if (lastate[lookstate[j]].lset[k] != wsets[lambdarule].ws[k])
394 /* cannot merge states */ goto nextj;
395 }
396
397 /* we have a match with state j ! */
398
399 if( cdebug ){
400 settty();
401 fprintf( cout , "state %d matches state %d\n", i, j);
402 }
403 tystate[i] = -j;
404 zzacsave += tystate[j];
405 zznsave++;
406 wrstate(i);
407 /* merged, so no need for future consideration */
408 stateflags[i] = 0;
409 return;
410
411 nextj: ;
412 }
413
414
415 standard:
416 tystate[i] = 2;
417 wrstate(i);
418 if ((stateflags[i] & (SINGLE_NT|NEEDSREDUCE|GENLAMBDA)) ==
419 (SINGLE_NT|NEEDSREDUCE|GENLAMBDA)) {
420 if (savedlook + 1 >= maxlastate) {
421 settty();
422 fprintf(cout,
423 "Warning: _maxlastate too small (%d), state packing impared\n",
424 maxlastate);
425 /* cannot consider future merger with this state */
426 stateflags[i] = 0;
427 } else {
428 if( cdebug ){
429 settty();
430 fprintf( cout , "save lookahead for state %d\n", i);
431 }
432 lookstate[i] = savedlook;
433 for (k = 0; k < tbitset; ++k)
434 lastate[savedlook].lset[k] = wsets[lambdarule].ws[k];
435 savedlook++;
436 }
437 }
438
439 size = 0;
440 for( p0=1; p0<=nterms; ++p0 )
441 if( (p1=temp1[p0])!=0 ) {
442 /***** UCB MOD - test actions are negative of symbol to be tested
443 this speeds up the parser as it is easy to check for
444 *****/
445 arrval( -trmset[p0].value );
446 if( p1 < 0 ) arrval( REDUCACT - p1 );
447 else if( p1 == ACCEPTCODE ) arrval( ACCEPTACT );
448 else if( p1 == ERRCODE ) arrval( ERRACT );
449 else arrval( SHIFTACT + p1 );
450 size += 2;
451 }
452 if( lastred ) arrval( REDUCACT + lastred );
453 else arrval( ERRACT );
454 tystate[i] = size+1; /* store entry size in tystate */
455 zzacent += (size+1);
456 return;
457 }
458
459wrstate(i){ /* writes state i */
460 int j0,j1,s;
461 struct item *pp, *qq;
462 settty();
463 fprintf( cout , "\nstate %d\n",i);
464 qq = pstate[i+1];
465 for( pp=pstate[i]; pp<qq; ++pp) fprintf( cout , "\t%s\n", writem(pp));
466
467 /* check for state equal to another */
468
469 if( tystate[i] <= 0 ){
470 fprintf( cout , "\n\tsame as %d\n\n", -tystate[i] );
471 return;
472 }
473
474 for( j0=1; j0<=nterms; ++j0 ) if( (j1=temp1[j0]) != 0 ){
475 fprintf( cout , "\n\t%s ", symnam(j0) );
476 if( j1>0 ){ /* shift, error, or accept */
477 if( j1 == ACCEPTCODE ) fprintf( cout , "accept" );
478 else if( j1 == ERRCODE ) fprintf( cout , "error" );
479 else fprintf( cout , "shift %d", j1 );
480 }
481 else fprintf( cout , "reduce %d",-j1 );
482 }
483
484 /* output the final production */
485
486 if( lastred ) fprintf( cout , "\n\t. reduce %d\n\n", lastred );
487 else fprintf( cout , "\n\t. error\n\n" );
488
489ret:
490 settab();
491 }