+#include "print-xml.h"
+#include "reader.h"
+#include "reduce.h"
+#include "symtab.h"
+
+/* Comments for these variables are in gram.h. */
+
+item_number *ritem = NULL;
+unsigned int nritems = 0;
+
+rule *rules = NULL;
+rule_number nrules = 0;
+
+symbol **symbols = NULL;
+int nsyms = 0;
+int ntokens = 1;
+int nvars = 0;
+
+symbol_number *token_translations = NULL;
+
+int max_user_token_number = 256;
+
+bool
+rule_useful_in_grammar_p (rule *r)
+{
+ return r->number < nrules;
+}
+
+bool
+rule_useless_in_grammar_p (rule *r)
+{
+ return !rule_useful_in_grammar_p (r);
+}
+
+bool
+rule_useless_in_parser_p (rule *r)
+{
+ return !r->useful && rule_useful_in_grammar_p (r);
+}
+
+void
+rule_lhs_print (rule *r, symbol *previous_lhs, FILE *out)
+{
+ fprintf (out, " %3d ", r->number);
+ if (previous_lhs != r->lhs)
+ {
+ fprintf (out, "%s:", r->lhs->tag);
+ }
+ else
+ {
+ int n;
+ for (n = strlen (previous_lhs->tag); n > 0; --n)
+ fputc (' ', out);
+ fputc ('|', out);
+ }
+}
+
+void
+rule_lhs_print_xml (rule *r, FILE *out, int level)
+{
+ xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag);
+}
+
+size_t
+rule_rhs_length (rule *r)
+{
+ size_t res = 0;
+ item_number *rhsp;
+ for (rhsp = r->rhs; *rhsp >= 0; ++rhsp)
+ ++res;
+ return res;
+}
+
+void
+rule_rhs_print (rule *r, FILE *out)
+{
+ if (*r->rhs >= 0)
+ {
+ item_number *rp;
+ for (rp = r->rhs; *rp >= 0; rp++)
+ fprintf (out, " %s", symbols[*rp]->tag);
+ fputc ('\n', out);
+ }
+ else
+ {
+ fprintf (out, " /* %s */\n", _("empty"));
+ }
+}
+
+static void
+rule_rhs_print_xml (rule *r, FILE *out, int level)
+{
+ if (*r->rhs >= 0)
+ {
+ item_number *rp;
+ xml_puts (out, level, "<rhs>");
+ for (rp = r->rhs; *rp >= 0; rp++)
+ xml_printf (out, level + 1, "<symbol>%s</symbol>",
+ xml_escape (symbols[*rp]->tag));
+ xml_puts (out, level, "</rhs>");
+ }
+ else
+ {
+ xml_puts (out, level, "<rhs>");
+ xml_puts (out, level + 1, "<empty/>");
+ xml_puts (out, level, "</rhs>");
+ }
+}
+
+void
+rule_print (rule *r, FILE *out)
+{
+ fprintf (out, "%s:", r->lhs->tag);
+ rule_rhs_print (r, out);
+}
+
+void
+ritem_print (FILE *out)
+{
+ unsigned int i;
+ fputs ("RITEM\n", out);
+ for (i = 0; i < nritems; ++i)
+ if (ritem[i] >= 0)
+ fprintf (out, " %s", symbols[ritem[i]]->tag);
+ else
+ fprintf (out, " (rule %d)\n", item_number_as_rule_number (ritem[i]));
+ fputs ("\n\n", out);
+}
+
+size_t
+ritem_longest_rhs (void)
+{
+ int max = 0;
+ rule_number r;
+
+ for (r = 0; r < nrules; ++r)
+ {
+ int length = rule_rhs_length (&rules[r]);
+ if (length > max)
+ max = length;
+ }
+
+ return max;
+}
+
+void
+grammar_rules_partial_print (FILE *out, const char *title,
+ rule_filter filter)
+{
+ rule_number r;
+ bool first = true;
+ symbol *previous_lhs = NULL;
+
+ /* rule # : LHS -> RHS */
+ for (r = 0; r < nrules + nuseless_productions; r++)
+ {
+ if (filter && !filter (&rules[r]))
+ continue;
+ if (first)
+ fprintf (out, "%s\n\n", title);
+ else if (previous_lhs && previous_lhs != rules[r].lhs)
+ fputc ('\n', out);
+ first = false;
+ rule_lhs_print (&rules[r], previous_lhs, out);
+ rule_rhs_print (&rules[r], out);
+ previous_lhs = rules[r].lhs;
+ }
+ if (!first)
+ fputs ("\n\n", out);
+}