1 /* $NetBSD: verbose.c,v 1.14 2024/09/14 21:29:02 christos Exp $ */
2
3 /* Id: verbose.c,v 1.14 2021/05/20 23:57:23 tom Exp */
4
5 #include "defs.h"
6
7 #include <sys/cdefs.h>
8 __RCSID("$NetBSD: verbose.c,v 1.14 2024/09/14 21:29:02 christos Exp $");
9
10 static void log_conflicts(void);
11 static void log_unused(void);
12 static void print_actions(int stateno);
13 static void print_conflicts(int state);
14 static void print_core(int state);
15 static void print_gotos(int stateno);
16 static void print_nulls(int state);
17 static void print_shifts(action *p);
18 static void print_state(int state);
19 static void print_reductions(action *p, int defred2);
20
21 static Value_t *null_rules;
22
23 void
verbose(void)24 verbose(void)
25 {
26 int i;
27
28 if (!vflag)
29 return;
30
31 null_rules = TMALLOC(Value_t, nrules);
32 NO_SPACE(null_rules);
33
34 fprintf(verbose_file, "\f\n");
35 for (i = 0; i < nstates; i++)
36 print_state(i);
37 FREE(null_rules);
38
39 if (nunused)
40 log_unused();
41 if (SRtotal || RRtotal)
42 log_conflicts();
43
44 fprintf(verbose_file, "\n\n%ld terminals, %ld nonterminals\n",
45 (long)ntokens, (long)nvars);
46 fprintf(verbose_file, "%ld grammar rules, %ld states\n",
47 (long)(nrules - 2), (long)nstates);
48 #if defined(YYBTYACC)
49 { /* print out the grammar symbol # and parser internal symbol # for each
50 symbol as an aide to writing the implementation for YYDESTRUCT_CALL()
51 and YYSTYPE_TOSTRING() */
52 int maxtok = 0;
53
54 fputs("\ngrammar parser grammar\n", verbose_file);
55 fputs("symbol# value# symbol\n", verbose_file);
56 for (i = 0; i < ntokens; ++i)
57 {
58 fprintf(verbose_file, " %5d %5d %s\n",
59 i, symbol_value[i], symbol_name[i]);
60 if (symbol_value[i] > maxtok)
61 maxtok = symbol_value[i];
62 }
63 for (i = ntokens; i < nsyms; ++i)
64 fprintf(verbose_file, " %5d %5d %s\n",
65 i, (maxtok + 1) + symbol_value[i] + 1, symbol_name[i]);
66 }
67 #endif
68 }
69
70 static void
log_unused(void)71 log_unused(void)
72 {
73 int i;
74 Value_t *p;
75
76 fprintf(verbose_file, "\n\nRules never reduced:\n");
77 for (i = 3; i < nrules; ++i)
78 {
79 if (!rules_used[i])
80 {
81 fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
82 for (p = ritem + rrhs[i]; *p >= 0; ++p)
83 fprintf(verbose_file, " %s", symbol_name[*p]);
84 fprintf(verbose_file, " (%d)\n", i - 2);
85 }
86 }
87 }
88
89 static void
log_conflicts(void)90 log_conflicts(void)
91 {
92 int i;
93
94 fprintf(verbose_file, "\n\n");
95 for (i = 0; i < nstates; i++)
96 {
97 if (SRconflicts[i] || RRconflicts[i])
98 {
99 fprintf(verbose_file, "State %d contains ", i);
100 if (SRconflicts[i] > 0)
101 fprintf(verbose_file, "%ld shift/reduce conflict%s",
102 (long)SRconflicts[i],
103 PLURAL(SRconflicts[i]));
104 if (SRconflicts[i] && RRconflicts[i])
105 fprintf(verbose_file, ", ");
106 if (RRconflicts[i] > 0)
107 fprintf(verbose_file, "%ld reduce/reduce conflict%s",
108 (long)RRconflicts[i],
109 PLURAL(RRconflicts[i]));
110 fprintf(verbose_file, ".\n");
111 }
112 }
113 }
114
115 static void
print_state(int state)116 print_state(int state)
117 {
118 if (state)
119 fprintf(verbose_file, "\n\n");
120 if (SRconflicts[state] || RRconflicts[state])
121 print_conflicts(state);
122 fprintf(verbose_file, "state %d\n", state);
123 print_core(state);
124 print_nulls(state);
125 print_actions(state);
126 }
127
128 static void
print_conflicts(int state)129 print_conflicts(int state)
130 {
131 int symbol, act, number;
132 action *p;
133
134 act = 0; /* not shift/reduce... */
135 number = -1;
136 symbol = -1;
137 for (p = parser[state]; p; p = p->next)
138 {
139 if (p->suppressed == 2)
140 continue;
141
142 if (p->symbol != symbol)
143 {
144 symbol = p->symbol;
145 number = p->number;
146 if (p->action_code == SHIFT)
147 act = SHIFT;
148 else
149 act = REDUCE;
150 }
151 else if (p->suppressed == 1)
152 {
153 if (state == final_state && symbol == 0)
154 {
155 fprintf(verbose_file, "%d: shift/reduce conflict \
156 (accept, reduce %ld) on $end\n", state, (long)(p->number - 2));
157 }
158 else
159 {
160 if (act == SHIFT)
161 {
162 fprintf(verbose_file, "%d: shift/reduce conflict \
163 (shift %ld, reduce %ld) on %s\n", state, (long)number, (long)(p->number - 2),
164 symbol_name[symbol]);
165 }
166 else
167 {
168 fprintf(verbose_file, "%d: reduce/reduce conflict \
169 (reduce %ld, reduce %ld) on %s\n", state, (long)(number - 2), (long)(p->number - 2),
170 symbol_name[symbol]);
171 }
172 }
173 }
174 }
175 }
176
177 static void
print_core(int state)178 print_core(int state)
179 {
180 int i;
181 core *statep = state_table[state];
182 int k = statep->nitems;
183
184 for (i = 0; i < k; i++)
185 {
186 int rule;
187 Value_t *sp = ritem + statep->items[i];
188 Value_t *sp1 = sp;
189
190 while (*sp >= 0)
191 ++sp;
192 rule = -(*sp);
193 fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
194
195 for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
196 fprintf(verbose_file, "%s ", symbol_name[*sp]);
197
198 putc('.', verbose_file);
199
200 while (*sp >= 0)
201 {
202 fprintf(verbose_file, " %s", symbol_name[*sp]);
203 sp++;
204 }
205 fprintf(verbose_file, " (%ld)\n", (long)(-2 - *sp));
206 }
207 }
208
209 static void
print_nulls(int state)210 print_nulls(int state)
211 {
212 action *p;
213 Value_t 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 = (Value_t)(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 : . (%ld)\n", symbol_name[rlhs[j]],
247 (long)(j - 2));
248 }
249 fprintf(verbose_file, "\n");
250 }
251
252 static void
print_actions(int stateno)253 print_actions(int stateno)
254 {
255 action *p;
256 shifts *sp;
257
258 if (stateno == final_state)
259 fprintf(verbose_file, "\t$end accept\n");
260
261 p = parser[stateno];
262 if (p)
263 {
264 print_shifts(p);
265 print_reductions(p, defred[stateno]);
266 }
267
268 sp = shift_table[stateno];
269 if (sp && sp->nshifts > 0)
270 {
271 int as = accessing_symbol[sp->shift[sp->nshifts - 1]];
272
273 if (ISVAR(as))
274 print_gotos(stateno);
275 }
276 }
277
278 static void
print_shifts(action * p)279 print_shifts(action *p)
280 {
281 int count;
282 action *q;
283
284 count = 0;
285 for (q = p; q; q = q->next)
286 {
287 if (q->suppressed < 2 && q->action_code == SHIFT)
288 ++count;
289 }
290
291 if (count > 0)
292 {
293 for (; p; p = p->next)
294 {
295 if (p->action_code == SHIFT && p->suppressed == 0)
296 fprintf(verbose_file, "\t%s shift %ld\n",
297 symbol_name[p->symbol], (long)p->number);
298 #if defined(YYBTYACC)
299 if (backtrack && p->action_code == SHIFT && p->suppressed == 1)
300 fprintf(verbose_file, "\t%s [trial] shift %d\n",
301 symbol_name[p->symbol], p->number);
302 #endif
303 }
304 }
305 }
306
307 static void
print_reductions(action * p,int defred2)308 print_reductions(action *p, int defred2)
309 {
310 int anyreds;
311 action *q;
312
313 anyreds = 0;
314 for (q = p; q; q = q->next)
315 {
316 if (q->action_code == REDUCE && q->suppressed < 2)
317 {
318 anyreds = 1;
319 break;
320 }
321 }
322
323 if (anyreds == 0)
324 fprintf(verbose_file, "\t. error\n");
325 else
326 {
327 for (; p; p = p->next)
328 {
329 if (p->action_code == REDUCE && p->number != defred2)
330 {
331 int k = p->number - 2;
332
333 if (p->suppressed == 0)
334 fprintf(verbose_file, "\t%s reduce %d\n",
335 symbol_name[p->symbol], k);
336 #if defined(YYBTYACC)
337 if (backtrack && p->suppressed == 1)
338 fprintf(verbose_file, "\t%s [trial] reduce %d\n",
339 symbol_name[p->symbol], k);
340 #endif
341 }
342 }
343
344 if (defred2 > 0)
345 fprintf(verbose_file, "\t. reduce %d\n", defred2 - 2);
346 }
347 }
348
349 static void
print_gotos(int stateno)350 print_gotos(int stateno)
351 {
352 int i;
353 Value_t *to_state2;
354 shifts *sp;
355
356 putc('\n', verbose_file);
357 sp = shift_table[stateno];
358 to_state2 = sp->shift;
359 for (i = 0; i < sp->nshifts; ++i)
360 {
361 int k = to_state2[i];
362 int as = accessing_symbol[k];
363
364 if (ISVAR(as))
365 fprintf(verbose_file, "\t%s goto %d\n", symbol_name[as], k);
366 }
367 }
368