Beispiel #1
0
static void
resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs)
{
  symbol_number i;
  reductions *reds = s->reductions;
  /* Find the rule to reduce by to get precedence of reduction.  */
  rule *redrule = reds->rules[ruleno];
  int redprec = redrule->prec->prec;
  bitset lookahead_tokens = reds->lookahead_tokens[ruleno];

  for (i = 0; i < ntokens; i++)
    if (bitset_test (lookahead_tokens, i)
	&& bitset_test (lookahead_set, i)
	&& symbols[i]->prec)
      {
	/* Shift-reduce conflict occurs for token number i
	   and it has a precedence.
	   The precedence of shifting is that of token i.  */
	if (symbols[i]->prec < redprec)
	  {
	    log_resolution (redrule, i, reduce_resolution);
	    flush_shift (s, i);
	  }
	else if (symbols[i]->prec > redprec)
	  {
	    log_resolution (redrule, i, shift_resolution);
	    flush_reduce (lookahead_tokens, i);
	  }
	else
	  /* Matching precedence levels.
	     For left association, keep only the reduction.
	     For right association, keep only the shift.
	     For nonassociation, keep neither.  */

	  switch (symbols[i]->assoc)
	    {
	    default:
	      abort ();

	    case right_assoc:
	      log_resolution (redrule, i, right_resolution);
	      flush_reduce (lookahead_tokens, i);
	      break;

	    case left_assoc:
	      log_resolution (redrule, i, left_resolution);
	      flush_shift (s, i);
	      break;

	    case non_assoc:
	      log_resolution (redrule, i, nonassoc_resolution);
	      flush_shift (s, i);
	      flush_reduce (lookahead_tokens, i);
	      /* Record an explicit error for this token.  */
	      errors[(*nerrs)++] = symbols[i];
	      break;
	    }
      }
}
Beispiel #2
0
void
output_red (state const *s, reductions const *reds, FILE *fout)
{
  bitset no_reduce_set;
  int j;
  int source = s->number;

  /* Two obstacks are needed: one for the enabled reductions, and one
     for the disabled reductions, because in the end we want two
     separate edges, even though in most cases only one will actually
     be printed. */
  struct obstack dout;
  struct obstack eout;

  no_reduce_bitset_init (s, &no_reduce_set);
  obstack_init (&dout);
  obstack_init (&eout);

  for (j = 0; j < reds->num; ++j)
    {
      bool defaulted = false;
      bool firstd = true;
      bool firste = true;
      rule_number ruleno = reds->rules[j]->number;
      rule *default_reduction = NULL;

      if (yydefact[s->number] != 0)
        default_reduction = &rules[yydefact[s->number] - 1];

      /* Build the lookahead tokens lists, one for enabled transitions and one
         for disabled transistions. */
      if (default_reduction && default_reduction == reds->rules[j])
        defaulted = true;
      if (reds->lookahead_tokens)
        {
          int i;
          for (i = 0; i < ntokens; i++)
            if (bitset_test (reds->lookahead_tokens[j], i))
              {
                if (bitset_test (no_reduce_set, i))
                  firstd = print_token (&dout, firstd, symbols[i]->tag);
                else
                  {
                    if (! defaulted)
                      firste = print_token (&eout, firste, symbols[i]->tag);
                    bitset_set (no_reduce_set, i);
                  }
              }
        }

      /* Do the actual output. */
      conclude_red (&dout, source, ruleno, false, firstd, fout);
      conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout);
    }
  obstack_free (&dout, 0);
  obstack_free (&eout, 0);
  bitset_free (no_reduce_set);
}
Beispiel #3
0
static void
nonterminals_reduce (void)
{
  /* Map the nonterminals to their new index: useful first, useless
     afterwards.  Kept for later report.  */

  symbol_number *nontermmap = xnmalloc (nvars, sizeof *nontermmap);
  symbol_number n = ntokens;
  symbol_number i;
  for (i = ntokens; i < nsyms; i++)
    if (bitset_test (V, i))
      nontermmap[i - ntokens] = n++;
  for (i = ntokens; i < nsyms; i++)
    if (!bitset_test (V, i))
      {
        nontermmap[i - ntokens] = n++;
        if (symbols[i]->status != used)
          complain (&symbols[i]->location, Wother,
                    _("nonterminal useless in grammar: %s"),
                    symbols[i]->tag);
      }


  /* Shuffle elements of tables indexed by symbol number.  */
  {
    symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted);

    for (i = ntokens; i < nsyms; i++)
      symbols[i]->number = nontermmap[i - ntokens];
    for (i = ntokens; i < nsyms; i++)
      symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i];
    for (i = ntokens; i < nsyms; i++)
      symbols[i] = symbols_sorted[i - ntokens];
    free (symbols_sorted);
  }

  {
    rule_number r;
    for (r = 0; r < nrules; ++r)
      {
        item_number *rhsp;
        for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
          if (ISVAR (*rhsp))
            *rhsp =  symbol_number_as_item_number (nontermmap[*rhsp
                                                              - ntokens]);
      }
    accept->number = nontermmap[accept->number - ntokens];
  }

  nsyms -= nuseless_nonterminals;
  nvars -= nuseless_nonterminals;

  free (nontermmap);
}
Beispiel #4
0
/* Obtain and set a PID for the new process.
 * O(1) in average case, O(N) degenerate case (more than PID_MAX procs)
 * Uses hardware FFS instruction, so runs in very quick N/32 time */
static int _set_pid(process_create_data *data) {
    // Try to increment _last_pid.
    int err;
    sos_pcb *pcb = data->pcb;
    int cur_pid = _last_pid + 1;
    sos_pcb *taken = NULL;

    if (!pids) {
        dprintf(6, "Allocating PID set...\n");
        bitset_alloc(&pids, SOS_PID_MAX - SOS_PID_MIN);
    }

    dprintf(1, "bs size: %d\n", pids->size);

    if (bitset_test(pids, cur_pid)) {
        dprintf(6, "\tPID %d is already taken.\n", cur_pid);
        // cur_pid is taken
        cur_pid = bitset_ffz(pids);
        dprintf(6, "\tfirst free PID: %d\n", cur_pid);
        if (cur_pid < 0 || cur_pid > pids->size) {
            return SOS_PROCESS_MAXPROC;
        }
    }

    // cur_pid is known to be free
    bitset_set(pids, cur_pid);
    pcb->pid = cur_pid + SOS_PID_MIN;
    _last_pid = cur_pid;
    HASH_ADD_INT(_process_table, pid, pcb);
    return SOS_PROCESS_SUCCESS;
}
Beispiel #5
0
bool
bitset_index_contains_value(struct bitset_index *index, size_t value)
{
	assert(index != NULL);

	return bitset_test(index->bitsets[0], value);
}
Beispiel #6
0
int bitset_toggle(bitset *bs, unsigned int bit) {
    if (bs == NULL || bit >= bs->size) return -BITSET_ERROR;
    if (bitset_test(bs, bit) > 0) {
        return bitset_clear(bs, bit);
    } else {
        return bitset_set(bs, bit);
    }
}
Beispiel #7
0
/* Given a vector BSETV of N bitsets of size N, modify its contents to
   be the transitive closure of what was given.  */
void
bitsetv_transitive_closure (bitsetv bsetv)
{
  bitset_bindex i;
  bitset_bindex j;

  for (i = 0; bsetv[i]; i++)
    for (j = 0; bsetv[j]; j++)
      if (bitset_test (bsetv[j], i))
	bitset_or (bsetv[j], bsetv[j], bsetv[i]);
}
Beispiel #8
0
static bool
useful_production (rule_number r, bitset N0)
{
  item_number *rhsp;

  /* A production is useful if all of the nonterminals in its appear
     in the set of useful nonterminals.  */

  for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
    if (ISVAR (*rhsp) && !bitset_test (N0, *rhsp - ntokens))
      return false;
  return true;
}
Beispiel #9
0
sdm_idset
bitset_to_idset(bitset *b)
{
	int bit;

	sdm_set_clear(tmp_idset);

	for (bit = 0; bit < bitset_size(b); bit++) {
		if (bitset_test(b, bit)) {
			sdm_set_add_element(tmp_idset, bit);
		}
	}

	return tmp_idset;
}
Beispiel #10
0
static void
useless_nonterminals (void)
{
  bitset Np, Ns;
  rule_number r;

  /* N is set as built.  Np is set being built this iteration. P is
     set of all productions which have a RHS all in N.  */

  Np = bitset_create (nvars, BITSET_FIXED);


  /* The set being computed is a set of nonterminals which can derive
     the empty string or strings consisting of all terminals. At each
     iteration a nonterminal is added to the set if there is a
     production with that nonterminal as its LHS for which all the
     nonterminals in its RHS are already in the set.  Iterate until
     the set being computed remains unchanged.  Any nonterminals not
     in the set at that point are useless in that they will never be
     used in deriving a sentence of the language.

     This iteration doesn't use any special traversal over the
     productions.  A set is kept of all productions for which all the
     nonterminals in the RHS are in useful.  Only productions not in
     this set are scanned on each iteration.  At the end, this set is
     saved to be used when finding useful productions: only
     productions in this set will appear in the final grammar.  */

  while (1)
    {
      bitset_copy (Np, N);
      for (r = 0; r < nrules; r++)
        if (!bitset_test (P, r)
            && useful_production (r, N))
          {
            bitset_set (Np, rules[r].lhs->number - ntokens);
            bitset_set (P, r);
          }
      if (bitset_equal_p (N, Np))
        break;
      Ns = Np;
      Np = N;
      N = Ns;
    }
  bitset_free (N);
  N = Np;
}
Beispiel #11
0
static void
reduce_grammar_tables (void)
{
  /* Report and flag useless productions.  */
  {
    rule_number r;
    for (r = 0; r < nrules; r++)
      rules[r].useful = bitset_test (P, r);
    grammar_rules_useless_report (_("rule useless in grammar"));
  }

  /* Map the nonterminals to their new index: useful first, useless
     afterwards.  Kept for later report.  */
  {
    int useful = 0;
    int useless = nrules - nuseless_productions;
    rule *rules_sorted = xnmalloc (nrules, sizeof *rules_sorted);
    rule_number r;
    for (r = 0; r < nrules; ++r)
      rules_sorted[rules[r].useful ? useful++ : useless++] = rules[r];
    free (rules);
    rules = rules_sorted;

    /* Renumber the rules markers in RITEMS.  */
    for (r = 0; r < nrules; ++r)
      {
        item_number *rhsp = rules[r].rhs;
        for (/* Nothing. */; *rhsp >= 0; ++rhsp)
          /* Nothing. */;
        *rhsp = rule_number_as_item_number (r);
        rules[r].number = r;
      }
    nrules -= nuseless_productions;
  }

  /* Adjust NRITEMS.  */
  {
    rule_number r;
    int length;
    for (r = nrules; r < nrules + nuseless_productions; ++r)
      {
        length = rule_rhs_length (&rules[r]);
        nritems -= length + 1;
      }
  }
}
Beispiel #12
0
void part_two_describe()
{

	cout<<"******************************************"<<endl;
	cout<<"*         第二章 C++ STL泛型编程         *"<<endl;
	cout<<"******************************************"<<endl;
	cout<<"*(1) 一个简单的测试案例                 *"<<endl;
	cout<<"*(2) vector向量容器                     *"<<endl;
	cout<<"*(3) string基本字符系列容器             *"<<endl;
	cout<<"*(4) set集合容器                        *"<<endl;
	cout<<"*(5) mutiset多种集合容器                *"<<endl;
	cout<<"*(6) map映照容器                        *"<<endl;
	cout<<"*(7) mutimap多重映照容器                *"<<endl;
	cout<<"*(8) deque双端队列容器                  *"<<endl;
	cout<<"*(9) list双向链表容器                   *"<<endl;
	cout<<"*(10)bitset位集合容器                   *"<<endl;
	cout<<"*(11)stack堆栈容器                      *"<<endl;
	cout<<"*(12)queue队列容器                      *"<<endl;
	cout<<"*(13)priority_queue优先队列容器         *"<<endl;
	cout<<"******************************************"<<endl;
	cout<<"请输入对应的编号进入相应的题目(返回上级输入0):"<<endl;
	int num;
	cin>>num;
	while(num!=0&&num!=1&&num!=2&&num!=3&&num!=4&&num!=5&&num!=6&&num!=7&&num!=8&&num!=9&&num!=10&&num!=11&&num!=12&&num!=13){
		cout<<"编号不存在"<<endl;
		cout<<"请输入对应的编号进入相应的题目(返回上级输入0):"<<endl;
		cin>>num;
	}
	switch(num){
		case 0:total_describe();break;	
		case 1:test();break;
		case 2:vector_test();break;
		case 3:string_test();break;
		case 4:set_test();break;
		case 5:multiset_test();break;
		case 6:map_test();break;
		case 7:multimap_test();break;
		case 8:deque_test();break;
		case 9:list_test();break;
		case 10:bitset_test();break;
		case 11:stack_test();break;
		case 12:queue_test();break;
		case 13:priority_queue_test();break;
		}
	}
Beispiel #13
0
void
bitsetv_matrix_dump (FILE * out, const char *title, bitsetv bset)
{
  bitset_bindex i, j;
  bitset_bindex hsize = bitset_size (bset[0]);

  /* Title. */
  fprintf (out, "%s BEGIN\n", title);

  /* Column numbers. */
  fputs ("   ", out);
  for (i = 0; i < hsize; ++i)
    putc (i / 10 ? '0' + i / 10 : ' ', out);
  putc ('\n', out);
  fputs ("   ", out);
  for (i = 0; i < hsize; ++i)
    fprintf (out, "%d", (int) (i % 10));
  putc ('\n', out);

  /* Bar. */
  fputs ("  .", out);
  for (i = 0; i < hsize; ++i)
    putc ('-', out);
  fputs (".\n", out);

  /* Contents. */
  for (i = 0; bset[i]; ++i)
    {
      fprintf (out, "%2lu|", (unsigned long int) i);
      for (j = 0; j < hsize; ++j)
        fputs (bitset_test (bset[i], j) ? "1" : " ", out);
      fputs ("|\n", out);
    }

  /* Bar. */
  fputs ("  `", out);
  for (i = 0; i < hsize; ++i)
    putc ('-', out);
  fputs ("'\n", out);

  /* End title. */
  fprintf (out, "%s END\n\n", title);
}
Beispiel #14
0
void
reduce_grammar (void)
{
  bool reduced;

  /* Allocate the global sets used to compute the reduced grammar */

  N = bitset_create (nvars, BITSET_FIXED);
  P =  bitset_create (nrules, BITSET_FIXED);
  V = bitset_create (nsyms, BITSET_FIXED);
  V1 = bitset_create (nsyms, BITSET_FIXED);

  useless_nonterminals ();
  inaccessable_symbols ();

  reduced = (nuseless_nonterminals + nuseless_productions > 0);
  if (!reduced)
    return;

  reduce_print ();

  if (!bitset_test (N, accept->number - ntokens))
    complain (&startsymbol_location, fatal,
              _("start symbol %s does not derive any sentence"),
              startsymbol->tag);

  /* First reduce the nonterminals, as they renumber themselves in the
     whole grammar.  If you change the order, nonterms would be
     renumbered only in the reduced grammar.  */
  if (nuseless_nonterminals > 0)
    nonterminals_reduce ();
  if (nuseless_productions > 0)
    reduce_grammar_tables ();

  if (trace_flag & trace_grammar)
    {
      grammar_dump (stderr, "Reduced Grammar");

      fprintf (stderr, "reduced %s defines %d terminals, %d nonterminals"
               ", and %d productions.\n",
               grammar_file, ntokens, nvars, nrules);
    }
}
Beispiel #15
0
static int
count_rr_conflicts (state *s, bool one_per_token)
{
  int i;
  reductions *reds = s->reductions;
  int rrc_count = 0;

  for (i = 0; i < ntokens; i++)
    {
      int count = 0;
      int j;
      for (j = 0; j < reds->num; ++j)
	if (bitset_test (reds->lookahead_tokens[j], i))
	  count++;

      if (count >= 2)
	rrc_count += one_per_token ? 1 : count-1;
    }

  return rrc_count;
}
Beispiel #16
0
/**
 * Return a string representation of a bitset. We use hex to compress
 * the string somewhat and drop leading zeros.
 *
 * Format is "NN:HHHHHH..." where "NN" is the actual number of bits in hex,
 * and "HHHHH...." is a hex representation of the bits in the set. The number
 * of characters in the bit string is always rounded to the nearest byte.
 *
 * e.g. "111" -> "3:07"
 * 		"11011010101011101" -> "11:01b55d"
 */
char *bitset_to_str(bitset *b)
{
	int			bytes;
	int		        pbit;
	int                     bit;
	char                    *str;
	char                    *s;
	unsigned char           val;
	int                     found = 0;

	if (!b)
		return strdup("00");

	/*
	 * Find out how many bytes needed (rounded up)
	 */
	bytes = NUM_BYTES(b->bs_nbits);

	str = (char *)calloc(bytes * 2 + 1, 1);
	s = str;

	for (pbit = (bytes << 3) - 1; pbit > 0; ) {
		for (val = 0, bit = 3; bit >= 0; bit--, pbit--) {
			if (pbit < (int)b->bs_nbits && bitset_test(b, pbit)) {
				val |= (1 << bit);
                                found = 1;
			}
		}
		if (found)
			*s++ = tohex[val & 0x0f];
	}

	if (b->bs_nbits == 0) {
		*s++ = '0';
	}

	*s = '\0';

	return str;
}
Beispiel #17
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);
    }
}
Beispiel #18
0
static void setclear(){
	int i;
	bitset_t set=bitset_create(16,16);

    printf("setting 5 and 60\n");
	bitset_set(set,5);
	bitset_set(set,60);
	for(i=0;i<80;i++) printf("%s",bitset_test(set,i)?"1":"0");
	printf("\n");
	
	int N=10;
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("set %d\n",N);
    bitset_set(set,N);
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("clear %d\n",N);
	bitset_clear(set,N);
	printf("%d in set is %d\n",N,bitset_test(set,N));

	N=100;
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("set %d\n",N);
	bitset_set(set,N);
	printf("%d in set is %d\n",10,bitset_test(set,10));
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("clear %d\n",N);
	bitset_clear(set,N);
	printf("%d in set is %d\n",N,bitset_test(set,N));

	N=200;
	printf("%d in set is %d\n",N,bitset_test(set,N));
	bitset_fprint(stdout,set);
	printf("set %d\n",N);
	bitset_set(set,N);
	bitset_fprint(stdout,set);
	printf("%d in set is %d\n",10,bitset_test(set,10));
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("clear %d\n",N);
	bitset_clear(set,N);
	printf("%d in set is %d\n",N,bitset_test(set,N));
	bitset_fprint(stdout,set);
	printf("\n");

	N=1000000;
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("set %d\n",N);
	bitset_set(set,N);
	printf("%d in set is %d\n",10,bitset_test(set,10));
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("clear %d\n",N);
	bitset_clear(set,N);
	printf("%d in set is %d\n",N,bitset_test(set,N));

	N=10000;
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("set %d\n",N);
	bitset_set(set,N);
	printf("%d in set is %d\n",10,bitset_test(set,10));
	printf("%d in set is %d\n",N,bitset_test(set,N));
	printf("clear %d\n",N);
	bitset_clear(set,N);
	printf("%d in set is %d\n",N,bitset_test(set,N));

    printf("setting 5 and 60\n");
	bitset_set(set,5);
	bitset_set(set,60);
	for(i=0;i<80;i++) printf("%s",bitset_test(set,i)?"1":"0");
	printf("\n");
	
	
	N=1222333;
	printf("set %d\n",N);
	bitset_set(set,N);
	
	printf("set:{");
	for(element_t e=0;bitset_next_set(set,&e);e++){
	    printf(" %u",e);
	}
	printf(" }\n");
	
	bitset_destroy(set);
}
Beispiel #19
0
/* This is a complex, recursive function to determine the cost for
 * calculating a condition after any still-needed variables have been
 * generated.  Cost is measured in terms of the anticipated number of
 * generated new variable sets, as provided by "*float" annotations
 * on generator and condition lines.
 *
 * Call this with a condition and varsneeded.  The soln_xxx fields will
 * be filled with the requested information, namely the total cost
 * and the generators needed to get there.  The soln_generators bitset
 * is assumed to already exist.
 *
 * This function may not always be able to determine a solution; this
 * can be the case if variables are mentioned in conditions but not in
 * generators, for instance.  In such situations, the function returns
 * false.  It is considered a success if all variables that are needed
 * for a condition are resolved by at least one generator.
 *
 * This is an important function when determining the "path of least
 * resistence" from any generator activity; the least costly condition
 * will always be calculated first, then the calculations are redone,
 * and what is then the least will be selected, and so on.  The
 * generators required will be inserted into the path before their
 * dependent conditions, in the order of least-costly ones first.
 *
 * This is a rather heavy form of analysis, but it is executed only
 * once, at startup of the environment.  After that, the SyncRepl
 * updates can ripple through in great speed.  Note that the complexity
 * and time delays of these procedures rise with the (usually modest)
 * degree of interrelationships between generators and conditions.
 */
bool cnd_get_min_total_cost (struct condition *cc, bitset_t *varsneeded,
				float *soln_mincost,
				bitset_t *soln_generators) {
	bool have_soln = false;
	float soln_mincost;
	varnum_t v, v_max;
	gennum_t g, g_max;
	//
	// Allocate bitsets that will be used while cycling, but not
	// across recursive uses.  To that and, a pile or pool of
	// bitsets could come in handy...  TODO: Optimisation
	//
	bitset_t *cand_varsneeded = bitset_new (varsneeded->type);
	bitset_t *cand_generators = bitset_new (soln_generators->type);
	//
	// If there is no need for further variables to calculate this
	// condition, then terminate recursion on this function.  There
	// will be no requirement to include a generator, and so there
	// will be no generator-incurred expenses.  There will only be
	// the cost of the condition itself, which must still compare
	// with other conditions that might be tighter.
	//
	if (bitset_isempty (varsneeded)) {
		/* Recursion ends, so neither generators nor their cost */
		bitset_empty (out_generators);
		return cc->cost;
	}
	//
	// Iterate over the variables that will need to be generated.
	// For each, iterate over the generators producing it.
	// See how this reduces the variable need, and recurse.
	//
	v_max = bitset_max (varsneeded);
	for (v=0; v<v_max; v++) {
		//
		// Skip this loop iteration if v is not actually needed.
		//
		if (!bitset_test (varsneeded, v)) {
			continue;
		}
		//
		// Iterate over generators for this variable.
		// Note that there may be none left?
		//
		bitset_t *vargenerators;
		vargenerators = var_share_generators (cc->vartab, v);
		g_max = bitset_max (vargenerators);
		if (g_max = BITNUM_BAD) {
			// Apparently, there are no generators for v
			// Skip for-loop (and trouble looping to BITNUM_BAD).
			continue;
		}
		for (g=0; g<g_max; g++) {
			bitset_t *cand_generators = NULL;
			bitset_t *generatorvars;
			float cand_cost;
			//
			// Reduce the variable need.
			//
			cand_varsneeded = bitset_copy (varsneeded);
			generatorvars = gen_share_variables (v);
			bitset_subtract (cand_varsneeded, generatorvars);
			//
			// Determine the cost for generating the remainder.
			//
			if (!cnd_get_cost_total (
					cc, cand_varsneeded,
					&cand_cost, cand_generators)) {
				continue;
			}
			cand_mincost *= generator_cost (g);
			if (have_soln && (cand_cost > soln_mincost)) {
				continue;
			}
			tmp_generators = soln_generators;
			soln_generators = cand_generators;
			cand_generators = tmp_generators; // Reuse in loops
			bitset_set (soln_generators, g);
			soln_mincost = cand_mincost;
			have_soln = true;
		}
	}
	//
	// Cleanup temporary allocations.
	//
	bitset_destroy (cand_varsneeded);
	bitset_destroy (cand_generators);
	//
	// Collect results.  Return success only if we do indeed have
	// found a solution.
	//
	return have_soln;
}
Beispiel #20
0
static void
print_reductions (FILE *out, int level, state *s)
{
  transitions *trans = s->transitions;
  reductions *reds = s->reductions;
  rule *default_reduction = NULL;
  int report = false;
  int i, j;

  if (reds->num == 0)
    {
      xml_puts (out, level, "<reductions/>");
      return;
    }

  if (yydefact[s->number] != 0)
    default_reduction = &rules[yydefact[s->number] - 1];

  bitset_zero (no_reduce_set);
  FOR_EACH_SHIFT (trans, i)
    bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
  for (i = 0; i < s->errs->num; ++i)
    if (s->errs->symbols[i])
      bitset_set (no_reduce_set, s->errs->symbols[i]->number);

  if (default_reduction)
    report = true;

  if (reds->lookahead_tokens)
    for (i = 0; i < ntokens; i++)
      {
        bool count = bitset_test (no_reduce_set, i);

        for (j = 0; j < reds->num; ++j)
          if (bitset_test (reds->lookahead_tokens[j], i))
            {
              if (! count)
                {
                  if (reds->rules[j] != default_reduction)
                    report = true;
                  count = true;
                }
              else
                {
                  report = true;
                }
            }
      }

  /* Nothing to report. */
  if (!report)
    {
      xml_puts (out, level, "<reductions/>");
      return;
    }

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

  /* Report lookahead tokens (or $default) and reductions.  */
  if (reds->lookahead_tokens)
    for (i = 0; i < ntokens; i++)
      {
        bool defaulted = false;
        bool count = bitset_test (no_reduce_set, i);

        for (j = 0; j < reds->num; ++j)
          if (bitset_test (reds->lookahead_tokens[j], i))
            {
              if (! count)
                {
                  if (reds->rules[j] != default_reduction)
                    print_reduction (out, level + 1, symbols[i]->tag,
                                     reds->rules[j], true);
                  else
                    defaulted = true;
                  count = true;
                }
              else
                {
                  if (defaulted)
                    print_reduction (out, level + 1, symbols[i]->tag,
                                     default_reduction, true);
                  defaulted = false;
                  print_reduction (out, level + 1, symbols[i]->tag,
                                   reds->rules[j], false);
                }
            }
      }

  if (default_reduction)
    print_reduction (out, level + 1,
                     "$default", default_reduction, true);

  xml_puts (out, level, "</reductions>");
}
Beispiel #21
0
static void
print_reductions (FILE *out, state *s)
{
  transitions *trans = s->transitions;
  reductions *reds = s->reductions;
  rule *default_rule = NULL;
  size_t width = 0;
  int i, j;

  if (reds->num == 0)
    return;

  default_rule = state_default_rule (s);

  bitset_zero (shift_set);
  FOR_EACH_SHIFT (trans, i)
    bitset_set (shift_set, TRANSITION_SYMBOL (trans, i));

  /* Compute the width of the look-ahead token column.  */
  if (default_rule)
    width = strlen (_("$default"));

  if (reds->look_ahead_tokens)
    for (i = 0; i < ntokens; i++)
      {
	bool count = bitset_test (shift_set, i);

	for (j = 0; j < reds->num; ++j)
	  if (bitset_test (reds->look_ahead_tokens[j], i))
	    {
	      if (! count)
		{
		  if (reds->rules[j] != default_rule)
		    max_length (&width, symbols[i]->tag);
		  count = true;
		}
	      else
		{
		  max_length (&width, symbols[i]->tag);
		}
	    }
      }

  /* Nothing to report. */
  if (!width)
    return;

  fputc ('\n', out);
  width += 2;

  /* Report look-ahead tokens (or $default) and reductions.  */
  if (reds->look_ahead_tokens)
    for (i = 0; i < ntokens; i++)
      {
	bool defaulted = false;
	bool count = bitset_test (shift_set, i);

	for (j = 0; j < reds->num; ++j)
	  if (bitset_test (reds->look_ahead_tokens[j], i))
	    {
	      if (! count)
		{
		  if (reds->rules[j] != default_rule)
		    print_reduction (out, width,
				     symbols[i]->tag,
				     reds->rules[j], true);
		  else
		    defaulted = true;
		  count = true;
		}
	      else
		{
		  if (defaulted)
		    print_reduction (out, width,
				     symbols[i]->tag,
				     default_rule, true);
		  defaulted = false;
		  print_reduction (out, width,
				   symbols[i]->tag,
				   reds->rules[j], false);
		}
	    }
      }

  if (default_rule)
    print_reduction (out, width,
		     _("$default"), default_rule, true);
}
Beispiel #22
0
bool
reduce_token_unused_in_grammar (symbol_number i)
{
  aver (i < ntokens);
  return !bitset_test (V, i) && !bitset_test (V1, i);
}
Beispiel #23
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 #24
0
static void
inaccessable_symbols (void)
{
  bitset Vp, Vs, Pp;

  /* Find out which productions are reachable and which symbols are
     used.  Starting with an empty set of productions and a set of
     symbols which only has the start symbol in it, iterate over all
     productions until the set of productions remains unchanged for an
     iteration.  For each production which has a LHS in the set of
     reachable symbols, add the production to the set of reachable
     productions, and add all of the nonterminals in the RHS of the
     production to the set of reachable symbols.

     Consider only the (partially) reduced grammar which has only
     nonterminals in N and productions in P.

     The result is the set P of productions in the reduced grammar,
     and the set V of symbols in the reduced grammar.

     Although this algorithm also computes the set of terminals which
     are reachable, no terminal will be deleted from the grammar. Some
     terminals might not be in the grammar but might be generated by
     semantic routines, and so the user might want them available with
     specified numbers.  (Is this true?)  However, the nonreachable
     terminals are printed (if running in verbose mode) so that the
     user can know.  */

  Vp = bitset_create (nsyms, BITSET_FIXED);
  Pp = bitset_create (nrules, BITSET_FIXED);

  /* If the start symbol isn't useful, then nothing will be useful. */
  if (bitset_test (N, accept->number - ntokens))
    {
      bitset_set (V, accept->number);

      while (1)
        {
          rule_number r;
          bitset_copy (Vp, V);
          for (r = 0; r < nrules; r++)
            {
              if (!bitset_test (Pp, r)
                  && bitset_test (P, r)
                  && bitset_test (V, rules[r].lhs->number))
                {
                  item_number *rhsp;
                  for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++)
                    if (ISTOKEN (*rhsp) || bitset_test (N, *rhsp - ntokens))
                      bitset_set (Vp, *rhsp);
                  bitset_set (Pp, r);
                }
            }
          if (bitset_equal_p (V, Vp))
            break;
          Vs = Vp;
          Vp = V;
          V = Vs;
        }
    }

  bitset_free (V);
  V = Vp;

  /* Tokens 0, 1, and 2 are internal to Bison.  Consider them useful. */
  bitset_set (V, endtoken->number);             /* end-of-input token */
  bitset_set (V, errtoken->number);             /* error token */
  bitset_set (V, undeftoken->number);           /* some undefined token */

  bitset_free (P);
  P = Pp;

  nuseful_productions = bitset_count (P);
  nuseless_productions = nrules - nuseful_productions;

  nuseful_nonterminals = 0;
  {
    symbol_number i;
    for (i = ntokens; i < nsyms; i++)
      if (bitset_test (V, i))
        nuseful_nonterminals++;
  }
  nuseless_nonterminals = nvars - nuseful_nonterminals;

  /* A token that was used in %prec should not be warned about.  */
  {
    rule_number r;
    for (r = 0; r < nrules; ++r)
      if (rules[r].precsym != 0)
        bitset_set (V1, rules[r].precsym->number);
  }
}
Beispiel #25
0
void set2_reduce_strong(lts_t lts){
	int *map,count,*newmap,i,*tmp,iter,setcount,j,set;
	bitset_t has_repr;

	has_repr=bitset_create(8,16);
	lts_uniq(lts);
	lts_sort(lts);
	lts_set_type(lts,LTS_BLOCK);
	map=(int*)malloc(sizeof(int)*lts->states);
	newmap=(int*)malloc(sizeof(int)*lts->states);
	if (!map || !newmap || !has_repr) Fatal(1,1,"out of memory");
	for(i=0;i<lts->states;i++){
		map[i]=0;
	}
	count=1;
	iter=0;
	for(;;){
		SetClear(-1);
		iter++;
		setcount=0;
		for(i=0;i<lts->states;i++){
			set=EMPTY_SET;
			for(j=lts->begin[i];j<lts->begin[i+1];j++){
				set=SetInsert(set,lts->label[j],map[lts->dest[j]]);
			}
			newmap[i]=set;
			if (!bitset_test(has_repr,set)){
				bitset_set(has_repr,set);
				setcount++;
			}
		}
		Warning(2,"count is %d",setcount);
		if(count==setcount) break;
		bitset_clear_all(has_repr);
		count=setcount;
		tmp=map;
		map=newmap;
		newmap=tmp;
	}
	setcount=0;
	for(i=0;i<lts->states;i++){
		newmap[i]=SetGetTag(map[i]);
		if (newmap[i]<0) {
			SetSetTag(map[i],setcount);
			newmap[i]=setcount;
			setcount++;
		}
	}
	free(map);
	map=newmap;
	Warning(2,"final count is %d",setcount);
	SetFree();
	lts_set_type(lts,LTS_LIST);
	lts->root=map[lts->root];
        lts->root2=map[lts->root2];
	for(i=0;i<lts->transitions;i++){
		lts->src[i]=map[lts->src[i]];
		lts->dest[i]=map[lts->dest[i]];
	}
	lts->states=count;
	lts_uniq(lts);
	free(map);
	bitset_destroy(has_repr);
	Warning(1,"reduction took %d iterations",iter);
}
Beispiel #26
0
static
void test_get_set()
{
	header();

	struct bitset bm;
	bitset_create(&bm, realloc);

	const size_t NUM_SIZE = (size_t) 1 << 14;
	size_t *nums = malloc(NUM_SIZE * sizeof(size_t));

	printf("Generating test set... ");
	for(size_t i = 0; i < NUM_SIZE; i++) {
		nums[i] = rand();
	}
	printf("ok\n");

	printf("Settings bits... ");
	for(size_t i = 0; i < NUM_SIZE; i++) {
		fail_if(bitset_set(&bm, nums[i]) < 0);
	}
	printf("ok\n");

	printf("Checking bits... ");
	shuffle(nums, NUM_SIZE);
	for(size_t i = 0; i < NUM_SIZE; i++) {
		fail_unless(bitset_test(&bm, nums[i]));
	}
	printf("ok\n");

	printf("Unsetting random bits... ");
	shuffle(nums, NUM_SIZE);
	for(size_t i = 0; i < NUM_SIZE; i++) {
		if (nums[i] % 5 == 0) {
			fail_if(bitset_clear(&bm, nums[i]) < 0);
			// printf("Clear :%zu\n", nums[i]);
			fail_if(bitset_test(&bm, nums[i]));
		}
	}
	printf("ok\n");

	printf("Checking set bits... ");
	shuffle(nums, NUM_SIZE);
	for(size_t i = 0; i < NUM_SIZE; i++) {
		if (nums[i] % 5 == 0) {
			continue;
		}

		if (!bitset_test(&bm, nums[i])) {
			printf("Fail :%zu\n", nums[i]);
		}
		fail_unless(bitset_test(&bm, nums[i]));
	}
	printf("ok\n");

	printf("Checking all bits... ");
	qsort(nums, NUM_SIZE, sizeof(size_t), size_compator);

	size_t *pn = nums;

	size_t i_max = (size_t) 1 << 14;
	if (i_max > RAND_MAX) {
		i_max = RAND_MAX;
	}

	for(size_t i = 0; i < i_max; i++) {
		if (*pn < SIZE_MAX && *pn == i) {
			fail_unless(bitset_test(&bm, *pn));
			pn++;
		} else {
			fail_if(bitset_test(&bm, i));
		}
	}
	printf("ok\n");


	printf("Unsetting all bits... ");
	shuffle(nums, NUM_SIZE);
	for(size_t i = 0; i < NUM_SIZE; i++) {
		if (nums[i] == SIZE_MAX) {
			continue;
		}

		fail_if(bitset_clear(&bm, nums[i]) < 0);
	}
	printf("ok\n");


	printf("Checking all bits... ");
	for(size_t i = 0; i < i_max; i++) {
		fail_if(bitset_test(&bm, i));
	}
	printf("ok\n");

	free(nums);

	bitset_destroy(&bm);

	footer();
}
Beispiel #27
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);
    }
}
Beispiel #28
0
bool char_bitset_test(CharBitSet *b, unsigned char i)
{
    return bitset_test((BitSet *)b, i);
}
Beispiel #29
0
static void
print_reductions (FILE *out, state *s)
{
  transitions *trans = s->transitions;
  reductions *reds = s->reductions;
  rule *default_reduction = NULL;
  size_t width = 0;
  int i, j;
  bool default_reduction_only = true;

  if (reds->num == 0)
    return;

  if (yydefact[s->number] != 0)
    default_reduction = &rules[yydefact[s->number] - 1];

  bitset_zero (no_reduce_set);
  FOR_EACH_SHIFT (trans, i)
    bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i));
  for (i = 0; i < s->errs->num; ++i)
    if (s->errs->symbols[i])
      bitset_set (no_reduce_set, s->errs->symbols[i]->number);

  /* Compute the width of the lookahead token column.  */
  if (default_reduction)
    width = strlen (_("$default"));

  if (reds->lookahead_tokens)
    for (i = 0; i < ntokens; i++)
      {
	bool count = bitset_test (no_reduce_set, i);

	for (j = 0; j < reds->num; ++j)
	  if (bitset_test (reds->lookahead_tokens[j], i))
	    {
	      if (! count)
		{
		  if (reds->rules[j] != default_reduction)
		    max_length (&width, symbols[i]->tag);
		  count = true;
		}
	      else
		{
		  max_length (&width, symbols[i]->tag);
		}
	    }
      }

  /* Nothing to report. */
  if (!width)
    return;

  fputc ('\n', out);
  width += 2;

  /* Report lookahead tokens (or $default) and reductions.  */
  if (reds->lookahead_tokens)
    for (i = 0; i < ntokens; i++)
      {
	bool defaulted = false;
	bool count = bitset_test (no_reduce_set, i);
        if (count)
          default_reduction_only = false;

	for (j = 0; j < reds->num; ++j)
	  if (bitset_test (reds->lookahead_tokens[j], i))
	    {
	      if (! count)
		{
		  if (reds->rules[j] != default_reduction)
                    {
                      default_reduction_only = false;
                      print_reduction (out, width,
                                       symbols[i]->tag,
                                       reds->rules[j], true);
                    }
		  else
		    defaulted = true;
		  count = true;
		}
	      else
		{
                  default_reduction_only = false;
		  if (defaulted)
		    print_reduction (out, width,
				     symbols[i]->tag,
				     default_reduction, true);
		  defaulted = false;
		  print_reduction (out, width,
				   symbols[i]->tag,
				   reds->rules[j], false);
		}
	    }
      }

  if (default_reduction)
    {
      char *default_reductions =
        muscle_percent_define_get ("lr.default-reductions");
      print_reduction (out, width, _("$default"), default_reduction, true);
      aver (0 == strcmp (default_reductions, "most")
            || (0 == strcmp (default_reductions, "consistent")
                && default_reduction_only)
            || (reds->num == 1 && reds->rules[0]->number == 0));
      free (default_reductions);
    }
}