Exemple #1
0
static void
new_itemsets (state *s)
{
  size_t i;

  if (trace_flag & trace_automaton)
    fprintf (stderr, "Entering new_itemsets, state = %d\n", s->number);

  memset (kernel_size, 0, nsyms * sizeof *kernel_size);

  nshifts = 0;

  for (i = 0; i < nitemset; ++i)
    if (item_number_is_symbol_number (ritem[itemset[i]]))
      {
	symbol_number sym = item_number_as_symbol_number (ritem[itemset[i]]);
	if (!kernel_size[sym])
	  {
	    shift_symbol[nshifts] = sym;
	    nshifts++;
	  }

	kernel_base[sym][kernel_size[sym]] = itemset[i] + 1;
	kernel_size[sym]++;
      }
}
Exemple #2
0
/**
 * \post:
 *   - \c result = a new \c bitset of size \c ::nritems such that any bit \c i
 *     is set iff <tt>ritem[i]</tt> is a nonterminal after which all ritems in
 *     the same RHS are nullable nonterminals.  In other words, the follows of
 *     a goto on <tt>ritem[i]</tt> include the lookahead set of the item.
 */
static bitset
ielr_compute_ritem_sees_lookahead_set (void)
{
  bitset result = bitset_create (nritems, BITSET_FIXED);
  unsigned int i = nritems-1;
  while (i>0)
    {
      --i;
      while (!item_number_is_rule_number (ritem[i])
             && ISVAR (ritem[i])
             && nullable [item_number_as_symbol_number (ritem[i]) - ntokens])
        bitset_set (result, i--);
      if (!item_number_is_rule_number (ritem[i]) && ISVAR (ritem[i]))
        bitset_set (result, i--);
      while (!item_number_is_rule_number (ritem[i]) && i>0)
        --i;
    }
  if (trace_flag & trace_ielr)
    {
      fprintf (stderr, "ritem_sees_lookahead_set:\n");
      debug_bitset (result);
      fprintf (stderr, "\n");
    }
  return result;
}
Exemple #3
0
/**
 * \pre:
 *   - \c ritem_sees_lookahead_set was computed by
 *     \c ielr_compute_ritem_sees_lookahead_set.
 *   - \c internal_follow_edges was computed by
 *     \c ielr_compute_internal_follow_edges.
 * \post:
 *   - \c *follow_kernel_itemsp is a new \c bitsetv in which the number of rows
 *     is \c ngotos and the number of columns is maximum number of kernel items
 *     in any state.
 *   - <tt>(*follow_kernel_itemsp)[i][j]</tt> is set iff the follows of goto
 *     \c i include the lookahead set of item \c j in the from state of goto
 *     \c i.
 *   - Thus, <tt>(*follow_kernel_itemsp)[i][j]</tt> is always unset if there is
 *     no item \c j in the from state of goto \c i.
 */
static void
ielr_compute_follow_kernel_items (bitset ritem_sees_lookahead_set,
                                  goto_number **internal_follow_edges,
                                  bitsetv *follow_kernel_itemsp)
{
  {
    size_t max_nitems = 0;
    state_number i;
    for (i = 0; i < nstates; ++i)
      if (states[i]->nitems > max_nitems)
        max_nitems = states[i]->nitems;
    *follow_kernel_itemsp = bitsetv_create (ngotos, max_nitems, BITSET_FIXED);
  }
  {
    goto_number i;
    for (i = 0; i < ngotos; ++i)
      {
        size_t nitems = states[from_state[i]]->nitems;
        item_number *items = states[from_state[i]]->items;
        size_t j;
        for (j = 0; j < nitems; ++j)
          /* If this item has this goto and if all subsequent symbols in this
             RHS (if any) are nullable nonterminals, then record this item as
             one whose lookahead set is included in this goto's follows.  */
          if (item_number_is_symbol_number (ritem[items[j]])
              && item_number_as_symbol_number (ritem[items[j]])
                == states[to_state[i]]->accessing_symbol
              && bitset_test (ritem_sees_lookahead_set, items[j]))
            bitset_set ((*follow_kernel_itemsp)[i], j);
      }
  }
  relation_digraph (internal_follow_edges, ngotos, follow_kernel_itemsp);

  if (trace_flag & trace_ielr)
    {
      fprintf (stderr, "follow_kernel_items:\n");
      debug_bitsetv (*follow_kernel_itemsp);
    }
}
Exemple #4
0
/**
 * \pre:
 *   - \c ritem_sees_lookahead_set was computed by
 *     \c ielr_compute_ritem_sees_lookahead_set.
 * \post:
 *   - Each of \c *edgesp and \c *edge_countsp is a new array of size
 *     \c ::ngotos.
 *   - <tt>(*edgesp)[i]</tt> points to a \c goto_number array of size
 *     <tt>(*edge_countsp)[i]+1</tt>.
 *   - In such a \c goto_number array, the last element is \c ::END_NODE.
 *   - All remaining elements are the indices of the gotos to which there is an
 *     internal follow edge from goto \c i.
 *   - There is an internal follow edge from goto \c i to goto \c j iff both:
 *     - The from states of gotos \c i and \c j are the same.
 *     - The transition nonterminal for goto \c i appears as the first RHS
 *       symbol of at least one production for which both:
 *       - The LHS is the transition symbol of goto \c j.
 *       - All other RHS symbols are nullable nonterminals.
 *     - In other words, the follows of goto \c i include the follows of
 *       goto \c j and it's an internal edge because the from states are the
 *       same.
 */
static void
ielr_compute_internal_follow_edges (bitset ritem_sees_lookahead_set,
                                    goto_number ***edgesp, int **edge_countsp)
{
  *edgesp = xnmalloc (ngotos, sizeof **edgesp);
  *edge_countsp = xnmalloc (ngotos, sizeof **edge_countsp);
  {
    bitset sources = bitset_create (ngotos, BITSET_FIXED);
    goto_number i;
    for (i = 0; i < ngotos; ++i)
      (*edge_countsp)[i] = 0;
    for (i = 0; i < ngotos; ++i)
      {
        int nsources = 0;
        {
          rule **rulep;
          for (rulep = derives[states[to_state[i]]->accessing_symbol
                               - ntokens];
               *rulep;
               ++rulep)
            {
              /* If there is at least one RHS symbol, if the first RHS symbol
                 is a nonterminal, and if all remaining RHS symbols (if any)
                 are nullable nonterminals, create an edge from the LHS
                 symbol's goto to the first RHS symbol's goto such that the RHS
                 symbol's goto will be the source of the edge after the
                 eventual relation_transpose below.

                 Unlike in ielr_compute_always_follows, I use a bitset for
                 edges rather than an array because it is possible that
                 multiple RHS's with the same first symbol could fit and thus
                 that we could end up with redundant edges.  With the
                 possibility of redundant edges, it's hard to know ahead of
                 time how large to make such an array.  Another possible
                 redundancy is that source and destination might be the same
                 goto.  Eliminating all these possible redundancies now might
                 possibly help performance a little.  I have not proven any of
                 this, but I'm guessing the bitset shouldn't entail much of a
                 performance penalty, if any.  */
              if (bitset_test (ritem_sees_lookahead_set,
                               (*rulep)->rhs - ritem))
                {
                  goto_number source =
                    map_goto (from_state[i],
                              item_number_as_symbol_number (*(*rulep)->rhs));
                  if (i != source && !bitset_test (sources, source))
                    {
                      bitset_set (sources, source);
                      ++nsources;
                      ++(*edge_countsp)[source];
                    }
                }
            }
        }
        if (nsources == 0)
          (*edgesp)[i] = NULL;
        else
          {
            (*edgesp)[i] = xnmalloc (nsources + 1, sizeof *(*edgesp)[i]);
            {
              bitset_iterator biter_source;
              bitset_bindex source;
              int j = 0;
              BITSET_FOR_EACH (biter_source, sources, source, 0)
                (*edgesp)[i][j++] = source;
            }
            (*edgesp)[i][nsources] = END_NODE;
          }
        bitset_zero (sources);
      }
    bitset_free (sources);
  }

  relation_transpose (edgesp, ngotos);

  if (trace_flag & trace_ielr)
    {
      fprintf (stderr, "internal_follow_edges:\n");
      relation_print (*edgesp, ngotos, stderr);
    }
}
Exemple #5
0
static void
print_grammar (FILE *out)
{
  symbol_number i;
  char buffer[90];
  int column = 0;

  grammar_rules_print (out);

  /* TERMINAL (type #) : rule #s terminal is on RHS */
  fprintf (out, "%s\n\n", _("Terminals, with rules where they appear"));
  for (i = 0; i < max_user_token_number + 1; i++)
    if (token_translations[i] != undeftoken->number)
      {
	const char *tag = symbols[token_translations[i]]->tag;
	rule_number r;
	item_number *rhsp;

	buffer[0] = 0;
	column = strlen (tag);
	fputs (tag, out);
	END_TEST (50);
	sprintf (buffer, " (%d)", i);

	for (r = 0; r < nrules; r++)
	  for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
	    if (item_number_as_symbol_number (*rhsp) == token_translations[i])
	      {
		END_TEST (65);
		sprintf (buffer + strlen (buffer), " %d", r);
		break;
	      }
	fprintf (out, "%s\n", buffer);
      }
  fputs ("\n\n", out);


  fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear"));
  for (i = ntokens; i < nsyms; i++)
    {
      int left_count = 0, right_count = 0;
      rule_number r;
      const char *tag = symbols[i]->tag;

      for (r = 0; r < nrules; r++)
	{
	  item_number *rhsp;
	  if (rules[r].lhs->number == i)
	    left_count++;
	  for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
	    if (item_number_as_symbol_number (*rhsp) == i)
	      {
		right_count++;
		break;
	      }
	}

      buffer[0] = 0;
      fputs (tag, out);
      column = strlen (tag);
      sprintf (buffer, " (%d)", i);
      END_TEST (0);

      if (left_count > 0)
	{
	  END_TEST (50);
	  sprintf (buffer + strlen (buffer), _(" on left:"));

	  for (r = 0; r < nrules; r++)
	    {
	      END_TEST (65);
	      if (rules[r].lhs->number == i)
		sprintf (buffer + strlen (buffer), " %d", r);
	    }
	}

      if (right_count > 0)
	{
	  if (left_count > 0)
	    sprintf (buffer + strlen (buffer), ",");
	  END_TEST (50);
	  sprintf (buffer + strlen (buffer), _(" on right:"));
	  for (r = 0; r < nrules; r++)
	    {
	      item_number *rhsp;
	      for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
		if (item_number_as_symbol_number (*rhsp) == i)
		  {
		    END_TEST (65);
		    sprintf (buffer + strlen (buffer), " %d", r);
		    break;
		  }
	    }
	}
      fprintf (out, "%s\n", buffer);
    }
}