]> git.saurik.com Git - bison.git/blame - src/print-xml.c
comment changes
[bison.git] / src / print-xml.c
CommitLineData
41d7a5f2
PE
1/* Print an xml on generated parser, for Bison,
2
7d6bad19 3 Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc.
41d7a5f2
PE
4
5 This file is part of Bison, the GNU Compiler Compiler.
6
2f658d53 7 This program is free software: you can redistribute it and/or modify
41d7a5f2 8 it under the terms of the GNU General Public License as published by
2f658d53
JD
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
41d7a5f2 11
2f658d53 12 This program is distributed in the hope that it will be useful,
41d7a5f2
PE
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
2f658d53 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
41d7a5f2
PE
19
20#include <config.h>
21#include "system.h"
22
23#include <stdarg.h>
24
25#include <bitset.h>
41d7a5f2
PE
26
27#include "LR0.h"
28#include "closure.h"
29#include "conflicts.h"
30#include "files.h"
31#include "getargs.h"
32#include "gram.h"
33#include "lalr.h"
34#include "print.h"
35#include "print-xml.h"
36#include "reader.h"
37#include "reduce.h"
38#include "state.h"
39#include "symtab.h"
40#include "tables.h"
41
42static bitset no_reduce_set;
34cdeddf
JD
43struct escape_buf
44{
45 char *ptr;
46 size_t size;
47};
c0efa83c
AD
48enum { num_escape_bufs = 3 };
49static struct escape_buf escape_bufs[num_escape_bufs];
41d7a5f2
PE
50
51
41d7a5f2
PE
52/*--------------------------------.
53| Report information on a state. |
54`--------------------------------*/
55
56static void
57print_core (FILE *out, int level, state *s)
58{
59 size_t i;
60 item_number *sitems = s->items;
61 size_t snritems = s->nitems;
62
63 /* Output all the items of a state, not only its kernel. */
ef1b4273
JD
64 closure (sitems, snritems);
65 sitems = itemset;
66 snritems = nitemset;
41d7a5f2
PE
67
68 if (!snritems) {
69 xml_puts (out, level, "<itemset/>");
70 return;
71 }
72
73 xml_puts (out, level, "<itemset>");
74
75 for (i = 0; i < snritems; i++)
76 {
25f6da67 77 bool printed = false;
41d7a5f2
PE
78 item_number *sp;
79 item_number *sp1;
80 rule_number r;
81
82 sp1 = sp = ritem + sitems[i];
83
84 while (*sp >= 0)
e9690142 85 sp++;
41d7a5f2
PE
86
87 r = item_number_as_rule_number (*sp);
25f6da67 88 sp = rules[r].rhs;
41d7a5f2
PE
89
90 /* Display the lookahead tokens? */
ef1b4273 91 if (item_number_is_rule_number (*sp1))
e9690142
JD
92 {
93 reductions *reds = s->reductions;
94 int red = state_reduction_find (s, &rules[r]);
95 /* Print item with lookaheads if there are. */
96 if (reds->lookahead_tokens && red != -1)
97 {
98 xml_printf (out, level + 1,
99 "<item rule-number=\"%d\" point=\"%d\">",
100 rules[r].number, sp1 - sp);
101 state_rule_lookahead_tokens_print_xml (s, &rules[r],
102 out, level + 2);
103 xml_puts (out, level + 1, "</item>");
104 printed = true;
105 }
106 }
41d7a5f2 107
25f6da67 108 if (!printed)
e9690142
JD
109 {
110 xml_printf (out, level + 1,
111 "<item rule-number=\"%d\" point=\"%d\"/>",
112 rules[r].number,
113 sp1 - sp);
114 }
41d7a5f2
PE
115 }
116 xml_puts (out, level, "</itemset>");
117}
118
119
120/*-----------------------------------------------------------.
121| Report the shifts if DISPLAY_SHIFTS_P or the gotos of S on |
122| OUT. |
123`-----------------------------------------------------------*/
124
125static void
126print_transitions (state *s, FILE *out, int level)
127{
128 transitions *trans = s->transitions;
129 int n = 0;
130 int i;
131
132 for (i = 0; i < trans->num; i++)
133 if (!TRANSITION_IS_DISABLED (trans, i))
134 {
e9690142 135 n++;
41d7a5f2
PE
136 }
137
138 /* Nothing to report. */
139 if (!n) {
140 xml_puts (out, level, "<transitions/>");
141 return;
142 }
143
144 /* Report lookahead tokens and shifts. */
145 xml_puts (out, level, "<transitions>");
146
147 for (i = 0; i < trans->num; i++)
148 if (!TRANSITION_IS_DISABLED (trans, i)
e9690142 149 && TRANSITION_IS_SHIFT (trans, i))
41d7a5f2 150 {
e9690142
JD
151 symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
152 char const *tag = sym->tag;
153 state *s1 = trans->states[i];
41d7a5f2 154
e9690142
JD
155 xml_printf (out, level + 1,
156 "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>",
157 xml_escape (tag), s1->number);
41d7a5f2
PE
158 }
159
160 for (i = 0; i < trans->num; i++)
161 if (!TRANSITION_IS_DISABLED (trans, i)
e9690142 162 && !TRANSITION_IS_SHIFT (trans, i))
41d7a5f2 163 {
e9690142
JD
164 symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
165 char const *tag = sym->tag;
166 state *s1 = trans->states[i];
41d7a5f2 167
e9690142
JD
168 xml_printf (out, level + 1,
169 "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>",
170 xml_escape (tag), s1->number);
41d7a5f2
PE
171 }
172
173 xml_puts (out, level, "</transitions>");
174}
175
176
177/*--------------------------------------------------------.
178| Report the explicit errors of S raised from %nonassoc. |
179`--------------------------------------------------------*/
180
181static void
182print_errs (FILE *out, int level, state *s)
183{
184 errs *errp = s->errs;
185 bool count = false;
186 int i;
187
188 for (i = 0; i < errp->num; ++i)
189 if (errp->symbols[i])
190 count = true;
191
192 /* Nothing to report. */
193 if (!count) {
194 xml_puts (out, level, "<errors/>");
195 return;
196 }
197
198 /* Report lookahead tokens and errors. */
199 xml_puts (out, level, "<errors>");
200 for (i = 0; i < errp->num; ++i)
201 if (errp->symbols[i])
202 {
e9690142
JD
203 char const *tag = errp->symbols[i]->tag;
204 xml_printf (out, level + 1,
205 "<error symbol=\"%s\">nonassociative</error>",
206 xml_escape (tag));
41d7a5f2
PE
207 }
208 xml_puts (out, level, "</errors>");
209}
210
211
212/*-------------------------------------------------------------------------.
45eebca4 213| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). |
41d7a5f2
PE
214| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
215| R/R conflicts). |
216`-------------------------------------------------------------------------*/
217
218static void
219print_reduction (FILE *out, int level, char const *lookahead_token,
e9690142 220 rule *r, bool enabled)
41d7a5f2
PE
221{
222 if (r->number)
223 xml_printf (out, level,
e9690142
JD
224 "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
225 xml_escape (lookahead_token),
226 r->number,
227 enabled ? "true" : "false");
41d7a5f2
PE
228 else
229 xml_printf (out, level,
e9690142
JD
230 "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
231 xml_escape (lookahead_token),
232 enabled ? "true" : "false");
41d7a5f2
PE
233}
234
235
236/*-------------------------------------------.
237| Report on OUT the reduction actions of S. |
238`-------------------------------------------*/
239
240static void
241print_reductions (FILE *out, int level, state *s)
242{
243 transitions *trans = s->transitions;
244 reductions *reds = s->reductions;
110ef36a 245 rule *default_reduction = NULL;
41d7a5f2
PE
246 int report = false;
247 int i, j;
248
41976786
AD
249 if (reds->num == 0)
250 {
251 xml_puts (out, level, "<reductions/>");
252 return;
253 }
41d7a5f2
PE
254
255 if (yydefact[s->number] != 0)
110ef36a 256 default_reduction = &rules[yydefact[s->number] - 1];
41d7a5f2
PE
257
258 bitset_zero (no_reduce_set);
259 FOR_EACH_SHIFT (trans, i)
260 bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
261 for (i = 0; i < s->errs->num; ++i)
262 if (s->errs->symbols[i])
263 bitset_set (no_reduce_set, s->errs->symbols[i]->number);
264
110ef36a 265 if (default_reduction)
41d7a5f2
PE
266 report = true;
267
268 if (reds->lookahead_tokens)
269 for (i = 0; i < ntokens; i++)
270 {
e9690142
JD
271 bool count = bitset_test (no_reduce_set, i);
272
273 for (j = 0; j < reds->num; ++j)
274 if (bitset_test (reds->lookahead_tokens[j], i))
275 {
276 if (! count)
277 {
278 if (reds->rules[j] != default_reduction)
279 report = true;
280 count = true;
281 }
282 else
283 {
284 report = true;
285 }
286 }
41d7a5f2
PE
287 }
288
289 /* Nothing to report. */
290 if (!report) {
291 xml_puts (out, level, "<reductions/>");
292 return;
293 }
294
295 xml_puts (out, level, "<reductions>");
296
297 /* Report lookahead tokens (or $default) and reductions. */
298 if (reds->lookahead_tokens)
299 for (i = 0; i < ntokens; i++)
300 {
e9690142
JD
301 bool defaulted = false;
302 bool count = bitset_test (no_reduce_set, i);
303
304 for (j = 0; j < reds->num; ++j)
305 if (bitset_test (reds->lookahead_tokens[j], i))
306 {
307 if (! count)
308 {
309 if (reds->rules[j] != default_reduction)
310 print_reduction (out, level + 1, symbols[i]->tag,
311 reds->rules[j], true);
312 else
313 defaulted = true;
314 count = true;
315 }
316 else
317 {
318 if (defaulted)
319 print_reduction (out, level + 1, symbols[i]->tag,
320 default_reduction, true);
321 defaulted = false;
322 print_reduction (out, level + 1, symbols[i]->tag,
323 reds->rules[j], false);
324 }
325 }
41d7a5f2
PE
326 }
327
110ef36a 328 if (default_reduction)
41d7a5f2 329 print_reduction (out, level + 1,
e9690142 330 "$default", default_reduction, true);
41d7a5f2
PE
331
332 xml_puts (out, level, "</reductions>");
333}
334
335
336/*--------------------------------------------------------------.
337| Report on OUT all the actions (shifts, gotos, reductions, and |
338| explicit erros from %nonassoc) of S. |
339`--------------------------------------------------------------*/
340
341static void
342print_actions (FILE *out, int level, state *s)
343{
344 xml_puts (out, level, "<actions>");
345 print_transitions (s, out, level + 1);
346 print_errs (out, level + 1, s);
347 print_reductions (out, level + 1, s);
348 xml_puts (out, level, "</actions>");
349}
350
351
352/*----------------------------------.
353| Report all the data on S on OUT. |
354`----------------------------------*/
355
356static void
357print_state (FILE *out, int level, state *s)
358{
359 fputc ('\n', out);
360 xml_printf (out, level, "<state number=\"%d\">", s->number);
361 print_core (out, level + 1, s);
362 print_actions (out, level + 1, s);
ef1b4273 363 if (s->solved_conflicts_xml)
41d7a5f2
PE
364 {
365 xml_puts (out, level + 1, "<solved-conflicts>");
366 fputs (s->solved_conflicts_xml, out);
367 xml_puts (out, level + 1, "</solved-conflicts>");
368 }
369 else
370 xml_puts (out, level + 1, "<solved-conflicts/>");
371 xml_puts (out, level, "</state>");
372}
373
374
375/*-----------------------------------------.
376| Print information on the whole grammar. |
377`-----------------------------------------*/
378
379static void
380print_grammar (FILE *out, int level)
381{
382 symbol_number i;
383
384 fputc ('\n', out);
385 xml_puts (out, level, "<grammar>");
386 grammar_rules_print_xml (out, level);
387
388 /* Terminals */
389 xml_puts (out, level + 1, "<terminals>");
390 for (i = 0; i < max_user_token_number + 1; i++)
391 if (token_translations[i] != undeftoken->number)
392 {
e9690142 393 char const *tag = symbols[token_translations[i]]->tag;
408476bc
JD
394 int precedence = symbols[token_translations[i]]->prec;
395 assoc associativity = symbols[token_translations[i]]->assoc;
396 xml_indent (out, level + 2);
397 fprintf (out,
398 "<terminal symbol-number=\"%d\" token-number=\"%d\""
399 " name=\"%s\" usefulness=\"%s\"",
400 token_translations[i], i, xml_escape (tag),
401 reduce_token_unused_in_grammar (token_translations[i])
402 ? "unused-in-grammar" : "useful");
403 if (precedence)
404 fprintf (out, " prec=\"%d\"", precedence);
405 if (associativity != undef_assoc)
406 fprintf (out, " assoc=\"%s\"", assoc_to_string (associativity) + 1);
407 fputs ("/>\n", out);
41d7a5f2
PE
408 }
409 xml_puts (out, level + 1, "</terminals>");
410
411 /* Nonterminals */
412 xml_puts (out, level + 1, "<nonterminals>");
d80fb37a 413 for (i = ntokens; i < nsyms + nuseless_nonterminals; i++)
41d7a5f2 414 {
41d7a5f2 415 char const *tag = symbols[i]->tag;
41d7a5f2 416 xml_printf (out, level + 2,
e9690142 417 "<nonterminal symbol-number=\"%d\" name=\"%s\""
d4a26c48 418 " usefulness=\"%s\"/>",
e9690142 419 i, xml_escape (tag),
d80fb37a
JD
420 reduce_nonterminal_useless_in_grammar (i)
421 ? "useless-in-grammar" : "useful");
41d7a5f2
PE
422 }
423 xml_puts (out, level + 1, "</nonterminals>");
424 xml_puts (out, level, "</grammar>");
425}
426
427void
408476bc 428xml_indent (FILE *out, int level)
41d7a5f2
PE
429{
430 int i;
41d7a5f2 431 for (i = 0; i < level; i++)
a4f75309 432 fputs (" ", out);
408476bc
JD
433}
434
435void
436xml_puts (FILE *out, int level, char const *s)
437{
438 xml_indent (out, level);
41d7a5f2
PE
439 fputs (s, out);
440 fputc ('\n', out);
441}
442
443void
444xml_printf (FILE *out, int level, char const *fmt, ...)
445{
41d7a5f2
PE
446 va_list arglist;
447
408476bc 448 xml_indent (out, level);
41d7a5f2
PE
449
450 va_start (arglist, fmt);
451 vfprintf (out, fmt, arglist);
452 va_end (arglist);
453
454 fputc ('\n', out);
455}
456
41d7a5f2
PE
457static char const *
458xml_escape_string (struct escape_buf *buf, char const *str)
459{
460 size_t len = strlen (str);
461 size_t max_expansion = sizeof "&quot;" - 1;
462 char *p;
463
464 if (buf->size <= max_expansion * len)
465 {
466 buf->size = max_expansion * len + 1;
467 buf->ptr = x2realloc (buf->ptr, &buf->size);
468 }
469 p = buf->ptr;
470
471 for (; *str; str++)
472 switch (*str)
473 {
474 default: *p++ = *str; break;
475 case '&': p = stpcpy (p, "&amp;" ); break;
476 case '<': p = stpcpy (p, "&lt;" ); break;
477 case '>': p = stpcpy (p, "&gt;" ); break;
478 case '"': p = stpcpy (p, "&quot;"); break;
479 }
480
481 *p = '\0';
482 return buf->ptr;
483}
484
485char const *
486xml_escape_n (int n, char const *str)
487{
34cdeddf 488 return xml_escape_string (escape_bufs + n, str);
41d7a5f2
PE
489}
490
491char const *
492xml_escape (char const *str)
493{
494 return xml_escape_n (0, str);
495}
496
497void
498print_xml (void)
499{
41d7a5f2
PE
500 int level = 0;
501
502 FILE *out = xfopen (spec_xml_file, "w");
503
504 fputs ("<?xml version=\"1.0\"?>\n\n", out);
bc81de36
JD
505 xml_printf (out, level,
506 "<bison-xml-report version=\"%s\" bug-report=\"%s\""
507 " url=\"%s\">",
508 xml_escape_n (0, VERSION),
509 xml_escape_n (1, PACKAGE_BUGREPORT),
510 xml_escape_n (2, PACKAGE_URL));
41d7a5f2
PE
511
512 fputc ('\n', out);
513 xml_printf (out, level + 1, "<filename>%s</filename>",
e9690142 514 xml_escape (grammar_file));
41d7a5f2 515
41d7a5f2
PE
516 /* print grammar */
517 print_grammar (out, level + 1);
518
ef1b4273 519 new_closure (nritems);
41d7a5f2
PE
520 no_reduce_set = bitset_create (ntokens, BITSET_FIXED);
521
522 /* print automaton */
523 fputc ('\n', out);
524 xml_puts (out, level + 1, "<automaton>");
c0efa83c
AD
525 {
526 state_number i;
527 for (i = 0; i < nstates; i++)
528 print_state (out, level + 2, states[i]);
529 }
41d7a5f2
PE
530 xml_puts (out, level + 1, "</automaton>");
531
532 bitset_free (no_reduce_set);
ef1b4273 533 free_closure ();
41d7a5f2
PE
534
535 xml_puts (out, 0, "</bison-xml-report>");
536
c0efa83c
AD
537 {
538 int i;
539 for (i = 0; i < num_escape_bufs; ++i)
540 free (escape_bufs[i].ptr);
541 }
34cdeddf 542
41d7a5f2
PE
543 xfclose (out);
544}