]>
git.saurik.com Git - bison.git/blob - src/print-xml.c
1 /* Print an xml on generated parser, for Bison,
3 Copyright (C) 2007, 2009 Free Software Foundation, Inc.
5 This file is part of Bison, the GNU Compiler Compiler.
7 Bison is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 Bison is distributed in the hope that it will be useful,
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.
17 You should have received a copy of the GNU General Public License
18 along with Bison; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
32 #include "conflicts.h"
38 #include "print-xml.h"
45 static bitset no_reduce_set
;
51 static struct escape_buf escape_bufs
[2];
54 /*--------------------------------.
55 | Report information on a state. |
56 `--------------------------------*/
59 print_core (FILE *out
, int level
, state
*s
)
62 item_number
*sitems
= s
->items
;
63 size_t snritems
= s
->nitems
;
65 /* Output all the items of a state, not only its kernel. */
66 closure (sitems
, snritems
);
71 xml_puts (out
, level
, "<itemset/>");
75 xml_puts (out
, level
, "<itemset>");
77 for (i
= 0; i
< snritems
; i
++)
84 sp1
= sp
= ritem
+ sitems
[i
];
89 r
= item_number_as_rule_number (*sp
);
92 /* Display the lookahead tokens? */
93 if (item_number_is_rule_number (*sp1
))
95 reductions
*reds
= s
->reductions
;
96 int red
= state_reduction_find (s
, &rules
[r
]);
97 /* Print item with lookaheads if there are. */
98 if (reds
->lookahead_tokens
&& red
!= -1)
100 xml_printf (out
, level
+ 1,
101 "<item rule-number=\"%d\" point=\"%d\">",
102 rules
[r
].number
, sp1
- sp
);
103 state_rule_lookahead_tokens_print_xml (s
, &rules
[r
],
105 xml_puts (out
, level
+ 1, "</item>");
112 xml_printf (out
, level
+ 1,
113 "<item rule-number=\"%d\" point=\"%d\"/>",
118 xml_puts (out
, level
, "</itemset>");
122 /*-----------------------------------------------------------.
123 | Report the shifts if DISPLAY_SHIFTS_P or the gotos of S on |
125 `-----------------------------------------------------------*/
128 print_transitions (state
*s
, FILE *out
, int level
)
130 transitions
*trans
= s
->transitions
;
134 for (i
= 0; i
< trans
->num
; i
++)
135 if (!TRANSITION_IS_DISABLED (trans
, i
))
140 /* Nothing to report. */
142 xml_puts (out
, level
, "<transitions/>");
146 /* Report lookahead tokens and shifts. */
147 xml_puts (out
, level
, "<transitions>");
149 for (i
= 0; i
< trans
->num
; i
++)
150 if (!TRANSITION_IS_DISABLED (trans
, i
)
151 && TRANSITION_IS_SHIFT (trans
, i
))
153 symbol
*sym
= symbols
[TRANSITION_SYMBOL (trans
, i
)];
154 char const *tag
= sym
->tag
;
155 state
*s1
= trans
->states
[i
];
157 xml_printf (out
, level
+ 1,
158 "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>",
159 xml_escape (tag
), s1
->number
);
162 for (i
= 0; i
< trans
->num
; i
++)
163 if (!TRANSITION_IS_DISABLED (trans
, i
)
164 && !TRANSITION_IS_SHIFT (trans
, i
))
166 symbol
*sym
= symbols
[TRANSITION_SYMBOL (trans
, i
)];
167 char const *tag
= sym
->tag
;
168 state
*s1
= trans
->states
[i
];
170 xml_printf (out
, level
+ 1,
171 "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>",
172 xml_escape (tag
), s1
->number
);
175 xml_puts (out
, level
, "</transitions>");
179 /*--------------------------------------------------------.
180 | Report the explicit errors of S raised from %nonassoc. |
181 `--------------------------------------------------------*/
184 print_errs (FILE *out
, int level
, state
*s
)
186 errs
*errp
= s
->errs
;
190 for (i
= 0; i
< errp
->num
; ++i
)
191 if (errp
->symbols
[i
])
194 /* Nothing to report. */
196 xml_puts (out
, level
, "<errors/>");
200 /* Report lookahead tokens and errors. */
201 xml_puts (out
, level
, "<errors>");
202 for (i
= 0; i
< errp
->num
; ++i
)
203 if (errp
->symbols
[i
])
205 char const *tag
= errp
->symbols
[i
]->tag
;
206 xml_printf (out
, level
+ 1,
207 "<error symbol=\"%s\">nonassociative</error>",
210 xml_puts (out
, level
, "</errors>");
214 /*-------------------------------------------------------------------------.
215 | Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default'). |
216 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and |
218 `-------------------------------------------------------------------------*/
221 print_reduction (FILE *out
, int level
, char const *lookahead_token
,
222 rule
*r
, bool enabled
)
225 xml_printf (out
, level
,
226 "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>",
227 xml_escape (lookahead_token
),
229 enabled
? "true" : "false");
231 xml_printf (out
, level
,
232 "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>",
233 xml_escape (lookahead_token
),
234 enabled
? "true" : "false");
238 /*-------------------------------------------.
239 | Report on OUT the reduction actions of S. |
240 `-------------------------------------------*/
243 print_reductions (FILE *out
, int level
, state
*s
)
245 transitions
*trans
= s
->transitions
;
246 reductions
*reds
= s
->reductions
;
247 rule
*default_reduction
= NULL
;
253 xml_puts (out
, level
, "<reductions/>");
257 if (yydefact
[s
->number
] != 0)
258 default_reduction
= &rules
[yydefact
[s
->number
] - 1];
260 bitset_zero (no_reduce_set
);
261 FOR_EACH_SHIFT (trans
, i
)
262 bitset_set (no_reduce_set
, TRANSITION_SYMBOL (trans
, i
));
263 for (i
= 0; i
< s
->errs
->num
; ++i
)
264 if (s
->errs
->symbols
[i
])
265 bitset_set (no_reduce_set
, s
->errs
->symbols
[i
]->number
);
267 if (default_reduction
)
270 if (reds
->lookahead_tokens
)
271 for (i
= 0; i
< ntokens
; i
++)
273 bool count
= bitset_test (no_reduce_set
, i
);
275 for (j
= 0; j
< reds
->num
; ++j
)
276 if (bitset_test (reds
->lookahead_tokens
[j
], i
))
280 if (reds
->rules
[j
] != default_reduction
)
291 /* Nothing to report. */
293 xml_puts (out
, level
, "<reductions/>");
297 xml_puts (out
, level
, "<reductions>");
299 /* Report lookahead tokens (or $default) and reductions. */
300 if (reds
->lookahead_tokens
)
301 for (i
= 0; i
< ntokens
; i
++)
303 bool defaulted
= false;
304 bool count
= bitset_test (no_reduce_set
, i
);
306 for (j
= 0; j
< reds
->num
; ++j
)
307 if (bitset_test (reds
->lookahead_tokens
[j
], i
))
311 if (reds
->rules
[j
] != default_reduction
)
312 print_reduction (out
, level
+ 1, symbols
[i
]->tag
,
313 reds
->rules
[j
], true);
321 print_reduction (out
, level
+ 1, symbols
[i
]->tag
,
322 default_reduction
, true);
324 print_reduction (out
, level
+ 1, symbols
[i
]->tag
,
325 reds
->rules
[j
], false);
330 if (default_reduction
)
331 print_reduction (out
, level
+ 1,
332 "$default", default_reduction
, true);
334 xml_puts (out
, level
, "</reductions>");
338 /*--------------------------------------------------------------.
339 | Report on OUT all the actions (shifts, gotos, reductions, and |
340 | explicit erros from %nonassoc) of S. |
341 `--------------------------------------------------------------*/
344 print_actions (FILE *out
, int level
, state
*s
)
346 xml_puts (out
, level
, "<actions>");
347 print_transitions (s
, out
, level
+ 1);
348 print_errs (out
, level
+ 1, s
);
349 print_reductions (out
, level
+ 1, s
);
350 xml_puts (out
, level
, "</actions>");
354 /*----------------------------------.
355 | Report all the data on S on OUT. |
356 `----------------------------------*/
359 print_state (FILE *out
, int level
, state
*s
)
362 xml_printf (out
, level
, "<state number=\"%d\">", s
->number
);
363 print_core (out
, level
+ 1, s
);
364 print_actions (out
, level
+ 1, s
);
365 if (s
->solved_conflicts_xml
)
367 xml_puts (out
, level
+ 1, "<solved-conflicts>");
368 fputs (s
->solved_conflicts_xml
, out
);
369 xml_puts (out
, level
+ 1, "</solved-conflicts>");
372 xml_puts (out
, level
+ 1, "<solved-conflicts/>");
373 xml_puts (out
, level
, "</state>");
377 /*-----------------------------------------.
378 | Print information on the whole grammar. |
379 `-----------------------------------------*/
382 print_grammar (FILE *out
, int level
)
387 xml_puts (out
, level
, "<grammar>");
388 grammar_rules_print_xml (out
, level
);
391 xml_puts (out
, level
+ 1, "<terminals>");
392 for (i
= 0; i
< max_user_token_number
+ 1; i
++)
393 if (token_translations
[i
] != undeftoken
->number
)
395 char const *tag
= symbols
[token_translations
[i
]]->tag
;
396 int precedence
= symbols
[token_translations
[i
]]->prec
;
397 assoc associativity
= symbols
[token_translations
[i
]]->assoc
;
398 xml_indent (out
, level
+ 2);
400 "<terminal symbol-number=\"%d\" token-number=\"%d\""
401 " name=\"%s\" usefulness=\"%s\"",
402 token_translations
[i
], i
, xml_escape (tag
),
403 reduce_token_unused_in_grammar (token_translations
[i
])
404 ? "unused-in-grammar" : "useful");
406 fprintf (out
, " prec=\"%d\"", precedence
);
407 if (associativity
!= undef_assoc
)
408 fprintf (out
, " assoc=\"%s\"", assoc_to_string (associativity
) + 1);
411 xml_puts (out
, level
+ 1, "</terminals>");
414 xml_puts (out
, level
+ 1, "<nonterminals>");
415 for (i
= ntokens
; i
< nsyms
+ nuseless_nonterminals
; i
++)
417 char const *tag
= symbols
[i
]->tag
;
418 xml_printf (out
, level
+ 2,
419 "<nonterminal symbol-number=\"%d\" name=\"%s\""
420 " usefulness=\"%s\"/>",
422 reduce_nonterminal_useless_in_grammar (i
)
423 ? "useless-in-grammar" : "useful");
425 xml_puts (out
, level
+ 1, "</nonterminals>");
426 xml_puts (out
, level
, "</grammar>");
430 xml_indent (FILE *out
, int level
)
433 for (i
= 0; i
< level
; i
++)
438 xml_puts (FILE *out
, int level
, char const *s
)
440 xml_indent (out
, level
);
446 xml_printf (FILE *out
, int level
, char const *fmt
, ...)
450 xml_indent (out
, level
);
452 va_start (arglist
, fmt
);
453 vfprintf (out
, fmt
, arglist
);
460 xml_escape_string (struct escape_buf
*buf
, char const *str
)
462 size_t len
= strlen (str
);
463 size_t max_expansion
= sizeof """ - 1;
466 if (buf
->size
<= max_expansion
* len
)
468 buf
->size
= max_expansion
* len
+ 1;
469 buf
->ptr
= x2realloc (buf
->ptr
, &buf
->size
);
476 default: *p
++ = *str
; break;
477 case '&': p
= stpcpy (p
, "&" ); break;
478 case '<': p
= stpcpy (p
, "<" ); break;
479 case '>': p
= stpcpy (p
, ">" ); break;
480 case '"': p
= stpcpy (p
, """); break;
488 xml_escape_n (int n
, char const *str
)
490 return xml_escape_string (escape_bufs
+ n
, str
);
494 xml_escape (char const *str
)
496 return xml_escape_n (0, str
);
505 FILE *out
= xfopen (spec_xml_file
, "w");
507 fputs ("<?xml version=\"1.0\"?>\n\n", out
);
508 xml_printf (out
, level
, "<bison-xml-report version=\"%s\">",
509 xml_escape (VERSION
));
512 xml_printf (out
, level
+ 1, "<filename>%s</filename>",
513 xml_escape (grammar_file
));
516 print_grammar (out
, level
+ 1);
518 new_closure (nritems
);
519 no_reduce_set
= bitset_create (ntokens
, BITSET_FIXED
);
521 /* print automaton */
523 xml_puts (out
, level
+ 1, "<automaton>");
524 for (i
= 0; i
< nstates
; i
++)
525 print_state (out
, level
+ 2, states
[i
]);
526 xml_puts (out
, level
+ 1, "</automaton>");
528 bitset_free (no_reduce_set
);
531 xml_puts (out
, 0, "</bison-xml-report>");
533 free (escape_bufs
[0].ptr
);
534 free (escape_bufs
[1].ptr
);