]> git.saurik.com Git - bison.git/blob - src/print.c
e1f53a1e12dce3521eeb04cb98eb67994449a785
[bison.git] / src / print.c
1 /* Print information on generated parser, for bison,
2 Copyright 1984, 1986, 1989, 2000, 2001 Free Software Foundation, Inc.
3
4 This file is part of Bison, the GNU Compiler Compiler.
5
6 Bison is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 Bison is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Bison; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include "system.h"
23 #include "files.h"
24 #include "gram.h"
25 #include "LR0.h"
26 #include "lalr.h"
27 #include "conflicts.h"
28 #include "getargs.h"
29 #include "state.h"
30 #include "reader.h"
31 #include "print.h"
32 #include "reduce.h"
33 #include "closure.h"
34
35 static unsigned *shiftset = NULL;
36 static unsigned *lookaheadset = NULL;
37
38 #if 0
39 static void
40 print_token (int extnum, int token)
41 {
42 fprintf (out, _(" type %d is %s\n"), extnum, tags[token]);
43 }
44 #endif
45
46 \f
47 /*--------------------------------.
48 | Report information on a state. |
49 `--------------------------------*/
50
51 static void
52 print_core (FILE *out, state_t *state)
53 {
54 int i;
55 short *sitems = state->items;
56 int snitems = state->nitems;
57
58 /* New experimental feature: if TRACE_FLAGS output all the items of
59 a state, not only its kernel. */
60 if (trace_flag)
61 {
62 closure (sitems, snitems);
63 sitems = itemset;
64 snitems = nitemset;
65 }
66
67 if (snitems)
68 {
69 for (i = 0; i < snitems; i++)
70 {
71 short *sp;
72 short *sp1;
73 int rule;
74
75 sp1 = sp = ritem + sitems[i];
76
77 while (*sp > 0)
78 sp++;
79
80 rule = -(*sp);
81 fprintf (out, " %s -> ", tags[rule_table[rule].lhs]);
82
83 for (sp = ritem + rule_table[rule].rhs; sp < sp1; sp++)
84 fprintf (out, "%s ", tags[*sp]);
85
86 fputc ('.', out);
87
88 for (/* Nothing */; *sp > 0; ++sp)
89 fprintf (out, " %s", tags[*sp]);
90
91 fprintf (out, _(" (rule %d)"), rule);
92 fputc ('\n', out);
93 }
94
95 fputc ('\n', out);
96 }
97 }
98
99
100 static void
101 print_shifts (FILE *out, state_t *state)
102 {
103 int i;
104 shifts *shiftp = state->shifts;
105
106 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
107 if (!SHIFT_IS_DISABLED (shiftp, i))
108 {
109 int state1 = shiftp->shifts[i];
110 int symbol = state_table[state1]->accessing_symbol;
111 fprintf (out,
112 _(" %-4s\tshift, and go to state %d\n"),
113 tags[symbol], state1);
114 }
115
116 if (i > 0)
117 fputc ('\n', out);
118 }
119
120
121 static void
122 print_errs (FILE *out, state_t *state)
123 {
124 errs *errp = state->errs;
125 int i;
126
127 if (!errp)
128 return;
129
130 for (i = 0; i < errp->nerrs; ++i)
131 if (errp->errs[i])
132 fprintf (out, _(" %-4s\terror (nonassociative)\n"),
133 tags[errp->errs[i]]);
134
135 if (i > 0)
136 fputc ('\n', out);
137 }
138
139
140 static void
141 print_gotos (FILE *out, state_t *state)
142 {
143 int i;
144 shifts *shiftp = state->shifts;
145
146 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
147 /* Skip token shifts. */;
148
149 if (i < shiftp->nshifts)
150 {
151 for (; i < shiftp->nshifts; i++)
152 if (!SHIFT_IS_DISABLED (shiftp, i))
153 {
154 int state1 = shiftp->shifts[i];
155 int symbol = state_table[state1]->accessing_symbol;
156 fprintf (out, _(" %-4s\tgo to state %d\n"),
157 tags[symbol], state1);
158 }
159
160 fputc ('\n', out);
161 }
162 }
163
164 static void
165 print_reductions (FILE *out, state_t *state)
166 {
167 int i;
168 shifts *shiftp = state->shifts;
169 reductions *redp = state->reductions;
170 errs *errp = state->errs;
171 int nodefault = 0;
172
173 if (state->consistent)
174 {
175 int rule = redp->rules[0];
176 int symbol = rule_table[rule].lhs;
177 fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
178 rule, tags[symbol]);
179 return;
180 }
181
182 for (i = 0; i < tokensetsize; i++)
183 shiftset[i] = 0;
184
185 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
186 if (!SHIFT_IS_DISABLED (shiftp, i))
187 {
188 /* if this state has a shift for the error token, don't use a
189 default rule. */
190 if (SHIFT_IS_ERROR (shiftp, i))
191 nodefault = 1;
192 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
193 }
194
195 if (errp)
196 for (i = 0; i < errp->nerrs; i++)
197 if (errp->errs[i])
198 SETBIT (shiftset, errp->errs[i]);
199
200 if (state->nlookaheads == 1 && !nodefault)
201 {
202 int k;
203 int default_rule = LAruleno[state->lookaheadsp];
204
205 for (k = 0; k < tokensetsize; ++k)
206 lookaheadset[k] = LA (state->lookaheadsp)[k] & shiftset[k];
207
208 for (i = 0; i < ntokens; i++)
209 if (BITISSET (lookaheadset, i))
210 fprintf (out, _(" %-4s\t[reduce using rule %d (%s)]\n"),
211 tags[i], default_rule,
212 tags[rule_table[default_rule].lhs]);
213
214 fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
215 default_rule, tags[rule_table[default_rule].lhs]);
216 }
217 else if (state->nlookaheads >= 1)
218 {
219 int cmax = 0;
220 int default_LA = -1;
221 int default_rule = 0;
222
223 if (!nodefault)
224 for (i = 0; i < state->nlookaheads; ++i)
225 {
226 int count = 0;
227 int j, k;
228
229 for (k = 0; k < tokensetsize; ++k)
230 lookaheadset[k] = LA (state->lookaheadsp + i)[k] & ~shiftset[k];
231
232 for (j = 0; j < ntokens; j++)
233 if (BITISSET (lookaheadset, j))
234 count++;
235
236 if (count > cmax)
237 {
238 cmax = count;
239 default_LA = state->lookaheadsp + i;
240 default_rule = LAruleno[state->lookaheadsp + i];
241 }
242
243 for (k = 0; k < tokensetsize; ++k)
244 shiftset[k] |= lookaheadset[k];
245 }
246
247 for (i = 0; i < tokensetsize; i++)
248 shiftset[i] = 0;
249
250 for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++)
251 if (!SHIFT_IS_DISABLED (shiftp, i))
252 SETBIT (shiftset, SHIFT_SYMBOL (shiftp, i));
253
254 for (i = 0; i < ntokens; i++)
255 {
256 int j;
257 int defaulted = 0;
258 int count = BITISSET (shiftset, i);
259
260 for (j = 0; j < state->nlookaheads; ++j)
261 {
262 if (BITISSET (LA (state->lookaheadsp + j), i))
263 {
264 if (count == 0)
265 {
266 if (state->lookaheadsp + j != default_LA)
267 fprintf (out,
268 _(" %-4s\treduce using rule %d (%s)\n"),
269 tags[i],
270 LAruleno[state->lookaheadsp + j],
271 tags[rule_table[LAruleno[state->lookaheadsp + j]].lhs]);
272 else
273 defaulted = 1;
274
275 count++;
276 }
277 else
278 {
279 if (defaulted)
280 fprintf (out,
281 _(" %-4s\treduce using rule %d (%s)\n"),
282 tags[i],
283 LAruleno[default_LA],
284 tags[rule_table[LAruleno[default_LA]].lhs]);
285 defaulted = 0;
286 fprintf (out,
287 _(" %-4s\t[reduce using rule %d (%s)]\n"),
288 tags[i],
289 LAruleno[state->lookaheadsp + j],
290 tags[rule_table[LAruleno[state->lookaheadsp + j]].lhs]);
291 }
292 }
293 }
294 }
295
296 if (default_LA >= 0)
297 fprintf (out, _(" $default\treduce using rule %d (%s)\n"),
298 default_rule, tags[rule_table[default_rule].lhs]);
299 }
300 }
301
302
303 static void
304 print_actions (FILE *out, state_t *state)
305 {
306 reductions *redp = state->reductions;
307 shifts *shiftp = state->shifts;
308
309 if (!shiftp->nshifts && !redp)
310 {
311 if (final_state == state->number)
312 fprintf (out, _(" $default\taccept\n"));
313 else
314 fprintf (out, _(" NO ACTIONS\n"));
315 return;
316 }
317
318 print_shifts (out, state);
319 print_errs (out, state);
320 if (redp)
321 print_reductions (out, state);
322 print_gotos (out, state);
323 }
324
325 static void
326 print_state (FILE *out, state_t *state)
327 {
328 fprintf (out, _("state %d"), state->number);
329 fputs ("\n\n", out);
330 print_core (out, state);
331 print_actions (out, state);
332 fputs ("\n\n", out);
333 }
334 \f
335 /*-----------------------------------------.
336 | Print information on the whole grammar. |
337 `-----------------------------------------*/
338
339 #define END_TEST(End) \
340 do { \
341 if (column + strlen(buffer) > (End)) \
342 { \
343 fprintf (out, "%s\n ", buffer); \
344 column = 3; \
345 buffer[0] = 0; \
346 } \
347 } while (0)
348
349
350 static void
351 print_grammar (FILE *out)
352 {
353 int i, j;
354 short *rule;
355 char buffer[90];
356 int column = 0;
357
358 /* rule # : LHS -> RHS */
359 fprintf (out, "%s\n\n", _("Grammar"));
360 fprintf (out, " %s\n", _("Number, Line, Rule"));
361 for (i = 1; i <= nrules; i++)
362 /* Don't print rules disabled in reduce_grammar_tables. */
363 if (rule_table[i].useful)
364 {
365 fprintf (out, _(" %3d %3d %s ->"),
366 i, rule_table[i].line, tags[rule_table[i].lhs]);
367 rule = &ritem[rule_table[i].rhs];
368 if (*rule > 0)
369 while (*rule > 0)
370 fprintf (out, " %s", tags[*rule++]);
371 else
372 fprintf (out, " /* %s */", _("empty"));
373 fputc ('\n', out);
374 }
375 fputs ("\n\n", out);
376
377
378 /* TERMINAL (type #) : rule #s terminal is on RHS */
379 fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
380 fprintf (out, "%s (-1)\n", tags[0]);
381
382 for (i = 0; i <= max_user_token_number; i++)
383 if (token_translations[i] != 2)
384 {
385 buffer[0] = 0;
386 column = strlen (tags[token_translations[i]]);
387 fputs (tags[token_translations[i]], out);
388 END_TEST (50);
389 sprintf (buffer, " (%d)", i);
390
391 for (j = 1; j <= nrules; j++)
392 for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
393 if (*rule == token_translations[i])
394 {
395 END_TEST (65);
396 sprintf (buffer + strlen (buffer), " %d", j);
397 break;
398 }
399 fprintf (out, "%s\n", buffer);
400 }
401 fputs ("\n\n", out);
402
403
404 fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
405 for (i = ntokens; i <= nsyms - 1; i++)
406 {
407 int left_count = 0, right_count = 0;
408
409 for (j = 1; j <= nrules; j++)
410 {
411 if (rule_table[j].lhs == i)
412 left_count++;
413 for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
414 if (*rule == i)
415 {
416 right_count++;
417 break;
418 }
419 }
420
421 buffer[0] = 0;
422 fputs (tags[i], out);
423 column = strlen (tags[i]);
424 sprintf (buffer, " (%d)", i);
425 END_TEST (0);
426
427 if (left_count > 0)
428 {
429 END_TEST (50);
430 sprintf (buffer + strlen (buffer), _(" on left:"));
431
432 for (j = 1; j <= nrules; j++)
433 {
434 END_TEST (65);
435 if (rule_table[j].lhs == i)
436 sprintf (buffer + strlen (buffer), " %d", j);
437 }
438 }
439
440 if (right_count > 0)
441 {
442 if (left_count > 0)
443 sprintf (buffer + strlen (buffer), ",");
444 END_TEST (50);
445 sprintf (buffer + strlen (buffer), _(" on right:"));
446 for (j = 1; j <= nrules; j++)
447 {
448 for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
449 if (*rule == i)
450 {
451 END_TEST (65);
452 sprintf (buffer + strlen (buffer), " %d", j);
453 break;
454 }
455 }
456 }
457 fprintf (out, "%s\n", buffer);
458 }
459 fputs ("\n\n", out);
460 }
461 \f
462 void
463 print_results (void)
464 {
465 int i;
466
467 /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but
468 that conflicts with Posix. */
469 FILE *out = xfopen (spec_verbose_file, "w");
470
471 size_t size = obstack_object_size (&output_obstack);
472 fwrite (obstack_finish (&output_obstack), 1, size, out);
473 obstack_free (&output_obstack, NULL);
474
475 if (size)
476 fputs ("\n\n", out);
477
478 reduce_output (out);
479 conflicts_output (out);
480
481 print_grammar (out);
482
483 /* New experimental feature: output all the items of a state, not
484 only its kernel. Requires to run closure, which need memory
485 allocation/deallocation. */
486 if (trace_flag)
487 new_closure (nitems);
488 /* Storage for print_reductions. */
489 shiftset = XCALLOC (unsigned, tokensetsize);
490 lookaheadset = XCALLOC (unsigned, tokensetsize);
491 for (i = 0; i < nstates; i++)
492 print_state (out, state_table[i]);
493 free (shiftset);
494 free (lookaheadset);
495 if (trace_flag)
496 free_closure ();
497
498 xfclose (out);
499 }