mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-23 11:13:03 +00:00
Merge tag 'v3.7.5'
Three new commits: commit8358090292Author: Paul Eggert <eggert@cs.ucla.edu> Date: Wed Jan 20 18:30:16 2021 -0800 c: port to HP-UX 11.23 commit2c294c1325Author: Vincent Imbimbo <vmi6@cornell.edu> Date: Sat Jan 23 13:25:18 2021 -0500 cex: fix state-item pruning commitc22902e360Author: Akim Demaille <akim.demaille@gmail.com> Date: Sat Jan 23 18:40:15 2021 +0100 tables: fix handling for useless tokens
This commit is contained in:
23
NEWS
23
NEWS
@@ -1,6 +1,27 @@
|
|||||||
GNU Bison NEWS
|
GNU Bison NEWS
|
||||||
|
|
||||||
* Noteworthy changes in release ?.? (????-??-??) [?]
|
* Noteworthy changes in release 3.7.5 (2021-01-24) [stable]
|
||||||
|
|
||||||
|
** Bug fixes
|
||||||
|
|
||||||
|
*** Counterexample Generation
|
||||||
|
|
||||||
|
In some cases counterexample generation could crash. This is fixed.
|
||||||
|
|
||||||
|
*** Fix Table Generation
|
||||||
|
|
||||||
|
In some very rare conditions, when there are many useless tokens, it was
|
||||||
|
possible to generate incorrect parsers.
|
||||||
|
|
||||||
|
*** GLR parsers now support %merge together with api.value.type=union.
|
||||||
|
|
||||||
|
*** C++ parsers use noexcept in more places.
|
||||||
|
|
||||||
|
*** Generated parsers avoid some warnings about signedness issues.
|
||||||
|
|
||||||
|
*** C-language parsers now avoid warnings from pedantic clang.
|
||||||
|
|
||||||
|
*** C-language parsers now work around quirks of HP-UX 11.23 (2003).
|
||||||
|
|
||||||
** Changes
|
** Changes
|
||||||
|
|
||||||
|
|||||||
1
cfg.mk
1
cfg.mk
@@ -156,6 +156,7 @@ exclude = \
|
|||||||
$(call exclude, \
|
$(call exclude, \
|
||||||
bindtextdomain=^lib/main.c$$ \
|
bindtextdomain=^lib/main.c$$ \
|
||||||
cast_of_argument_to_free=^src/muscle-tab.c$$ \
|
cast_of_argument_to_free=^src/muscle-tab.c$$ \
|
||||||
|
copyright_check=gnulib/lib/version-etc.c$$ \
|
||||||
error_message_uppercase=etc/bench.pl.in$$ \
|
error_message_uppercase=etc/bench.pl.in$$ \
|
||||||
po_check=^tests|(^po/POTFILES.in|.md)$$ \
|
po_check=^tests|(^po/POTFILES.in|.md)$$ \
|
||||||
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
|
preprocessor_indentation=^data/|^lib/|^src/parse-gram.[ch]$$ \
|
||||||
|
|||||||
@@ -254,6 +254,18 @@ typedef int_least16_t yytype_int16;
|
|||||||
typedef short yytype_int16;
|
typedef short yytype_int16;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Work around bug in HP-UX 11.23, which defines these macros
|
||||||
|
incorrectly for preprocessor constants. This workaround can likely
|
||||||
|
be removed in 2023, as HPE has promised support for HP-UX 11.23
|
||||||
|
(aka HP-UX 11i v2) only through the end of 2022; see Table 2 of
|
||||||
|
<https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */
|
||||||
|
#ifdef __hpux
|
||||||
|
# undef UINT_LEAST8_MAX
|
||||||
|
# undef UINT_LEAST16_MAX
|
||||||
|
# define UINT_LEAST8_MAX 255
|
||||||
|
# define UINT_LEAST16_MAX 65535
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
|
#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
|
||||||
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
|
typedef __UINT_LEAST8_TYPE__ yytype_uint8;
|
||||||
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
|
#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \
|
||||||
|
|||||||
@@ -384,11 +384,10 @@ disable_state_item (state_item *si)
|
|||||||
bitset_free (si->prods);
|
bitset_free (si->prods);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable all transitions and productions that can only be
|
/* Disable all state_item paths that lead to/from SI and nowhere
|
||||||
* reached through this state_item.
|
else. */
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
prune_forward (const state_item *si)
|
prune_state_item (const state_item *si)
|
||||||
{
|
{
|
||||||
state_item_list queue =
|
state_item_list queue =
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
||||||
@@ -398,8 +397,16 @@ prune_forward (const state_item *si)
|
|||||||
{
|
{
|
||||||
state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
|
state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
|
||||||
gl_list_remove_at (queue, 0);
|
gl_list_remove_at (queue, 0);
|
||||||
if (dsi->trans >= 0)
|
if (SI_DISABLED (dsi - state_items))
|
||||||
gl_list_add_last (queue, &state_items[dsi->trans]);
|
continue;
|
||||||
|
|
||||||
|
if (dsi->trans >= 0 && !SI_DISABLED (dsi->trans))
|
||||||
|
{
|
||||||
|
const state_item *trans = &state_items[dsi->trans];
|
||||||
|
bitset_reset (trans->revs, dsi - state_items);
|
||||||
|
if (bitset_empty_p (trans->revs))
|
||||||
|
gl_list_add_last (queue, trans);
|
||||||
|
}
|
||||||
|
|
||||||
if (dsi->prods)
|
if (dsi->prods)
|
||||||
{
|
{
|
||||||
@@ -407,32 +414,15 @@ prune_forward (const state_item *si)
|
|||||||
state_item_number sin;
|
state_item_number sin;
|
||||||
BITSET_FOR_EACH (biter, dsi->prods, sin, 0)
|
BITSET_FOR_EACH (biter, dsi->prods, sin, 0)
|
||||||
{
|
{
|
||||||
|
if (SI_DISABLED (sin))
|
||||||
|
continue;
|
||||||
const state_item *prod = &state_items[sin];
|
const state_item *prod = &state_items[sin];
|
||||||
bitset_reset (prod->revs, dsi - state_items);
|
bitset_reset (prod->revs, dsi - state_items);
|
||||||
if (bitset_empty_p (prod->revs))
|
if (bitset_empty_p (prod->revs))
|
||||||
gl_list_add_last (queue, prod);
|
gl_list_add_last (queue, prod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dsi != si)
|
|
||||||
disable_state_item (dsi);
|
|
||||||
}
|
|
||||||
gl_list_free (queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable all state_item paths that lead to
|
|
||||||
* si and nowhere else.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
prune_backward (const state_item *si)
|
|
||||||
{
|
|
||||||
state_item_list queue =
|
|
||||||
gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1,
|
|
||||||
(const void **) &si);
|
|
||||||
|
|
||||||
while (gl_list_size (queue) > 0)
|
|
||||||
{
|
|
||||||
state_item *dsi = (state_item *) gl_list_get_at (queue, 0);
|
|
||||||
gl_list_remove_at (queue, 0);
|
|
||||||
bitset_iterator biter;
|
bitset_iterator biter;
|
||||||
state_item_number sin;
|
state_item_number sin;
|
||||||
BITSET_FOR_EACH (biter, dsi->revs, sin, 0)
|
BITSET_FOR_EACH (biter, dsi->revs, sin, 0)
|
||||||
@@ -440,7 +430,9 @@ prune_backward (const state_item *si)
|
|||||||
if (SI_DISABLED (sin))
|
if (SI_DISABLED (sin))
|
||||||
continue;
|
continue;
|
||||||
state_item *rev = &state_items[sin];
|
state_item *rev = &state_items[sin];
|
||||||
if (rev->prods)
|
if (&state_items[rev->trans] == dsi)
|
||||||
|
gl_list_add_last (queue, rev);
|
||||||
|
else if (rev->prods)
|
||||||
{
|
{
|
||||||
bitset_reset (rev->prods, dsi - state_items);
|
bitset_reset (rev->prods, dsi - state_items);
|
||||||
if (bitset_empty_p (rev->prods))
|
if (bitset_empty_p (rev->prods))
|
||||||
@@ -449,16 +441,13 @@ prune_backward (const state_item *si)
|
|||||||
else
|
else
|
||||||
gl_list_add_last (queue, rev);
|
gl_list_add_last (queue, rev);
|
||||||
}
|
}
|
||||||
if (dsi != si)
|
disable_state_item (dsi);
|
||||||
disable_state_item (dsi);
|
|
||||||
}
|
}
|
||||||
gl_list_free (queue);
|
gl_list_free (queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* To make searches more efficient, prune away paths that are caused
|
||||||
To make searches more efficient, we can prune away paths that are
|
by disabled transitions. */
|
||||||
caused by disabled transitions.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
prune_disabled_paths (void)
|
prune_disabled_paths (void)
|
||||||
{
|
{
|
||||||
@@ -466,11 +455,7 @@ prune_disabled_paths (void)
|
|||||||
{
|
{
|
||||||
state_item *si = &state_items[i];
|
state_item *si = &state_items[i];
|
||||||
if (si->trans == -1 && item_number_is_symbol_number (*si->item))
|
if (si->trans == -1 && item_number_is_symbol_number (*si->item))
|
||||||
{
|
prune_state_item (si);
|
||||||
prune_forward (si);
|
|
||||||
prune_backward (si);
|
|
||||||
disable_state_item (si);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
83
src/tables.c
83
src/tables.c
@@ -111,9 +111,13 @@ base_number *base = NULL;
|
|||||||
computation equals to BASE_MINIMUM, later mapped to BASE_NINF to
|
computation equals to BASE_MINIMUM, later mapped to BASE_NINF to
|
||||||
keep parser tables small. */
|
keep parser tables small. */
|
||||||
base_number base_ninf = 0;
|
base_number base_ninf = 0;
|
||||||
|
|
||||||
/* Bitset representing an integer set in the range
|
/* Bitset representing an integer set in the range
|
||||||
-nstates..table_size (as an upper bound) */
|
POS_SET_OFFSET..(POS_SET_OFFSET + SIZE). POS_SET_OFFSET is
|
||||||
|
nonpositive. */
|
||||||
static bitset pos_set = NULL;
|
static bitset pos_set = NULL;
|
||||||
|
/* The integer denoted by bitno 0 in pos_set. */
|
||||||
|
static int pos_set_base = 0;
|
||||||
|
|
||||||
static int *conflrow;
|
static int *conflrow;
|
||||||
int *conflict_table;
|
int *conflict_table;
|
||||||
@@ -138,6 +142,71 @@ int high;
|
|||||||
state_number *yydefgoto;
|
state_number *yydefgoto;
|
||||||
rule_number *yydefact;
|
rule_number *yydefact;
|
||||||
|
|
||||||
|
|
||||||
|
/*----------.
|
||||||
|
| pos_set. |
|
||||||
|
`----------*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
pos_set_dump (void)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "pos_set (%ld, %d) =", bitset_size (pos_set), pos_set_base);
|
||||||
|
bitset_iterator biter;
|
||||||
|
int i;
|
||||||
|
BITSET_FOR_EACH (biter, pos_set, i, 0)
|
||||||
|
fprintf (stderr, " %d", i + pos_set_base);
|
||||||
|
putc ('\n', stderr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* The size and base of POS_SET are not known, we need to be able to
|
||||||
|
move the base farther "on the left", and grow "on the right".
|
||||||
|
|
||||||
|
It would be nice to be able to predict the base accurately, but it
|
||||||
|
seems difficult (-nstates seems to work most of the time, except
|
||||||
|
when there are useless tokens).
|
||||||
|
|
||||||
|
FIXME: The current approach is correct, but with poor performances.
|
||||||
|
Bitsets need to support 'assign' and 'shift'. And instead of
|
||||||
|
extending POS_SET just for the out-of-range new values, we need
|
||||||
|
something like doubling the size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
pos_set_set (int pos)
|
||||||
|
{
|
||||||
|
int bitno = pos - pos_set_base;
|
||||||
|
if (bitno < 0)
|
||||||
|
{
|
||||||
|
const int delta = pos_set_base - pos;
|
||||||
|
const int old_size = bitset_size (pos_set);
|
||||||
|
const int new_size = old_size + delta;
|
||||||
|
bitset_resize (pos_set, new_size);
|
||||||
|
// Shift all the bits by DELTA.
|
||||||
|
// FIXME: add bitset_assign, and bitset_shift?
|
||||||
|
for (int i = new_size - 1; delta <= i ; --i)
|
||||||
|
if (bitset_test (pos_set, i))
|
||||||
|
bitset_set (pos_set, i + delta);
|
||||||
|
else
|
||||||
|
bitset_reset (pos_set, i + delta);
|
||||||
|
pos_set_base = pos;
|
||||||
|
bitno = 0;
|
||||||
|
}
|
||||||
|
else if (bitset_size (pos_set) <= bitno)
|
||||||
|
bitset_resize (pos_set, bitno + 1);
|
||||||
|
bitset_set (pos_set, bitno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
pos_set_test (int pos)
|
||||||
|
{
|
||||||
|
const int bitno = pos - pos_set_base;
|
||||||
|
return bitset_test (pos_set, bitno);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------.
|
/*-------------------------------------------------------------------.
|
||||||
| If TABLE, CONFLICT_TABLE, and CHECK are too small to be addressed |
|
| If TABLE, CONFLICT_TABLE, and CHECK are too small to be addressed |
|
||||||
| at DESIRED, grow them. TABLE[DESIRED] can be used, so the desired |
|
| at DESIRED, grow them. TABLE[DESIRED] can be used, so the desired |
|
||||||
@@ -168,8 +237,6 @@ table_grow (int desired)
|
|||||||
check = xnrealloc (check, table_size, sizeof *check);
|
check = xnrealloc (check, table_size, sizeof *check);
|
||||||
for (int i = old_size; i < table_size; ++i)
|
for (int i = old_size; i < table_size; ++i)
|
||||||
check[i] = -1;
|
check[i] = -1;
|
||||||
|
|
||||||
bitset_resize (pos_set, table_size + nstates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -672,7 +739,7 @@ pack_vector (vector_number vector)
|
|||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok && bitset_test (pos_set, nstates + res))
|
if (ok && pos_set_test (res))
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,6 +799,7 @@ pack_table (void)
|
|||||||
{
|
{
|
||||||
base = xnmalloc (nvectors, sizeof *base);
|
base = xnmalloc (nvectors, sizeof *base);
|
||||||
pos_set = bitset_create (table_size + nstates, BITSET_FRUGAL);
|
pos_set = bitset_create (table_size + nstates, BITSET_FRUGAL);
|
||||||
|
pos_set_base = -nstates;
|
||||||
table = xcalloc (table_size, sizeof *table);
|
table = xcalloc (table_size, sizeof *table);
|
||||||
conflict_table = xcalloc (table_size, sizeof *conflict_table);
|
conflict_table = xcalloc (table_size, sizeof *conflict_table);
|
||||||
check = xnmalloc (table_size, sizeof *check);
|
check = xnmalloc (table_size, sizeof *check);
|
||||||
@@ -757,12 +825,7 @@ pack_table (void)
|
|||||||
/* Action of I were already coded for S. */
|
/* Action of I were already coded for S. */
|
||||||
place = base[s];
|
place = base[s];
|
||||||
|
|
||||||
/* Store PLACE into POS_SET. PLACE might not belong to the set
|
pos_set_set (place);
|
||||||
of possible values for instance with useless tokens. It
|
|
||||||
would be more satisfying to eliminate the need for this
|
|
||||||
'if'. */
|
|
||||||
if (0 <= nstates + place)
|
|
||||||
bitset_set (pos_set, nstates + place);
|
|
||||||
base[order[i]] = place;
|
base[order[i]] = place;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user