Blame src/closure.c

Packit Service c3aa71
/* Closures for Bison
Packit Service c3aa71
Packit Service c3aa71
   Copyright (C) 1984, 1989, 2000-2002, 2004-2005, 2007, 2009-2015 Free
Packit Service c3aa71
   Software Foundation, Inc.
Packit Service c3aa71
Packit Service c3aa71
   This file is part of Bison, the GNU Compiler Compiler.
Packit Service c3aa71
Packit Service c3aa71
   This program is free software: you can redistribute it and/or modify
Packit Service c3aa71
   it under the terms of the GNU General Public License as published by
Packit Service c3aa71
   the Free Software Foundation, either version 3 of the License, or
Packit Service c3aa71
   (at your option) any later version.
Packit Service c3aa71
Packit Service c3aa71
   This program is distributed in the hope that it will be useful,
Packit Service c3aa71
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service c3aa71
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service c3aa71
   GNU General Public License for more details.
Packit Service c3aa71
Packit Service c3aa71
   You should have received a copy of the GNU General Public License
Packit Service c3aa71
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service c3aa71
Packit Service c3aa71
#include <config.h>
Packit Service c3aa71
#include "system.h"
Packit Service c3aa71
Packit Service c3aa71
#include <bitset.h>
Packit Service c3aa71
#include <bitsetv-print.h>
Packit Service c3aa71
#include <bitsetv.h>
Packit Service c3aa71
Packit Service c3aa71
#include "closure.h"
Packit Service c3aa71
#include "derives.h"
Packit Service c3aa71
#include "getargs.h"
Packit Service c3aa71
#include "gram.h"
Packit Service c3aa71
#include "reader.h"
Packit Service c3aa71
#include "symtab.h"
Packit Service c3aa71
Packit Service c3aa71
/* NITEMSET is the size of the array ITEMSET.  */
Packit Service c3aa71
item_number *itemset;
Packit Service c3aa71
size_t nitemset;
Packit Service c3aa71
Packit Service c3aa71
static bitset ruleset;
Packit Service c3aa71
Packit Service c3aa71
/* internal data.  See comments before set_fderives and set_firsts.  */
Packit Service c3aa71
static bitsetv fderives = NULL;
Packit Service c3aa71
static bitsetv firsts = NULL;
Packit Service c3aa71
Packit Service c3aa71
/* Retrieve the FDERIVES/FIRSTS sets of the nonterminals numbered Var.  */
Packit Service c3aa71
#define FDERIVES(Var)   fderives[(Var) - ntokens]
Packit Service c3aa71
#define FIRSTS(Var)   firsts[(Var) - ntokens]
Packit Service c3aa71

Packit Service c3aa71
Packit Service c3aa71
/*-----------------.
Packit Service c3aa71
| Debugging code.  |
Packit Service c3aa71
`-----------------*/
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
print_closure (char const *title, item_number const *array, size_t size)
Packit Service c3aa71
{
Packit Service c3aa71
  size_t i;
Packit Service c3aa71
  fprintf (stderr, "Closure: %s\n", title);
Packit Service c3aa71
  for (i = 0; i < size; ++i)
Packit Service c3aa71
    {
Packit Service c3aa71
      item_number *rp;
Packit Service c3aa71
      fprintf (stderr, "  %2d: .", array[i]);
Packit Service c3aa71
      for (rp = &ritem[array[i]]; *rp >= 0; ++rp)
Packit Service c3aa71
        fprintf (stderr, " %s", symbols[*rp]->tag);
Packit Service c3aa71
      fprintf (stderr, "  (rule %d)\n", -*rp - 1);
Packit Service c3aa71
    }
Packit Service c3aa71
  fputs ("\n\n", stderr);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
print_firsts (void)
Packit Service c3aa71
{
Packit Service c3aa71
  symbol_number i, j;
Packit Service c3aa71
Packit Service c3aa71
  fprintf (stderr, "FIRSTS\n");
Packit Service c3aa71
  for (i = ntokens; i < nsyms; i++)
Packit Service c3aa71
    {
Packit Service c3aa71
      bitset_iterator iter;
Packit Service c3aa71
      fprintf (stderr, "  %s firsts\n", symbols[i]->tag);
Packit Service c3aa71
      BITSET_FOR_EACH (iter, FIRSTS (i), j, 0)
Packit Service c3aa71
        fprintf (stderr, "    %s\n", symbols[j + ntokens]->tag);
Packit Service c3aa71
    }
Packit Service c3aa71
  fprintf (stderr, "\n\n");
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
print_fderives (void)
Packit Service c3aa71
{
Packit Service c3aa71
  int i;
Packit Service c3aa71
  rule_number r;
Packit Service c3aa71
Packit Service c3aa71
  fprintf (stderr, "FDERIVES\n");
Packit Service c3aa71
  for (i = ntokens; i < nsyms; i++)
Packit Service c3aa71
    {
Packit Service c3aa71
      bitset_iterator iter;
Packit Service c3aa71
      fprintf (stderr, "  %s derives\n", symbols[i]->tag);
Packit Service c3aa71
      BITSET_FOR_EACH (iter, FDERIVES (i), r, 0)
Packit Service c3aa71
        {
Packit Service c3aa71
          fprintf (stderr, "    %3d ", r);
Packit Service c3aa71
          rule_rhs_print (&rules[r], stderr);
Packit Service c3aa71
          fprintf (stderr, "\n");
Packit Service c3aa71
        }
Packit Service c3aa71
    }
Packit Service c3aa71
  fprintf (stderr, "\n\n");
Packit Service c3aa71
}
Packit Service c3aa71

Packit Service c3aa71
/*------------------------------------------------------------------.
Packit Service c3aa71
| Set FIRSTS to be an NVARS array of NVARS bitsets indicating which |
Packit Service c3aa71
| items can represent the beginning of the input corresponding to   |
Packit Service c3aa71
| which other items.                                                |
Packit Service c3aa71
|                                                                   |
Packit Service c3aa71
| For example, if some rule expands symbol 5 into the sequence of   |
Packit Service c3aa71
| symbols 8 3 20, the symbol 8 can be the beginning of the data for |
Packit Service c3aa71
| symbol 5, so the bit [8 - ntokens] in first[5 - ntokens] (= FIRST |
Packit Service c3aa71
| (5)) is set.                                                      |
Packit Service c3aa71
`------------------------------------------------------------------*/
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
set_firsts (void)
Packit Service c3aa71
{
Packit Service c3aa71
  symbol_number i, j;
Packit Service c3aa71
Packit Service c3aa71
  firsts = bitsetv_create (nvars, nvars, BITSET_FIXED);
Packit Service c3aa71
Packit Service c3aa71
  for (i = ntokens; i < nsyms; i++)
Packit Service c3aa71
    for (j = 0; derives[i - ntokens][j]; ++j)
Packit Service c3aa71
      {
Packit Service c3aa71
        item_number sym = derives[i - ntokens][j]->rhs[0];
Packit Service c3aa71
        if (ISVAR (sym))
Packit Service c3aa71
          bitset_set (FIRSTS (i), sym - ntokens);
Packit Service c3aa71
      }
Packit Service c3aa71
Packit Service c3aa71
  if (trace_flag & trace_sets)
Packit Service c3aa71
    bitsetv_matrix_dump (stderr, "RTC: Firsts Input", firsts);
Packit Service c3aa71
  bitsetv_reflexive_transitive_closure (firsts);
Packit Service c3aa71
  if (trace_flag & trace_sets)
Packit Service c3aa71
    bitsetv_matrix_dump (stderr, "RTC: Firsts Output", firsts);
Packit Service c3aa71
Packit Service c3aa71
  if (trace_flag & trace_sets)
Packit Service c3aa71
    print_firsts ();
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
/*-------------------------------------------------------------------.
Packit Service c3aa71
| Set FDERIVES to an NVARS by NRULES matrix of bits indicating which |
Packit Service c3aa71
| rules can help derive the beginning of the data for each           |
Packit Service c3aa71
| nonterminal.                                                       |
Packit Service c3aa71
|                                                                    |
Packit Service c3aa71
| For example, if symbol 5 can be derived as the sequence of symbols |
Packit Service c3aa71
| 8 3 20, and one of the rules for deriving symbol 8 is rule 4, then |
Packit Service c3aa71
| the [5 - NTOKENS, 4] bit in FDERIVES is set.                       |
Packit Service c3aa71
`-------------------------------------------------------------------*/
Packit Service c3aa71
Packit Service c3aa71
static void
Packit Service c3aa71
set_fderives (void)
Packit Service c3aa71
{
Packit Service c3aa71
  symbol_number i, j;
Packit Service c3aa71
  rule_number k;
Packit Service c3aa71
Packit Service c3aa71
  fderives = bitsetv_create (nvars, nrules, BITSET_FIXED);
Packit Service c3aa71
Packit Service c3aa71
  set_firsts ();
Packit Service c3aa71
Packit Service c3aa71
  for (i = ntokens; i < nsyms; ++i)
Packit Service c3aa71
    for (j = ntokens; j < nsyms; ++j)
Packit Service c3aa71
      if (bitset_test (FIRSTS (i), j - ntokens))
Packit Service c3aa71
        for (k = 0; derives[j - ntokens][k]; ++k)
Packit Service c3aa71
          bitset_set (FDERIVES (i), derives[j - ntokens][k]->number);
Packit Service c3aa71
Packit Service c3aa71
  if (trace_flag & trace_sets)
Packit Service c3aa71
    print_fderives ();
Packit Service c3aa71
Packit Service c3aa71
  bitsetv_free (firsts);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71

Packit Service c3aa71
Packit Service c3aa71
void
Packit Service c3aa71
new_closure (unsigned int n)
Packit Service c3aa71
{
Packit Service c3aa71
  itemset = xnmalloc (n, sizeof *itemset);
Packit Service c3aa71
Packit Service c3aa71
  ruleset = bitset_create (nrules, BITSET_FIXED);
Packit Service c3aa71
Packit Service c3aa71
  set_fderives ();
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
void
Packit Service c3aa71
closure (item_number const *core, size_t n)
Packit Service c3aa71
{
Packit Service c3aa71
  /* Index over CORE. */
Packit Service c3aa71
  size_t c;
Packit Service c3aa71
Packit Service c3aa71
  /* A bit index over RULESET. */
Packit Service c3aa71
  rule_number ruleno;
Packit Service c3aa71
Packit Service c3aa71
  bitset_iterator iter;
Packit Service c3aa71
Packit Service c3aa71
  if (trace_flag & trace_sets)
Packit Service c3aa71
    print_closure ("input", core, n);
Packit Service c3aa71
Packit Service c3aa71
  bitset_zero (ruleset);
Packit Service c3aa71
Packit Service c3aa71
  for (c = 0; c < n; ++c)
Packit Service c3aa71
    if (ISVAR (ritem[core[c]]))
Packit Service c3aa71
      bitset_or (ruleset, ruleset, FDERIVES (ritem[core[c]]));
Packit Service c3aa71
Packit Service c3aa71
  /* core is sorted on item index in ritem, which is sorted on rule number.
Packit Service c3aa71
     Compute itemset with the same sort.  */
Packit Service c3aa71
  nitemset = 0;
Packit Service c3aa71
  c = 0;
Packit Service c3aa71
  BITSET_FOR_EACH (iter, ruleset, ruleno, 0)
Packit Service c3aa71
    {
Packit Service c3aa71
      item_number itemno = rules[ruleno].rhs - ritem;
Packit Service c3aa71
      while (c < n && core[c] < itemno)
Packit Service c3aa71
        {
Packit Service c3aa71
          itemset[nitemset] = core[c];
Packit Service c3aa71
          nitemset++;
Packit Service c3aa71
          c++;
Packit Service c3aa71
        }
Packit Service c3aa71
      itemset[nitemset] = itemno;
Packit Service c3aa71
      nitemset++;
Packit Service c3aa71
    };
Packit Service c3aa71
Packit Service c3aa71
  while (c < n)
Packit Service c3aa71
    {
Packit Service c3aa71
      itemset[nitemset] = core[c];
Packit Service c3aa71
      nitemset++;
Packit Service c3aa71
      c++;
Packit Service c3aa71
    }
Packit Service c3aa71
Packit Service c3aa71
  if (trace_flag & trace_sets)
Packit Service c3aa71
    print_closure ("output", itemset, nitemset);
Packit Service c3aa71
}
Packit Service c3aa71
Packit Service c3aa71
Packit Service c3aa71
void
Packit Service c3aa71
free_closure (void)
Packit Service c3aa71
{
Packit Service c3aa71
  free (itemset);
Packit Service c3aa71
  bitset_free (ruleset);
Packit Service c3aa71
  bitsetv_free (fderives);
Packit Service c3aa71
}