]> git.saurik.com Git - bison.git/blob - src/print.c
New experimental feature: if --verbose --trace output all the
[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 #if 0
36 static void
37 print_token (int extnum, int token)
38 {
39 fprintf (out, _(" type %d is %s\n"), extnum, tags[token]);
40 }
41 #endif
42
43 \f
44 /*--------------------------------.
45 | Report information on a state. |
46 `--------------------------------*/
47
48 static void
49 print_core (FILE *out, int state)
50 {
51 int i;
52 short *sitems = state_table[state].state->items;
53 int snitems = state_table[state].state->nitems;
54
55 /* New experimental feature: if TRACE_FLAGS output all the items of
56 a state, not only its kernel. */
57 if (trace_flag)
58 {
59 closure (sitems, snitems);
60 sitems = itemset;
61 snitems = nitemset;
62 }
63
64 if (snitems)
65 {
66 for (i = 0; i < snitems; i++)
67 {
68 short *sp;
69 short *sp1;
70 int rule;
71
72 sp1 = sp = ritem + sitems[i];
73
74 while (*sp > 0)
75 sp++;
76
77 rule = -(*sp);
78 fprintf (out, " %s -> ", tags[rule_table[rule].lhs]);
79
80 for (sp = ritem + rule_table[rule].rhs; sp < sp1; sp++)
81 fprintf (out, "%s ", tags[*sp]);
82
83 fputc ('.', out);
84
85 for (/* Nothing */; *sp > 0; ++sp)
86 fprintf (out, " %s", tags[*sp]);
87
88 fprintf (out, _(" (rule %d)"), rule);
89 fputc ('\n', out);
90 }
91
92 fputc ('\n', out);
93 }
94 }
95
96 static void
97 print_actions (FILE *out, int state)
98 {
99 int i;
100
101 shifts *shiftp = state_table[state].shift_table;
102 reductions *redp = state_table[state].reduction_table;
103 errs *errp = err_table[state];
104
105 if (!shiftp->nshifts && !redp)
106 {
107 if (final_state == state)
108 fprintf (out, _(" $default\taccept\n"));
109 else
110 fprintf (out, _(" NO ACTIONS\n"));
111 return;
112 }
113
114 for (i = 0; i < shiftp->nshifts; i++)
115 if (!SHIFT_IS_DISABLED (shiftp, i))
116 {
117 int state1 = shiftp->shifts[i];
118 int symbol = state_table[state1].accessing_symbol;
119 /* The following line used to be turned off. */
120 if (ISVAR (symbol))
121 break;
122 if (symbol == 0) /* I.e. strcmp(tags[symbol],"$")==0 */
123 fprintf (out,
124 _(" $ \tgo to state %d\n"), state1);
125 else
126 fprintf (out,
127 _(" %-4s\tshift, and go to state %d\n"),
128 tags[symbol], state1);
129 }
130
131 if (i > 0)
132 fputc ('\n', out);
133
134 if (errp)
135 {
136 int j;
137 for (j = 0; j < errp->nerrs; j++)
138 {
139 int symbol = errp->errs[j];
140 if (!symbol)
141 continue;
142 fprintf (out, _(" %-4s\terror (nonassociative)\n"),
143 tags[symbol]);
144 }
145
146 if (j > 0)
147 fputc ('\n', out);
148 }
149
150 if (state_table[state].consistent && redp)
151 {
152 int rule = redp->rules[0];
153 int symbol = rule_table[rule].lhs;
154 fprintf (out, _(" $default\treduce using rule %d (%s)\n\n"),
155 rule, tags[symbol]);
156 }
157 else if (redp)
158 {
159 print_reductions (out, state);
160 }
161
162 if (i < shiftp->nshifts)
163 {
164 for (; i < shiftp->nshifts; i++)
165 if (!SHIFT_IS_DISABLED (shiftp, i))
166 {
167 int state1 = shiftp->shifts[i];
168 int symbol = state_table[state1].accessing_symbol;
169 fprintf (out, _(" %-4s\tgo to state %d\n"),
170 tags[symbol], state1);
171 }
172
173 fputc ('\n', out);
174 }
175 }
176
177 static void
178 print_state (FILE *out, int state)
179 {
180 fprintf (out, _("state %d"), state);
181 fputs ("\n\n", out);
182 print_core (out, state);
183 print_actions (out, state);
184 fputs ("\n\n", out);
185 }
186 \f
187 /*-----------------------------------------.
188 | Print information on the whole grammar. |
189 `-----------------------------------------*/
190
191 #define END_TEST(End) \
192 do { \
193 if (column + strlen(buffer) > (End)) \
194 { \
195 fprintf (out, "%s\n ", buffer); \
196 column = 3; \
197 buffer[0] = 0; \
198 } \
199 } while (0)
200
201
202 static void
203 print_grammar (FILE *out)
204 {
205 int i, j;
206 short *rule;
207 char buffer[90];
208 int column = 0;
209
210 /* rule # : LHS -> RHS */
211 fprintf (out, "%s\n\n", _("Grammar"));
212 fprintf (out, " %s\n", _("Number, Line, Rule"));
213 for (i = 1; i <= nrules; i++)
214 /* Don't print rules disabled in reduce_grammar_tables. */
215 if (rule_table[i].useful)
216 {
217 fprintf (out, _(" %3d %3d %s ->"),
218 i, rule_table[i].line, tags[rule_table[i].lhs]);
219 rule = &ritem[rule_table[i].rhs];
220 if (*rule > 0)
221 while (*rule > 0)
222 fprintf (out, " %s", tags[*rule++]);
223 else
224 fprintf (out, " /* %s */", _("empty"));
225 fputc ('\n', out);
226 }
227 fputs ("\n\n", out);
228
229
230 /* TERMINAL (type #) : rule #s terminal is on RHS */
231 fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
232 fprintf (out, "%s (-1)\n", tags[0]);
233
234 for (i = 0; i <= max_user_token_number; i++)
235 if (token_translations[i] != 2)
236 {
237 buffer[0] = 0;
238 column = strlen (tags[token_translations[i]]);
239 fputs (tags[token_translations[i]], out);
240 END_TEST (50);
241 sprintf (buffer, " (%d)", i);
242
243 for (j = 1; j <= nrules; j++)
244 for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
245 if (*rule == token_translations[i])
246 {
247 END_TEST (65);
248 sprintf (buffer + strlen (buffer), " %d", j);
249 break;
250 }
251 fprintf (out, "%s\n", buffer);
252 }
253 fputs ("\n\n", out);
254
255
256 fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
257 for (i = ntokens; i <= nsyms - 1; i++)
258 {
259 int left_count = 0, right_count = 0;
260
261 for (j = 1; j <= nrules; j++)
262 {
263 if (rule_table[j].lhs == i)
264 left_count++;
265 for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
266 if (*rule == i)
267 {
268 right_count++;
269 break;
270 }
271 }
272
273 buffer[0] = 0;
274 fputs (tags[i], out);
275 column = strlen (tags[i]);
276 sprintf (buffer, " (%d)", i);
277 END_TEST (0);
278
279 if (left_count > 0)
280 {
281 END_TEST (50);
282 sprintf (buffer + strlen (buffer), _(" on left:"));
283
284 for (j = 1; j <= nrules; j++)
285 {
286 END_TEST (65);
287 if (rule_table[j].lhs == i)
288 sprintf (buffer + strlen (buffer), " %d", j);
289 }
290 }
291
292 if (right_count > 0)
293 {
294 if (left_count > 0)
295 sprintf (buffer + strlen (buffer), ",");
296 END_TEST (50);
297 sprintf (buffer + strlen (buffer), _(" on right:"));
298 for (j = 1; j <= nrules; j++)
299 {
300 for (rule = &ritem[rule_table[j].rhs]; *rule > 0; rule++)
301 if (*rule == i)
302 {
303 END_TEST (65);
304 sprintf (buffer + strlen (buffer), " %d", j);
305 break;
306 }
307 }
308 }
309 fprintf (out, "%s\n", buffer);
310 }
311 fputs ("\n\n", out);
312 }
313 \f
314 void
315 print_results (void)
316 {
317 if (verbose_flag)
318 {
319 int i;
320
321 /* We used to use just .out if spec_name_prefix (-p) was used, but
322 that conflicts with Posix. */
323 FILE *out = xfopen (spec_verbose_file, "w");
324
325 size_t size = obstack_object_size (&output_obstack);
326 fwrite (obstack_finish (&output_obstack), 1, size, out);
327 if (size)
328 fputs ("\n\n", out);
329
330 reduce_output (out);
331 conflicts_output (out);
332
333 print_grammar (out);
334
335 /* New experimental feature: output all the items of a state,
336 not only its kernel. Requires to run closure, which need
337 memory allocation/deallocation. */
338 if (trace_flag)
339 new_closure (nitems);
340 for (i = 0; i < nstates; i++)
341 print_state (out, i);
342 if (trace_flag)
343 free_closure ();
344
345 xfclose (out);
346 }
347 obstack_free (&output_obstack, NULL);
348 }