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