|
|
1.1 root 1: /* (c) 1979 Regents of the University of California */
2: # include "ey.h"
3: /* * * * * e y a c c * * * * */
4:
5: /**** NB -----
6: *
7: * This version of yacc, known as "eyacc" has been slightly but
8: * importantly modified to allow error recovery in the UNIX Pascal
9: * translator "pi" and also in "pix".
10: *
11: * Changes here include:
12: *
13: * 1) Enumeration of test actions when "error" is an input token.
14: *
15: * 2) Change to the encoding of the action entries. Test entries
16: * are encoded as the arithmetic inverse of the symbol being tested
17: * for. This is an optimization that makes the parser run at the
18: * same speed even though, with error productions and enumerated
19: * lookaheads, it would normally be much slower. Of course the
20: * same thing could be done to the regular yacc...
21: *
22: * 3) Different table sizes
23: *
24: * 4) Recognizes form feeds
25: *
26: * 5) Also most of the numbers for the sizes of the tables have been
27: * increased, to an extent to allow for "eyacc"ing of the Pascal grammar
28: * and of a grammar which I have for "EUCLID".
29: *
30: * There seem to be subtle dependencies between the various magic
31: * numbers... I found some of them but to be safe most of the limits
32: * are very generous... for this reason "eyacc" will most likely
33: * have to run separate i/d... no matter.
34: *
35: * Bill Joy
36: * Computer Science Division
37: * EECS Department
38: * University of California, Berkeley
39: * Berkeley, California 94704
40: *
41: * Office: (415) 642-4948
42: * Home: (415) 524-4510
43: ****/
44:
45: /* features to be fixed up ...
46:
47: *** Print estimate of total space needed for parser
48: *** Either list inputs on y.output, or list empty prdn's in states
49: *** Mention nonterms not used (or, rules. not reduced) as nonfatal error
50: *** Output states where conflicts were found by default on y.output
51: *** Engage in newspeak: production=>grammar rules, term=>token, etc.
52: *** handle # define, #ifdef, etc., in yacc actions, %{ %}
53: */
54:
55: /* new features to be added
56:
57: *** reductions by single productions ( by request )
58: *** follow sets for start symbol
59: *** option to only do slr(1)
60: *** easily changed array names on output
61: *** allocate core, rather than predefined
62: *** input controlled by a grammar
63: *** support multiple choices for conflicts
64: *** better conflict diagnostics
65: */
66:
67: extern char *symnam();
68:
69: main(argc,argv) int argc; char *argv[]; {
70: auto int n;
71:
72: whereami();
73: setup(argc,argv); /* initialize and read productions */
74: tbitset = (nterms+16)/16;
75: cpres(); /* make table of which productions yield a given nonterminal */
76: cempty(); /* make a table of which nonterminals can match the empty string */
77: cpfir(); /* make a table of e free first lists */
78: stagen(); /* generate the states */
79: output(); /* write the states and the tables */
80: go2out();
81: summary();
82: windup();
83: }
84:
85: whereami(){ /* sets the variable machine to UNIX, GCOS, or IBM */
86:
87: int i;
88:
89: i = 1;
90: i = i << 30;
91: if( i == 0 ) {
92: machine = UNIX;
93: return;
94: }
95: i = i << 4;
96: if( i == 0 ){
97: machine = IBM;
98: return;
99: }
100: machine = GCOS;
101: }
102:
103: windup(){
104: /* no errors, do the optimization if appropriate */
105: char *cp;
106: int i;
107:
108: cflush(1);
109: if( !oflag ) cexit(0);
110:
111: for( i=3; i<10; ++i ) cclose(i);
112: switch( machine ){
113:
114: case GCOS:
115: if( rflag ){
116: if( foutput<0 ) system( "./yopt -r" );
117: else system( "./yopt -rv" );
118: }
119: else {
120: if( foutput<0 ) system( "./yopt" );
121: else system( "./yopt -v" );
122: }
123: cexit(0); /* terminate */
124:
125: case UNIX:
126: cp = "/usr/nlib/yaccopt";
127: if( rflag ) execl( cp, cp, (foutput<0)?"-r":"-rv", 0 );
128: else if( foutput<0 ) execl( cp, cp, 0 );
129: else execl( cp, cp, "-v", 0 );
130: error( "optimization execl call fails" );
131:
132: case IBM:
133: if( rflag ){
134: if( foutput<0 ) system( "MH2019.yaccopt -r" );
135: else system( "MH2019.yaccopt -rv" );
136: }
137: else {
138: if( foutput<0 ) system( "MH2019.yaccopt" );
139: else system( "MH2019.yaccopt -v" );
140: }
141: cexit(0);
142:
143: }
144:
145: }
146:
147: settty()
148: /* sets the output file to y.output */
149: {
150: cflush( foutput ); /* a bit of a cheat */
151: cout = foutput;
152: }
153:
154: settab(){ /* sets the output file to y.tab.c */
155:
156: cflush( ftable );
157: cout = ftable;
158: }
159:
160: char *chcopy( p, q ) char *p, *q; {
161: /* copies string q into p, returning next free char ptr */
162: while( *p = *q++ ) ++p;
163: return( p );
164: }
165:
166: char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */
167: int i,*p;
168: static char sarr[100];
169: char *q;
170:
171: for( p=pp->pitem; *p>0 ; ++p ) ;
172: p = prdptr[-*p];
173: q = chcopy( sarr, nontrst[*p-NTBASE].name );
174: q = chcopy( q, " : " );
175:
176: for(;;){
177: *q++ = ++p==(pp->pitem) ? '_' : ' ';
178: if((i = *p) <= 0) break;
179: q = chcopy( q, symnam(i) );
180: }
181:
182: *q = '\0' ;
183: return( sarr );
184: }
185:
186: char *symnam(i){ /* return a pointer to the name of symbol i */
187: char *cp;
188:
189: cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ;
190: if( *cp == ' ' ) ++cp;
191: return( cp );
192: }
193:
194: summary(){ /* output the summary on the tty */
195:
196: int i, s, *pn;
197:
198:
199: if( !rflag ){
200: settab();
201: fprintf( cout , "\nint nterms %d;",nterms);
202: fprintf( cout , "\nint nnonter %d;", nnonter);
203: fprintf( cout , "\nint nstate %d;", nstate);
204: fprintf( cout , "\nchar *yysterm[] {");
205: for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) fprintf( cout , "\n\"%s\",",symnam(i));
206: fprintf( cout , "\n0 };\n" );
207: fprintf( cout , "\nchar *yysnter[] {");
208: for (i=0;i<nnonter;i++) fprintf( cout , "\n\"%s\",",nontrst[i].name);
209: fprintf( cout , "\n\"%s\" };\n",nontrst[nnonter].name);
210: }
211:
212: settty();
213: fprintf( cout , "\n%d/%d terminals, %d/%d nonterminals\n", nterms, tlim,
214: nnonter, ntlim );
215: fprintf( cout , "%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize );
216: fprintf( cout , "%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf );
217: pn = pstate[nstate+1];
218: fprintf( cout , "%d/%d working sets used\n", zzcwset, wssize );
219: fprintf( cout , "memory: states,etc. %d/%d, parser %d/%d\n", pn-mem0, memsiz,
220: memact, actsiz );
221: fprintf( cout , "%d/%d distinct lookahead sets\n", nlset, lsetsz );
222: fprintf( cout , "%d extra closures\n", zzclose - 2*nstate );
223: fprintf( cout , "%d action entries\n", zzacent );
224: fprintf( cout , "%d action entries saved through merging %d states\n",zzacsave,zznsave);
225: fprintf( cout , "%d goto entries\n", zzgoent );
226: fprintf( cout , "%d entries saved by goto default\n", zzgobest );
227: if( zzsrconf!=0 || zzrrconf!=0 ){
228: cflush( errfileno );
229: cout = errfileno;
230: fprintf( cout , "\nconflicts: ");
231: if( zzsrconf )fprintf( cout , "%d shift/reduce" , zzsrconf );
232: if( zzsrconf && zzrrconf )fprintf( cout , ", " );
233: if( zzrrconf )fprintf( cout , "%d reduce/reduce" , zzrrconf );
234: fprintf( cout , "\n" );
235: }
236: }
237:
238: error(s,a1){ /* write out error comment */
239:
240: int c;
241: ++nerrors;
242: cflush( errfileno );
243: cout = errfileno; /* set output to tty */
244: fprintf( cout , "\n fatal error: ");
245: fprintf( cout , s,a1);
246: fprintf( cout , ", line %d\n", lineno );
247: if( !fatfl ) return;
248: summary();
249: cexit(1);
250: }
251:
252: arrset(s) char s[]; {
253: fprintf( cout , "\nint %s[] {0", s );
254: arrndx = 1;
255: }
256:
257: arrval(n){
258: fprintf( cout , ",%d",n);
259: if( (++arrndx%10) == 0 ) fprintf( cout , "\n");
260: }
261:
262: arrdone(){
263: fprintf( cout , ",-1};\n");
264: }
265:
266: copy(v) char *v; { /* copy ctokn to v */
267: char *p;
268:
269: p=ctokn;
270: while( *v++ = *p++ );
271: }
272:
273: compare(v) char *v; { /* compare ctokn with v */
274: char *p;
275:
276: for( p=ctokn; ; ++p ){
277: if( *p != *v++ ) return( 0 );
278: if( *p == 0 ) return(1);
279: }
280: }
281:
282: int *yalloc(n){ /* allocate n+1 words from vector mem */
283: int *omem;
284: omem = mem;
285: mem += n+1;
286: if(mem-mem0 >= memsiz) error("memory overflow");
287: return(omem);
288: }
289:
290: aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */
291: int i;
292: for( i=0; i<n; ++i ) v[i] = c;
293: }
294:
295: UNION( a, b, c ) int *a, *b, *c; {
296: /* set a to the UNION of b and c */
297: /* a may equal b */
298: /* return 1 if c is not a subset of b, 0 otherwise */
299:
300: _REGISTER int i, x, sub;
301:
302: sub = 0;
303: for( i=0; i<tbitset; ++i ){
304: x = b[i] | c[i];
305: if( x != b[i] ) sub=1;
306: a[i] = x;
307: }
308: return( sub );
309: }
310:
311: prlook( pp ) int *pp;{
312: int j;
313: pp = pp->lset;
314: if( pp == 0 ) fprintf( cout , "\tNULL");
315: else {
316: fprintf( cout , " { " );
317: for( j=1; j<=nterms; ++j ){
318: if( (pp[j>>4]>>(j&017) )&01 != 0 ) fprintf( cout , "%s ", symnam(j) );
319: }
320: fprintf( cout , "}" );
321: }
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.