summaryrefslogtreecommitdiff
path: root/src/ielr.c
diff options
context:
space:
mode:
authorAkim Demaille <akim.demaille@gmail.com>2020-11-08 13:30:14 +0100
committerAkim Demaille <akim.demaille@gmail.com>2020-11-10 07:08:07 +0100
commit70ee8c77a8287612c038b9a6f14f6f3b38281bfc (patch)
treeddd61fcca4aaa9614b75dc80145cbaa3a4882c5e /src/ielr.c
parente9a43ed4ae9c9c4d6f4e250e4f929ac9602d7452 (diff)
downloadbison-70ee8c77a8287612c038b9a6f14f6f3b38281bfc.tar.gz
multistart: fix IELR computations
IELR needs to rule out the successors of the kernel items of the initial state (`$accept: input • $end`). In the case of multistart, this condition must be expressed differently: the mere item index does not suffice. * src/ielr.c (ielr_item_has_lookahead, ielr_compute_lookaheads): Don't rely on the item index to check whether is_successor_of_initial_item. It is certainly more costly than just checking the item index, but (i) we need to compute the rule anyway, so it's not very much more costly, and (ii) in ielr_item_has_lookahead, this situation is actually impossible, so an optimizing compiler reading the assertions should actually avoid this computation.
Diffstat (limited to 'src/ielr.c')
-rw-r--r--src/ielr.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/ielr.c b/src/ielr.c
index 9490ec72..91fccaa4 100644
--- a/src/ielr.c
+++ b/src/ielr.c
@@ -413,15 +413,16 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item,
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. */
- aver (s->items[item] != 1);
- const bool is_successor_of_initial_item = s->items[item] <= 1;
+ 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 = item_rule (&ritem[s->items[item]])->lhs->number;
+ 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]))
@@ -625,7 +626,9 @@ ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows,
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 bool is_successor_of_initial_item = t->items[t_item] <= 1;
+ const rule *r = item_rule (&ritem[t->items[t_item]]);
+ const bool is_successor_of_initial_item
+ = rule_is_accepting (r) && &ritem[t->items[t_item]] == r->rhs + 1;
if (!is_successor_of_initial_item
&& !bitset_empty_p (lookahead_filter[t_item]))
{
@@ -633,7 +636,7 @@ ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows,
if (item_number_is_rule_number (ritem[t->items[t_item] - 2]))
ielr_compute_goto_follow_set (
follow_kernel_items, always_follows, s,
- item_rule (&ritem[t->items[t_item]])->lhs,
+ r->lhs,
lookaheads[t_item]);
else if (s->lookaheads)
{