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