1 /* Allocate input grammar variables for Bison. 2 3 Copyright (C) 1984, 1986, 1989, 2001-2003, 2005-2012 Free Software 4 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 "complain.h" 25 #include "getargs.h" 26 #include "gram.h" 27 #include "print-xml.h" 28 #include "reader.h" 29 #include "reduce.h" 30 #include "symtab.h" 31 32 /* Comments for these variables are in gram.h. */ 33 34 item_number *ritem = NULL; 35 unsigned int nritems = 0; 36 37 rule *rules = NULL; 38 rule_number nrules = 0; 39 40 symbol **symbols = NULL; 41 int nsyms = 0; 42 int ntokens = 1; 43 int nvars = 0; 44 45 symbol_number *token_translations = NULL; 46 47 int max_user_token_number = 256; 48 49 bool 50 rule_useful_in_grammar_p (rule *r) 51 { 52 return r->number < nrules; 53 } 54 55 bool 56 rule_useless_in_grammar_p (rule *r) 57 { 58 return !rule_useful_in_grammar_p (r); 59 } 60 61 bool 62 rule_useless_in_parser_p (rule *r) 63 { 64 return !r->useful && rule_useful_in_grammar_p (r); 65 } 66 67 void 68 rule_lhs_print (rule *r, symbol *previous_lhs, FILE *out) 69 { 70 fprintf (out, " %3d ", r->number); 71 if (previous_lhs != r->lhs) 72 { 73 fprintf (out, "%s:", r->lhs->tag); 74 } 75 else 76 { 77 int n; 78 for (n = strlen (previous_lhs->tag); n > 0; --n) 79 fputc (' ', out); 80 fputc ('|', out); 81 } 82 } 83 84 void 85 rule_lhs_print_xml (rule *r, FILE *out, int level) 86 { 87 xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag); 88 } 89 90 int 91 rule_rhs_length (rule *r) 92 { 93 int res = 0; 94 item_number *rhsp; 95 for (rhsp = r->rhs; *rhsp >= 0; ++rhsp) 96 ++res; 97 return res; 98 } 99 100 void 101 rule_rhs_print (rule *r, FILE *out) 102 { 103 if (*r->rhs >= 0) 104 { 105 item_number *rp; 106 for (rp = r->rhs; *rp >= 0; rp++) 107 fprintf (out, " %s", symbols[*rp]->tag); 108 fputc ('\n', out); 109 } 110 else 111 { 112 fprintf (out, " /* %s */\n", _("empty")); 113 } 114 } 115 116 static void 117 rule_rhs_print_xml (rule *r, FILE *out, int level) 118 { 119 if (*r->rhs >= 0) 120 { 121 item_number *rp; 122 xml_puts (out, level, "<rhs>"); 123 for (rp = r->rhs; *rp >= 0; rp++) 124 xml_printf (out, level + 1, "<symbol>%s</symbol>", 125 xml_escape (symbols[*rp]->tag)); 126 xml_puts (out, level, "</rhs>"); 127 } 128 else 129 { 130 xml_puts (out, level, "<rhs>"); 131 xml_puts (out, level + 1, "<empty/>"); 132 xml_puts (out, level, "</rhs>"); 133 } 134 } 135 136 void 137 rule_print (rule *r, FILE *out) 138 { 139 fprintf (out, "%s:", r->lhs->tag); 140 rule_rhs_print (r, out); 141 } 142 143 void 144 ritem_print (FILE *out) 145 { 146 unsigned int i; 147 fputs ("RITEM\n", out); 148 for (i = 0; i < nritems; ++i) 149 if (ritem[i] >= 0) 150 fprintf (out, " %s", symbols[ritem[i]]->tag); 151 else 152 fprintf (out, " (rule %d)\n", item_number_as_rule_number (ritem[i])); 153 fputs ("\n\n", out); 154 } 155 156 size_t 157 ritem_longest_rhs (void) 158 { 159 int max = 0; 160 rule_number r; 161 162 for (r = 0; r < nrules; ++r) 163 { 164 int length = rule_rhs_length (&rules[r]); 165 if (length > max) 166 max = length; 167 } 168 169 return max; 170 } 171 172 void 173 grammar_rules_partial_print (FILE *out, const char *title, 174 rule_filter filter) 175 { 176 rule_number r; 177 bool first = true; 178 symbol *previous_lhs = NULL; 179 180 /* rule # : LHS -> RHS */ 181 for (r = 0; r < nrules + nuseless_productions; r++) 182 { 183 if (filter && !filter (&rules[r])) 184 continue; 185 if (first) 186 fprintf (out, "%s\n\n", title); 187 else if (previous_lhs && previous_lhs != rules[r].lhs) 188 fputc ('\n', out); 189 first = false; 190 rule_lhs_print (&rules[r], previous_lhs, out); 191 rule_rhs_print (&rules[r], out); 192 previous_lhs = rules[r].lhs; 193 } 194 if (!first) 195 fputs ("\n\n", out); 196 } 197 198 void 199 grammar_rules_print (FILE *out) 200 { 201 grammar_rules_partial_print (out, _("Grammar"), rule_useful_in_grammar_p); 202 } 203 204 void 205 grammar_rules_print_xml (FILE *out, int level) 206 { 207 rule_number r; 208 bool first = true; 209 210 for (r = 0; r < nrules + nuseless_productions; r++) 211 { 212 if (first) 213 xml_puts (out, level + 1, "<rules>"); 214 first = false; 215 { 216 char const *usefulness; 217 if (rule_useless_in_grammar_p (&rules[r])) 218 usefulness = "useless-in-grammar"; 219 else if (rule_useless_in_parser_p (&rules[r])) 220 usefulness = "useless-in-parser"; 221 else 222 usefulness = "useful"; 223 xml_indent (out, level + 2); 224 fprintf (out, "<rule number=\"%d\" usefulness=\"%s\"", 225 rules[r].number, usefulness); 226 if (rules[r].precsym) 227 fprintf (out, " percent_prec=\"%s\"", 228 xml_escape (rules[r].precsym->tag)); 229 fputs (">\n", out); 230 } 231 rule_lhs_print_xml (&rules[r], out, level + 3); 232 rule_rhs_print_xml (&rules[r], out, level + 3); 233 xml_puts (out, level + 2, "</rule>"); 234 } 235 if (!first) 236 xml_puts (out, level + 1, "</rules>"); 237 else 238 xml_puts (out, level + 1, "<rules/>"); 239 } 240 241 void 242 grammar_dump (FILE *out, const char *title) 243 { 244 fprintf (out, "%s\n\n", title); 245 fprintf (out, 246 "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n", 247 ntokens, nvars, nsyms, nrules, nritems); 248 249 250 fprintf (out, "Variables\n---------\n\n"); 251 { 252 symbol_number i; 253 fprintf (out, "Value Sprec Sassoc Tag\n"); 254 255 for (i = ntokens; i < nsyms; i++) 256 fprintf (out, "%5d %5d %5d %s\n", 257 i, 258 symbols[i]->prec, symbols[i]->assoc, 259 symbols[i]->tag); 260 fprintf (out, "\n\n"); 261 } 262 263 fprintf (out, "Rules\n-----\n\n"); 264 { 265 rule_number i; 266 fprintf (out, "Num (Prec, Assoc, Useful, Ritem Range) Lhs -> Rhs (Ritem range) [Num]\n"); 267 for (i = 0; i < nrules + nuseless_productions; i++) 268 { 269 rule *rule_i = &rules[i]; 270 item_number *rp = NULL; 271 unsigned int rhs_itemno = rule_i->rhs - ritem; 272 unsigned int rhs_count = 0; 273 /* Find the last RHS index in ritems. */ 274 for (rp = rule_i->rhs; *rp >= 0; ++rp) 275 ++rhs_count; 276 fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u) %2d ->", 277 i, 278 rule_i->prec ? rule_i->prec->prec : 0, 279 rule_i->prec ? rule_i->prec->assoc : 0, 280 rule_i->useful, 281 rhs_itemno, 282 rhs_itemno + rhs_count - 1, 283 rule_i->lhs->number); 284 /* Dumped the RHS. */ 285 for (rp = rule_i->rhs; *rp >= 0; rp++) 286 fprintf (out, " %3d", *rp); 287 fprintf (out, " [%d]\n", item_number_as_rule_number (*rp)); 288 } 289 } 290 fprintf (out, "\n\n"); 291 292 fprintf (out, "Rules interpreted\n-----------------\n\n"); 293 { 294 rule_number r; 295 for (r = 0; r < nrules + nuseless_productions; r++) 296 { 297 fprintf (out, "%-5d ", r); 298 rule_print (&rules[r], out); 299 } 300 } 301 fprintf (out, "\n\n"); 302 } 303 304 void 305 grammar_rules_useless_report (const char *message) 306 { 307 rule_number r; 308 for (r = 0; r < nrules ; ++r) 309 if (!rules[r].useful) 310 { 311 if (feature_flag & feature_caret) 312 warn_at (rules[r].location, "%s", message); 313 else 314 { 315 warn_at (rules[r].location, "%s: ", message); 316 if (warnings_flag & warnings_other) 317 { 318 rule_print (&rules[r], stderr); 319 fflush (stderr); 320 } 321 } 322 } 323 } 324 325 void 326 grammar_free (void) 327 { 328 if (ritem) 329 free (ritem - 1); 330 free (rules); 331 free (token_translations); 332 /* Free the symbol table data structure. */ 333 symbols_free (); 334 free_merger_functions (); 335 } 336