]> git.saurik.com Git - bison.git/blame - src/print-xml.c
gnulib: update
[bison.git] / src / print-xml.c
CommitLineData
41d7a5f2
PE
1/* Print an xml on generated parser, for Bison,
2
3209eb1c 3 Copyright (C) 2007, 2009-2015 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 67
d4399854
AD
68 if (!snritems)
69 {
70 xml_puts (out, level, "<itemset/>");
71 return;
72 }
41d7a5f2
PE
73
74 xml_puts (out, level, "<itemset>");
75
76 for (i = 0; i < snritems; i++)
77 {
25f6da67 78 bool printed = false;
d4399854
AD
79 item_number *sp1 = ritem + sitems[i];
80 item_number *sp = sp1;
81 rule *r;
41d7a5f2 82
d4399854 83 while (0 <= *sp)
e9690142 84 sp++;
41d7a5f2 85
d4399854
AD
86 r = &rules[item_number_as_rule_number (*sp)];
87 sp = r->rhs;
41d7a5f2
PE
88
89 /* Display the lookahead tokens? */
ef1b4273 90 if (item_number_is_rule_number (*sp1))
e9690142
JD
91 {
92 reductions *reds = s->reductions;
d4399854 93 int red = state_reduction_find (s, r);
e9690142
JD
94 /* Print item with lookaheads if there are. */
95 if (reds->lookahead_tokens && red != -1)
96 {
97 xml_printf (out, level + 1,
98 "<item rule-number=\"%d\" point=\"%d\">",
d4399854
AD
99 r->number, sp1 - sp);
100 state_rule_lookahead_tokens_print_xml (s, r,
e9690142
JD
101 out, level + 2);
102 xml_puts (out, level + 1, "</item>");
103 printed = true;
104 }
105 }
41d7a5f2 106
25f6da67 107 if (!printed)
d4399854
AD
108 xml_printf (out, level + 1,
109 "<item rule-number=\"%d\" point=\"%d\"/>",
110 r->number,
111 sp1 - sp);
41d7a5f2
PE
112 }
113 xml_puts (out, level, "</itemset>");
114}
115
116
117/*-----------------------------------------------------------.
118| Report the shifts if DISPLAY_SHIFTS_P or the gotos of S on |
119| OUT. |
120`-----------------------------------------------------------*/
121
122static void
123print_transitions (state *s, FILE *out, int level)
124{
125 transitions *trans = s->transitions;
126 int n = 0;
127 int i;
128
129 for (i = 0; i < trans->num; i++)
130 if (!TRANSITION_IS_DISABLED (trans, i))
131 {
e9690142 132 n++;
41d7a5f2
PE
133 }
134
135 /* Nothing to report. */
d4399854
AD
136 if (!n)
137 {
138 xml_puts (out, level, "<transitions/>");
139 return;
140 }
41d7a5f2
PE
141
142 /* Report lookahead tokens and shifts. */
143 xml_puts (out, level, "<transitions>");
144
145 for (i = 0; i < trans->num; i++)
146 if (!TRANSITION_IS_DISABLED (trans, i)
e9690142 147 && TRANSITION_IS_SHIFT (trans, i))
41d7a5f2 148 {
e9690142
JD
149 symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
150 char const *tag = sym->tag;
151 state *s1 = trans->states[i];
41d7a5f2 152
e9690142
JD
153 xml_printf (out, level + 1,
154 "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>",
155 xml_escape (tag), s1->number);
41d7a5f2
PE
156 }
157
158 for (i = 0; i < trans->num; i++)
159 if (!TRANSITION_IS_DISABLED (trans, i)
e9690142 160 && !TRANSITION_IS_SHIFT (trans, i))
41d7a5f2 161 {
e9690142
JD
162 symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)];
163 char const *tag = sym->tag;
164 state *s1 = trans->states[i];
41d7a5f2 165
e9690142
JD
166 xml_printf (out, level + 1,
167 "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>",
168 xml_escape (tag), s1->number);
41d7a5f2
PE
169 }
170
171 xml_puts (out, level, "</transitions>");
172}
173
174
175/*--------------------------------------------------------.
176| Report the explicit errors of S raised from %nonassoc. |
177`--------------------------------------------------------*/
178
179static void
180print_errs (FILE *out, int level, state *s)
181{
182 errs *errp = s->errs;
183 bool count = false;
184 int i;
185
186 for (i = 0; i < errp->num; ++i)
187 if (errp->symbols[i])
188 count = true;
189
190 /* Nothing to report. */
d4399854
AD
191 if (!count)
192 {
193 xml_puts (out, level, "<errors/>");
194 return;
195 }
41d7a5f2
PE
196
197 /* Report lookahead tokens and errors. */
198 xml_puts (out, level, "<errors>");
199 for (i = 0; i < errp->num; ++i)
200 if (errp->symbols[i])
201 {
e9690142
JD
202 char const *tag = errp->symbols[i]->tag;
203 xml_printf (out, level + 1,
204 "<error symbol=\"%s\">nonassociative</error>",
205 xml_escape (tag));
41d7a5f2
PE
206 }
207 xml_puts (out, level, "</errors>");
208}
209
210
211/*-------------------------------------------------------------------------.
45eebca4 212| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). |
41d7a5f2
PE
213| If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
214| R/R conflicts). |
215`-------------------------------------------------------------------------*/
216
217static void
218print_reduction (FILE *out, int level, char const *lookahead_token,
e9690142 219 rule *r, bool enabled)
41d7a5f2
PE
220{
221 if (r->number)
222 xml_printf (out, level,
e9690142
JD
223 "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
224 xml_escape (lookahead_token),
225 r->number,
226 enabled ? "true" : "false");
41d7a5f2
PE
227 else
228 xml_printf (out, level,
e9690142
JD
229 "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
230 xml_escape (lookahead_token),
231 enabled ? "true" : "false");
41d7a5f2
PE
232}
233
234
235/*-------------------------------------------.
236| Report on OUT the reduction actions of S. |
237`-------------------------------------------*/
238
239static void
240print_reductions (FILE *out, int level, state *s)
241{
242 transitions *trans = s->transitions;
243 reductions *reds = s->reductions;
110ef36a 244 rule *default_reduction = NULL;
41d7a5f2
PE
245 int report = false;
246 int i, j;
247
41976786
AD
248 if (reds->num == 0)
249 {
250 xml_puts (out, level, "<reductions/>");
251 return;
252 }
41d7a5f2
PE
253
254 if (yydefact[s->number] != 0)
110ef36a 255 default_reduction = &rules[yydefact[s->number] - 1];
41d7a5f2
PE
256
257 bitset_zero (no_reduce_set);
258 FOR_EACH_SHIFT (trans, i)
259 bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
260 for (i = 0; i < s->errs->num; ++i)
261 if (s->errs->symbols[i])
262 bitset_set (no_reduce_set, s->errs->symbols[i]->number);
263
110ef36a 264 if (default_reduction)
41d7a5f2
PE
265 report = true;
266
267 if (reds->lookahead_tokens)
268 for (i = 0; i < ntokens; i++)
269 {
e9690142
JD
270 bool count = bitset_test (no_reduce_set, i);
271
272 for (j = 0; j < reds->num; ++j)
273 if (bitset_test (reds->lookahead_tokens[j], i))
274 {
275 if (! count)
276 {
277 if (reds->rules[j] != default_reduction)
278 report = true;
279 count = true;
280 }
281 else
282 {
283 report = true;
284 }
285 }
41d7a5f2
PE
286 }
287
288 /* Nothing to report. */
d4399854
AD
289 if (!report)
290 {
291 xml_puts (out, level, "<reductions/>");
292 return;
293 }
41d7a5f2
PE
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}