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 <https://www.gnu.org/licenses/>. */
32 #include "conflicts.h"
33 #include "counterexample.h"
39 #include "muscle-tab.h"
46 static bitset no_reduce_set
;
50 /*---------------------------------------.
51 | *WIDTH := max (*WIDTH, strlen (STR)). |
52 `---------------------------------------*/
55 max_length (size_t *width
, const char *str
)
57 size_t len
= mbswidth (str
, 0);
62 /*--------------------------------.
63 | Report information on a state. |
64 `--------------------------------*/
67 print_core (FILE *out
, const state
*s
)
69 const item_index
*sitems
= s
->items
;
70 size_t snritems
= s
->nitems
;
71 /* Output all the items of a state, not only its kernel. */
72 if (report_flag
& report_itemsets
)
74 closure (sitems
, snritems
);
84 rule
const *previous_rule
= NULL
;
85 for (size_t i
= 0; i
< snritems
; i
++)
87 item_number
*sp1
= ritem
+ sitems
[i
];
88 rule
const *r
= item_rule (sp1
);
89 item_print (sp1
, previous_rule
, out
);
92 /* Display the lookahead tokens? */
93 if (report_flag
& report_lookaheads
94 && item_number_is_rule_number (*sp1
))
95 state_rule_lookaheads_print (s
, r
, out
);
101 /*------------------------------------------------------------.
102 | Report the shifts iff DISPLAY_SHIFTS_P or the gotos of S on |
104 `------------------------------------------------------------*/
107 print_transitions (const state
*s
, FILE *out
, bool display_transitions_p
)
109 transitions
*trans
= s
->transitions
;
112 /* Compute the width of the lookahead token column. */
113 for (int i
= 0; i
< trans
->num
; i
++)
114 if (!TRANSITION_IS_DISABLED (trans
, i
)
115 && TRANSITION_IS_SHIFT (trans
, i
) == display_transitions_p
)
117 symbol
*sym
= symbols
[TRANSITION_SYMBOL (trans
, i
)];
118 max_length (&width
, sym
->tag
);
121 /* Nothing to report. */
128 /* Report lookahead tokens and shifts. */
129 for (int i
= 0; i
< trans
->num
; i
++)
130 if (!TRANSITION_IS_DISABLED (trans
, i
)
131 && TRANSITION_IS_SHIFT (trans
, i
) == display_transitions_p
)
133 symbol
*sym
= symbols
[TRANSITION_SYMBOL (trans
, i
)];
134 const char *tag
= sym
->tag
;
135 const state
*s1
= trans
->states
[i
];
137 fprintf (out
, " %s", tag
);
138 for (int j
= width
- mbswidth (tag
, 0); j
> 0; --j
)
140 if (display_transitions_p
)
141 fprintf (out
, _("shift, and go to state %d\n"), s1
->number
);
143 fprintf (out
, _("go to state %d\n"), s1
->number
);
148 /*--------------------------------------------------------.
149 | Report the explicit errors of S raised from %nonassoc. |
150 `--------------------------------------------------------*/
153 print_errs (FILE *out
, const state
*s
)
155 errs
*errp
= s
->errs
;
158 /* Compute the width of the lookahead token column. */
159 for (int i
= 0; i
< errp
->num
; ++i
)
160 if (errp
->symbols
[i
])
161 max_length (&width
, errp
->symbols
[i
]->tag
);
163 /* Nothing to report. */
170 /* Report lookahead tokens and errors. */
171 for (int i
= 0; i
< errp
->num
; ++i
)
172 if (errp
->symbols
[i
])
174 const char *tag
= errp
->symbols
[i
]->tag
;
175 fprintf (out
, " %s", tag
);
176 for (int j
= width
- mbswidth (tag
, 0); j
> 0; --j
)
178 fputs (_("error (nonassociative)\n"), out
);
183 /*-------------------------------------------------------------------.
184 | Report a reduction of RULE on LOOKAHEAD (which can be 'default'). |
185 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
187 `-------------------------------------------------------------------*/
190 print_reduction (FILE *out
, size_t width
,
191 const char *lookahead
,
192 rule
*r
, bool enabled
)
194 fprintf (out
, " %s", lookahead
);
195 for (int j
= width
- mbswidth (lookahead
, 0); j
> 0; --j
)
200 fprintf (out
, _("reduce using rule %d (%s)"), r
->number
,
201 r
->lhs
->symbol
->tag
);
203 fprintf (out
, _("accept"));
210 /*-------------------------------------------.
211 | Report on OUT the reduction actions of S. |
212 `-------------------------------------------*/
215 print_reductions (FILE *out
, const state
*s
)
217 reductions
*reds
= s
->reductions
;
221 rule
*default_reduction
= NULL
;
222 if (yydefact
[s
->number
] != 0)
223 default_reduction
= &rules
[yydefact
[s
->number
] - 1];
225 transitions
*trans
= s
->transitions
;
227 bitset_zero (no_reduce_set
);
230 FOR_EACH_SHIFT (trans
, i
)
231 bitset_set (no_reduce_set
, TRANSITION_SYMBOL (trans
, i
));
233 for (int i
= 0; i
< s
->errs
->num
; ++i
)
234 if (s
->errs
->symbols
[i
])
235 bitset_set (no_reduce_set
, s
->errs
->symbols
[i
]->content
->number
);
237 /* Compute the width of the lookahead token column. */
239 if (default_reduction
)
240 width
= mbswidth (_("$default"), 0);
242 if (reds
->lookaheads
)
243 for (int i
= 0; i
< ntokens
; i
++)
245 bool count
= bitset_test (no_reduce_set
, i
);
247 for (int j
= 0; j
< reds
->num
; ++j
)
248 if (bitset_test (reds
->lookaheads
[j
], i
))
252 if (reds
->rules
[j
] != default_reduction
)
253 max_length (&width
, symbols
[i
]->tag
);
257 max_length (&width
, symbols
[i
]->tag
);
261 /* Nothing to report. */
268 bool default_reduction_only
= true;
270 /* Report lookahead tokens (or $default) and reductions. */
271 if (reds
->lookaheads
)
272 for (int i
= 0; i
< ntokens
; i
++)
274 bool defaulted
= false;
275 bool count
= bitset_test (no_reduce_set
, i
);
277 default_reduction_only
= false;
279 for (int j
= 0; j
< reds
->num
; ++j
)
280 if (bitset_test (reds
->lookaheads
[j
], i
))
284 if (reds
->rules
[j
] != default_reduction
)
286 default_reduction_only
= false;
287 print_reduction (out
, width
,
289 reds
->rules
[j
], true);
297 default_reduction_only
= false;
299 print_reduction (out
, width
,
301 default_reduction
, true);
303 print_reduction (out
, width
,
305 reds
->rules
[j
], false);
310 if (default_reduction
)
312 char *default_reductions
=
313 muscle_percent_define_get ("lr.default-reduction");
314 print_reduction (out
, width
, _("$default"), default_reduction
, true);
315 aver (STREQ (default_reductions
, "most")
316 || (STREQ (default_reductions
, "consistent")
317 && default_reduction_only
)
318 || (reds
->num
== 1 && reds
->rules
[0]->number
== 0));
319 (void) default_reduction_only
;
320 free (default_reductions
);
325 /*--------------------------------------------------------------.
326 | Report on OUT all the actions (shifts, gotos, reductions, and |
327 | explicit errors from %nonassoc) of S. |
328 `--------------------------------------------------------------*/
331 print_actions (FILE *out
, const state
*s
)
334 print_transitions (s
, out
, true);
336 print_reductions (out
, s
);
338 print_transitions (s
, out
, false);
342 /*----------------------------------.
343 | Report all the data on S on OUT. |
344 `----------------------------------*/
347 print_state (FILE *out
, const state
*s
)
350 fprintf (out
, _("State %d"), s
->number
);
353 print_actions (out
, s
);
354 if ((report_flag
& report_solved_conflicts
) && s
->solved_conflicts
)
357 fputs (s
->solved_conflicts
, out
);
359 if (has_conflicts (s
)
360 && (report_flag
& report_cex
361 || warning_is_enabled (Wcounterexamples
)))
364 counterexample_report_state (s
, out
, " ");
368 /*-----------------------------------------.
369 | Print information on the whole grammar. |
370 `-----------------------------------------*/
373 print_terminal_symbols (FILE *out
)
375 /* TERMINAL (type #) : rule #s terminal is on RHS */
376 fprintf (out
, "%s\n\n", _("Terminals, with rules where they appear"));
377 for (int i
= 0; i
< max_code
+ 1; ++i
)
378 if (token_translations
[i
] != undeftoken
->content
->number
)
380 const symbol
*sym
= symbols
[token_translations
[i
]];
381 const char *tag
= sym
->tag
;
382 fprintf (out
, "%4s%s", "", tag
);
383 if (sym
->content
->type_name
)
384 fprintf (out
, " <%s>", sym
->content
->type_name
);
385 fprintf (out
, " (%d)", i
);
387 for (rule_number r
= 0; r
< nrules
; r
++)
388 for (item_number
*rhsp
= rules
[r
].rhs
; *rhsp
>= 0; rhsp
++)
389 if (item_number_as_symbol_number (*rhsp
) == token_translations
[i
])
391 fprintf (out
, " %d", r
);
401 print_nonterminal_symbols (FILE *out
)
403 fprintf (out
, "%s\n\n", _("Nonterminals, with rules where they appear"));
404 for (symbol_number i
= ntokens
; i
< nsyms
; i
++)
406 const symbol
*sym
= symbols
[i
];
407 const char *tag
= sym
->tag
;
408 bool on_left
= false;
409 bool on_right
= false;
411 for (rule_number r
= 0; r
< nrules
; r
++)
413 on_left
|= rules
[r
].lhs
->number
== i
;
414 for (item_number
*rhsp
= rules
[r
].rhs
; !on_right
&& 0 <= *rhsp
; ++rhsp
)
415 on_right
|= item_number_as_symbol_number (*rhsp
) == i
;
416 if (on_left
&& on_right
)
420 int column
= 4 + mbswidth (tag
, 0);
421 fprintf (out
, "%4s%s", "", tag
);
422 if (sym
->content
->type_name
)
423 column
+= fprintf (out
, " <%s>",
424 sym
->content
->type_name
);
425 fprintf (out
, " (%d)\n", i
);
429 fprintf (out
, "%8s%s", "", _("on left:"));
430 for (rule_number r
= 0; r
< nrules
; r
++)
431 if (rules
[r
].lhs
->number
== i
)
432 fprintf (out
, " %d", r
);
438 fprintf (out
, "%8s%s", "", _("on right:"));
439 for (rule_number r
= 0; r
< nrules
; r
++)
440 for (item_number
*rhsp
= rules
[r
].rhs
; 0 <= *rhsp
; ++rhsp
)
441 if (item_number_as_symbol_number (*rhsp
) == i
)
443 fprintf (out
, " %d", r
);
454 /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but
455 that conflicts with Posix. */
456 FILE *out
= xfopen (spec_verbose_file
, "w");
459 grammar_rules_partial_print (out
,
460 _("Rules useless in parser due to conflicts"),
461 rule_useless_in_parser_p
);
462 conflicts_output (out
);
464 grammar_rules_print (out
);
465 print_terminal_symbols (out
);
466 print_nonterminal_symbols (out
);
468 /* Storage for print_reductions. */
469 no_reduce_set
= bitset_create (ntokens
, BITSET_FIXED
);
470 for (state_number i
= 0; i
< nstates
; i
++)
471 print_state (out
, states
[i
]);
472 bitset_free (no_reduce_set
);