xref: /netbsd-src/external/bsd/byacc/dist/verbose.c (revision c5e820cae412164fcbee52f470436200af5358ea)
1 /*	$NetBSD: verbose.c,v 1.6 2011/09/10 21:29:04 christos Exp $	*/
2 /* Id: verbose.c,v 1.9 2010/06/09 08:58:29 tom Exp */
3 
4 #include "defs.h"
5 
6 #include <sys/cdefs.h>
7 __RCSID("$NetBSD: verbose.c,v 1.6 2011/09/10 21:29:04 christos Exp $");
8 
9 static void log_conflicts(void);
10 static void log_unused(void);
11 static void print_actions(int stateno);
12 static void print_conflicts(int state);
13 static void print_core(int state);
14 static void print_gotos(int stateno);
15 static void print_nulls(int state);
16 static void print_shifts(action *p);
17 static void print_state(int state);
18 static void print_reductions(action *p, int defred2);
19 
20 static short *null_rules;
21 
22 void
23 verbose(void)
24 {
25     int i;
26 
27     if (!vflag)
28 	return;
29 
30     null_rules = (short *)MALLOC((unsigned)nrules * sizeof(short));
31     NO_SPACE(null_rules);
32 
33     fprintf(verbose_file, "\f\n");
34     for (i = 0; i < nstates; i++)
35 	print_state(i);
36     FREE(null_rules);
37 
38     if (nunused)
39 	log_unused();
40     if (SRtotal || RRtotal)
41 	log_conflicts();
42 
43     fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
44 	    nvars);
45     fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
46 }
47 
48 static void
49 log_unused(void)
50 {
51     int i;
52     short *p;
53 
54     fprintf(verbose_file, "\n\nRules never reduced:\n");
55     for (i = 3; i < nrules; ++i)
56     {
57 	if (!rules_used[i])
58 	{
59 	    fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
60 	    for (p = ritem + rrhs[i]; *p >= 0; ++p)
61 		fprintf(verbose_file, " %s", symbol_name[*p]);
62 	    fprintf(verbose_file, "  (%d)\n", i - 2);
63 	}
64     }
65 }
66 
67 static void
68 log_conflicts(void)
69 {
70     int i;
71 
72     fprintf(verbose_file, "\n\n");
73     for (i = 0; i < nstates; i++)
74     {
75 	if (SRconflicts[i] || RRconflicts[i])
76 	{
77 	    fprintf(verbose_file, "State %d contains ", i);
78 	    if (SRconflicts[i] > 0)
79 		fprintf(verbose_file, "%d shift/reduce conflict%s",
80 			SRconflicts[i],
81 			PLURAL(SRconflicts[i]));
82 	    if (SRconflicts[i] && RRconflicts[i])
83 		fprintf(verbose_file, ", ");
84 	    if (RRconflicts[i] > 0)
85 		fprintf(verbose_file, "%d reduce/reduce conflict%s",
86 			RRconflicts[i],
87 			PLURAL(RRconflicts[i]));
88 	    fprintf(verbose_file, ".\n");
89 	}
90     }
91 }
92 
93 static void
94 print_state(int state)
95 {
96     if (state)
97 	fprintf(verbose_file, "\n\n");
98     if (SRconflicts[state] || RRconflicts[state])
99 	print_conflicts(state);
100     fprintf(verbose_file, "state %d\n", state);
101     print_core(state);
102     print_nulls(state);
103     print_actions(state);
104 }
105 
106 static void
107 print_conflicts(int state)
108 {
109     int symbol, act, number;
110     action *p;
111 
112     act = 0;			/* not shift/reduce... */
113     number = -1;
114     symbol = -1;
115     for (p = parser[state]; p; p = p->next)
116     {
117 	if (p->suppressed == 2)
118 	    continue;
119 
120 	if (p->symbol != symbol)
121 	{
122 	    symbol = p->symbol;
123 	    number = p->number;
124 	    if (p->action_code == SHIFT)
125 		act = SHIFT;
126 	    else
127 		act = REDUCE;
128 	}
129 	else if (p->suppressed == 1)
130 	{
131 	    if (state == final_state && symbol == 0)
132 	    {
133 		fprintf(verbose_file, "%d: shift/reduce conflict \
134 (accept, reduce %d) on $end\n", state, p->number - 2);
135 	    }
136 	    else
137 	    {
138 		if (act == SHIFT)
139 		{
140 		    fprintf(verbose_file, "%d: shift/reduce conflict \
141 (shift %d, reduce %d) on %s\n", state, number, p->number - 2,
142 			    symbol_name[symbol]);
143 		}
144 		else
145 		{
146 		    fprintf(verbose_file, "%d: reduce/reduce conflict \
147 (reduce %d, reduce %d) on %s\n", state, number - 2, p->number - 2,
148 			    symbol_name[symbol]);
149 		}
150 	    }
151 	}
152     }
153 }
154 
155 static void
156 print_core(int state)
157 {
158     int i;
159     int k;
160     int rule;
161     core *statep;
162     short *sp;
163     short *sp1;
164 
165     statep = state_table[state];
166     k = statep->nitems;
167 
168     for (i = 0; i < k; i++)
169     {
170 	sp1 = sp = ritem + statep->items[i];
171 
172 	while (*sp >= 0)
173 	    ++sp;
174 	rule = -(*sp);
175 	fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
176 
177 	for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
178 	    fprintf(verbose_file, "%s ", symbol_name[*sp]);
179 
180 	putc('.', verbose_file);
181 
182 	while (*sp >= 0)
183 	{
184 	    fprintf(verbose_file, " %s", symbol_name[*sp]);
185 	    sp++;
186 	}
187 	fprintf(verbose_file, "  (%d)\n", -2 - *sp);
188     }
189 }
190 
191 static void
192 print_nulls(int state)
193 {
194     action *p;
195     Value_t i, j, k, nnulls;
196 
197     nnulls = 0;
198     for (p = parser[state]; p; p = p->next)
199     {
200 	if (p->action_code == REDUCE &&
201 	    (p->suppressed == 0 || p->suppressed == 1))
202 	{
203 	    i = p->number;
204 	    if (rrhs[i] + 1 == rrhs[i + 1])
205 	    {
206 		for (j = 0; j < nnulls && i > null_rules[j]; ++j)
207 		    continue;
208 
209 		if (j == nnulls)
210 		{
211 		    ++nnulls;
212 		    null_rules[j] = i;
213 		}
214 		else if (i != null_rules[j])
215 		{
216 		    ++nnulls;
217 		    for (k = (Value_t) (nnulls - 1); k > j; --k)
218 			null_rules[k] = null_rules[k - 1];
219 		    null_rules[j] = i;
220 		}
221 	    }
222 	}
223     }
224 
225     for (i = 0; i < nnulls; ++i)
226     {
227 	j = null_rules[i];
228 	fprintf(verbose_file, "\t%s : .  (%d)\n", symbol_name[rlhs[j]],
229 		j - 2);
230     }
231     fprintf(verbose_file, "\n");
232 }
233 
234 static void
235 print_actions(int stateno)
236 {
237     action *p;
238     shifts *sp;
239     int as;
240 
241     if (stateno == final_state)
242 	fprintf(verbose_file, "\t$end  accept\n");
243 
244     p = parser[stateno];
245     if (p)
246     {
247 	print_shifts(p);
248 	print_reductions(p, defred[stateno]);
249     }
250 
251     sp = shift_table[stateno];
252     if (sp && sp->nshifts > 0)
253     {
254 	as = accessing_symbol[sp->shift[sp->nshifts - 1]];
255 	if (ISVAR(as))
256 	    print_gotos(stateno);
257     }
258 }
259 
260 static void
261 print_shifts(action *p)
262 {
263     int count;
264     action *q;
265 
266     count = 0;
267     for (q = p; q; q = q->next)
268     {
269 	if (q->suppressed < 2 && q->action_code == SHIFT)
270 	    ++count;
271     }
272 
273     if (count > 0)
274     {
275 	for (; p; p = p->next)
276 	{
277 	    if (p->action_code == SHIFT && p->suppressed == 0)
278 		fprintf(verbose_file, "\t%s  shift %d\n",
279 			symbol_name[p->symbol], p->number);
280 	}
281     }
282 }
283 
284 static void
285 print_reductions(action *p, int defred2)
286 {
287     int k, anyreds;
288     action *q;
289 
290     anyreds = 0;
291     for (q = p; q; q = q->next)
292     {
293 	if (q->action_code == REDUCE && q->suppressed < 2)
294 	{
295 	    anyreds = 1;
296 	    break;
297 	}
298     }
299 
300     if (anyreds == 0)
301 	fprintf(verbose_file, "\t.  error\n");
302     else
303     {
304 	for (; p; p = p->next)
305 	{
306 	    if (p->action_code == REDUCE && p->number != defred2)
307 	    {
308 		k = p->number - 2;
309 		if (p->suppressed == 0)
310 		    fprintf(verbose_file, "\t%s  reduce %d\n",
311 			    symbol_name[p->symbol], k);
312 	    }
313 	}
314 
315 	if (defred2 > 0)
316 	    fprintf(verbose_file, "\t.  reduce %d\n", defred2 - 2);
317     }
318 }
319 
320 static void
321 print_gotos(int stateno)
322 {
323     int i, k;
324     int as;
325     short *to_state2;
326     shifts *sp;
327 
328     putc('\n', verbose_file);
329     sp = shift_table[stateno];
330     to_state2 = sp->shift;
331     for (i = 0; i < sp->nshifts; ++i)
332     {
333 	k = to_state2[i];
334 	as = accessing_symbol[k];
335 	if (ISVAR(as))
336 	    fprintf(verbose_file, "\t%s  goto %d\n", symbol_name[as], k);
337     }
338 }
339