]> git.saurik.com Git - bison.git/blob - src/print.c
* src/gram.c (rule_rhs_print_xml): Now static, since it isn't used
[bison.git] / src / print.c
1 /* Print information on generated parser, for bison,
2
3 Copyright (C) 1984, 1986, 1989, 2000, 2001, 2002, 2003, 2004, 2005, 2007
4 Free Software Foundation, Inc.
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22 #include "system.h"
23
24 #include <bitset.h>
25 #include <quotearg.h>
26
27 #include "LR0.h"
28 #include "closure.h"
29 #include "conflicts.h"
30 #include "files.h"
31 #include "getargs.h"
32 #include "gram.h"
33 #include "lalr.h"
34 #include "print.h"
35 #include "reader.h"
36 #include "reduce.h"
37 #include "state.h"
38 #include "symtab.h"
39 #include "tables.h"
40
41 static bitset no_reduce_set;
42
43 #if 0
44 static void
45 print_token (int extnum, int token)
46 {
47 fprintf (out, _(" type %d is %s\n"), extnum, tags[token]);
48 }
49 #endif
50
51 \f
52
53 /*---------------------------------------.
54 | *WIDTH := max (*WIDTH, strlen (STR)). |
55 `---------------------------------------*/
56
57 static void
58 max_length (size_t *width, const char *str)
59 {
60 size_t len = strlen (str);
61 if (len > *width)
62 *width = len;
63 }
64
65 /*--------------------------------.
66 | Report information on a state. |
67 `--------------------------------*/
68
69 static void
70 print_core (FILE *out, state *s)
71 {
72 size_t i;
73 item_number *sitems = s->items;
74 size_t snritems = s->nitems;
75 symbol *previous_lhs = NULL;
76
77 /* Output all the items of a state, not only its kernel. */
78 if (report_flag & report_itemsets)
79 {
80 closure (sitems, snritems);
81 sitems = itemset;
82 snritems = nitemset;
83 }
84
85 if (!snritems)
86 return;
87
88 fputc ('\n', out);
89
90 for (i = 0; i < snritems; i++)
91 {
92 item_number *sp;
93 item_number *sp1;
94 rule_number r;
95
96 sp1 = sp = ritem + sitems[i];
97
98 while (*sp >= 0)
99 sp++;
100
101 r = item_number_as_rule_number (*sp);
102
103 rule_lhs_print (&rules[r], previous_lhs, out);
104 previous_lhs = rules[r].lhs;
105
106 for (sp = rules[r].rhs; sp < sp1; sp++)
107 fprintf (out, " %s", symbols[*sp]->tag);
108 fputs (" .", out);
109 for (/* Nothing */; *sp >= 0; ++sp)
110 fprintf (out, " %s", symbols[*sp]->tag);
111
112 /* Display the lookahead tokens? */
113 if (report_flag & report_lookahead_tokens)
114 state_rule_lookahead_tokens_print (s, &rules[r], out);
115
116 fputc ('\n', out);
117 }
118 }
119
120
121 /*------------------------------------------------------------.
122 | Report the shifts iff DISPLAY_SHIFTS_P or the gotos of S on |
123 | OUT. |
124 `------------------------------------------------------------*/
125
126 static void
127 print_transitions (state *s, FILE *out, bool display_transitions_p)
128 {
129 transitions *trans = s->transitions;
130 size_t width = 0;
131 int i;
132
133 /* Compute the width of the lookahead token column. */
134 for (i = 0; i < trans->num; i++)
135 if (!TRANSITION_IS_DISABLED (trans, i)
136 && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
137 {
138 symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
139 max_length (&width, sym->tag);
140 }
141
142 /* Nothing to report. */
143 if (!width)
144 return;
145
146 fputc ('\n', out);
147 width += 2;
148
149 /* Report lookahead tokens and shifts. */
150 for (i = 0; i < trans->num; i++)
151 if (!TRANSITION_IS_DISABLED (trans, i)
152 && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p)
153 {
154 symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
155 const char *tag = sym->tag;
156 state *s1 = trans->states[i];
157 int j;
158
159 fprintf (out, " %s", tag);
160 for (j = width - strlen (tag); j > 0; --j)
161 fputc (' ', out);
162 if (display_transitions_p)
163 fprintf (out, _("shift, and go to state %d\n"), s1->number);
164 else
165 fprintf (out, _("go to state %d\n"), s1->number);
166 }
167 }
168
169
170 /*--------------------------------------------------------.
171 | Report the explicit errors of S raised from %nonassoc. |
172 `--------------------------------------------------------*/
173
174 static void
175 print_errs (FILE *out, state *s)
176 {
177 errs *errp = s->errs;
178 size_t width = 0;
179 int i;
180
181 /* Compute the width of the lookahead token column. */
182 for (i = 0; i < errp->num; ++i)
183 if (errp->symbols[i])
184 max_length (&width, errp->symbols[i]->tag);
185
186 /* Nothing to report. */
187 if (!width)
188 return;
189
190 fputc ('\n', out);
191 width += 2;
192
193 /* Report lookahead tokens and errors. */
194 for (i = 0; i < errp->num; ++i)
195 if (errp->symbols[i])
196 {
197 const char *tag = errp->symbols[i]->tag;
198 int j;
199 fprintf (out, " %s", tag);
200 for (j = width - strlen (tag); j > 0; --j)
201 fputc (' ', out);
202 fputs (_("error (nonassociative)\n"), out);
203 }
204 }
205
206
207 /*-------------------------------------------------------------------------.
208 | Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default'). |
209 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
210 | R/R conflicts). |
211 `-------------------------------------------------------------------------*/
212
213 static void
214 print_reduction (FILE *out, size_t width,
215 const char *lookahead_token,
216 rule *r, bool enabled)
217 {
218 int j;
219 fprintf (out, " %s", lookahead_token);
220 for (j = width - strlen (lookahead_token); j > 0; --j)
221 fputc (' ', out);
222 if (!enabled)
223 fputc ('[', out);
224 if (r->number)
225 fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag);
226 else
227 fprintf (out, _("accept"));
228 if (!enabled)
229 fputc (']', out);
230 fputc ('\n', out);
231 }
232
233
234 /*-------------------------------------------.
235 | Report on OUT the reduction actions of S. |
236 `-------------------------------------------*/
237
238 static void
239 print_reductions (FILE *out, state *s)
240 {
241 transitions *trans = s->transitions;
242 reductions *reds = s->reductions;
243 rule *default_rule = NULL;
244 size_t width = 0;
245 int i, j;
246
247 if (reds->num == 0)
248 return;
249
250 if (yydefact[s->number] != 0)
251 default_rule = &rules[yydefact[s->number] - 1];
252
253 bitset_zero (no_reduce_set);
254 FOR_EACH_SHIFT (trans, i)
255 bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
256 for (i = 0; i < s->errs->num; ++i)
257 if (s->errs->symbols[i])
258 bitset_set (no_reduce_set, s->errs->symbols[i]->number);
259
260 /* Compute the width of the lookahead token column. */
261 if (default_rule)
262 width = strlen (_("$default"));
263
264 if (reds->lookahead_tokens)
265 for (i = 0; i < ntokens; i++)
266 {
267 bool count = bitset_test (no_reduce_set, i);
268
269 for (j = 0; j < reds->num; ++j)
270 if (bitset_test (reds->lookahead_tokens[j], i))
271 {
272 if (! count)
273 {
274 if (reds->rules[j] != default_rule)
275 max_length (&width, symbols[i]->tag);
276 count = true;
277 }
278 else
279 {
280 max_length (&width, symbols[i]->tag);
281 }
282 }
283 }
284
285 /* Nothing to report. */
286 if (!width)
287 return;
288
289 fputc ('\n', out);
290 width += 2;
291
292 /* Report lookahead tokens (or $default) and reductions. */
293 if (reds->lookahead_tokens)
294 for (i = 0; i < ntokens; i++)
295 {
296 bool defaulted = false;
297 bool count = bitset_test (no_reduce_set, i);
298
299 for (j = 0; j < reds->num; ++j)
300 if (bitset_test (reds->lookahead_tokens[j], i))
301 {
302 if (! count)
303 {
304 if (reds->rules[j] != default_rule)
305 print_reduction (out, width,
306 symbols[i]->tag,
307 reds->rules[j], true);
308 else
309 defaulted = true;
310 count = true;
311 }
312 else
313 {
314 if (defaulted)
315 print_reduction (out, width,
316 symbols[i]->tag,
317 default_rule, true);
318 defaulted = false;
319 print_reduction (out, width,
320 symbols[i]->tag,
321 reds->rules[j], false);
322 }
323 }
324 }
325
326 if (default_rule)
327 print_reduction (out, width,
328 _("$default"), default_rule, true);
329 }
330
331
332 /*--------------------------------------------------------------.
333 | Report on OUT all the actions (shifts, gotos, reductions, and |
334 | explicit erros from %nonassoc) of S. |
335 `--------------------------------------------------------------*/
336
337 static void
338 print_actions (FILE *out, state *s)
339 {
340 /* Print shifts. */
341 print_transitions (s, out, true);
342 print_errs (out, s);
343 print_reductions (out, s);
344 /* Print gotos. */
345 print_transitions (s, out, false);
346 }
347
348
349 /*----------------------------------.
350 | Report all the data on S on OUT. |
351 `----------------------------------*/
352
353 static void
354 print_state (FILE *out, state *s)
355 {
356 fputs ("\n\n", out);
357 fprintf (out, _("state %d"), s->number);
358 fputc ('\n', out);
359 print_core (out, s);
360 print_actions (out, s);
361 if ((report_flag & report_solved_conflicts) && s->solved_conflicts)
362 {
363 fputc ('\n', out);
364 fputs (s->solved_conflicts, out);
365 }
366 }
367 \f
368 /*-----------------------------------------.
369 | Print information on the whole grammar. |
370 `-----------------------------------------*/
371
372 #define END_TEST(End) \
373 do { \
374 if (column + strlen(buffer) > (End)) \
375 { \
376 fprintf (out, "%s\n ", buffer); \
377 column = 3; \
378 buffer[0] = 0; \
379 } \
380 } while (0)
381
382
383 static void
384 print_grammar (FILE *out)
385 {
386 symbol_number i;
387 char buffer[90];
388 int column = 0;
389
390 grammar_rules_print (out);
391
392 /* TERMINAL (type #) : rule #s terminal is on RHS */
393 fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
394 for (i = 0; i < max_user_token_number + 1; i++)
395 if (token_translations[i] != undeftoken->number)
396 {
397 const char *tag = symbols[token_translations[i]]->tag;
398 rule_number r;
399 item_number *rhsp;
400
401 buffer[0] = 0;
402 column = strlen (tag);
403 fputs (tag, out);
404 END_TEST (50);
405 sprintf (buffer, " (%d)", i);
406
407 for (r = 0; r < nrules; r++)
408 for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
409 if (item_number_as_symbol_number (*rhsp) == token_translations[i])
410 {
411 END_TEST (65);
412 sprintf (buffer + strlen (buffer), " %d", r);
413 break;
414 }
415 fprintf (out, "%s\n", buffer);
416 }
417 fputs ("\n\n", out);
418
419
420 fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
421 for (i = ntokens; i < nsyms; i++)
422 {
423 int left_count = 0, right_count = 0;
424 rule_number r;
425 const char *tag = symbols[i]->tag;
426
427 for (r = 0; r < nrules; r++)
428 {
429 item_number *rhsp;
430 if (rules[r].lhs->number == i)
431 left_count++;
432 for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
433 if (item_number_as_symbol_number (*rhsp) == i)
434 {
435 right_count++;
436 break;
437 }
438 }
439
440 buffer[0] = 0;
441 fputs (tag, out);
442 column = strlen (tag);
443 sprintf (buffer, " (%d)", i);
444 END_TEST (0);
445
446 if (left_count > 0)
447 {
448 END_TEST (50);
449 sprintf (buffer + strlen (buffer), _(" on left:"));
450
451 for (r = 0; r < nrules; r++)
452 {
453 END_TEST (65);
454 if (rules[r].lhs->number == i)
455 sprintf (buffer + strlen (buffer), " %d", r);
456 }
457 }
458
459 if (right_count > 0)
460 {
461 if (left_count > 0)
462 sprintf (buffer + strlen (buffer), ",");
463 END_TEST (50);
464 sprintf (buffer + strlen (buffer), _(" on right:"));
465 for (r = 0; r < nrules; r++)
466 {
467 item_number *rhsp;
468 for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
469 if (item_number_as_symbol_number (*rhsp) == i)
470 {
471 END_TEST (65);
472 sprintf (buffer + strlen (buffer), " %d", r);
473 break;
474 }
475 }
476 }
477 fprintf (out, "%s\n", buffer);
478 }
479 }
480 \f
481 void
482 print_results (void)
483 {
484 state_number i;
485
486 /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but
487 that conflicts with Posix. */
488 FILE *out = xfopen (spec_verbose_file, "w");
489
490 reduce_output (out);
491 grammar_rules_partial_print (out,
492 _("Rules never reduced"), rule_never_reduced_p);
493 conflicts_output (out);
494
495 print_grammar (out);
496
497 /* If the whole state item sets, not only the kernels, are wanted,
498 `closure' will be run, which needs memory allocation/deallocation. */
499 if (report_flag & report_itemsets)
500 new_closure (nritems);
501 /* Storage for print_reductions. */
502 no_reduce_set = bitset_create (ntokens, BITSET_FIXED);
503 for (i = 0; i < nstates; i++)
504 print_state (out, states[i]);
505 bitset_free (no_reduce_set);
506 if (report_flag & report_itemsets)
507 free_closure ();
508
509 xfclose (out);
510 }