Abort recoveries before popping if better versions already exist

This commit is contained in:
Max Brunsfeld 2017-09-13 09:56:51 -07:00
parent 65ed4281d4
commit 07fb3ab0e6
3 changed files with 17 additions and 1 deletions

View file

@ -830,12 +830,23 @@ static void parser__halt_parse(Parser *self) {
static void parser__recover(Parser *self, StackVersion version, Tree *lookahead) {
bool did_recover = false;
unsigned previous_version_count = ts_stack_version_count(self->stack);
Length position = ts_stack_top_position(self->stack, version);
StackSummary *summary = ts_stack_get_summary(self->stack, version);
for (unsigned i = 0; i < summary->size; i++) {
StackSummaryEntry entry = summary->contents[i];
if (entry.state == ERROR_STATE) continue;
unsigned depth = entry.depth + ts_stack_depth_since_error(self->stack, version);
ErrorStatus status = {
.recovering = false,
.push_count = 0,
.cost =
depth * ERROR_COST_PER_SKIPPED_TREE +
(position.chars - entry.position.chars) * ERROR_COST_PER_SKIPPED_CHAR +
(position.extent.row - entry.position.extent.row) * ERROR_COST_PER_SKIPPED_LINE
};
if (parser__better_version_exists(self, version, status)) break;
unsigned count = 0;
if (ts_language_actions(self->language, entry.state, lookahead->symbol, &count) && count > 0) {
LOG("recover state:%u, depth:%u", entry.state, depth);

View file

@ -492,7 +492,11 @@ inline StackIterateAction summarize_stack_callback(void *payload, const Iterator
if (entry.depth < depth) break;
if (entry.depth == depth && entry.state == state) return StackIterateNone;
}
array_push(session->summary, ((StackSummaryEntry){.depth = depth, .state = state}));
array_push(session->summary, ((StackSummaryEntry){
.position = iterator->node->position,
.depth = depth,
.state = state,
}));
return StackIterateNone;
}

View file

@ -34,6 +34,7 @@ enum {
};
typedef struct {
Length position;
unsigned depth;
TSStateId state;
} StackSummaryEntry;