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