Beispiel #1
0
static void
save_reductions (state *s)
{
  int count = 0;
  size_t i;

  /* Find and count the active items that represent ends of rules. */
  for (i = 0; i < nitemset; ++i)
    {
      item_number item = ritem[itemset[i]];
      if (item_number_is_rule_number (item))
	{
	  rule_number r = item_number_as_rule_number (item);
	  redset[count++] = &rules[r];
	  if (r == 0)
	    {
	      /* This is "reduce 0", i.e., accept. */
	      aver (!final_state);
	      final_state = s;
	    }
	}
    }

  /* Make a reductions structure and copy the data into it.  */
  state_reductions_set (s, count, redset);
}
Beispiel #2
0
static void
print_core (FILE *out, int level, state *s)
{
  size_t i;
  item_number *sitems = s->items;
  size_t snritems = s->nitems;

  /* Output all the items of a state, not only its kernel.  */
  closure (sitems, snritems);
  sitems = itemset;
  snritems = nitemset;

  if (!snritems)
    {
      xml_puts (out, level, "<itemset/>");
      return;
    }

  xml_puts (out, level, "<itemset>");

  for (i = 0; i < snritems; i++)
    {
      bool printed = false;
      item_number *sp1 = ritem + sitems[i];
      item_number *sp = sp1;
      rule *r;

      while (0 <= *sp)
        sp++;

      r = &rules[item_number_as_rule_number (*sp)];
      sp = r->rhs;

      /* Display the lookahead tokens?  */
      if (item_number_is_rule_number (*sp1))
        {
          reductions *reds = s->reductions;
          int red = state_reduction_find (s, r);
          /* Print item with lookaheads if there are. */
          if (reds->lookahead_tokens && red != -1)
            {
              xml_printf (out, level + 1,
                          "<item rule-number=\"%d\" point=\"%d\">",
                          r->number, sp1 - sp);
              state_rule_lookahead_tokens_print_xml (s, r,
                                                     out, level + 2);
              xml_puts (out, level + 1, "</item>");
              printed = true;
            }
        }

      if (!printed)
        xml_printf (out, level + 1,
                    "<item rule-number=\"%d\" point=\"%d\"/>",
                    r->number,
                    sp1 - sp);
    }
  xml_puts (out, level, "</itemset>");
}
Beispiel #3
0
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);
}
Beispiel #4
0
static void
print_core (FILE *out, state *s)
{
  size_t i;
  item_number *sitems = s->items;
  size_t snritems = s->nitems;
  symbol *previous_lhs = NULL;

  /* Output all the items of a state, not only its kernel.  */
  if (report_flag & report_itemsets)
    {
      closure (sitems, snritems);
      sitems = itemset;
      snritems = nitemset;
    }

  if (!snritems)
    return;

  fputc ('\n', out);

  for (i = 0; i < snritems; i++)
    {
      item_number *sp;
      item_number *sp1;
      rule_number r;

      sp1 = sp = ritem + sitems[i];

      while (*sp >= 0)
	sp++;

      r = item_number_as_rule_number (*sp);

      rule_lhs_print (&rules[r], previous_lhs, out);
      previous_lhs = rules[r].lhs;

      for (sp = rules[r].rhs; sp < sp1; sp++)
	fprintf (out, " %s", symbols[*sp]->tag);
      fputs (" .", out);
      for (/* Nothing */; *sp >= 0; ++sp)
	fprintf (out, " %s", symbols[*sp]->tag);

      /* Display the lookahead tokens?  */
      if (report_flag & report_lookahead_tokens
          && item_number_is_rule_number (*sp1))
	state_rule_lookahead_tokens_print (s, &rules[r], out);

      fputc ('\n', out);
    }
}
Beispiel #5
0
/**
 * \note
 *   - FIXME: It might be an interesting experiment to compare the space and
 *     time efficiency of computing \c item_lookahead_sets either:
 *     - Fully up front.
 *     - Just-in-time, as implemented below.
 *     - Not at all.  That is, just let annotations continue even when
 *       unnecessary.
 */
bool
ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
                         symbol_number lookahead, state ***predecessors,
                         bitset **item_lookahead_sets)
{
  if (!item_lookahead_sets[s->number])
    {
      size_t i;
      item_lookahead_sets[s->number] =
        xnmalloc (s->nitems, sizeof item_lookahead_sets[s->number][0]);
      for (i = 0; i < s->nitems; ++i)
        item_lookahead_sets[s->number][i] = NULL;
    }
  if (!item_lookahead_sets[s->number][item])
    {
      item_lookahead_sets[s->number][item] =
        bitset_create (ntokens, BITSET_FIXED);
      /* If this kernel item is the beginning of a RHS, it must be the kernel
         item in the start state, and so its LHS has no follows and no goto to
         check.  If, instead, this kernel item is the successor of the start
         state's kernel item, there are still no follows and no goto.  This
         situation is fortunate because we want to avoid the - 2 below in both
         cases.

         Actually, IELR(1) should never invoke this function for either of
         those cases because (1) follow_kernel_items will never reference a
         kernel item for this RHS because the end token blocks sight of the
         lookahead set from the RHS's only nonterminal, and (2) no reduction
         has a lookback dependency on this lookahead set.  Nevertheless, I
         didn't change this test to an aver just in case the usage of this
         function evolves to need those two cases.  In both cases, the current
         implementation returns the right result.  */
      if (s->items[item] > 1)
        {
          /* If the LHS symbol of this item isn't known (because this is a
             top-level invocation), go get it.  */
          if (!lhs)
            {
              unsigned int i;
              for (i = s->items[item];
                   !item_number_is_rule_number (ritem[i]);
                   ++i)
                ;
              lhs = rules[item_number_as_rule_number (ritem[i])].lhs->number;
            }
          /* If this kernel item is next to the beginning of the RHS, then
             check all predecessors' goto follows for the LHS.  */
          if (item_number_is_rule_number (ritem[s->items[item] - 2]))
            {
              state **predecessor;
              aver (lhs != accept->number);
              for (predecessor = predecessors[s->number];
                   *predecessor;
                   ++predecessor)
                bitset_or (item_lookahead_sets[s->number][item],
                           item_lookahead_sets[s->number][item],
                           goto_follows[map_goto ((*predecessor)->number,
                                                  lhs)]);
            }
          /* If this kernel item is later in the RHS, then check all
             predecessor items' lookahead sets.  */
          else
            {
              state **predecessor;
              for (predecessor = predecessors[s->number];
                   *predecessor;
                   ++predecessor)
                {
                  size_t predecessor_item;
                  for (predecessor_item = 0;
                       predecessor_item < (*predecessor)->nitems;
                       ++predecessor_item)
                    if ((*predecessor)->items[predecessor_item]
                        == s->items[item] - 1)
                      break;
                  aver (predecessor_item != (*predecessor)->nitems);
                  ielr_item_has_lookahead (*predecessor, lhs,
                                           predecessor_item, 0 /*irrelevant*/,
                                           predecessors, item_lookahead_sets);
                  bitset_or (item_lookahead_sets[s->number][item],
                             item_lookahead_sets[s->number][item],
                             item_lookahead_sets[(*predecessor)->number]
                                                [predecessor_item]);
                }
            }
        }
    }
  return bitset_test (item_lookahead_sets[s->number][item], lookahead);
}
Beispiel #6
0
void
nullable_compute (void)
{
  rule_number ruleno;
  symbol_number *s1;
  symbol_number *s2;
  rule_list *p;

  symbol_number *squeue = xnmalloc (nvars, sizeof *squeue);
  size_t *rcount = xcalloc (nrules, sizeof *rcount);
  /* RITEM contains all the rules, including useless productions.
     Hence we must allocate room for useless nonterminals too.  */
  rule_list **rsets = xcalloc (nvars, sizeof *rsets);
  /* This is said to be more elements than we actually use.
     Supposedly NRITEMS - NRULES is enough.  But why take the risk?  */
  rule_list *relts = xnmalloc (nritems + nvars + 1, sizeof *relts);

  nullable = xcalloc (nvars, sizeof *nullable);

  s1 = s2 = squeue;
  p = relts;

  for (ruleno = 0; ruleno < nrules; ++ruleno)
    if (rules[ruleno].useful)
      {
        rule *rules_ruleno = &rules[ruleno];
        if (rules_ruleno->rhs[0] >= 0)
          {
            /* This rule has a non empty RHS. */
            item_number *rp = NULL;
            bool any_tokens = false;
            for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
              if (ISTOKEN (*rp))
                any_tokens = true;

            /* This rule has only nonterminals: schedule it for the second
               pass.  */
            if (!any_tokens)
              for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
                {
                  rcount[ruleno]++;
                  p->next = rsets[*rp - ntokens];
                  p->value = rules_ruleno;
                  rsets[*rp - ntokens] = p;
                  p++;
                }
          }
        else
          {
            /* This rule has an empty RHS. */
            aver (item_number_as_rule_number (rules_ruleno->rhs[0])
                  == ruleno);
            if (rules_ruleno->useful
                && ! nullable[rules_ruleno->lhs->number - ntokens])
              {
                nullable[rules_ruleno->lhs->number - ntokens] = true;
                *s2++ = rules_ruleno->lhs->number;
              }
          }
      }

  while (s1 < s2)
    for (p = rsets[*s1++ - ntokens]; p; p = p->next)
      {
        rule *r = p->value;
        if (--rcount[r->number] == 0)
          if (r->useful && ! nullable[r->lhs->number - ntokens])
            {
              nullable[r->lhs->number - ntokens] = true;
              *s2++ = r->lhs->number;
            }
      }

  free (squeue);
  free (rcount);
  free (rsets);
  free (relts);

  if (trace_flag & trace_sets)
    nullable_print (stderr);
}
Beispiel #7
0
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");
}