]>
Commit | Line | Data |
---|---|---|
e06f0c34 | 1 | /* Print information on generated parser, for bison, |
b0299a2e AD |
2 | Copyright (C) 1984, 1986, 1989, 2000, 2001, 2002 |
3 | Free Software Foundation, Inc. | |
e06f0c34 | 4 | |
c29240e7 | 5 | This file is part of Bison, the GNU Compiler Compiler. |
e06f0c34 | 6 | |
c29240e7 AD |
7 | Bison is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
e06f0c34 | 11 | |
c29240e7 AD |
12 | Bison is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
e06f0c34 | 16 | |
c29240e7 AD |
17 | You should have received a copy of the GNU General Public License |
18 | along with Bison; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
e06f0c34 RS |
21 | |
22 | ||
e06f0c34 | 23 | #include "system.h" |
8adfa272 | 24 | #include "quotearg.h" |
e06f0c34 | 25 | #include "files.h" |
ad949da9 | 26 | #include "symtab.h" |
e06f0c34 | 27 | #include "gram.h" |
b2ca4022 | 28 | #include "LR0.h" |
720d742f | 29 | #include "lalr.h" |
0619caf0 | 30 | #include "conflicts.h" |
07a58c13 AD |
31 | #include "getargs.h" |
32 | #include "state.h" | |
b2ca4022 | 33 | #include "reader.h" |
d7913476 | 34 | #include "print.h" |
09b503c8 | 35 | #include "reduce.h" |
43168960 | 36 | #include "closure.h" |
34ba9743 | 37 | #include "bitset.h" |
e06f0c34 | 38 | |
34ba9743 AD |
39 | static bitset shiftset; |
40 | static bitset lookaheadset; | |
5092aba5 | 41 | |
07a58c13 | 42 | #if 0 |
4a120d45 | 43 | static void |
d2729d44 | 44 | print_token (int extnum, int token) |
e06f0c34 | 45 | { |
342b8b6e | 46 | fprintf (out, _(" type %d is %s\n"), extnum, tags[token]); |
e06f0c34 | 47 | } |
4a120d45 | 48 | #endif |
e06f0c34 | 49 | |
07a58c13 | 50 | \f |
342b8b6e | 51 | /*--------------------------------. |
07a58c13 | 52 | | Report information on a state. | |
342b8b6e | 53 | `--------------------------------*/ |
e06f0c34 | 54 | |
4a120d45 | 55 | static void |
065fbd27 | 56 | print_core (FILE *out, state_t *state) |
e06f0c34 | 57 | { |
c29240e7 | 58 | int i; |
62a3e4f0 | 59 | item_number_t *sitems = state->items; |
5123689b | 60 | int snritems = state->nitems; |
ce4ccb4b | 61 | symbol_t *previous_lhs = NULL; |
e06f0c34 | 62 | |
ec3bc396 AD |
63 | /* Output all the items of a state, not only its kernel. */ |
64 | if (report_flag & report_itemsets) | |
43168960 | 65 | { |
5123689b | 66 | closure (sitems, snritems); |
43168960 | 67 | sitems = itemset; |
5123689b | 68 | snritems = nritemset; |
43168960 | 69 | } |
e06f0c34 | 70 | |
ce4ccb4b AD |
71 | if (!snritems) |
72 | return; | |
e06f0c34 | 73 | |
ce4ccb4b AD |
74 | for (i = 0; i < snritems; i++) |
75 | { | |
76 | item_number_t *sp; | |
77 | item_number_t *sp1; | |
78 | int rule; | |
e06f0c34 | 79 | |
ce4ccb4b | 80 | sp1 = sp = ritem + sitems[i]; |
e06f0c34 | 81 | |
ce4ccb4b AD |
82 | while (*sp >= 0) |
83 | sp++; | |
e06f0c34 | 84 | |
ce4ccb4b | 85 | rule = -(*sp); |
e06f0c34 | 86 | |
ce4ccb4b AD |
87 | rule_lhs_print (&rules[rule], previous_lhs, out); |
88 | previous_lhs = rules[rule].lhs; | |
43168960 | 89 | |
ce4ccb4b AD |
90 | for (sp = rules[rule].rhs; sp < sp1; sp++) |
91 | fprintf (out, " %s", symbol_tag_get (symbols[*sp])); | |
92 | fputs (" .", out); | |
93 | for (/* Nothing */; *sp >= 0; ++sp) | |
94 | fprintf (out, " %s", symbol_tag_get (symbols[*sp])); | |
d4e7d3a1 | 95 | |
ce4ccb4b AD |
96 | /* Display the lookaheads? */ |
97 | if (report_flag & report_lookaheads) | |
98 | state_rule_lookaheads_print (state, &rules[rule], out); | |
e06f0c34 | 99 | |
342b8b6e | 100 | fputc ('\n', out); |
e06f0c34 | 101 | } |
ce4ccb4b AD |
102 | |
103 | fputc ('\n', out); | |
e06f0c34 RS |
104 | } |
105 | ||
5092aba5 | 106 | |
4a120d45 | 107 | static void |
5092aba5 | 108 | print_shifts (FILE *out, state_t *state) |
e06f0c34 | 109 | { |
c29240e7 | 110 | int i; |
32e1e0a4 | 111 | shifts_t *shiftp = state->shifts; |
e06f0c34 | 112 | |
2e729273 | 113 | for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++) |
d954473d AD |
114 | if (!SHIFT_IS_DISABLED (shiftp, i)) |
115 | { | |
d57650a5 | 116 | state_number_t state1 = shiftp->shifts[i]; |
a49aecd5 | 117 | symbol_number_t symbol = states[state1]->accessing_symbol; |
2e729273 AD |
118 | fprintf (out, |
119 | _(" %-4s\tshift, and go to state %d\n"), | |
6b98e4b5 | 120 | symbol_tag_get (symbols[symbol]), state1); |
d954473d | 121 | } |
e06f0c34 | 122 | |
d954473d AD |
123 | if (i > 0) |
124 | fputc ('\n', out); | |
5092aba5 | 125 | } |
e06f0c34 | 126 | |
e06f0c34 | 127 | |
5092aba5 AD |
128 | static void |
129 | print_errs (FILE *out, state_t *state) | |
130 | { | |
8a731ca8 | 131 | errs_t *errp = state->errs; |
5092aba5 AD |
132 | int i; |
133 | ||
5092aba5 AD |
134 | for (i = 0; i < errp->nerrs; ++i) |
135 | if (errp->errs[i]) | |
136 | fprintf (out, _(" %-4s\terror (nonassociative)\n"), | |
6b98e4b5 | 137 | symbol_tag_get (symbols[errp->errs[i]])); |
5092aba5 AD |
138 | |
139 | if (i > 0) | |
2cec70b9 | 140 | fputc ('\n', out); |
5092aba5 | 141 | } |
e06f0c34 | 142 | |
5092aba5 AD |
143 | |
144 | static void | |
145 | print_gotos (FILE *out, state_t *state) | |
146 | { | |
147 | int i; | |
32e1e0a4 | 148 | shifts_t *shiftp = state->shifts; |
5092aba5 AD |
149 | |
150 | for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++) | |
151 | /* Skip token shifts. */; | |
e06f0c34 | 152 | |
d954473d | 153 | if (i < shiftp->nshifts) |
e06f0c34 | 154 | { |
d954473d AD |
155 | for (; i < shiftp->nshifts; i++) |
156 | if (!SHIFT_IS_DISABLED (shiftp, i)) | |
157 | { | |
d57650a5 | 158 | state_number_t state1 = shiftp->shifts[i]; |
a49aecd5 | 159 | symbol_number_t symbol = states[state1]->accessing_symbol; |
d954473d | 160 | fprintf (out, _(" %-4s\tgo to state %d\n"), |
6b98e4b5 | 161 | symbol_tag_get (symbols[symbol]), state1); |
d954473d | 162 | } |
e06f0c34 | 163 | |
342b8b6e | 164 | fputc ('\n', out); |
e06f0c34 RS |
165 | } |
166 | } | |
167 | ||
bc933ef1 AD |
168 | |
169 | /*----------------------------------------------------------. | |
170 | | Return the default rule of this STATE if it has one, NULL | | |
171 | | otherwise. | | |
172 | `----------------------------------------------------------*/ | |
173 | ||
174 | static rule_t * | |
175 | state_default_rule_compute (state_t *state) | |
176 | { | |
177 | reductions_t *redp = state->reductions; | |
178 | rule_t *default_rule = NULL; | |
179 | int cmax = 0; | |
180 | int i; | |
181 | ||
182 | /* No need for a lookahead. */ | |
183 | if (state->consistent) | |
184 | return &rules[redp->rules[0]]; | |
185 | ||
186 | /* 1. Each reduction is possibly masked by the lookaheads on which | |
187 | we shift (S/R conflicts)... */ | |
188 | bitset_zero (shiftset); | |
189 | { | |
190 | shifts_t *shiftp = state->shifts; | |
191 | for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++) | |
192 | if (!SHIFT_IS_DISABLED (shiftp, i)) | |
193 | { | |
194 | /* If this state has a shift for the error token, don't use a | |
195 | default rule. */ | |
196 | if (SHIFT_IS_ERROR (shiftp, i)) | |
197 | return NULL; | |
198 | bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i)); | |
199 | } | |
200 | } | |
201 | ||
202 | /* 2. Each reduction is possibly masked by the lookaheads on which | |
203 | we raise an error (due to %nonassoc). */ | |
204 | { | |
205 | errs_t *errp = state->errs; | |
206 | for (i = 0; i < errp->nerrs; i++) | |
207 | if (errp->errs[i]) | |
208 | bitset_set (shiftset, errp->errs[i]); | |
209 | } | |
210 | ||
211 | for (i = 0; i < state->nlookaheads; ++i) | |
212 | { | |
213 | int count = 0; | |
214 | ||
215 | /* How many non-masked lookaheads are there for this reduction? | |
216 | */ | |
217 | bitset_andn (lookaheadset, state->lookaheads[i], shiftset); | |
218 | count = bitset_count (lookaheadset); | |
219 | ||
220 | if (count > cmax) | |
221 | { | |
222 | cmax = count; | |
223 | default_rule = state->lookaheads_rule[i]; | |
224 | } | |
225 | ||
226 | /* 3. And finally, each reduction is possibly masked by previous | |
227 | reductions (in R/R conflicts, we keep the first reductions). | |
228 | */ | |
229 | bitset_or (shiftset, shiftset, state->lookaheads[i]); | |
230 | } | |
231 | ||
232 | return default_rule; | |
233 | } | |
234 | ||
235 | ||
236 | /*----------------------------------------------------. | |
237 | | Report on OUT the reduction actions of this STATE. | | |
238 | `----------------------------------------------------*/ | |
239 | ||
5092aba5 AD |
240 | static void |
241 | print_reductions (FILE *out, state_t *state) | |
242 | { | |
243 | int i; | |
32e1e0a4 | 244 | shifts_t *shiftp = state->shifts; |
8a731ca8 | 245 | reductions_t *redp = state->reductions; |
bc933ef1 | 246 | rule_t *default_rule = NULL; |
5092aba5 | 247 | |
80dac38c AD |
248 | if (redp->nreds == 0) |
249 | return; | |
250 | ||
bc933ef1 | 251 | default_rule = state_default_rule_compute (state); |
5092aba5 | 252 | |
34ba9743 | 253 | bitset_zero (shiftset); |
5092aba5 AD |
254 | for (i = 0; i < shiftp->nshifts && SHIFT_IS_SHIFT (shiftp, i); i++) |
255 | if (!SHIFT_IS_DISABLED (shiftp, i)) | |
bc933ef1 | 256 | bitset_set (shiftset, SHIFT_SYMBOL (shiftp, i)); |
5092aba5 | 257 | |
bc933ef1 | 258 | for (i = 0; i < ntokens; i++) |
5092aba5 | 259 | { |
bc933ef1 AD |
260 | int j; |
261 | int defaulted = 0; | |
262 | int count = bitset_test (shiftset, i); | |
5092aba5 | 263 | |
bc933ef1 AD |
264 | for (j = 0; j < state->nlookaheads; ++j) |
265 | if (bitset_test (state->lookaheads[j], i)) | |
5092aba5 | 266 | { |
bc933ef1 | 267 | if (count == 0) |
5092aba5 | 268 | { |
bc933ef1 AD |
269 | if (state->lookaheads_rule[j] != default_rule) |
270 | fprintf (out, | |
271 | _(" %-4s\treduce using rule %d (%s)\n"), | |
272 | symbol_tag_get (symbols[i]), | |
273 | state->lookaheads_rule[j]->number - 1, | |
274 | symbol_tag_get_n (state->lookaheads_rule[j]->lhs, 1)); | |
275 | else | |
276 | defaulted = 1; | |
277 | count++; | |
5092aba5 | 278 | } |
bc933ef1 | 279 | else |
f9abaa2c | 280 | { |
bc933ef1 AD |
281 | if (defaulted) |
282 | fprintf (out, | |
283 | _(" %-4s\treduce using rule %d (%s)\n"), | |
284 | symbol_tag_get (symbols[i]), | |
285 | default_rule->number - 1, | |
286 | symbol_tag_get_n (default_rule->lhs, 1)); | |
287 | defaulted = 0; | |
288 | fprintf (out, | |
289 | _(" %-4s\t[reduce using rule %d (%s)]\n"), | |
290 | symbol_tag_get (symbols[i]), | |
291 | state->lookaheads_rule[j]->number - 1, | |
292 | symbol_tag_get_n (state->lookaheads_rule[j]->lhs, 1)); | |
f9abaa2c | 293 | } |
bc933ef1 | 294 | } |
5092aba5 | 295 | } |
bc933ef1 AD |
296 | |
297 | if (default_rule) | |
298 | fprintf (out, _(" $default\treduce using rule %d (%s)\n"), | |
299 | default_rule->number - 1, | |
300 | symbol_tag_get (default_rule->lhs)); | |
301 | fputc ('\n', out); | |
5092aba5 AD |
302 | } |
303 | ||
304 | ||
bc933ef1 AD |
305 | /*--------------------------------------------------------------. |
306 | | Report on OUT all the actions (shifts, gotos, reductions, and | | |
307 | | explicit erros from %nonassoc) of STATE. | | |
308 | `--------------------------------------------------------------*/ | |
309 | ||
5092aba5 AD |
310 | static void |
311 | print_actions (FILE *out, state_t *state) | |
312 | { | |
8a731ca8 | 313 | reductions_t *redp = state->reductions; |
32e1e0a4 | 314 | shifts_t *shiftp = state->shifts; |
5092aba5 | 315 | |
80dac38c | 316 | if (shiftp->nshifts == 0 && redp->nreds == 0) |
5092aba5 | 317 | { |
d57650a5 | 318 | if (state->number == final_state->number) |
bc933ef1 | 319 | fprintf (out, _(" $default\taccept\n")); |
5092aba5 | 320 | else |
bc933ef1 | 321 | fprintf (out, _(" NO ACTIONS\n")); |
5092aba5 AD |
322 | return; |
323 | } | |
324 | ||
325 | print_shifts (out, state); | |
326 | print_errs (out, state); | |
80dac38c | 327 | print_reductions (out, state); |
5092aba5 AD |
328 | print_gotos (out, state); |
329 | } | |
330 | ||
bc933ef1 | 331 | |
07a58c13 | 332 | static void |
065fbd27 | 333 | print_state (FILE *out, state_t *state) |
07a58c13 | 334 | { |
065fbd27 | 335 | fprintf (out, _("state %d"), state->number); |
342b8b6e AD |
336 | fputs ("\n\n", out); |
337 | print_core (out, state); | |
338 | print_actions (out, state); | |
b408954b AD |
339 | if ((report_flag & report_solved_conflicts) |
340 | && state->solved_conflicts) | |
341 | fputs (state->solved_conflicts, out); | |
d2d1b42b | 342 | fputs ("\n\n", out); |
07a58c13 AD |
343 | } |
344 | \f | |
345 | /*-----------------------------------------. | |
346 | | Print information on the whole grammar. | | |
347 | `-----------------------------------------*/ | |
348 | ||
342b8b6e AD |
349 | #define END_TEST(End) \ |
350 | do { \ | |
351 | if (column + strlen(buffer) > (End)) \ | |
352 | { \ | |
353 | fprintf (out, "%s\n ", buffer); \ | |
354 | column = 3; \ | |
355 | buffer[0] = 0; \ | |
356 | } \ | |
ff4423cc | 357 | } while (0) |
e06f0c34 | 358 | |
07a58c13 | 359 | |
4a120d45 | 360 | static void |
342b8b6e | 361 | print_grammar (FILE *out) |
e06f0c34 | 362 | { |
a49aecd5 | 363 | symbol_number_t i; |
e06f0c34 RS |
364 | char buffer[90]; |
365 | int column = 0; | |
366 | ||
6b98e4b5 | 367 | grammar_rules_print (out); |
e06f0c34 RS |
368 | |
369 | /* TERMINAL (type #) : rule #s terminal is on RHS */ | |
d2d1b42b | 370 | fprintf (out, "%s\n\n", _("Terminals, with rules where they appear")); |
18bcecb0 | 371 | for (i = 0; i < max_user_token_number + 1; i++) |
007a50a4 | 372 | if (token_translations[i] != undeftoken->number) |
342b8b6e | 373 | { |
6b98e4b5 | 374 | const char *tag = symbol_tag_get (symbols[token_translations[i]]); |
9222837b AD |
375 | rule_number_t r; |
376 | item_number_t *rhsp; | |
377 | ||
342b8b6e | 378 | buffer[0] = 0; |
6b98e4b5 AD |
379 | column = strlen (tag); |
380 | fputs (tag, out); | |
342b8b6e AD |
381 | END_TEST (50); |
382 | sprintf (buffer, " (%d)", i); | |
e06f0c34 | 383 | |
6b98e4b5 | 384 | for (r = 1; r < nrules + 1; r++) |
9222837b AD |
385 | for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) |
386 | if (item_number_as_symbol_number (*rhsp) == token_translations[i]) | |
342b8b6e AD |
387 | { |
388 | END_TEST (65); | |
6b98e4b5 | 389 | sprintf (buffer + strlen (buffer), " %d", r - 1); |
342b8b6e AD |
390 | break; |
391 | } | |
392 | fprintf (out, "%s\n", buffer); | |
393 | } | |
d2d1b42b AD |
394 | fputs ("\n\n", out); |
395 | ||
342b8b6e | 396 | |
d2d1b42b | 397 | fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear")); |
18bcecb0 | 398 | for (i = ntokens; i < nsyms; i++) |
e06f0c34 RS |
399 | { |
400 | int left_count = 0, right_count = 0; | |
9222837b | 401 | rule_number_t r; |
6b98e4b5 | 402 | const char *tag = symbol_tag_get (symbols[i]); |
e06f0c34 | 403 | |
6b98e4b5 | 404 | for (r = 1; r < nrules + 1; r++) |
e06f0c34 | 405 | { |
9222837b | 406 | item_number_t *rhsp; |
6b98e4b5 | 407 | if (rules[r].lhs->number == i) |
e06f0c34 | 408 | left_count++; |
9222837b AD |
409 | for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) |
410 | if (item_number_as_symbol_number (*rhsp) == i) | |
e06f0c34 RS |
411 | { |
412 | right_count++; | |
413 | break; | |
414 | } | |
415 | } | |
416 | ||
417 | buffer[0] = 0; | |
6b98e4b5 AD |
418 | fputs (tag, out); |
419 | column = strlen (tag); | |
e06f0c34 RS |
420 | sprintf (buffer, " (%d)", i); |
421 | END_TEST (0); | |
422 | ||
423 | if (left_count > 0) | |
424 | { | |
425 | END_TEST (50); | |
c29240e7 | 426 | sprintf (buffer + strlen (buffer), _(" on left:")); |
e06f0c34 | 427 | |
6b98e4b5 | 428 | for (r = 1; r < nrules + 1; r++) |
e06f0c34 RS |
429 | { |
430 | END_TEST (65); | |
6b98e4b5 AD |
431 | if (rules[r].lhs->number == i) |
432 | sprintf (buffer + strlen (buffer), " %d", r - 1); | |
e06f0c34 RS |
433 | } |
434 | } | |
435 | ||
436 | if (right_count > 0) | |
437 | { | |
438 | if (left_count > 0) | |
c29240e7 | 439 | sprintf (buffer + strlen (buffer), ","); |
e06f0c34 | 440 | END_TEST (50); |
c29240e7 | 441 | sprintf (buffer + strlen (buffer), _(" on right:")); |
6b98e4b5 | 442 | for (r = 1; r < nrules + 1; r++) |
e06f0c34 | 443 | { |
9222837b AD |
444 | item_number_t *rhsp; |
445 | for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) | |
446 | if (item_number_as_symbol_number (*rhsp) == i) | |
e06f0c34 RS |
447 | { |
448 | END_TEST (65); | |
6b98e4b5 | 449 | sprintf (buffer + strlen (buffer), " %d", r - 1); |
e06f0c34 RS |
450 | break; |
451 | } | |
452 | } | |
453 | } | |
342b8b6e | 454 | fprintf (out, "%s\n", buffer); |
e06f0c34 | 455 | } |
d2d1b42b | 456 | fputs ("\n\n", out); |
e06f0c34 | 457 | } |
07a58c13 AD |
458 | \f |
459 | void | |
460 | print_results (void) | |
461 | { | |
d57650a5 | 462 | state_number_t i; |
07a58c13 | 463 | |
64d15509 AD |
464 | /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but |
465 | that conflicts with Posix. */ | |
466 | FILE *out = xfopen (spec_verbose_file, "w"); | |
07a58c13 | 467 | |
64d15509 AD |
468 | reduce_output (out); |
469 | conflicts_output (out); | |
342b8b6e | 470 | |
64d15509 | 471 | print_grammar (out); |
342b8b6e | 472 | |
ec3bc396 AD |
473 | /* If the whole state item sets, not only the kernels, are wanted, |
474 | `closure' will be run, which needs memory allocation/deallocation. */ | |
475 | if (report_flag & report_itemsets) | |
9e7f6bbd | 476 | new_closure (nritems); |
5092aba5 | 477 | /* Storage for print_reductions. */ |
34ba9743 | 478 | shiftset = bitset_create (ntokens, BITSET_FIXED); |
34ba9743 | 479 | lookaheadset = bitset_create (ntokens, BITSET_FIXED); |
64d15509 | 480 | for (i = 0; i < nstates; i++) |
29e88316 | 481 | print_state (out, states[i]); |
34ba9743 AD |
482 | bitset_free (shiftset); |
483 | bitset_free (lookaheadset); | |
ec3bc396 | 484 | if (report_flag & report_itemsets) |
64d15509 AD |
485 | free_closure (); |
486 | ||
487 | xfclose (out); | |
07a58c13 | 488 | } |