/* IELR's inadequacy list. Copyright (C) 2009-2015, 2018-2022 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 INADEQUACY_LIST_H_ # define INADEQUACY_LIST_H_ # include # include "gram.h" # include "state.h" # include "symtab.h" /** * A unique ID assigned to every \c InadequacyList node. */ typedef long long InadequacyListNodeCount; /** * For a conflict, each rule in the grammar can have at most one contributing * reduction except that rule 0 cannot have any because the reduction on rule 0 * cannot have lookaheads. For a conflict, exactly one shift can contribute. * Thus the number of rules in the grammar is an upper bound on the number of * possible contributions to any conflict. The maximum number of possible * items in a state is also an upper bound, but the \c nitems member of \c * state is currently a \c size_t and thus, if changed, risks becoming out of * sync with this type. Whatever the type, it must support negatives for sake * of the special values below. */ typedef rule_number ContributionIndex; /* Special \c ContributionIndex used to indicate null result when looking for a contribution. */ extern ContributionIndex const ContributionIndex__none; /* Special \c ContributionIndex used by \c AnnotationList__computeDominantContribution to signal when the action chosen in a conflict is a syntax error because of a %nonassoc. */ extern ContributionIndex const ContributionIndex__error_action; /** * The description of a conflict. Don't break encapsulation by modifying the * fields directly. Use the provided interface functions for * \c InadequacyList. */ typedef struct { /** The \c token passed to \c InadequacyList__new_conflict. */ symbol *token; /** The \c actions passed to \c InadequacyList__new_conflict. */ bitset actions; } Conflict; /** * A node in a list that describes all the inadequacies that manifest in a * particular state. Don't break encapsulation by modifying the fields * directly. Use the provided interface functions. */ typedef struct InadequacyList { struct InadequacyList *next; InadequacyListNodeCount id; state *manifestingState; ContributionIndex contributionCount; union { Conflict conflict; } inadequacy; } InadequacyList; /** * \pre * - manifesting_state != NULL. * - \c token is a token. * - The size of \c actions is * manifesting_state->reductions->num + 1. * - If the set of all \c InadequacyList nodes with which the new * \c InadequacyList node might be compared is currently empty, then * it is best if *node_count is zero so that the node count * does not eventually overflow. However, if that set is not * currently empty, then *node_count has not been modified * by any function except \c InadequacyList__new_conflict since the * invocation of \c InadequacyList__new_conflict that constructed * the first existing member of that set. * \post * - \c result is a new \c InadequacyList with one node indicating that, in * \c manifesting_state, the following actions are in conflict on \c token: * - Shift iff * bitset_test (actions, manifesting_state->reductions->num). * - For any \c i such that * 0 <= i < manifesting_state->reductions->num, the reduction * for the rule manifesting_state->reductions->rules[i] iff * actions[i] is set. * - Given any node \c n from the set of all existing * \c InadequacyList nodes with which \c result might be compared * such that n != result, then n->id < result->id. * - \c result assumes responsibility for the memory of \c actions. */ InadequacyList *InadequacyList__new_conflict ( state *manifesting_state, symbol *token, bitset actions, InadequacyListNodeCount *node_count); /** * \post * - All memory associated with all nodes in the list \c self was freed. */ void InadequacyList__delete (InadequacyList *self); /** * \pre * - self != NULL. * \post * - \c result = either: * - \c ContributionIndex__none iff there is no shift contribution in * \c self (perhaps because \c self isn't a conflict). * - The index of the shift contribution, otherwise. */ ContributionIndex InadequacyList__getShiftContributionIndex (InadequacyList const *self); /** * \pre * - self != NULL. * - 0 <= i < self->contributionCount. * \post * - \c result = the token associated with contribution \c i in the * inadequacy described by the node \c self. */ symbol *InadequacyList__getContributionToken (InadequacyList const *self, ContributionIndex i); /** * \pre * - \c self is a single node. * - list != NULL. * \post * - \c list now contains \c self as its first node. * - \c list assumes responsibility for the memory of \c self. */ void InadequacyList__prependTo (InadequacyList *self, InadequacyList **list); #endif /* !INADEQUACY_LIST_H_ */