xref: /original-bsd/usr.bin/yacc/verbose.c (revision b3f911e0)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Paul Corbett.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #ifndef lint
22 static char sccsid[] = "@(#)verbose.c	5.1 (Berkeley) 12/25/89";
23 #endif /* not lint */
24 
25 #include "defs.h"
26 
27 
28 static short *null_rules;
29 
30 verbose()
31 {
32     register int i;
33 
34     if (!vflag) return;
35 
36     null_rules = (short *) MALLOC(nrules*sizeof(short));
37     if (null_rules == 0) no_space();
38     fprintf(verbose_file, "\f\n");
39     for (i = 0; i < nstates; i++)
40 	print_state(i);
41     FREE(null_rules);
42 
43     if (nunused)
44 	log_unused();
45     if (SRtotal || RRtotal)
46 	log_conflicts();
47 
48     fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
49 	    nvars);
50     fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
51 }
52 
53 
54 log_unused()
55 {
56     register int i;
57     register short *p;
58 
59     fprintf(verbose_file, "\n\nRules never reduced:\n");
60     for (i = 3; i < nrules; ++i)
61     {
62 	if (!rules_used[i])
63 	{
64 	    fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
65 	    for (p = ritem + rrhs[i]; *p >= 0; ++p)
66 		fprintf(verbose_file, " %s", symbol_name[*p]);
67 	    fprintf(verbose_file, "  (%d)\n", i - 2);
68 	}
69     }
70 }
71 
72 
73 log_conflicts()
74 {
75     register int i;
76 
77     fprintf(verbose_file, "\n\n");
78     for (i = 0; i < nstates; i++)
79     {
80 	if (SRconflicts[i] || RRconflicts[i])
81 	{
82 	    fprintf(verbose_file, "State %d contains ", i);
83 	    if (SRconflicts[i] == 1)
84 		fprintf(verbose_file, "1 shift/reduce conflict");
85 	    else if (SRconflicts[i] > 1)
86 		fprintf(verbose_file, "%d shift/reduce conflicts",
87 			SRconflicts[i]);
88 	    if (SRconflicts[i] && RRconflicts[i])
89 		fprintf(verbose_file, ", ");
90 	    if (RRconflicts[i] == 1)
91 		fprintf(verbose_file, "1 reduce/reduce conflict");
92 	    else if (RRconflicts[i] > 1)
93 		fprintf(verbose_file, "%d reduce/reduce conflicts",
94 			RRconflicts[i]);
95 	    fprintf(verbose_file, ".\n");
96 	}
97     }
98 }
99 
100 
101 print_state(state)
102 int state;
103 {
104     if (state)
105 	fprintf(verbose_file, "\n\n");
106     if (SRconflicts[state] || RRconflicts[state])
107 	print_conflicts(state);
108     fprintf(verbose_file, "state %d\n", state);
109     print_core(state);
110     print_nulls(state);
111     print_actions(state);
112 }
113 
114 
115 print_conflicts(state)
116 int state;
117 {
118     register int symbol;
119     register action *p, *q, *r;
120 
121     for (p = parser[state]; p; p = q->next)
122     {
123 	q = p;
124 	if (p->action_code == ERROR || p->suppressed == 2)
125 	    continue;
126 
127 	symbol = p->symbol;
128 	while (q->next && q->next->symbol == symbol)
129 	    q = q->next;
130 	if (state == final_state && symbol == 0)
131 	{
132 	    r = p;
133 	    for (;;)
134 	    {
135 		fprintf(verbose_file, "%d: shift/reduce conflict \
136 (accept, reduce %d) on $end\n", state, r->number - 2);
137 		if (r == q) break;
138 		r = r->next;
139 	    }
140 	}
141 	else if (p != q)
142 	{
143 	    r = p->next;
144 	    if (p->action_code == SHIFT)
145 	    {
146 		for (;;)
147 		{
148 		    if (r->action_code == REDUCE && p->suppressed != 2)
149 			fprintf(verbose_file, "%d: shift/reduce conflict \
150 (shift %d, reduce %d) on %s\n", state, p->number, r->number - 2,
151 				symbol_name[symbol]);
152 		    if (r == q) break;
153 		    r = r->next;
154 		}
155 	    }
156 	    else
157 	    {
158 		for (;;)
159 		{
160 		    if (r->action_code == REDUCE && p->suppressed != 2)
161 			fprintf(verbose_file, "%d: reduce/reduce conflict \
162 (reduce %d, reduce %d) on %s\n", state, p->number - 2, r->number - 2,
163 				symbol_name[symbol]);
164 		    if (r == q) break;
165 		    r = r->next;
166 		}
167 	    }
168 	}
169     }
170 }
171 
172 
173 print_core(state)
174 int state;
175 {
176     register int i;
177     register int k;
178     register int rule;
179     register core *statep;
180     register short *sp;
181     register short *sp1;
182 
183     statep = state_table[state];
184     k = statep->nitems;
185 
186     for (i = 0; i < k; i++)
187     {
188 	sp1 = sp = ritem + statep->items[i];
189 
190 	while (*sp >= 0) ++sp;
191 	rule = -(*sp);
192 	fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
193 
194         for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
195 	    fprintf(verbose_file, "%s ", symbol_name[*sp]);
196 
197 	putc('.', verbose_file);
198 
199 	while (*sp >= 0)
200 	{
201 	    fprintf(verbose_file, " %s", symbol_name[*sp]);
202 	    sp++;
203 	}
204 	fprintf(verbose_file, "  (%d)\n", -2 - *sp);
205     }
206 }
207 
208 
209 print_nulls(state)
210 int state;
211 {
212     register action *p;
213     register int i, j, k, nnulls;
214 
215     nnulls = 0;
216     for (p = parser[state]; p; p = p->next)
217     {
218 	if (p->action_code == REDUCE &&
219 		(p->suppressed == 0 || p->suppressed == 1))
220 	{
221 	    i = p->number;
222 	    if (rrhs[i] + 1 == rrhs[i+1])
223 	    {
224 		for (j = 0; j < nnulls && i > null_rules[j]; ++j)
225 		    continue;
226 
227 		if (j == nnulls)
228 		{
229 		    ++nnulls;
230 		    null_rules[j] = i;
231 		}
232 		else if (i != null_rules[j])
233 		{
234 		    ++nnulls;
235 		    for (k = nnulls - 1; k > j; --k)
236 			null_rules[k] = null_rules[k-1];
237 		    null_rules[j] = i;
238 		}
239 	    }
240 	}
241     }
242 
243     for (i = 0; i < nnulls; ++i)
244     {
245 	j = null_rules[i];
246 	fprintf(verbose_file, "\t%s : .  (%d)\n", symbol_name[rlhs[j]],
247 		j - 2);
248     }
249     fprintf(verbose_file, "\n");
250 }
251 
252 
253 print_actions(stateno)
254 int stateno;
255 {
256     register action *p;
257     register shifts *sp;
258     register int as;
259 
260     if (stateno == final_state)
261 	fprintf(verbose_file, "\t$end  accept\n");
262 
263     p = parser[stateno];
264     if (p)
265     {
266 	print_shifts(p);
267 	print_reductions(p, defred[stateno]);
268     }
269 
270     sp = shift_table[stateno];
271     if (sp && sp->nshifts > 0)
272     {
273 	as = accessing_symbol[sp->shift[sp->nshifts - 1]];
274 	if (ISVAR(as))
275 	    print_gotos(stateno);
276     }
277 }
278 
279 
280 print_shifts(p)
281 register action *p;
282 {
283     register int count;
284     register action *q;
285 
286     count = 0;
287     for (q = p; q; q = q->next)
288     {
289 	if (q->suppressed < 2 && q->action_code == SHIFT)
290 	    ++count;
291     }
292 
293     if (count > 0)
294     {
295 	for (; p; p = p->next)
296 	{
297 	    if (p->action_code == SHIFT && p->suppressed == 0)
298 		fprintf(verbose_file, "\t%s  shift %d\n",
299 			    symbol_name[p->symbol], p->number);
300 	}
301     }
302 }
303 
304 
305 print_reductions(p, defred)
306 register action *p;
307 register int defred;
308 {
309     register int k, anyreds;
310     register action *q;
311 
312     anyreds = 0;
313     for (q = p; q ; q = q->next)
314     {
315 	if (q->action_code == REDUCE && q->suppressed < 2)
316 	{
317 	    anyreds = 1;
318 	    break;
319 	}
320     }
321 
322     if (anyreds == 0)
323 	fprintf(verbose_file, "\t.  error\n");
324     else
325     {
326 	for (; p; p = p->next)
327 	{
328 	    if (p->action_code == REDUCE && p->number != defred)
329 	    {
330 		k = p->number - 2;
331 		if (p->suppressed == 0)
332 		    fprintf(verbose_file, "\t%s  reduce %d\n",
333 			    symbol_name[p->symbol], k);
334 	    }
335 	}
336 
337         if (defred > 0)
338 	    fprintf(verbose_file, "\t.  reduce %d\n", defred - 2);
339     }
340 }
341 
342 
343 print_gotos(stateno)
344 int stateno;
345 {
346     register int i, k;
347     register int as;
348     register short *to_state;
349     register shifts *sp;
350 
351     putc('\n', verbose_file);
352     sp = shift_table[stateno];
353     to_state = sp->shift;
354     for (i = 0; i < sp->nshifts; ++i)
355     {
356 	k = to_state[i];
357 	as = accessing_symbol[k];
358 	if (ISVAR(as))
359 	    fprintf(verbose_file, "\t%s  goto %d\n", symbol_name[as], k);
360     }
361 }
362