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