Add ts_tree_edit function
This commit is contained in:
parent
296d8cc1e8
commit
0467d190fe
5 changed files with 234 additions and 42 deletions
|
|
@ -8,6 +8,10 @@ static inline TSLength ts_length_add(TSLength len1, TSLength len2) {
|
|||
TSLength result;
|
||||
result.bytes = len1.bytes + len2.bytes;
|
||||
result.chars = len1.chars + len2.chars;
|
||||
|
||||
if ((len1.chars > 0 && len1.bytes == 0) || (len2.chars > 0 && len2.bytes == 0))
|
||||
result.bytes = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -15,6 +19,10 @@ static inline TSLength ts_length_sub(TSLength len1, TSLength len2) {
|
|||
TSLength result;
|
||||
result.bytes = len1.bytes - len2.bytes;
|
||||
result.chars = len1.chars - len2.chars;
|
||||
|
||||
if ((len1.chars > 0 && len1.bytes == 0) || (len2.chars > 0 && len2.bytes == 0))
|
||||
result.bytes = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ static TSTree *ts_lexer__accept(TSLexer *lexer, TSSymbol symbol,
|
|||
return ts_tree_make_error(size, padding, lexer->lookahead);
|
||||
} else {
|
||||
DEBUG("accept_token sym:%s", symbol_name);
|
||||
return ts_tree_make_leaf(symbol, size, padding, node_type);
|
||||
return ts_tree_make_leaf(symbol, padding, size, node_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "runtime/tree.h"
|
||||
#include "runtime/length.h"
|
||||
|
||||
TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength size, TSLength padding,
|
||||
TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength padding, TSLength size,
|
||||
TSNodeType node_type) {
|
||||
TSTree *result = malloc(sizeof(TSTree));
|
||||
*result = (TSTree){
|
||||
|
|
@ -31,7 +31,7 @@ TSTree *ts_tree_make_leaf(TSSymbol sym, TSLength size, TSLength padding,
|
|||
|
||||
TSTree *ts_tree_make_error(TSLength size, TSLength padding, char lookahead_char) {
|
||||
TSTree *result =
|
||||
ts_tree_make_leaf(ts_builtin_sym_error, size, padding, TSNodeTypeNamed);
|
||||
ts_tree_make_leaf(ts_builtin_sym_error, padding, size, TSNodeTypeNamed);
|
||||
result->lookahead_char = lookahead_char;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -194,3 +194,71 @@ void ts_tree_prepend_children(TSTree *tree, size_t count, TSTree **children) {
|
|||
|
||||
ts_tree__set_children(tree, new_children, new_child_count);
|
||||
}
|
||||
|
||||
static inline long min(long a, long b) {
|
||||
return a <= b ? a : b;
|
||||
}
|
||||
|
||||
void ts_tree_edit(TSTree *tree, TSInputEdit edit) {
|
||||
size_t start = edit.position;
|
||||
size_t old_end = edit.position + edit.chars_removed;
|
||||
size_t new_end = edit.position + edit.chars_inserted;
|
||||
|
||||
assert(start >= 0);
|
||||
assert(old_end <= ts_tree_total_size(tree).chars);
|
||||
|
||||
tree->options.has_changes = true;
|
||||
|
||||
if (start < tree->padding.chars) {
|
||||
tree->padding.bytes = 0;
|
||||
long remaining_padding = tree->padding.chars - old_end;
|
||||
if (remaining_padding >= 0) {
|
||||
tree->padding.chars = new_end + remaining_padding;
|
||||
} else {
|
||||
tree->padding.chars = new_end;
|
||||
tree->size.chars += remaining_padding;
|
||||
tree->size.bytes = 0;
|
||||
}
|
||||
} else if (start == tree->padding.chars && edit.chars_removed == 0) {
|
||||
tree->padding.bytes = 0;
|
||||
tree->padding.chars += edit.chars_inserted;
|
||||
} else {
|
||||
tree->size.bytes = 0;
|
||||
tree->size.chars += (edit.chars_inserted - edit.chars_removed);
|
||||
}
|
||||
|
||||
bool found_first_child = false;
|
||||
long remainder_to_delete = edit.chars_removed - edit.chars_inserted;
|
||||
size_t child_left = 0, child_right = 0;
|
||||
for (size_t i = 0; i < tree->child_count; i++) {
|
||||
TSTree *child = tree->children[i];
|
||||
size_t child_size = ts_tree_total_size(child).chars;
|
||||
child_left = child_right;
|
||||
child_right += child_size;
|
||||
|
||||
if (!found_first_child) {
|
||||
if (child_right >= start) {
|
||||
found_first_child = true;
|
||||
size_t chars_removed = min(edit.chars_removed, child_right - start);
|
||||
remainder_to_delete -= (chars_removed - edit.chars_inserted);
|
||||
ts_tree_edit(child, (TSInputEdit){
|
||||
.position = start - child_left,
|
||||
.chars_inserted = edit.chars_inserted,
|
||||
.chars_removed = chars_removed,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (remainder_to_delete > 0) {
|
||||
size_t chars_removed = min(remainder_to_delete, child_size);
|
||||
remainder_to_delete -= chars_removed;
|
||||
ts_tree_edit(child, (TSInputEdit){
|
||||
.position = 0,
|
||||
.chars_inserted = 0,
|
||||
.chars_removed = chars_removed,
|
||||
});
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct TSTree {
|
|||
bool extra : 1;
|
||||
bool fragile_left : 1;
|
||||
bool fragile_right : 1;
|
||||
bool has_changes : 1;
|
||||
} options;
|
||||
unsigned short int ref_count;
|
||||
};
|
||||
|
|
@ -76,6 +77,7 @@ char *ts_tree_string(const TSTree *tree, const char **names);
|
|||
char *ts_tree_error_string(const TSTree *tree, const char **names);
|
||||
TSLength ts_tree_total_size(const TSTree *tree);
|
||||
void ts_tree_prepend_children(TSTree *, size_t, TSTree **);
|
||||
void ts_tree_edit(TSTree *, TSInputEdit);
|
||||
|
||||
static inline bool ts_tree_is_empty(TSTree *tree) {
|
||||
return ts_tree_total_size(tree).bytes == 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue