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