Fix bug in stack breakdown procedure
This commit is contained in:
parent
cbc66b359e
commit
bdbe69258a
4 changed files with 76 additions and 32 deletions
|
|
@ -268,34 +268,45 @@ static ts_lr_parser * ts_lr_parser_make() {
|
|||
result->stack = ts_stack_make();
|
||||
return result;
|
||||
}
|
||||
|
||||
static size_t ts_lr_parser_breakdown_stack(ts_lr_parser *parser, ts_input_edit *edit) {
|
||||
if (parser->stack.size == 0) return 0;
|
||||
|
||||
ts_tree *node = ts_stack_top_node(&parser->stack);
|
||||
size_t left_position = 0;
|
||||
size_t right_position = node->offset + node->size;
|
||||
size_t child_count;
|
||||
ts_tree ** children = ts_tree_children(node, &child_count);
|
||||
|
||||
while (right_position > edit->position || children) {
|
||||
parser->stack.size--;
|
||||
ts_tree *child;
|
||||
for (size_t i = 0; i < child_count; i++) {
|
||||
child = children[i];
|
||||
right_position = left_position + child->offset + child->size;
|
||||
ts_tree_retain(child);
|
||||
state_id parse_state = ts_parse_actions[ts_stack_top_state(&parser->stack)][child->symbol].data.to_state;
|
||||
ts_stack_push(&parser->stack, parse_state, child);
|
||||
if (right_position >= edit->position) break;
|
||||
left_position = right_position;
|
||||
}
|
||||
ts_tree_release(node);
|
||||
node = child;
|
||||
children = ts_tree_children(node, &child_count);
|
||||
}
|
||||
static size_t ts_lr_parser_breakdown_stack(ts_lr_parser *parser, ts_input_edit *edit) {
|
||||
if (!edit) return 0;
|
||||
|
||||
ts_tree *node;
|
||||
size_t position;
|
||||
|
||||
return right_position;
|
||||
for (;;) {
|
||||
node = ts_stack_top_node(&parser->stack);
|
||||
if (!node) break;
|
||||
|
||||
position = 0;
|
||||
for (size_t i = 0; i < parser->stack.size; i++) {
|
||||
ts_tree *node = parser->stack.entries[i].node;
|
||||
position += node->offset + node->size;
|
||||
}
|
||||
|
||||
size_t child_count = 0;
|
||||
ts_tree **children = ts_tree_children(node, &child_count);
|
||||
|
||||
if (position <= edit->position && !children) break;
|
||||
|
||||
parser->stack.size--;
|
||||
position -= (node->offset + node->size);
|
||||
|
||||
for (size_t i = 0; i < child_count && position < edit->position; i++) {
|
||||
ts_tree *child = children[i];
|
||||
|
||||
state_id state = ts_stack_top_state(&parser->stack);
|
||||
state_id next_state = ts_parse_actions[state][child->symbol].data.to_state;
|
||||
ts_stack_push(&parser->stack, next_state, child);
|
||||
ts_tree_retain(child);
|
||||
position += child->offset + child->size;
|
||||
}
|
||||
|
||||
ts_tree_release(node);
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
static void ts_lr_parser_initialize(ts_lr_parser *parser, ts_input input, ts_input_edit *edit) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ describe("incremental parsing", [&]() {
|
|||
})));
|
||||
});
|
||||
|
||||
describe("modifying the input", [&]() {
|
||||
describe("modifying the end of the input", [&]() {
|
||||
before_each([&]() {
|
||||
size_t position(string("{ \"key\": [1, 2]").length());
|
||||
string inserted_text(", \"key2\": 4");
|
||||
|
|
@ -69,6 +69,39 @@ describe("incremental parsing", [&]() {
|
|||
AssertThat(reader->strings_read[1], Equals(", \"key2\": 4 }"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("modifying the beginning of the input", [&]() {
|
||||
before_each([&]() {
|
||||
size_t position(string("{ ").length());
|
||||
string inserted_text("\"key2\": 4, ");
|
||||
|
||||
reader->content.insert(position, inserted_text);
|
||||
ts_document_edit(doc, {
|
||||
.position = position,
|
||||
.bytes_removed = 0,
|
||||
.bytes_inserted = inserted_text.length()
|
||||
});
|
||||
});
|
||||
|
||||
it("2 updates the parse tree", [&]() {
|
||||
AssertThat(string(ts_document_string(doc)), Equals(
|
||||
"(value "
|
||||
"(object "
|
||||
"(string) "
|
||||
"(value (number)) "
|
||||
"(string) "
|
||||
"(value (array "
|
||||
"(value (number)) "
|
||||
"(value (number))))))"
|
||||
));
|
||||
});
|
||||
|
||||
it_skip("re-reads only the changed portion of the input", [&]() {
|
||||
AssertThat(reader->strings_read.size(), Equals<size_t>(2));
|
||||
AssertThat(reader->strings_read[1], Equals("\"key2\": 4, "));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
END_TEST
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ namespace tree_sitter {
|
|||
body += _default("LEX_PANIC();");
|
||||
return _switch("LEX_STATE()", body);
|
||||
}
|
||||
|
||||
|
||||
string symbol_count() {
|
||||
return "#define TS_SYMBOL_COUNT " + to_string(parse_table.symbols.size());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ int ts_tree_equals(const ts_tree *node1, const ts_tree *node2) {
|
|||
}
|
||||
|
||||
ts_tree ** ts_tree_children(const ts_tree *tree, size_t *count) {
|
||||
if (tree->symbol == ts_builtin_sym_error) {
|
||||
if (!tree || tree->symbol == ts_builtin_sym_error) {
|
||||
if (count) *count = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -82,13 +82,13 @@ ts_tree ** ts_tree_children(const ts_tree *tree, size_t *count) {
|
|||
static size_t tree_write_to_string(const ts_tree *tree, const char **symbol_names, char *string, size_t limit, int is_beginning) {
|
||||
char *cursor = string;
|
||||
char **destination = (limit > 0) ? &cursor : &string;
|
||||
|
||||
|
||||
if (!tree)
|
||||
return snprintf(*destination, limit, "(NULL)");
|
||||
|
||||
if (!tree->is_hidden && !is_beginning)
|
||||
cursor += snprintf(*destination, limit, " ");
|
||||
|
||||
|
||||
if (tree->symbol == ts_builtin_sym_error) {
|
||||
cursor += snprintf(*destination, limit, "(ERROR)");
|
||||
return cursor - string;
|
||||
|
|
@ -104,7 +104,7 @@ static size_t tree_write_to_string(const ts_tree *tree, const char **symbol_name
|
|||
|
||||
if (!tree->is_hidden)
|
||||
cursor += snprintf(*destination, limit, ")");
|
||||
|
||||
|
||||
return cursor - string;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue