/* Allocate input grammar variables for Bison.

   Copyright (C) 1984, 1986, 1989, 2001-2003, 2005-2012 Free Software
   Foundation, Inc.

   This file is part of Bison, the GNU Compiler Compiler.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include <config.h>
#include "system.h"

#include "complain.h"
#include "getargs.h"
#include "gram.h"
#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);
}

int
rule_rhs_length (rule *r)
{
  int 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);
}

void
grammar_rules_print (FILE *out)
{
  grammar_rules_partial_print (out, _("Grammar"), rule_useful_in_grammar_p);
}

void
grammar_rules_print_xml (FILE *out, int level)
{
  rule_number r;
  bool first = true;

  for (r = 0; r < nrules + nuseless_productions; r++)
    {
      if (first)
	xml_puts (out, level + 1, "<rules>");
      first = false;
      {
        char const *usefulness;
        if (rule_useless_in_grammar_p (&rules[r]))
          usefulness = "useless-in-grammar";
        else if (rule_useless_in_parser_p (&rules[r]))
          usefulness = "useless-in-parser";
        else
          usefulness = "useful";
        xml_indent (out, level + 2);
        fprintf (out, "<rule number=\"%d\" usefulness=\"%s\"",
                 rules[r].number, usefulness);
        if (rules[r].precsym)
          fprintf (out, " percent_prec=\"%s\"",
                   xml_escape (rules[r].precsym->tag));
        fputs (">\n", out);
      }
      rule_lhs_print_xml (&rules[r], out, level + 3);
      rule_rhs_print_xml (&rules[r], out, level + 3);
      xml_puts (out, level + 2, "</rule>");
    }
  if (!first)
    xml_puts (out, level + 1, "</rules>");
  else
   xml_puts (out, level + 1, "<rules/>");
}

void
grammar_dump (FILE *out, const char *title)
{
  fprintf (out, "%s\n\n", title);
  fprintf (out,
	   "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n",
	   ntokens, nvars, nsyms, nrules, nritems);


  fprintf (out, "Variables\n---------\n\n");
  {
    symbol_number i;
    fprintf (out, "Value  Sprec  Sassoc  Tag\n");

    for (i = ntokens; i < nsyms; i++)
      fprintf (out, "%5d  %5d   %5d  %s\n",
	       i,
	       symbols[i]->prec, symbols[i]->assoc,
	       symbols[i]->tag);
    fprintf (out, "\n\n");
  }

  fprintf (out, "Rules\n-----\n\n");
  {
    rule_number i;
    fprintf (out, "Num (Prec, Assoc, Useful, Ritem Range) Lhs -> Rhs (Ritem range) [Num]\n");
    for (i = 0; i < nrules + nuseless_productions; i++)
      {
	rule *rule_i = &rules[i];
	item_number *rp = NULL;
	unsigned int rhs_itemno = rule_i->rhs - ritem;
	unsigned int rhs_count = 0;
	/* Find the last RHS index in ritems. */
	for (rp = rule_i->rhs; *rp >= 0; ++rp)
	  ++rhs_count;
	fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u)   %2d ->",
		 i,
		 rule_i->prec ? rule_i->prec->prec : 0,
		 rule_i->prec ? rule_i->prec->assoc : 0,
		 rule_i->useful,
		 rhs_itemno,
		 rhs_itemno + rhs_count - 1,
		 rule_i->lhs->number);
	/* Dumped the RHS. */
	for (rp = rule_i->rhs; *rp >= 0; rp++)
	  fprintf (out, " %3d", *rp);
	fprintf (out, "  [%d]\n", item_number_as_rule_number (*rp));
      }
  }
  fprintf (out, "\n\n");

  fprintf (out, "Rules interpreted\n-----------------\n\n");
  {
    rule_number r;
    for (r = 0; r < nrules + nuseless_productions; r++)
      {
	fprintf (out, "%-5d  ", r);
	rule_print (&rules[r], out);
      }
  }
  fprintf (out, "\n\n");
}

void
grammar_rules_useless_report (const char *message)
{
  rule_number r;
  for (r = 0; r < nrules ; ++r)
    if (!rules[r].useful)
      {
        if (feature_flag & feature_caret)
          warn_at (rules[r].location, "%s", message);
        else
          {
            warn_at (rules[r].location, "%s: ", message);
            if (warnings_flag & warnings_other)
              {
                rule_print (&rules[r], stderr);
                fflush (stderr);
              }
          }
      }
}

void
grammar_free (void)
{
  if (ritem)
    free (ritem - 1);
  free (rules);
  free (token_translations);
  /* Free the symbol table data structure.  */
  symbols_free ();
  free_merger_functions ();
}
