portability: <' and >' are not always defined on addresses.

Specifically, don't sort objects by their memory addresses when
they're not allocated in the same array or other object.  Though
I haven't found a test case where that fails on my platform, C
says the behavior is undefined.
* src/AnnotationList.c (AnnotationList__insertInto): Remove
FIXME.  Use new id field of InadequacyList nodes rather than
their memory addresses when sorting.
(AnnotationList__compute_from_inadequacies): Add
inadequacy_list_node_count argument to pass to
InadequacyList__new_conflict.
* src/AnnotationList.h
(AnnotationList__compute_from_inadequacies): Update prototype
and documentation for new argument.
* src/InadequacyList.c (InadequacyList__new_conflict): Add
node_count argument and use it to assign a unique ID.
* src/InadequacyList.h (InadequacyListNodeCount): New typedef.
(InadequacyList): Add id field.
(InadequacyList__new_conflict): Update prototype and
documentation for new argument.
* src/ielr.c (ielr_compute_annotation_lists): Update
AnnotationList__compute_from_inadequacies invocation.
This commit is contained in:
Joel E. Denny
2009-12-29 12:43:26 -05:00
parent abcc7c03cc
commit 2728ac7ecd
6 changed files with 96 additions and 46 deletions

View File

@@ -1,3 +1,28 @@
2009-12-29 Joel E. Denny <jdenny@clemson.edu>
portability: `<' and `>' are not always defined on addresses.
Specifically, don't sort objects by their memory addresses when
they're not allocated in the same array or other object. Though
I haven't found a test case where that fails on my platform, C
says the behavior is undefined.
* src/AnnotationList.c (AnnotationList__insertInto): Remove
FIXME. Use new id field of InadequacyList nodes rather than
their memory addresses when sorting.
(AnnotationList__compute_from_inadequacies): Add
inadequacy_list_node_count argument to pass to
InadequacyList__new_conflict.
* src/AnnotationList.h
(AnnotationList__compute_from_inadequacies): Update prototype
and documentation for new argument.
* src/InadequacyList.c (InadequacyList__new_conflict): Add
node_count argument and use it to assign a unique ID.
* src/InadequacyList.h (InadequacyListNodeCount): New typedef.
(InadequacyList): Add id field.
(InadequacyList__new_conflict): Update prototype and
documentation for new argument.
* src/ielr.c (ielr_compute_annotation_lists): Update
AnnotationList__compute_from_inadequacies invocation.
2009-12-20 Joel E. Denny <jdenny@clemson.edu> 2009-12-20 Joel E. Denny <jdenny@clemson.edu>
Fix handling of yychar manipulation in user semantic actions. Fix handling of yychar manipulation in user semantic actions.

View File

@@ -77,12 +77,11 @@ AnnotationList__isContributionAlways (AnnotationList const *self,
* - Otherwise, \c list now contains the node \c self, \c result is true, and * - Otherwise, \c list now contains the node \c self, \c result is true, and
* \c list assumes responsibility for the memory of \c self. * \c list assumes responsibility for the memory of \c self.
* - The sort in \c list is: * - The sort in \c list is:
* - Sort in reverse order on memory address of the associated inadequacy * - Sort in reverse order on the unique ID of the associated
* node. Because memory is usually allocated in ascending order (FIXME: * inadequacy node. Because these IDs are assigned in ascending
* Is this true enough? Should we keep some sort of global index to * order, this should mean that the insertion position within an
* guarantee it?), this should mean that the insertion position within an * annotation list is usually near the beginning with other
* annotation list is usually near the beginning with other annotations * annotations associated with the same inadequacy.
* associated with the same inadequacy.
* - Next, sort on the first contribution that is different as follows: * - Next, sort on the first contribution that is different as follows:
* - Sort an always-contribution before a never-contribution before a * - Sort an always-contribution before a never-contribution before a
* potential-contribution. * potential-contribution.
@@ -104,9 +103,9 @@ AnnotationList__insertInto (AnnotationList *self, AnnotationList **list,
{ {
int cmp = 0; int cmp = 0;
ContributionIndex ci; ContributionIndex ci;
if (self->inadequacyNode < (*node)->inadequacyNode) if (self->inadequacyNode->id < (*node)->inadequacyNode->id)
cmp = 1; cmp = 1;
else if ((*node)->inadequacyNode < self->inadequacyNode) else if ((*node)->inadequacyNode->id < self->inadequacyNode->id)
cmp = -1; cmp = -1;
else else
for (ci = 0; for (ci = 0;
@@ -408,18 +407,14 @@ AnnotationList__computePredecessorAnnotations (AnnotationList *self, state *s,
} }
void void
AnnotationList__compute_from_inadequacies (state *s, AnnotationList__compute_from_inadequacies (
bitsetv follow_kernel_items, state *s, bitsetv follow_kernel_items, bitsetv always_follows,
bitsetv always_follows, state ***predecessors, bitset **item_lookahead_sets,
state ***predecessors, InadequacyList **inadequacy_lists, AnnotationList **annotation_lists,
bitset **item_lookahead_sets, AnnotationIndex *annotation_counts,
InadequacyList **inadequacy_lists, ContributionIndex *max_contributionsp,
AnnotationList **annotation_lists, struct obstack *annotations_obstackp,
AnnotationIndex *annotation_counts, InadequacyListNodeCount *inadequacy_list_node_count)
ContributionIndex
*max_contributionsp,
struct obstack
*annotations_obstackp)
{ {
bitsetv all_lookaheads; bitsetv all_lookaheads;
bitset shift_tokens; bitset shift_tokens;
@@ -530,8 +525,9 @@ AnnotationList__compute_from_inadequacies (state *s,
} }
{ {
InadequacyList *conflict_node = InadequacyList *conflict_node =
InadequacyList__new_conflict (s, symbols[conflicted_token], InadequacyList__new_conflict (
actions); s, symbols[conflicted_token], actions,
inadequacy_list_node_count);
actions = NULL; actions = NULL;
annotation_node->inadequacyNode = conflict_node; annotation_node->inadequacyNode = conflict_node;
if (ContributionIndex__none if (ContributionIndex__none

View File

@@ -82,6 +82,15 @@ typedef struct AnnotationList
* computed by \c ielr_compute_auxiliary_tables. * computed by \c ielr_compute_auxiliary_tables.
* - The size of each of \c annotation_lists and \c annotation_counts is * - The size of each of \c annotation_lists and \c annotation_counts is
* \c ::nstates. * \c ::nstates.
* - If no \c InadequacyList nodes are currently allocated for the
* parser tables to which \c s belongs, then it is best if
* <tt>*inadequacy_list_node_count</tt> is zero to avoid overflow.
* Otherwise, <tt>*inadequacy_list_node_count</tt> 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 * \post
* - <tt>inadequacy_lists[s->number]</tt> now describes all inadequacies that * - <tt>inadequacy_lists[s->number]</tt> now describes all inadequacies that
* manifest in \c s. * manifest in \c s.
@@ -97,18 +106,14 @@ typedef struct AnnotationList
* \c annotations_obstackp. * \c annotations_obstackp.
*/ */
void void
AnnotationList__compute_from_inadequacies (state *s, AnnotationList__compute_from_inadequacies (
bitsetv follow_kernel_items, state *s, bitsetv follow_kernel_items, bitsetv always_follows,
bitsetv always_follows, state ***predecessors, bitset **item_lookahead_sets,
state ***predecessors, InadequacyList **inadequacy_lists, AnnotationList **annotation_lists,
bitset **item_lookahead_sets, AnnotationIndex *annotation_counts,
InadequacyList **inadequacy_lists, ContributionIndex *max_contributionsp,
AnnotationList **annotation_lists, struct obstack *annotations_obstackp,
AnnotationIndex *annotation_counts, InadequacyListNodeCount *inadequacy_list_node_count);
ContributionIndex
*max_contributionsp,
struct obstack
*annotations_obstackp);
/** /**
* \pre * \pre

View File

@@ -27,9 +27,12 @@ ContributionIndex const ContributionIndex__error_action = -2;
InadequacyList * InadequacyList *
InadequacyList__new_conflict (state *manifesting_state, symbol *token, InadequacyList__new_conflict (state *manifesting_state, symbol *token,
bitset actions) bitset actions,
InadequacyListNodeCount *node_count)
{ {
InadequacyList *result = xmalloc (sizeof *result); InadequacyList *result = xmalloc (sizeof *result);
result->id = (*node_count)++;
aver (*node_count != 0);
result->next = NULL; result->next = NULL;
result->manifestingState = manifesting_state; result->manifestingState = manifesting_state;
result->contributionCount = bitset_count (actions); result->contributionCount = bitset_count (actions);

View File

@@ -25,6 +25,14 @@
#include "state.h" #include "state.h"
#include "symtab.h" #include "symtab.h"
/**
* A unique ID assigned to every \c InadequacyList node.
*
* This must remain unsigned so that the overflow check in
* \c InadequacyList__new_conflict works properly.
*/
typedef unsigned long long int InadequacyListNodeCount;
/** /**
* For a conflict, each rule in the grammar can have at most one contributing * 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 * reduction except that rule 0 cannot have any because the reduction on rule 0
@@ -66,6 +74,7 @@ typedef struct {
*/ */
typedef struct InadequacyList { typedef struct InadequacyList {
struct InadequacyList *next; struct InadequacyList *next;
InadequacyListNodeCount id;
state *manifestingState; state *manifestingState;
ContributionIndex contributionCount; ContributionIndex contributionCount;
union { union {
@@ -79,6 +88,14 @@ typedef struct InadequacyList {
* - \c token is a token. * - \c token is a token.
* - The size of \c actions is * - The size of \c actions is
* <tt>manifesting_state->reductions->num + 1</tt>. * <tt>manifesting_state->reductions->num + 1</tt>.
* - 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 <tt>*node_count</t> is zero so that the node count
* does not eventually overflow. However, if that set is not
* currently empty, then <tt>*node_count</tt> 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 * \post
* - \c result is a new \c InadequacyList with one node indicating that, in * - \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: * \c manifesting_state, the following actions are in conflict on \c token:
@@ -88,10 +105,14 @@ typedef struct InadequacyList {
* <tt>0 <= i < manifesting_state->reductions->num</tt>, the reduction * <tt>0 <= i < manifesting_state->reductions->num</tt>, the reduction
* for the rule <tt>manifesting_state->reductions->rules[i]</tt> iff * for the rule <tt>manifesting_state->reductions->rules[i]</tt> iff
* <tt>actions[i]</tt> is set. * <tt>actions[i]</tt> 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 <tt>n != result</tt>, then <tt>n->id < result->id</tt>.
* - \c result assumes responsibility for the memory of \c actions. * - \c result assumes responsibility for the memory of \c actions.
*/ */
InadequacyList *InadequacyList__new_conflict (state *manifesting_state, InadequacyList *InadequacyList__new_conflict (
symbol *token, bitset actions); state *manifesting_state, symbol *token, bitset actions,
InadequacyListNodeCount *node_count);
/** /**
* \post * \post

View File

@@ -504,15 +504,15 @@ ielr_compute_annotation_lists (bitsetv follow_kernel_items,
(*annotation_listsp)[i] = NULL; (*annotation_listsp)[i] = NULL;
annotation_counts[i] = 0; annotation_counts[i] = 0;
} }
for (i = 0; i < nstates; ++i) {
AnnotationList__compute_from_inadequacies (states[i], follow_kernel_items, InadequacyListNodeCount inadequacy_list_node_count = 0;
always_follows, predecessors, for (i = 0; i < nstates; ++i)
item_lookahead_sets, AnnotationList__compute_from_inadequacies (
*inadequacy_listsp, states[i], follow_kernel_items, always_follows, predecessors,
*annotation_listsp, item_lookahead_sets, *inadequacy_listsp, *annotation_listsp,
annotation_counts, annotation_counts, &max_contributions, annotations_obstackp,
&max_contributions, &inadequacy_list_node_count);
annotations_obstackp); }
*max_annotationsp = 0; *max_annotationsp = 0;
for (i = 0; i < nstates; ++i) for (i = 0; i < nstates; ++i)
{ {