]>
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-2012 Free Software Foundation, Inc. 
   5    This file is part of Bison, the GNU Compiler Compiler. 
   7    This program 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 3 of the License, or 
  10    (at your option) any later version. 
  12    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */ 
  30 #include "conflicts.h" 
  36 #include "print-xml.h" 
  43 static bitset no_reduce_set
; 
  49 static struct escape_buf escape_bufs
[3]; 
  52 /*--------------------------------. 
  53 | Report information on a state.  | 
  54 `--------------------------------*/ 
  57 print_core (FILE *out
, int level
, state 
*s
) 
  60   item_number 
*sitems 
= s
->items
; 
  61   size_t snritems 
= s
->nitems
; 
  63   /* Output all the items of a state, not only its kernel.  */ 
  64   closure (sitems
, snritems
); 
  69     xml_puts (out
, level
, "<itemset/>"); 
  73   xml_puts (out
, level
, "<itemset>"); 
  75   for (i 
= 0; i 
< snritems
; i
++) 
  82       sp1 
= sp 
= ritem 
+ sitems
[i
]; 
  87       r 
= item_number_as_rule_number (*sp
); 
  90       /* Display the lookahead tokens?  */ 
  91       if (item_number_is_rule_number (*sp1
)) 
  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) 
  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
], 
 103               xml_puts (out
, level 
+ 1, "</item>"); 
 110           xml_printf (out
, level 
+ 1, 
 111                       "<item rule-number=\"%d\" point=\"%d\"/>", 
 116   xml_puts (out
, level
, "</itemset>"); 
 120 /*-----------------------------------------------------------. 
 121 | Report the shifts if DISPLAY_SHIFTS_P or the gotos of S on | 
 123 `-----------------------------------------------------------*/ 
 126 print_transitions (state 
*s
, FILE *out
, int level
) 
 128   transitions 
*trans 
= s
->transitions
; 
 132   for (i 
= 0; i 
< trans
->num
; i
++) 
 133     if (!TRANSITION_IS_DISABLED (trans
, i
)) 
 138   /* Nothing to report. */ 
 140     xml_puts (out
, level
, "<transitions/>"); 
 144   /* Report lookahead tokens and shifts.  */ 
 145   xml_puts (out
, level
, "<transitions>"); 
 147   for (i 
= 0; i 
< trans
->num
; i
++) 
 148     if (!TRANSITION_IS_DISABLED (trans
, i
) 
 149         && TRANSITION_IS_SHIFT (trans
, i
)) 
 151         symbol 
*sym 
= symbols
[TRANSITION_SYMBOL (trans
, i
)]; 
 152         char const *tag 
= sym
->tag
; 
 153         state 
*s1 
= trans
->states
[i
]; 
 155         xml_printf (out
, level 
+ 1, 
 156                     "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>", 
 157                     xml_escape (tag
), s1
->number
); 
 160   for (i 
= 0; i 
< trans
->num
; i
++) 
 161     if (!TRANSITION_IS_DISABLED (trans
, i
) 
 162         && !TRANSITION_IS_SHIFT (trans
, i
)) 
 164         symbol 
*sym 
= symbols
[TRANSITION_SYMBOL (trans
, i
)]; 
 165         char const *tag 
= sym
->tag
; 
 166         state 
*s1 
= trans
->states
[i
]; 
 168         xml_printf (out
, level 
+ 1, 
 169                     "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>", 
 170                     xml_escape (tag
), s1
->number
); 
 173   xml_puts (out
, level
, "</transitions>"); 
 177 /*--------------------------------------------------------. 
 178 | Report the explicit errors of S raised from %nonassoc.  | 
 179 `--------------------------------------------------------*/ 
 182 print_errs (FILE *out
, int level
, state 
*s
) 
 184   errs 
*errp 
= s
->errs
; 
 188   for (i 
= 0; i 
< errp
->num
; ++i
) 
 189     if (errp
->symbols
[i
]) 
 192   /* Nothing to report. */ 
 194     xml_puts (out
, level
, "<errors/>"); 
 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
]) 
 203         char const *tag 
= errp
->symbols
[i
]->tag
; 
 204         xml_printf (out
, level 
+ 1, 
 205                     "<error symbol=\"%s\">nonassociative</error>", 
 208   xml_puts (out
, level
, "</errors>"); 
 212 /*-------------------------------------------------------------------------. 
 213 | Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be `default').  | 
 214 | If not ENABLED, the rule is masked by a shift or a reduce (S/R and       | 
 216 `-------------------------------------------------------------------------*/ 
 219 print_reduction (FILE *out
, int level
, char const *lookahead_token
, 
 220                  rule 
*r
, bool enabled
) 
 223     xml_printf (out
, level
, 
 224                 "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>", 
 225                 xml_escape (lookahead_token
), 
 227                 enabled 
? "true" : "false"); 
 229     xml_printf (out
, level
, 
 230                 "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>", 
 231                 xml_escape (lookahead_token
), 
 232                 enabled 
? "true" : "false"); 
 236 /*-------------------------------------------. 
 237 | Report on OUT the reduction actions of S.  | 
 238 `-------------------------------------------*/ 
 241 print_reductions (FILE *out
, int level
, state 
*s
) 
 243   transitions 
*trans 
= s
->transitions
; 
 244   reductions 
*reds 
= s
->reductions
; 
 245   rule 
*default_reduction 
= NULL
; 
 251       xml_puts (out
, level
, "<reductions/>"); 
 255   if (yydefact
[s
->number
] != 0) 
 256     default_reduction 
= &rules
[yydefact
[s
->number
] - 1]; 
 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
); 
 265   if (default_reduction
) 
 268   if (reds
->lookahead_tokens
) 
 269     for (i 
= 0; i 
< ntokens
; i
++) 
 271         bool count 
= bitset_test (no_reduce_set
, i
); 
 273         for (j 
= 0; j 
< reds
->num
; ++j
) 
 274           if (bitset_test (reds
->lookahead_tokens
[j
], i
)) 
 278                   if (reds
->rules
[j
] != default_reduction
) 
 289   /* Nothing to report. */ 
 291     xml_puts (out
, level
, "<reductions/>"); 
 295   xml_puts (out
, level
, "<reductions>"); 
 297   /* Report lookahead tokens (or $default) and reductions.  */ 
 298   if (reds
->lookahead_tokens
) 
 299     for (i 
= 0; i 
< ntokens
; i
++) 
 301         bool defaulted 
= false; 
 302         bool count 
= bitset_test (no_reduce_set
, i
); 
 304         for (j 
= 0; j 
< reds
->num
; ++j
) 
 305           if (bitset_test (reds
->lookahead_tokens
[j
], i
)) 
 309                   if (reds
->rules
[j
] != default_reduction
) 
 310                     print_reduction (out
, level 
+ 1, symbols
[i
]->tag
, 
 311                                      reds
->rules
[j
], true); 
 319                     print_reduction (out
, level 
+ 1, symbols
[i
]->tag
, 
 320                                      default_reduction
, true); 
 322                   print_reduction (out
, level 
+ 1, symbols
[i
]->tag
, 
 323                                    reds
->rules
[j
], false); 
 328   if (default_reduction
) 
 329     print_reduction (out
, level 
+ 1, 
 330                      "$default", default_reduction
, true); 
 332   xml_puts (out
, level
, "</reductions>"); 
 336 /*--------------------------------------------------------------. 
 337 | Report on OUT all the actions (shifts, gotos, reductions, and | 
 338 | explicit erros from %nonassoc) of S.                          | 
 339 `--------------------------------------------------------------*/ 
 342 print_actions (FILE *out
, int level
, state 
*s
) 
 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>"); 
 352 /*----------------------------------. 
 353 | Report all the data on S on OUT.  | 
 354 `----------------------------------*/ 
 357 print_state (FILE *out
, int level
, state 
*s
) 
 360   xml_printf (out
, level
, "<state number=\"%d\">", s
->number
); 
 361   print_core (out
, level 
+ 1, s
); 
 362   print_actions (out
, level 
+ 1, s
); 
 363   if (s
->solved_conflicts_xml
) 
 365       xml_puts (out
, level 
+ 1, "<solved-conflicts>"); 
 366       fputs (s
->solved_conflicts_xml
, out
); 
 367       xml_puts (out
, level 
+ 1, "</solved-conflicts>"); 
 370     xml_puts (out
, level 
+ 1, "<solved-conflicts/>"); 
 371   xml_puts (out
, level
, "</state>"); 
 375 /*-----------------------------------------. 
 376 | Print information on the whole grammar.  | 
 377 `-----------------------------------------*/ 
 380 print_grammar (FILE *out
, int level
) 
 385   xml_puts (out
, level
, "<grammar>"); 
 386   grammar_rules_print_xml (out
, level
); 
 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
) 
 393         char const *tag 
= symbols
[token_translations
[i
]]->tag
; 
 394         int precedence 
= symbols
[token_translations
[i
]]->prec
; 
 395         assoc associativity 
= symbols
[token_translations
[i
]]->assoc
; 
 396         xml_indent (out
, level 
+ 2); 
 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"); 
 404           fprintf (out
, " prec=\"%d\"", precedence
); 
 405         if (associativity 
!= undef_assoc
) 
 406           fprintf (out
, " assoc=\"%s\"", assoc_to_string (associativity
) + 1); 
 409   xml_puts (out
, level 
+ 1, "</terminals>"); 
 412   xml_puts (out
, level 
+ 1, "<nonterminals>"); 
 413   for (i 
= ntokens
; i 
< nsyms 
+ nuseless_nonterminals
; i
++) 
 415       char const *tag 
= symbols
[i
]->tag
; 
 416       xml_printf (out
, level 
+ 2, 
 417                   "<nonterminal symbol-number=\"%d\" name=\"%s\"" 
 418                   " usefulness=\"%s\"/>", 
 420                   reduce_nonterminal_useless_in_grammar (i
) 
 421                     ? "useless-in-grammar" : "useful"); 
 423   xml_puts (out
, level 
+ 1, "</nonterminals>"); 
 424   xml_puts (out
, level
, "</grammar>"); 
 428 xml_indent (FILE *out
, int level
) 
 431   for (i 
= 0; i 
< level
; i
++) 
 436 xml_puts (FILE *out
, int level
, char const *s
) 
 438   xml_indent (out
, level
); 
 444 xml_printf (FILE *out
, int level
, char const *fmt
, ...) 
 448   xml_indent (out
, level
); 
 450   va_start (arglist
, fmt
); 
 451   vfprintf (out
, fmt
, arglist
); 
 458 xml_escape_string (struct escape_buf 
*buf
, char const *str
) 
 460   size_t len 
= strlen (str
); 
 461   size_t max_expansion 
= sizeof """ - 1; 
 464   if (buf
->size 
<= max_expansion 
* len
) 
 466       buf
->size 
= max_expansion 
* len 
+ 1; 
 467       buf
->ptr 
= x2realloc (buf
->ptr
, &buf
->size
); 
 474       default: *p
++ = *str
; break; 
 475       case '&': p 
= stpcpy (p
, "&" ); break; 
 476       case '<': p 
= stpcpy (p
, "<"  ); break; 
 477       case '>': p 
= stpcpy (p
, ">"  ); break; 
 478       case '"': p 
= stpcpy (p
, """); break; 
 486 xml_escape_n (int n
, char const *str
) 
 488   return xml_escape_string (escape_bufs 
+ n
, str
); 
 492 xml_escape (char const *str
) 
 494   return xml_escape_n (0, str
); 
 503   FILE *out 
= xfopen (spec_xml_file
, "w"); 
 505   fputs ("<?xml version=\"1.0\"?>\n\n", out
); 
 506   xml_printf (out
, level
, 
 507               "<bison-xml-report version=\"%s\" bug-report=\"%s\"" 
 509               xml_escape_n (0, VERSION
), 
 510               xml_escape_n (1, PACKAGE_BUGREPORT
), 
 511               xml_escape_n (2, PACKAGE_URL
)); 
 514   xml_printf (out
, level 
+ 1, "<filename>%s</filename>", 
 515               xml_escape (grammar_file
)); 
 518   print_grammar (out
, level 
+ 1); 
 520   new_closure (nritems
); 
 521   no_reduce_set 
=  bitset_create (ntokens
, BITSET_FIXED
); 
 523   /* print automaton */ 
 525   xml_puts (out
, level 
+ 1, "<automaton>"); 
 526   for (i 
= 0; i 
< nstates
; i
++) 
 527     print_state (out
, level 
+ 2, states
[i
]); 
 528   xml_puts (out
, level 
+ 1, "</automaton>"); 
 530   bitset_free (no_reduce_set
); 
 533   xml_puts (out
, 0, "</bison-xml-report>"); 
 535   free (escape_bufs
[0].ptr
); 
 536   free (escape_bufs
[1].ptr
);