]> git.saurik.com Git - bison.git/blob - src/gram.c
maint: prepare to use date ranges in copyright notices.
[bison.git] / src / gram.c
1 /* Allocate input grammar variables for Bison.
2
3 Copyright (C) 1984, 1986, 1989, 2001, 2002, 2003, 2005, 2006, 2007,
4 2008, 2009, 2010 Free Software Foundation, Inc.
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22 #include "system.h"
23
24 #include <quotearg.h>
25
26 #include "complain.h"
27 #include "gram.h"
28 #include "print-xml.h"
29 #include "reader.h"
30 #include "reduce.h"
31 #include "symtab.h"
32
33 /* Comments for these variables are in gram.h. */
34
35 item_number *ritem = NULL;
36 unsigned int nritems = 0;
37
38 rule *rules = NULL;
39 rule_number nrules = 0;
40
41 symbol **symbols = NULL;
42 int nsyms = 0;
43 int ntokens = 1;
44 int nvars = 0;
45
46 symbol_number *token_translations = NULL;
47
48 int max_user_token_number = 256;
49
50 bool
51 rule_useful_in_grammar_p (rule *r)
52 {
53 return r->number < nrules;
54 }
55
56 bool
57 rule_useless_in_grammar_p (rule *r)
58 {
59 return !rule_useful_in_grammar_p (r);
60 }
61
62 bool
63 rule_useless_in_parser_p (rule *r)
64 {
65 return !r->useful && rule_useful_in_grammar_p (r);
66 }
67
68 void
69 rule_lhs_print (rule *r, symbol *previous_lhs, FILE *out)
70 {
71 fprintf (out, " %3d ", r->number);
72 if (previous_lhs != r->lhs)
73 {
74 fprintf (out, "%s:", r->lhs->tag);
75 }
76 else
77 {
78 int n;
79 for (n = strlen (previous_lhs->tag); n > 0; --n)
80 fputc (' ', out);
81 fputc ('|', out);
82 }
83 }
84
85 void
86 rule_lhs_print_xml (rule *r, FILE *out, int level)
87 {
88 xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag);
89 }
90
91 int
92 rule_rhs_length (rule *r)
93 {
94 int res = 0;
95 item_number *rhsp;
96 for (rhsp = r->rhs; *rhsp >= 0; ++rhsp)
97 ++res;
98 return res;
99 }
100
101 void
102 rule_rhs_print (rule *r, FILE *out)
103 {
104 if (*r->rhs >= 0)
105 {
106 item_number *rp;
107 for (rp = r->rhs; *rp >= 0; rp++)
108 fprintf (out, " %s", symbols[*rp]->tag);
109 fputc ('\n', out);
110 }
111 else
112 {
113 fprintf (out, " /* %s */\n", _("empty"));
114 }
115 }
116
117 static void
118 rule_rhs_print_xml (rule *r, FILE *out, int level)
119 {
120 if (*r->rhs >= 0)
121 {
122 item_number *rp;
123 xml_puts (out, level, "<rhs>");
124 for (rp = r->rhs; *rp >= 0; rp++)
125 xml_printf (out, level + 1, "<symbol>%s</symbol>",
126 xml_escape (symbols[*rp]->tag));
127 xml_puts (out, level, "</rhs>");
128 }
129 else
130 {
131 xml_puts (out, level, "<rhs>");
132 xml_puts (out, level + 1, "<empty/>");
133 xml_puts (out, level, "</rhs>");
134 }
135 }
136
137 void
138 rule_print (rule *r, FILE *out)
139 {
140 fprintf (out, "%s:", r->lhs->tag);
141 rule_rhs_print (r, out);
142 }
143
144 void
145 ritem_print (FILE *out)
146 {
147 unsigned int i;
148 fputs ("RITEM\n", out);
149 for (i = 0; i < nritems; ++i)
150 if (ritem[i] >= 0)
151 fprintf (out, " %s", symbols[ritem[i]]->tag);
152 else
153 fprintf (out, " (rule %d)\n", item_number_as_rule_number (ritem[i]));
154 fputs ("\n\n", out);
155 }
156
157 size_t
158 ritem_longest_rhs (void)
159 {
160 int max = 0;
161 rule_number r;
162
163 for (r = 0; r < nrules; ++r)
164 {
165 int length = rule_rhs_length (&rules[r]);
166 if (length > max)
167 max = length;
168 }
169
170 return max;
171 }
172
173 void
174 grammar_rules_partial_print (FILE *out, const char *title,
175 rule_filter filter)
176 {
177 rule_number r;
178 bool first = true;
179 symbol *previous_lhs = NULL;
180
181 /* rule # : LHS -> RHS */
182 for (r = 0; r < nrules + nuseless_productions; r++)
183 {
184 if (filter && !filter (&rules[r]))
185 continue;
186 if (first)
187 fprintf (out, "%s\n\n", title);
188 else if (previous_lhs && previous_lhs != rules[r].lhs)
189 fputc ('\n', out);
190 first = false;
191 rule_lhs_print (&rules[r], previous_lhs, out);
192 rule_rhs_print (&rules[r], out);
193 previous_lhs = rules[r].lhs;
194 }
195 if (!first)
196 fputs ("\n\n", out);
197 }
198
199 void
200 grammar_rules_print (FILE *out)
201 {
202 grammar_rules_partial_print (out, _("Grammar"), rule_useful_in_grammar_p);
203 }
204
205 void
206 grammar_rules_print_xml (FILE *out, int level)
207 {
208 rule_number r;
209 bool first = true;
210
211 for (r = 0; r < nrules + nuseless_productions; r++)
212 {
213 if (first)
214 xml_puts (out, level + 1, "<rules>");
215 first = false;
216 {
217 char const *usefulness;
218 if (rule_useless_in_grammar_p (&rules[r]))
219 usefulness = "useless-in-grammar";
220 else if (rule_useless_in_parser_p (&rules[r]))
221 usefulness = "useless-in-parser";
222 else
223 usefulness = "useful";
224 xml_indent (out, level + 2);
225 fprintf (out, "<rule number=\"%d\" usefulness=\"%s\"",
226 rules[r].number, usefulness);
227 if (rules[r].precsym)
228 fprintf (out, " percent_prec=\"%s\"",
229 xml_escape (rules[r].precsym->tag));
230 fputs (">\n", out);
231 }
232 rule_lhs_print_xml (&rules[r], out, level + 3);
233 rule_rhs_print_xml (&rules[r], out, level + 3);
234 xml_puts (out, level + 2, "</rule>");
235 }
236 if (!first)
237 xml_puts (out, level + 1, "</rules>");
238 else
239 xml_puts (out, level + 1, "<rules/>");
240 }
241
242 void
243 grammar_dump (FILE *out, const char *title)
244 {
245 fprintf (out, "%s\n\n", title);
246 fprintf (out,
247 "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
248 ntokens, nvars, nsyms, nrules, nritems);
249
250
251 fprintf (out, "Variables\n---------\n\n");
252 {
253 symbol_number i;
254 fprintf (out, "Value Sprec Sassoc Tag\n");
255
256 for (i = ntokens; i < nsyms; i++)
257 fprintf (out, "%5d %5d %5d %s\n",
258 i,
259 symbols[i]->prec, symbols[i]->assoc,
260 symbols[i]->tag);
261 fprintf (out, "\n\n");
262 }
263
264 fprintf (out, "Rules\n-----\n\n");
265 {
266 rule_number i;
267 fprintf (out, "Num (Prec, Assoc, Useful, Ritem Range) Lhs -> Rhs (Ritem range) [Num]\n");
268 for (i = 0; i < nrules + nuseless_productions; i++)
269 {
270 rule *rule_i = &rules[i];
271 item_number *rp = NULL;
272 unsigned int rhs_itemno = rule_i->rhs - ritem;
273 unsigned int rhs_count = 0;
274 /* Find the last RHS index in ritems. */
275 for (rp = rule_i->rhs; *rp >= 0; ++rp)
276 ++rhs_count;
277 fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u) %2d ->",
278 i,
279 rule_i->prec ? rule_i->prec->prec : 0,
280 rule_i->prec ? rule_i->prec->assoc : 0,
281 rule_i->useful,
282 rhs_itemno,
283 rhs_itemno + rhs_count - 1,
284 rule_i->lhs->number);
285 /* Dumped the RHS. */
286 for (rp = rule_i->rhs; *rp >= 0; rp++)
287 fprintf (out, " %3d", *rp);
288 fprintf (out, " [%d]\n", item_number_as_rule_number (*rp));
289 }
290 }
291 fprintf (out, "\n\n");
292
293 fprintf (out, "Rules interpreted\n-----------------\n\n");
294 {
295 rule_number r;
296 for (r = 0; r < nrules + nuseless_productions; r++)
297 {
298 fprintf (out, "%-5d ", r);
299 rule_print (&rules[r], out);
300 }
301 }
302 fprintf (out, "\n\n");
303 }
304
305 void
306 grammar_rules_useless_report (const char *message)
307 {
308 rule_number r;
309 for (r = 0; r < nrules ; ++r)
310 if (!rules[r].useful)
311 {
312 warn_at (rules[r].location, "%s: ", message);
313 rule_print (&rules[r], stderr);
314 fflush (stderr);
315 }
316 }
317
318 void
319 grammar_free (void)
320 {
321 if (ritem)
322 free (ritem - 1);
323 free (rules);
324 free (token_translations);
325 /* Free the symbol table data structure. */
326 symbols_free ();
327 free_merger_functions ();
328 }