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