Halt stack pops at all error states, not just error trees

This commit is contained in:
Max Brunsfeld 2016-03-03 11:05:37 -08:00
parent 5f9be9d9b2
commit c0595c21c5
4 changed files with 127 additions and 103 deletions

View file

@ -52,7 +52,8 @@ struct LookaheadState {
typedef struct {
TSSymbol symbol;
TSStateId next_state;
size_t depth;
size_t stack_depth;
size_t child_count;
size_t skipped_subtree_count;
size_t in_progress_state_count;
} ErrorRepair;
@ -75,15 +76,16 @@ typedef enum {
*/
static StackSlice ts_parser__pop_one(TSParser *self, int head_index, int count) {
StackSliceArray slices = ts_stack_pop(self->stack, head_index, count, true);
assert(slices.size > 0);
assert(slices.contents[0].head_index == head_index);
for (size_t i = 1; i < slices.size; i++) {
ts_tree_array_clear(&slices.contents[i].trees);
array_delete(&slices.contents[i].trees);
ts_stack_remove_head(self->stack, slices.contents[i].head_index);
StackPopResult pop = ts_stack_pop(self->stack, head_index, count, true);
assert(pop.status == StackPopSucceeded);
assert(pop.slices.size > 0);
assert(pop.slices.contents[0].head_index == head_index);
for (size_t i = 1; i < pop.slices.size; i++) {
ts_tree_array_clear(&pop.slices.contents[i].trees);
array_delete(&pop.slices.contents[i].trees);
ts_stack_remove_head(self->stack, pop.slices.contents[i].head_index);
}
return slices.contents[0];
return pop.slices.contents[0];
}
static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self,
@ -91,18 +93,18 @@ static ParseActionResult ts_parser__breakdown_top_of_stack(TSParser *self,
TSTree *last_child = NULL;
do {
StackSliceArray slices = ts_stack_pop(self->stack, head, 1, false);
if (!slices.size)
StackPopResult pop = ts_stack_pop(self->stack, head, 1, false);
if (!pop.slices.size)
return ParseActionFailed;
assert(slices.size > 0);
assert(pop.slices.size > 0);
/*
* Since only one entry (not counting extra trees) is being popped from the
* stack, there should only be one possible array of removed trees.
*/
for (size_t i = 0; i < slices.size; i++) {
StackSlice slice = slices.contents[i];
for (size_t i = 0; i < pop.slices.size; i++) {
StackSlice slice = pop.slices.contents[i];
TreeArray removed_trees = slice.trees;
TSTree *parent = *array_front(&removed_trees);
int head_index = slice.head_index;
@ -349,28 +351,26 @@ static ReduceResult ts_parser__reduce(TSParser *self, int head, TSSymbol symbol,
int child_count, bool extra, bool fragile) {
array_clear(&self->reduce_parents);
TSSymbolMetadata metadata = ts_language_symbol_metadata(self->language, symbol);
StackSliceArray slices =
ts_stack_pop(self->stack, head, child_count, false);
if (!slices.size)
StackPopResult pop = ts_stack_pop(self->stack, head, child_count, false);
if (!pop.slices.size)
return ReduceFailed;
if (slices.contents[0].trees.size &&
slices.contents[0].trees.contents[0]->symbol == ts_builtin_sym_error) {
if (pop.status == StackPopStoppedAtError) {
if (self->partial_pop.size) {
ts_tree_array_clear(&self->partial_pop);
array_delete(&self->partial_pop);
}
self->partial_pop = slices.contents[0].trees;
for (size_t i = 1; i < slices.size; i++) {
ts_tree_array_clear(&slices.contents[i].trees);
array_delete(&slices.contents[i].trees);
self->partial_pop = pop.slices.contents[0].trees;
for (size_t i = 1; i < pop.slices.size; i++) {
ts_tree_array_clear(&pop.slices.contents[i].trees);
array_delete(&pop.slices.contents[i].trees);
}
return ReduceStoppedAtError;
}
size_t removed_heads = 0;
for (size_t i = 0; i < slices.size; i++) {
StackSlice slice = slices.contents[i];
for (size_t i = 0; i < pop.slices.size; i++) {
StackSlice slice = pop.slices.contents[i];
/*
* If the same set of trees led to a previous stack head, reuse the parent
@ -492,7 +492,7 @@ static ReduceResult ts_parser__reduce(TSParser *self, int head, TSSymbol symbol,
ts_tree_release(*parent);
}
if (removed_heads < slices.size)
if (removed_heads < pop.slices.size)
return ReduceSucceeded;
else
return ReduceMerged;
@ -555,8 +555,11 @@ static ParseActionResult ts_parser__repair_error(TSParser *self, int head_index,
const TSParseAction *actions,
size_t action_count) {
StackEntry *entry_below = ts_stack_head(self->stack, head_index);
while (entry_below && entry_below->state == ts_parse_state_error)
size_t initial_depth = 0;
while (entry_below && entry_below->state == ts_parse_state_error) {
entry_below = ts_stack_entry_next(entry_below, 0);
initial_depth++;
}
bool has_repair = false;
ErrorRepair best_repair;
@ -575,7 +578,7 @@ static ParseActionResult ts_parser__repair_error(TSParser *self, int head_index,
continue;
StackEntry *entry = entry_below;
size_t depth = 0;
size_t depth = initial_depth;
size_t child_count = 0;
size_t in_progress_state_count = 0;
@ -599,16 +602,12 @@ static ParseActionResult ts_parser__repair_error(TSParser *self, int head_index,
ErrorRepair repair = {
.symbol = action.data.symbol,
.next_state = next_state,
.depth = depth,
.child_count = action.data.child_count,
.stack_depth = depth,
.skipped_subtree_count = child_count + count_above_error - action.data.child_count,
.in_progress_state_count = in_progress_state_count,
};
LOG_ACTION("REPAIR_GOOD sym:%s, in_progress:%lu, skipped:%lu!",
SYM_NAME(action.data.symbol),
in_progress_state_count,
repair.skipped_subtree_count);
if (!has_repair ||
ts_parser__error_repair_is_better(best_repair, repair)) {
has_repair = true;
@ -637,6 +636,15 @@ static ParseActionResult ts_parser__repair_error(TSParser *self, int head_index,
return ParseActionRemoved;
}
LOG_ACTION(
"repair_found sym:%s, child_count:%lu, skip_count:%lu, match_count:%lu, DEPTH:%lu",
SYM_NAME(best_repair.symbol),
best_repair.child_count,
best_repair.in_progress_state_count,
best_repair.skipped_subtree_count,
best_repair.stack_depth
);
// Pop any trees that were skipped. Make a new extra error node that contains
// them and the error leaf node.
StackSlice slice = ts_parser__pop_one(self, head_index, best_repair.skipped_subtree_count);
@ -650,7 +658,7 @@ static ParseActionResult ts_parser__repair_error(TSParser *self, int head_index,
// Pop any additional trees that are needed for the chosen reduce action. Make
// a new wrapper node of the chosen symbol that contains them, the error node,
// and the trees that were popped above the error node.
slice = ts_parser__pop_one(self, head_index, best_repair.depth - (error->child_count - 1));
slice = ts_parser__pop_one(self, head_index, best_repair.stack_depth - (error->child_count - 1));
array_push(&slice.trees, error);
for (size_t i = 1; i < self->partial_pop.size; i++)
array_push(&slice.trees, self->partial_pop.contents[i]);
@ -698,12 +706,12 @@ static ParseActionResult ts_parser__start(TSParser *self, TSInput input,
}
static ParseActionResult ts_parser__accept(TSParser *self, int head) {
StackSliceArray slices = ts_stack_pop(self->stack, head, -1, true);
if (!slices.size)
StackPopResult pop = ts_stack_pop(self->stack, head, -1, true);
if (!pop.slices.size)
goto error;
for (size_t j = 0; j < slices.size; j++) {
StackSlice slice = slices.contents[j];
for (size_t j = 0; j < pop.slices.size; j++) {
StackSlice slice = pop.slices.contents[j];
TreeArray trees = slice.trees;
for (size_t i = trees.size - 1; i + 1 > 0; i--) {
@ -732,8 +740,8 @@ static ParseActionResult ts_parser__accept(TSParser *self, int head) {
return ParseActionRemoved;
error:
if (slices.size) {
StackSlice slice = *array_front(&slices);
if (pop.slices.size) {
StackSlice slice = *array_front(&pop.slices);
for (size_t i = 0; i < slice.trees.size; i++)
ts_tree_release(slice.trees.contents[i]);
array_delete(&slice.trees);