/* IELR main implementation.
Copyright (C) 2009-2015, 2018-2021 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 . */
#include
#include "ielr.h"
#include "system.h"
#include
#include
#include "AnnotationList.h"
#include "derives.h"
#include "getargs.h"
#include "lalr.h"
#include "muscle-tab.h"
#include "nullable.h"
#include "relation.h"
#include "state.h"
#include "symtab.h"
/** Records the value of the \%define variable lr.type. */
typedef enum
{
LR_TYPE__LR0,
LR_TYPE__LALR,
LR_TYPE__IELR,
LR_TYPE__CANONICAL_LR
} LrType;
/* The user's requested LR type. */
static LrType
lr_type_get (void)
{
char *type = muscle_percent_define_get ("lr.type");
LrType res;
if (STREQ (type, "lr""(0)"))
res = LR_TYPE__LR0;
else if (STREQ (type, "lalr"))
res = LR_TYPE__LALR;
else if (STREQ (type, "ielr"))
res = LR_TYPE__IELR;
else if (STREQ (type, "canonical-lr"))
res = LR_TYPE__CANONICAL_LR;
else
{
aver (false);
abort ();
}
free (type);
return res;
}
/**
* \post:
* - \c result = a new \c bitset of size \c ::nritems such that any bit \c i
* is set iff ritem[i] is a nonterminal after which all ritems in
* the same RHS are nullable nonterminals. In other words, the follows of
* a goto on ritem[i] include the lookahead set of the item.
*/
static bitset
ielr_compute_ritem_sees_lookahead_set (void)
{
bitset result = bitset_create (nritems, BITSET_FIXED);
int i = nritems-1;
while (0 < i)
{
--i;
// Walk the RHS right to left, as long as it's symbol,
// nonterminal, nullable.
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--);
// Flush the remainder of the RHS.
while (!item_number_is_rule_number (ritem[i]) && 0 < i)
--i;
}
if (trace_flag & trace_ielr)
{
fprintf (stderr, "ritem_sees_lookahead_set (indexes of ritems): ");
bitset_dump (stderr, result);
fprintf (stderr, "\n");
}
return result;
}
/**
* \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.
* - (*edgesp)[i] points to a \c goto_number array of size
* (*edge_countsp)[i]+1.
* - 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);
for (goto_number i = 0; i < ngotos; ++i)
(*edge_countsp)[i] = 0;
for (goto_number i = 0; i < ngotos; ++i)
{
int nsources = 0;
{
for (rule **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)
relation_print ("internal_follow_edges", *edgesp, ngotos, NULL, stderr);
}
/**
* \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.
* - (*follow_kernel_itemsp)[i][j] 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, (*follow_kernel_itemsp)[i][j] 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;
for (state_number 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);
}
for (goto_number i = 0; i < ngotos; ++i)
{
size_t nitems = states[from_state[i]]->nitems;
item_index *items = states[from_state[i]]->items;
for (size_t 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);
}
}
/**
* \pre
* - \c *edgesp and \c edge_counts were computed by
* \c ielr_compute_internal_follow_edges.
* \post
* - \c *always_followsp is a new \c bitsetv with \c ngotos rows and
* \c ntokens columns.
* - (*always_followsp)[i][j] is set iff token \c j is an always
* follow (that is, it's computed by internal and successor edges) of goto
* \c i.
* - Rows of \c *edgesp have been realloc'ed and extended to include
* successor follow edges. \c edge_counts has not been updated.
*/
static void
ielr_compute_always_follows (goto_number ***edgesp,
int const edge_counts[],
bitsetv *always_followsp)
{
*always_followsp = bitsetv_create (ngotos, ntokens, BITSET_FIXED);
{
goto_number *edge_array = xnmalloc (ngotos, sizeof *edge_array);
for (goto_number i = 0; i < ngotos; ++i)
{
goto_number nedges = edge_counts[i];
{
int j;
transitions *trans = states[to_state[i]]->transitions;
FOR_EACH_SHIFT (trans, j)
bitset_set ((*always_followsp)[i], TRANSITION_SYMBOL (trans, j));
for (; j < trans->num; ++j)
{
symbol_number sym = TRANSITION_SYMBOL (trans, j);
if (nullable[sym - ntokens])
edge_array[nedges++] = map_goto (to_state[i], sym);
}
}
if (nedges - edge_counts[i])
{
(*edgesp)[i] =
xnrealloc ((*edgesp)[i], nedges + 1, sizeof *(*edgesp)[i]);
memcpy ((*edgesp)[i] + edge_counts[i], edge_array + edge_counts[i],
(nedges - edge_counts[i]) * sizeof *(*edgesp)[i]);
(*edgesp)[i][nedges] = END_NODE;
}
}
free (edge_array);
}
relation_digraph (*edgesp, ngotos, *always_followsp);
if (trace_flag & trace_ielr)
{
relation_print ("always follow edges", *edgesp, ngotos, NULL, stderr);
fprintf (stderr, "always_follows:\n");
debug_bitsetv (*always_followsp);
}
}
/**
* \post
* - \c result is a new array of size \c ::nstates.
* - result[i] is an array of pointers to the predecessor
* state's of state \c i.
* - The last element of such an array is \c NULL.
*/
static state ***
ielr_compute_predecessors (void)
{
int *predecessor_counts = xnmalloc (nstates, sizeof *predecessor_counts);
state ***res = xnmalloc (nstates, sizeof *res);
for (state_number i = 0; i < nstates; ++i)
predecessor_counts[i] = 0;
for (state_number i = 0; i < nstates; ++i)
for (int j = 0; j < states[i]->transitions->num; ++j)
++predecessor_counts[states[i]->transitions->states[j]->number];
for (state_number i = 0; i < nstates; ++i)
{
res[i] = xnmalloc (predecessor_counts[i]+1, sizeof *res[i]);
res[i][predecessor_counts[i]] = NULL;
predecessor_counts[i] = 0;
}
for (state_number i = 0; i < nstates; ++i)
for (int j = 0; j < states[i]->transitions->num; ++j)
{
state_number k = states[i]->transitions->states[j]->number;
res[k][predecessor_counts[k]++] = states[i];
}
free (predecessor_counts);
return res;
}
/**
* \post
* - \c *follow_kernel_itemsp and \c *always_followsp were computed by
* \c ielr_compute_follow_kernel_items and
* \c ielr_compute_always_follows.
* - Iff predecessorsp != NULL, then \c *predecessorsp was computed
* by \c ielr_compute_predecessors.
*/
static void
ielr_compute_auxiliary_tables (bitsetv *follow_kernel_itemsp,
bitsetv *always_followsp,
state ****predecessorsp)
{
goto_number **edges;
int *edge_counts;
{
bitset ritem_sees_lookahead_set = ielr_compute_ritem_sees_lookahead_set ();
ielr_compute_internal_follow_edges (ritem_sees_lookahead_set,
&edges, &edge_counts);
ielr_compute_follow_kernel_items (ritem_sees_lookahead_set, edges,
follow_kernel_itemsp);
bitset_free (ritem_sees_lookahead_set);
}
ielr_compute_always_follows (&edges, edge_counts, always_followsp);
for (int i = 0; i < ngotos; ++i)
free (edges[i]);
free (edges);
free (edge_counts);
if (predecessorsp)
*predecessorsp = ielr_compute_predecessors ();
}
/**
* \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])
{
item_lookahead_sets[s->number] =
xnmalloc (s->nitems, sizeof item_lookahead_sets[s->number][0]);
for (size_t 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. */
const rule *r = item_rule (&ritem[s->items[item]]);
const bool is_successor_of_initial_item
= rule_is_initial (r) && &ritem[s->items[item]] == r->rhs + 1;
aver (!is_successor_of_initial_item);
if (!is_successor_of_initial_item)
{
/* If the LHS symbol of this item isn't known (because this is a
top-level invocation), go get it. */
if (!lhs)
lhs = r->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]))
{
aver (lhs != acceptsymbol->content->number);
for (state **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
{
for (state **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);
}
/**
* \pre
* - \c follow_kernel_items, \c always_follows, and \c predecessors
* were computed by \c ielr_compute_auxiliary_tables.
* \post
* - Each of *inadequacy_listsp and *annotation_listsp
* points to a new array of size \c ::nstates.
* - For 0 <= i < ::nstates:
* - (*inadequacy_listsp)[i] contains the \c InadequacyList head
* node for states[i].
* - (*annotation_listsp)[i] contains the \c AnnotationList head
* node for states[i].
* - *max_annotationsp is the maximum number of annotations per
* state.
*/
static void
ielr_compute_annotation_lists (bitsetv follow_kernel_items,
bitsetv always_follows, state ***predecessors,
AnnotationIndex *max_annotationsp,
InadequacyList ***inadequacy_listsp,
AnnotationList ***annotation_listsp,
struct obstack *annotations_obstackp)
{
bitset **item_lookahead_sets =
xnmalloc (nstates, sizeof *item_lookahead_sets);
AnnotationIndex *annotation_counts =
xnmalloc (nstates, sizeof *annotation_counts);
ContributionIndex max_contributions = 0;
int total_annotations = 0;
*inadequacy_listsp = xnmalloc (nstates, sizeof **inadequacy_listsp);
*annotation_listsp = xnmalloc (nstates, sizeof **annotation_listsp);
for (state_number i = 0; i < nstates; ++i)
{
item_lookahead_sets[i] = NULL;
(*inadequacy_listsp)[i] = NULL;
(*annotation_listsp)[i] = NULL;
annotation_counts[i] = 0;
}
{
InadequacyListNodeCount inadequacy_list_node_count = 0;
for (state_number i = 0; i < nstates; ++i)
AnnotationList__compute_from_inadequacies (
states[i], follow_kernel_items, always_follows, predecessors,
item_lookahead_sets, *inadequacy_listsp, *annotation_listsp,
annotation_counts, &max_contributions, annotations_obstackp,
&inadequacy_list_node_count);
}
*max_annotationsp = 0;
for (state_number i = 0; i < nstates; ++i)
{
if (annotation_counts[i] > *max_annotationsp)
*max_annotationsp = annotation_counts[i];
total_annotations += annotation_counts[i];
}
if (trace_flag & trace_ielr)
{
for (state_number i = 0; i < nstates; ++i)
{
fprintf (stderr, "Inadequacy annotations for state %d:\n", i);
AnnotationList__debug ((*annotation_listsp)[i],
states[i]->nitems, 2);
}
fprintf (stderr, "Number of LR(0)/LALR(1) states: %d\n", nstates);
fprintf (stderr, "Average number of annotations per state: %f\n",
(float)total_annotations/nstates);
fprintf (stderr, "Max number of annotations per state: %d\n",
*max_annotationsp);
fprintf (stderr, "Max number of contributions per annotation: %d\n",
max_contributions);
}
for (state_number i = 0; i < nstates; ++i)
if (item_lookahead_sets[i])
{
for (size_t j = 0; j < states[i]->nitems; ++j)
if (item_lookahead_sets[i][j])
bitset_free (item_lookahead_sets[i][j]);
free (item_lookahead_sets[i]);
}
free (item_lookahead_sets);
free (annotation_counts);
}
typedef struct state_list
{
struct state_list *next;
state *state;
/** Has this state been recomputed as a successor of another state? */
bool recomputedAsSuccessor;
/**
* \c NULL iff all lookahead sets are empty. lookaheads[i] = NULL
* iff the lookahead set on item \c i is empty.
*/
bitset *lookaheads;
/**
* nextIsocore is the next state in a circularly linked-list of all states
* with the same core. The one originally computed by generate_states in
* lr0.c is lr0Isocore.
*/
struct state_list *lr0Isocore;
struct state_list *nextIsocore;
} state_list;
MAYBE_UNUSED static void
state_list_print_ (const state_list *s, FILE *out, const char *sep)
{
if (s)
{
fprintf (out, "%s%d", sep, s->state->number);
state_list_print_ (s->next, out, " ");
}
}
MAYBE_UNUSED static void
state_list_print (const state_list *s, FILE *out)
{
fprintf (out, "{");
state_list_print_ (s, out, "");
fprintf (out, "}");
}
/**
* \pre
* - \c follow_kernel_items and \c always_follows were computed by
* \c ielr_compute_auxiliary_tables.
* - n->class = nterm_sym.
* \post
* - \c follow_set contains the follow set for the goto on nonterminal \c n
* in state \c s based on the lookaheads stored in s->lookaheads.
*/
static void
ielr_compute_goto_follow_set (bitsetv follow_kernel_items,
bitsetv always_follows, state_list *s,
sym_content *n, bitset follow_set)
{
goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number);
bitset_copy (follow_set, always_follows[n_goto]);
if (s->lookaheads)
{
bitset_iterator biter_item;
bitset_bindex item;
BITSET_FOR_EACH (biter_item, follow_kernel_items[n_goto], item, 0)
if (s->lookaheads[item])
bitset_or (follow_set, follow_set, s->lookaheads[item]);
}
}
/**
* \pre
* - \c follow_kernel_items and \c always_follows were computed by
* \c ielr_compute_auxiliary_tables.
* - \c lookahead_filter was computed by
* \c AnnotationList__computeLookaheadFilter for the original LR(0) isocore
* of \c t.
* - The number of rows in \c lookaheads is at least the number of items in
* \c t, and the number of columns is \c ::ntokens.
* \post
* - lookaheads[i][j] is set iff both:
* - lookahead_filter[i][j] is set.
* - The isocore of \c t that will be the transition successor of \c s will
* inherit from \c s token \c j into the lookahead set of item \c i.
*/
static void
ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows,
state_list *s, state *t, bitsetv lookahead_filter,
bitsetv lookaheads)
{
size_t s_item = 0;
bitsetv_zero (lookaheads);
for (size_t t_item = 0; t_item < t->nitems; ++t_item)
{
/* If this kernel item is the beginning of a RHS, it must be the
kernel item in the start state, but t is supposed to be a successor
state. If, instead, this kernel item is the successor of the start
state's kernel item, the lookahead set is empty. This second case is
a special case to avoid the - 2 below, but the next successor can be
handled fine without special casing it. */
aver (t->items[t_item] != 0);
const rule *r = item_rule (&ritem[t->items[t_item]]);
const bool is_successor_of_initial_item
= rule_is_initial (r) && &ritem[t->items[t_item]] == r->rhs + 1;
if (!is_successor_of_initial_item
&& !bitset_empty_p (lookahead_filter[t_item]))
{
/* Is this kernel item next to the beginning of the RHS? */
if (item_number_is_rule_number (ritem[t->items[t_item] - 2]))
ielr_compute_goto_follow_set (
follow_kernel_items, always_follows, s,
r->lhs,
lookaheads[t_item]);
else if (s->lookaheads)
{
/* We don't have to start the s item search at the beginning
every time because items from both states are sorted by their
indices in ritem. */
for (; s_item < s->state->nitems; ++s_item)
if (s->state->items[s_item] == t->items[t_item] - 1)
break;
aver (s_item != s->state->nitems);
if (s->lookaheads[s_item])
bitset_copy (lookaheads[t_item], s->lookaheads[s_item]);
}
bitset_and (lookaheads[t_item],
lookaheads[t_item], lookahead_filter[t_item]);
}
}
}
/**
* \pre
* - \c follow_kernel_items and \c always_follows were computed by
* \c ielr_compute_auxiliary_tables.
* - Either:
* - annotation_lists = NULL and all bits in work2 are set.
* - \c annotation_lists was computed by \c ielr_compute_annotation_lists.
* - The number of rows in each of \c lookaheads and \c work2 is the maximum
* number of items in any state. The number of columns in each is
* \c ::ntokens.
* - \c lookaheads was computed by \c ielr_compute_lookaheads for \c t.
* - \c ::nstates is the total number of states, some not yet fully computed,
* in the list ending at \c *last_statep. It is at least the number of
* original LR(0) states.
* - The size of \c work1 is at least the number of annotations for the LR(0)
* isocore of \c t.
* \post
* - Either:
* - In the case that annotation_lists != NULL,
* lookaheads \@pre was merged with some isocore of \c t if
* permitted by the annotations for the original LR(0) isocore of \c t.
* If this changed the lookaheads in that isocore, those changes were
* propagated to all already computed transition successors recursively
* possibly resulting in the splitting of some of those successors.
* - In the case that annotation_lists = NULL,
* lookaheads \@pre was merged with some isocore of \c t if the
* isocore's lookahead sets were identical to those specified by
* lookaheads \@pre.
* - If no such merge was permitted, a new isocore of \c t containing
* lookaheads \@pre was appended to the state list whose
* previous tail was *last_statep \@pre and \c ::nstates was
* incremented. It was also appended to \c t's isocore list.
* - *tp = the isocore of \c t into which
* lookaheads \@pre was placed/merged.
* - \c lookaheads, \c work1, and \c work2 may have been altered.
*/
static void
ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows,
AnnotationList **annotation_lists, state *t,
bitsetv lookaheads, state_list **last_statep,
ContributionIndex work1[], bitsetv work2, state **tp)
{
state_list *lr0_isocore = t->state_list->lr0Isocore;
state_list **this_isocorep;
/* Determine whether there's an isocore of t with which these lookaheads can
be merged. */
{
if (annotation_lists)
{
AnnotationIndex ai;
AnnotationList *a;
for (ai = 0, a = annotation_lists[lr0_isocore->state->number];
a;
++ai, a = a->next)
work1[ai] =
AnnotationList__computeDominantContribution (
a, lr0_isocore->state->nitems, lookaheads, false);
}
for (this_isocorep = &t->state_list;
this_isocorep == &t->state_list || *this_isocorep != t->state_list;
this_isocorep = &(*this_isocorep)->nextIsocore)
{
if (!(*this_isocorep)->recomputedAsSuccessor)
break;
if (annotation_lists)
{
AnnotationIndex ai;
AnnotationList *a;
for (ai = 0, a = annotation_lists[lr0_isocore->state->number];
a;
++ai, a = a->next)
{
if (work1[ai] != ContributionIndex__none)
{
/* This isocore compatibility test depends on the fact
that, if the dominant contributions are the same for the
two isocores, then merging their lookahead sets will not
produce a state with a different dominant contribution.
*/
ContributionIndex ci =
AnnotationList__computeDominantContribution (
a, lr0_isocore->state->nitems,
(*this_isocorep)->lookaheads, false);
if (ci != ContributionIndex__none && work1[ai] != ci)
break;
}
}
if (!a)
break;
}
else
{
size_t i;
for (i = 0; i < t->nitems; ++i)
{
if (!(*this_isocorep)->lookaheads
|| !(*this_isocorep)->lookaheads[i])
{
if (!bitset_empty_p (lookaheads[i]))
break;
}
/* bitset_equal_p uses the size of the first argument,
so lookaheads[i] must be the second argument. */
else if (!bitset_equal_p ((*this_isocorep)->lookaheads[i],
lookaheads[i]))
break;
}
if (i == t->nitems)
break;
}
}
}
bool has_lookaheads = false;
for (size_t i = 0; i < lr0_isocore->state->nitems; ++i)
if (!bitset_empty_p (lookaheads[i]))
{
has_lookaheads = true;
break;
}
/* Merge with an existing isocore. */
if (this_isocorep == &t->state_list || *this_isocorep != t->state_list)
{
bool new_lookaheads = false;
*tp = (*this_isocorep)->state;
/* Merge lookaheads into the state and record whether any of them are
actually new. */
if (has_lookaheads)
{
if (!(*this_isocorep)->lookaheads)
{
(*this_isocorep)->lookaheads =
xnmalloc (t->nitems, sizeof (*this_isocorep)->lookaheads);
for (size_t i = 0; i < t->nitems; ++i)
(*this_isocorep)->lookaheads[i] = NULL;
}
for (size_t i = 0; i < t->nitems; ++i)
if (!bitset_empty_p (lookaheads[i]))
{
if (!(*this_isocorep)->lookaheads[i])
(*this_isocorep)->lookaheads[i] =
bitset_create (ntokens, BITSET_FIXED);
bitset_andn (lookaheads[i],
lookaheads[i], (*this_isocorep)->lookaheads[i]);
bitset_or ((*this_isocorep)->lookaheads[i],
lookaheads[i], (*this_isocorep)->lookaheads[i]);
if (!bitset_empty_p (lookaheads[i]))
new_lookaheads = true;
}
}
/* If new lookaheads were merged, propagate those lookaheads to the
successors, possibly splitting them. If *tp is being recomputed for
the first time, this isn't necessary because the main
ielr_split_states loop will handle the successors later. */
if (!(*this_isocorep)->recomputedAsSuccessor)
(*this_isocorep)->recomputedAsSuccessor = true;
else if (new_lookaheads)
{
/* When merging demands identical lookahead sets, it is impossible to
merge new lookaheads. */
aver (annotation_lists);
for (int i = 0; i < (*tp)->transitions->num; ++i)
{
state *t2 = (*tp)->transitions->states[i];
/* At any time, there's at most one state for which we have so
far initially recomputed only some of its successors in the
main ielr_split_states loop. Because we recompute successors
in order, we can just stop at the first such successor. Of
course, *tp might be a state some of whose successors have
been recomputed as successors of other states rather than as
successors of *tp. It's fine if we go ahead and propagate to
some of those. We'll propagate to them again (but stop when
we see nothing changes) and to the others when we reach *tp in
the main ielr_split_states loop later. */
if (!t2->state_list->recomputedAsSuccessor)
break;
AnnotationList__computeLookaheadFilter (
annotation_lists[t2->state_list->lr0Isocore->state->number],
t2->nitems, work2);
ielr_compute_lookaheads (follow_kernel_items, always_follows,
(*this_isocorep), t2, work2,
lookaheads);
/* FIXME: If splitting t2 here, it's possible that lookaheads
that had already propagated from *tp to t2 will be left in t2
after *tp has been removed as t2's predecessor:
- We're going to recompute all lookaheads in phase 4, so these
extra lookaheads won't appear in the final parser table.
- If t2 has just one annotation, then these extra lookaheads
cannot alter the dominating contribution to the associated
inadequacy and thus cannot needlessly prevent a future merge
of some new state with t2. We can be sure of this because:
- The fact that we're splitting t2 now means that some
predecessors (at least one) other than *tp must be
propagating contributions to t2.
- The fact that t2 was merged in the first place means that,
if *tp propagated any contributions, the dominating
contribution must be the same as that from those other
predecessors.
- Thus, if some new state to be merged with t2 in the future
proves to be compatible with the contributions propagated
by the other predecessors, it will also be compatible with
the contributions made by the extra lookaheads left behind
by *tp.
- However, if t2 has more than one annotation and these extra
lookaheads contribute to one of their inadequacies, it's
possible these extra lookaheads may needlessly prevent a
future merge with t2. For example:
- Let's say there's an inadequacy A that makes the split
necessary as follows:
- There's currently just one other predecessor and it
propagates to t2 some contributions to inadequacy A.
- The new lookaheads that we were attempting to propagate
from *tp to t2 made contributions to inadequacy A with a
different dominating contribution than those from that
other predecessor.
- The extra lookaheads either make no contribution to
inadequacy A or have the same dominating contribution as
the contributions from the other predecessor. Either
way, as explained above, they can't prevent a future
merge.
- Let's say there's an inadequacy B that causes the trouble
with future merges as follows:
- The extra lookaheads make contributions to inadequacy B.
- Those extra contributions did not prevent the original
merge to create t2 because the other predecessor
propagates to t2 no contributions to inadequacy B.
- Thus, those extra contributions may prevent a future
merge with t2 even though the merge would be fine if *tp
had not left them behind.
- Is the latter case common enough to worry about?
- Perhaps we should track all predecessors and iterate them
now to recreate t2 without those extra lookaheads. */
ielr_compute_state (follow_kernel_items, always_follows,
annotation_lists, t2, lookaheads,
last_statep, work1, work2,
&(*tp)->transitions->states[i]);
}
}
}
/* Create a new isocore. */
else
{
state_list *old_isocore = *this_isocorep;
(*last_statep)->next = *this_isocorep = xmalloc (sizeof **last_statep);
*last_statep = *this_isocorep;
(*last_statep)->state = *tp = state_new_isocore (t);
(*tp)->state_list = *last_statep;
(*last_statep)->recomputedAsSuccessor = true;
(*last_statep)->next = NULL;
(*last_statep)->lookaheads = NULL;
if (has_lookaheads)
{
(*last_statep)->lookaheads =
xnmalloc (t->nitems, sizeof (*last_statep)->lookaheads);
for (size_t i = 0; i < t->nitems; ++i)
{
if (bitset_empty_p (lookaheads[i]))
(*last_statep)->lookaheads[i] = NULL;
else
{
(*last_statep)->lookaheads[i] =
bitset_create (ntokens, BITSET_FIXED);
bitset_copy ((*last_statep)->lookaheads[i], lookaheads[i]);
}
}
}
(*last_statep)->lr0Isocore = lr0_isocore;
(*last_statep)->nextIsocore = old_isocore;
}
}
/**
* \pre
* - \c follow_kernel_items and \c always_follows were computed by
* \c ielr_compute_auxiliary_tables.
* - Either:
* - annotation_lists = NULL and max_annotations=0.
* - \c annotation_lists and \c max_annotations were computed by
* \c ielr_compute_annotation_lists.
* \post
* - \c ::states is of size \c ::nstates (which might be greater than
* ::nstates \@pre) and no longer contains any LR(1)-relative
* inadequacy. \c annotation_lists was used to determine state
* compatibility or, if annotation_lists = NULL, the canonical
* LR(1) state compatibility test was used.
* - If annotation_lists = NULL, reduction lookahead sets were
* computed in all states. tv_ielr_phase4 was pushed while they were
* computed from item lookahead sets.
*/
static void
ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows,
AnnotationList **annotation_lists,
AnnotationIndex max_annotations)
{
state_list *first_state;
state_list *last_state;
bitsetv lookahead_filter = NULL;
bitsetv lookaheads;
/* Set up state list and some reusable bitsets. */
{
size_t max_nitems = 0;
state_list **nodep = &first_state;
for (state_number i = 0; i < nstates; ++i)
{
*nodep = states[i]->state_list = last_state = xmalloc (sizeof **nodep);
(*nodep)->state = states[i];
(*nodep)->recomputedAsSuccessor = false;
(*nodep)->lookaheads = NULL;
(*nodep)->lr0Isocore = *nodep;
(*nodep)->nextIsocore = *nodep;
nodep = &(*nodep)->next;
if (states[i]->nitems > max_nitems)
max_nitems = states[i]->nitems;
}
*nodep = NULL;
lookahead_filter = bitsetv_create (max_nitems, ntokens, BITSET_FIXED);
if (!annotation_lists)
bitsetv_ones (lookahead_filter);
lookaheads = bitsetv_create (max_nitems, ntokens, BITSET_FIXED);
}
/* Recompute states. */
{
ContributionIndex *work = xnmalloc (max_annotations, sizeof *work);
for (state_list *this_state = first_state;
this_state;
this_state = this_state->next)
{
const state *s = this_state->state;
for (int i = 0; i < s->transitions->num; ++i)
{
state *t = s->transitions->states[i];
if (annotation_lists)
AnnotationList__computeLookaheadFilter (
annotation_lists[t->state_list->lr0Isocore->state->number],
t->nitems, lookahead_filter);
ielr_compute_lookaheads (follow_kernel_items, always_follows,
this_state, t, lookahead_filter,
lookaheads);
ielr_compute_state (follow_kernel_items, always_follows,
annotation_lists, t, lookaheads, &last_state,
work, lookahead_filter,
&s->transitions->states[i]);
}
}
free (work);
}
bitsetv_free (lookahead_filter);
bitsetv_free (lookaheads);
/* Store states back in the states array. */
states = xnrealloc (states, nstates, sizeof *states);
for (state_list *node = first_state; node; node = node->next)
states[node->state->number] = node->state;
/* In the case of canonical LR(1), copy item lookahead sets to reduction
lookahead sets. */
if (!annotation_lists)
{
timevar_push (tv_ielr_phase4);
initialize_LA ();
for (state_list *node = first_state; node; node = node->next)
if (!node->state->consistent)
{
size_t i = 0;
item_index *itemset = node->state->items;
for (size_t r = 0; r < node->state->reductions->num; ++r)
{
rule *this_rule = node->state->reductions->rules[r];
bitset lookahead_set =
node->state->reductions->lookaheads[r];
if (item_number_is_rule_number (*this_rule->rhs))
ielr_compute_goto_follow_set (follow_kernel_items,
always_follows, node,
this_rule->lhs, lookahead_set);
else if (node->lookaheads)
{
/* We don't need to start the kernel item search back at
i=0 because both items and reductions are sorted on rule
number. */
while (!item_number_is_rule_number (ritem[itemset[i]])
|| item_number_as_rule_number (ritem[itemset[i]])
!= this_rule->number)
{
++i;
aver (i < node->state->nitems);
}
if (node->lookaheads[i])
bitset_copy (lookahead_set, node->lookaheads[i]);
}
}
}
timevar_pop (tv_ielr_phase4);
}
/* Free state list. */
while (first_state)
{
state_list *node = first_state;
if (node->lookaheads)
{
for (size_t i = 0; i < node->state->nitems; ++i)
if (node->lookaheads[i])
bitset_free (node->lookaheads[i]);
free (node->lookaheads);
}
first_state = node->next;
free (node);
}
}
void
ielr (void)
{
LrType lr_type = lr_type_get ();
/* Phase 0: LALR(1). */
switch (lr_type)
{
case LR_TYPE__LR0:
timevar_push (tv_lalr);
set_goto_map ();
timevar_pop (tv_lalr);
return;
case LR_TYPE__CANONICAL_LR:
timevar_push (tv_lalr);
set_goto_map ();
timevar_pop (tv_lalr);
break;
case LR_TYPE__LALR:
timevar_push (tv_lalr);
lalr ();
bitsetv_free (goto_follows);
timevar_pop (tv_lalr);
return;
case LR_TYPE__IELR:
timevar_push (tv_lalr);
lalr ();
timevar_pop (tv_lalr);
break;
}
{
bitsetv follow_kernel_items;
bitsetv always_follows;
InadequacyList **inadequacy_lists = NULL;
AnnotationList **annotation_lists = NULL;
struct obstack annotations_obstack;
AnnotationIndex max_annotations = 0;
{
/* Phase 1: Compute Auxiliary Tables. */
state ***predecessors;
timevar_push (tv_ielr_phase1);
ielr_compute_auxiliary_tables (
&follow_kernel_items, &always_follows,
lr_type == LR_TYPE__CANONICAL_LR ? NULL : &predecessors);
timevar_pop (tv_ielr_phase1);
/* Phase 2: Compute Annotations. */
timevar_push (tv_ielr_phase2);
if (lr_type != LR_TYPE__CANONICAL_LR)
{
obstack_init (&annotations_obstack);
ielr_compute_annotation_lists (follow_kernel_items, always_follows,
predecessors, &max_annotations,
&inadequacy_lists, &annotation_lists,
&annotations_obstack);
for (state_number i = 0; i < nstates; ++i)
free (predecessors[i]);
free (predecessors);
bitsetv_free (goto_follows);
lalr_free ();
}
timevar_pop (tv_ielr_phase2);
}
/* Phase 3: Split States. */
timevar_push (tv_ielr_phase3);
{
state_number nstates_lr0 = nstates;
ielr_split_states (follow_kernel_items, always_follows,
annotation_lists, max_annotations);
if (inadequacy_lists)
for (state_number i = 0; i < nstates_lr0; ++i)
InadequacyList__delete (inadequacy_lists[i]);
}
free (inadequacy_lists);
if (annotation_lists)
obstack_free (&annotations_obstack, NULL);
free (annotation_lists);
bitsetv_free (follow_kernel_items);
bitsetv_free (always_follows);
timevar_pop (tv_ielr_phase3);
}
/* Phase 4: Compute Reduction Lookaheads. */
timevar_push (tv_ielr_phase4);
free (goto_map);
free (from_state);
free (to_state);
if (lr_type == LR_TYPE__CANONICAL_LR)
{
/* Reduction lookaheads are computed in ielr_split_states above
but are timed as part of phase 4. */
set_goto_map ();
}
else
{
lalr ();
bitsetv_free (goto_follows);
}
timevar_pop (tv_ielr_phase4);
}