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