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