1 /* Print information on generated parser, for bison,
3 Copyright (C) 1984, 1986, 1989, 2000-2005, 2007, 2009-2015, 2018-2021
4 Free Software Foundation, Inc.
6 This file is part of Bison, the GNU Compiler Compiler.
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.
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.
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/>. */
32 #include "conflicts.h"
33 #include "counterexample.h"
39 #include "muscle-tab.h"
46 /* For a given state, the symbol numbers of the lookahead tokens for
47 shifts and errors (i.e. not reduce). */
48 static bitset no_reduce_set
;
52 /*---------------------------------------.
53 | *WIDTH := max (*WIDTH, strlen (STR)). |
54 `---------------------------------------*/
57 max_length (size_t *width
, const char *str
)
59 size_t len
= mbswidth (str
, 0);
64 /*--------------------------------.
65 | Report information on a state. |
66 `--------------------------------*/
69 print_core (FILE *out
, const state
*s
)
71 const item_index
*sitems
= s
->items
;
72 size_t snritems
= s
->nitems
;
73 /* Output all the items of a state, not only its kernel. */
74 if (report_flag
& report_itemsets
)
76 closure (sitems
, snritems
);
86 rule
const *previous_rule
= NULL
;
87 for (size_t i
= 0; i
< snritems
; i
++)
89 item_number
*sp1
= ritem
+ sitems
[i
];
90 rule
const *r
= item_rule (sp1
);
91 item_print (sp1
, previous_rule
, out
);
94 /* Display the lookahead tokens? */
95 if (report_flag
& report_lookaheads
96 && item_number_is_rule_number (*sp1
))
97 state_rule_lookaheads_print (s
, r
, out
);
103 /*------------------------------------------------------------.
104 | Report the shifts iff DISPLAY_SHIFTS_P or the gotos of S on |
106 `------------------------------------------------------------*/
109 print_transitions (const state
*s
, FILE *out
, bool display_transitions_p
)
111 transitions
*trans
= s
->transitions
;
114 /* Compute the width of the lookahead token column. */
115 for (int i
= 0; i
< trans
->num
; i
++)
116 if (!TRANSITION_IS_DISABLED (trans
, i
)
117 && TRANSITION_IS_SHIFT (trans
, i
) == display_transitions_p
)
119 symbol
*sym
= symbols
[TRANSITION_SYMBOL (trans
, i
)];
120 max_length (&width
, sym
->tag
);
123 /* Nothing to report. */
130 /* Report lookahead tokens and shifts. */
131 for (int i
= 0; i
< trans
->num
; i
++)
132 if (!TRANSITION_IS_DISABLED (trans
, i
)
133 && TRANSITION_IS_SHIFT (trans
, i
) == display_transitions_p
)
135 symbol
*sym
= symbols
[TRANSITION_SYMBOL (trans
, i
)];
136 const char *tag
= sym
->tag
;
137 const state
*s1
= trans
->states
[i
];
139 fprintf (out
, " %s", tag
);
140 for (int j
= width
- mbswidth (tag
, 0); j
> 0; --j
)
142 if (display_transitions_p
)
143 fprintf (out
, _("shift, and go to state %d\n"), s1
->number
);
145 fprintf (out
, _("go to state %d\n"), s1
->number
);
150 /*--------------------------------------------------------.
151 | Report the explicit errors of S raised from %nonassoc. |
152 `--------------------------------------------------------*/
155 print_errs (FILE *out
, const state
*s
)
157 errs
*errp
= s
->errs
;
160 /* Compute the width of the lookahead token column. */
161 for (int i
= 0; i
< errp
->num
; ++i
)
162 if (errp
->symbols
[i
])
163 max_length (&width
, errp
->symbols
[i
]->tag
);
165 /* Nothing to report. */
172 /* Report lookahead tokens and errors. */
173 for (int i
= 0; i
< errp
->num
; ++i
)
174 if (errp
->symbols
[i
])
176 const char *tag
= errp
->symbols
[i
]->tag
;
177 fprintf (out
, " %s", tag
);
178 for (int j
= width
- mbswidth (tag
, 0); j
> 0; --j
)
180 fputs (_("error (nonassociative)\n"), out
);
185 /*-------------------------------------------------------------------.
186 | Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
187 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
189 `-------------------------------------------------------------------*/
192 print_reduction (FILE *out
, size_t width
,
193 const char *lookahead
,
194 rule
*r
, bool enabled
)
196 fprintf (out
, " %s", lookahead
);
197 for (int j
= width
- mbswidth (lookahead
, 0); j
> 0; --j
)
201 if (rule_is_initial (r
))
202 fprintf (out
, _("accept"));
204 fprintf (out
, _("reduce using rule %d (%s)"), r
->number
,
205 r
->lhs
->symbol
->tag
);
212 /*-------------------------------------------.
213 | Report on OUT the reduction actions of S. |
214 `-------------------------------------------*/
217 print_reductions (FILE *out
, const state
*s
)
219 reductions
*reds
= s
->reductions
;
223 rule
*default_reduction
= NULL
;
224 if (yydefact
[s
->number
] != 0)
225 default_reduction
= &rules
[yydefact
[s
->number
] - 1];
227 transitions
*trans
= s
->transitions
;
229 bitset_zero (no_reduce_set
);
232 FOR_EACH_SHIFT (trans
, i
)
233 bitset_set (no_reduce_set
, TRANSITION_SYMBOL (trans
, i
));
235 for (int i
= 0; i
< s
->errs
->num
; ++i
)
236 if (s
->errs
->symbols
[i
])
237 bitset_set (no_reduce_set
, s
->errs
->symbols
[i
]->content
->number
);
239 /* Compute the width of the lookahead token column. */
241 if (default_reduction
)
242 width
= mbswidth (_("$default"), 0);
244 if (reds
->lookaheads
)
245 for (int i
= 0; i
< ntokens
; i
++)
247 bool count
= bitset_test (no_reduce_set
, i
);
249 for (int j
= 0; j
< reds
->num
; ++j
)
250 if (bitset_test (reds
->lookaheads
[j
], i
))
254 if (reds
->rules
[j
] != default_reduction
)
255 max_length (&width
, symbols
[i
]->tag
);
259 max_length (&width
, symbols
[i
]->tag
);
263 /* Nothing to report. */
270 bool default_reduction_only
= true;
272 /* Report lookahead tokens (or $default) and reductions. */
273 if (reds
->lookaheads
)
274 for (int i
= 0; i
< ntokens
; i
++)
276 bool defaulted
= false;
277 bool count
= bitset_test (no_reduce_set
, i
);
279 default_reduction_only
= false;
281 for (int j
= 0; j
< reds
->num
; ++j
)
282 if (bitset_test (reds
->lookaheads
[j
], i
))
286 if (reds
->rules
[j
] != default_reduction
)
288 default_reduction_only
= false;
289 print_reduction (out
, width
,
291 reds
->rules
[j
], true);
299 default_reduction_only
= false;
301 print_reduction (out
, width
,
303 default_reduction
, true);
305 print_reduction (out
, width
,
307 reds
->rules
[j
], false);
312 if (default_reduction
)
314 char *default_reductions
=
315 muscle_percent_define_get ("lr.default-reduction");
316 print_reduction (out
, width
, _("$default"), default_reduction
, true);
317 aver (STREQ (default_reductions
, "most")
318 || (STREQ (default_reductions
, "consistent")
319 && default_reduction_only
)
320 || (reds
->num
== 1 && rule_is_initial (reds
->rules
[0])));
321 (void) default_reduction_only
;
322 free (default_reductions
);
327 /*--------------------------------------------------------------.
328 | Report on OUT all the actions (shifts, gotos, reductions, and |
329 | explicit errors from %nonassoc) of S. |
330 `--------------------------------------------------------------*/
333 print_actions (FILE *out
, const state
*s
)
336 print_transitions (s
, out
, true);
338 print_reductions (out
, s
);
340 print_transitions (s
, out
, false);
344 /*----------------------------------.
345 | Report all the data on S on OUT. |
346 `----------------------------------*/
349 print_state (FILE *out
, const state
*s
)
352 fprintf (out
, _("State %d"), s
->number
);
355 print_actions (out
, s
);
356 if ((report_flag
& report_solved_conflicts
) && s
->solved_conflicts
)
359 fputs (s
->solved_conflicts
, out
);
361 if (has_conflicts (s
)
362 && (report_flag
& report_cex
363 || warning_is_enabled (Wcounterexamples
)))
366 counterexample_report_state (s
, out
, " ");
370 /*-----------------------------------------.
371 | Print information on the whole grammar. |
372 `-----------------------------------------*/
375 print_terminal_symbols (FILE *out
)
377 /* TERMINAL (type #) : rule #s terminal is on RHS */
378 fprintf (out
, "%s\n\n", _("Terminals, with rules where they appear"));
379 for (int i
= 0; i
< max_code
+ 1; ++i
)
380 if (token_translations
[i
] != undeftoken
->content
->number
)
382 const symbol
*sym
= symbols
[token_translations
[i
]];
383 const char *tag
= sym
->tag
;
384 fprintf (out
, "%4s%s", "", tag
);
385 if (sym
->content
->type_name
)
386 fprintf (out
, " <%s>", sym
->content
->type_name
);
387 fprintf (out
, " (%d)", i
);
389 for (rule_number r
= 0; r
< nrules
; r
++)
390 for (item_number
*rhsp
= rules
[r
].rhs
; *rhsp
>= 0; rhsp
++)
391 if (item_number_as_symbol_number (*rhsp
) == token_translations
[i
])
393 fprintf (out
, " %d", r
);
403 print_nonterminal_symbols (FILE *out
)
405 fprintf (out
, "%s\n\n", _("Nonterminals, with rules where they appear"));
406 for (symbol_number i
= ntokens
; i
< nsyms
; i
++)
408 const symbol
*sym
= symbols
[i
];
409 const char *tag
= sym
->tag
;
410 bool on_left
= false;
411 bool on_right
= false;
413 for (rule_number r
= 0; r
< nrules
; r
++)
415 on_left
|= rules
[r
].lhs
->number
== i
;
416 for (item_number
*rhsp
= rules
[r
].rhs
; !on_right
&& 0 <= *rhsp
; ++rhsp
)
417 on_right
|= item_number_as_symbol_number (*rhsp
) == i
;
418 if (on_left
&& on_right
)
422 int column
= 4 + mbswidth (tag
, 0);
423 fprintf (out
, "%4s%s", "", tag
);
424 if (sym
->content
->type_name
)
425 column
+= fprintf (out
, " <%s>",
426 sym
->content
->type_name
);
427 fprintf (out
, " (%d)\n", i
);
431 fprintf (out
, "%8s%s", "", _("on left:"));
432 for (rule_number r
= 0; r
< nrules
; r
++)
433 if (rules
[r
].lhs
->number
== i
)
434 fprintf (out
, " %d", r
);
440 fprintf (out
, "%8s%s", "", _("on right:"));
441 for (rule_number r
= 0; r
< nrules
; r
++)
442 for (item_number
*rhsp
= rules
[r
].rhs
; 0 <= *rhsp
; ++rhsp
)
443 if (item_number_as_symbol_number (*rhsp
) == i
)
445 fprintf (out
, " %d", r
);
456 /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but
457 that conflicts with Posix. */
458 FILE *out
= xfopen (spec_verbose_file
, "w");
461 grammar_rules_partial_print (out
,
462 _("Rules useless in parser due to conflicts"),
463 rule_useless_in_parser_p
);
464 conflicts_output (out
);
466 grammar_rules_print (out
);
467 print_terminal_symbols (out
);
468 print_nonterminal_symbols (out
);
470 /* Storage for print_reductions. */
471 no_reduce_set
= bitset_create (ntokens
, BITSET_FIXED
);
472 for (state_number i
= 0; i
< nstates
; i
++)
473 print_state (out
, states
[i
]);
474 bitset_free (no_reduce_set
);