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