/* IELR's inadequacy annotation list.
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 . */
#ifndef ANNOTATION_LIST_H_
# define ANNOTATION_LIST_H_
# include
# include "Sbitset.h"
# include "InadequacyList.h"
# include "state.h"
typedef int AnnotationIndex;
/**
* A node in a list of annotations on a particular LR(0) state. Each
* annotation records how isocores of that LR(0) state might contribute to an
* individual inadequacy, which might manifest in a different state. Don't
* break encapsulation by modifying the fields directly. Use the provided
* interface functions.
*/
typedef struct AnnotationList
{
/** The next node in the list or \c NULL if none. */
struct AnnotationList *next;
/** The \c InadequacyList node describing how this inadequacy manifests. */
InadequacyList *inadequacyNode;
/**
* List of how the "always", "never", and potential contributions of the
* inadequacy might be made by isocores of the annotated LR(0) state:
* - The number of rows is the number of contributions. That is,
* AnnotationList::inadequacyNode->contributionCount.
* - The token associated with contribution \c i is
* InadequacyList__getContributionToken (AnnotationList::inadequacyNode, i).
* - Iff AnnotationList::contributions[i] = NULL, contribution
* \c i is an "always" contribution. That is, for every isocore of the
* annotated LR(0) state, its core or the core of one its eventual
* successors will definitely make this contribution to the inadequacy.
* It may contribute by either:
* - Creating a shift of contribution i's token in the state
* that can manifest the inadequacy.
* - Propagating that token to the lookahead set of contribution
* i's reduction in the state that can manifest the
* inadequacy.
* - Otherwise:
* - The number of columns in AnnotationList::contributions[i]
* is the number of kernel items in any isocore of the annotated LR(0)
* state.
* - Iff AnnotationList::contributions[i] is empty, contribution
* \c i is a "never" contribution. That is, no isocore of the
* annotated LR(0) state can make this contribution to the inadequacy.
* - Otherwise, for each bit \c j that is set in
* AnnotationList::contributions[i], if the token associated
* with contribution \c i is present in the lookahead set of kernel
* item \c j of an isocore of the annotated LR(0) state, that isocore
* will make contribution \c i to the inadequacy by propagating the
* contribution's token to the lookahead set of the contribution's
* reduction in the state that can manifest the inadequacy.
*/
Sbitset contributions[1];
} AnnotationList;
/**
* \pre
* - s != NULL.
* - \c follow_kernel_items, \c always_follows, and \c predecessors were
* computed by \c ielr_compute_auxiliary_tables.
* - The size of each of \c annotation_lists and \c annotation_counts is
* \c ::nstates.
* - If no \c InadequacyList nodes are currently allocated for the
* parser tables to which \c s belongs, then it is best if
* *inadequacy_list_node_count is zero to avoid overflow.
* Otherwise, *inadequacy_list_node_count has not been
* modified by any function except
* \c AnnotationList__compute_from_inadequacies since the invocation
* of \c AnnotationList__compute_from_inadequacies that constructed
* the first of the \c InadequacyList nodes currently allocated for
* those parser tables.
* \post
* - inadequacy_lists[s->number] now describes all inadequacies that
* manifest in \c s.
* - For every state states[i], annotation_lists[i] now
* contains all annotations associated with all inadequacies that manifest
* in \c s.
* - annotation_counts[i] was incremented by the number of new
* annotations added to states[i].
* - *max_contributionsp is the higher of:
* - The maximum number of contributions computed per annotation.
* - *max_contributionsp \@pre.
* - All memory for all new annotations was allocated on
* \c annotations_obstackp.
*/
void
AnnotationList__compute_from_inadequacies (
state *s, bitsetv follow_kernel_items, bitsetv always_follows,
state ***predecessors, bitset **item_lookahead_sets,
InadequacyList **inadequacy_lists, AnnotationList **annotation_lists,
AnnotationIndex *annotation_counts,
ContributionIndex *max_contributionsp,
struct obstack *annotations_obstackp,
InadequacyListNodeCount *inadequacy_list_node_count);
/**
* \pre
* - self != NULL.
* - \c nitems is the number of kernel items in the LR(0) state that every
* node in the list \c self annotates.
* \post
* - A textual representation of all nodes in the list \c self was printed to
* stderr. \c spaces spaces were printed before each line of the text.
*/
void AnnotationList__debug (AnnotationList const *self, size_t nitems,
int spaces);
/**
* \pre
* - self != NULL.
* - \c nitems is the number of kernel items in the LR(0) state that \c self
* annotates.
* - The number of rows in \c lookahead_filter is at least \c nitems, and the
* number of columns is \c ::ntokens.
* \post
* - lookahead_filter[i][j] is set iff some annotation in the list
* \c self lists token \c j in kernel item \c i as a contributor.
*/
void AnnotationList__computeLookaheadFilter (AnnotationList const *self,
size_t nitems,
bitsetv lookahead_filter);
/**
* \pre
* - self != NULL.
* - \c nitems is the number of kernel items in the LR(0) state that \c self
* annotates.
* - \c lookaheads describes the lookahead sets on the kernel items of some
* isocore of the LR(0) state that \c self annotates. Either:
* - lookaheads = NULL only if the lookahead set on every kernel
* item is empty.
* - For any 0 <= i < nitems, lookaheads[i] is either:
* - \c NULL only if the lookahead set on kernel item \c i is empty.
* - The (possibly empty) lookahead set on kernel item \c i.
* \post
* - If require_split_stable = false, \c result = either:
* - \c ContributionIndex__none iff the state described by \c lookaheads
* makes none of the contributions in \c self.
* - The index of the dominating contribution in \c self that is made by
* that state.
* - \c ContributionIndex__error_action to indicate that the inadequacy
* manifests as a conflict and that a syntax error action (because of a
* %nonassoc) dominates instead.
* - Otherwise, \c result is the same as if require_split_stable =
* false except that it is also \c ContributionIndex__none if there
* are contributions made by the state but the dominating contribution is
* not split-stable. By split-stable, we mean that the dominating
* contribution cannot change due to loss of one or more potential
* contributions due to loss of lookaheads due to splitting of the state.
* - After determining which contributions are actually made by the state,
* the algorithm for determining which contribution dominates in the
* conflict is intended to choose exactly the same action as conflicts.c
* would choose... no matter how crazy conflicts.c's choice is.
*/
ContributionIndex
AnnotationList__computeDominantContribution (AnnotationList const *self,
size_t nitems, bitset *lookaheads,
bool require_split_stable);
#endif /* !ANNOTATION_LIST_H_ */