Fix case where loop was created in the parse stack

Fixes #133
This commit is contained in:
Max Brunsfeld 2018-03-01 22:41:53 -08:00
parent 32ef3e001a
commit 82c7e170b3
2 changed files with 40 additions and 5 deletions

View file

@ -167,6 +167,8 @@ static bool stack__tree_is_equivalent(const Tree *left, const Tree *right) {
}
static void stack_node_add_link(StackNode *self, StackLink link) {
if (link.node == self) return;
for (int i = 0; i < self->link_count; i++) {
StackLink existing_link = self->links[i];
if (stack__tree_is_equivalent(existing_link.tree, link.tree)) {

View file

@ -132,19 +132,19 @@ describe("Stack", [&]() {
describe("merge()", [&]() {
before_each([&]() {
// . <──0── A <──1── B*
// . <──0── A <─*
// ↑
// └───2─── C*
// └───*
ts_stack_push(stack, 0, trees[0], false, stateA);
ts_stack_copy_version(stack, 0);
ts_stack_push(stack, 0, trees[1], false, stateB);
ts_stack_push(stack, 1, trees[2], false, stateC);
});
it("combines versions that have the same top states and positions", [&]() {
// . <──0── A <──1── B <──3── D*
// ↑
// └───2─── C <──4── D*
ts_stack_push(stack, 0, trees[1], false, stateB);
ts_stack_push(stack, 1, trees[2], false, stateC);
ts_stack_push(stack, 0, trees[3], false, stateD);
ts_stack_push(stack, 1, trees[4], false, stateD);
@ -163,6 +163,12 @@ describe("Stack", [&]() {
});
it("does not combine versions that have different states", [&]() {
// . <──0── A <──1── B*
// ↑
// └───2─── C*
ts_stack_push(stack, 0, trees[1], false, stateB);
ts_stack_push(stack, 1, trees[2], false, stateC);
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
});
@ -172,6 +178,8 @@ describe("Stack", [&]() {
// ↑
// └───2─── C <──4── D*
trees[3]->size = tree_len * 3;
ts_stack_push(stack, 0, trees[1], false, stateB);
ts_stack_push(stack, 1, trees[2], false, stateC);
ts_stack_push(stack, 0, trees[3], false, stateD);
ts_stack_push(stack, 1, trees[4], false, stateD);
@ -184,9 +192,11 @@ describe("Stack", [&]() {
// . <──0── A <──1── B <──3── D <──5── E*
// ↑
// └───2─── C <──4── D <──5── E*
ts_stack_push(stack, 0, trees[1], false, stateB);
ts_stack_push(stack, 1, trees[2], false, stateC);
ts_stack_push(stack, 0, trees[3], false, stateD);
ts_stack_push(stack, 0, trees[5], false, stateE);
ts_stack_push(stack, 1, trees[4], false, stateD);
ts_stack_push(stack, 0, trees[5], false, stateE);
ts_stack_push(stack, 1, trees[5], false, stateE);
// . <──0── A <──1── B <──3── D <──5── E*
@ -204,6 +214,29 @@ describe("Stack", [&]() {
})));
});
});
describe("when one of the versions contains an extra (e.g. ERROR) tree of size zero", [&]() {
it("does not create a loop in the stack", [&]() {
// . <──0── A <────1──── B*
// ↑
// └2─ A <──1── B*
trees[2]->extra = true;
trees[2]->size = tree_len * 0;
ts_stack_push(stack, 0, trees[1], false, stateB);
ts_stack_push(stack, 1, trees[2], false, stateA);
ts_stack_push(stack, 1, trees[1], false, stateB);
// . <──0── A <──1── B*
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
{stateB, 0},
{stateA, 1},
{1, 2},
})));
});
});
});
describe("pop_count(version, count)", [&]() {