trimmed the fat
This commit is contained in:
parent
99e92e8d30
commit
d9bf7fa721
7 changed files with 156 additions and 4842 deletions
|
|
@ -1,501 +0,0 @@
|
||||||
#include "./get_changed_ranges.h"
|
|
||||||
#include "./subtree.h"
|
|
||||||
#include "./language.h"
|
|
||||||
#include "./error_costs.h"
|
|
||||||
#include "./tree_cursor.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
// #define DEBUG_GET_CHANGED_RANGES
|
|
||||||
|
|
||||||
static void ts_range_array_add(
|
|
||||||
TSRangeArray *self,
|
|
||||||
Length start,
|
|
||||||
Length end
|
|
||||||
) {
|
|
||||||
if (self->size > 0) {
|
|
||||||
TSRange *last_range = array_back(self);
|
|
||||||
if (start.bytes <= last_range->end_byte) {
|
|
||||||
last_range->end_byte = end.bytes;
|
|
||||||
last_range->end_point = end.extent;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start.bytes < end.bytes) {
|
|
||||||
TSRange range = { start.extent, end.extent, start.bytes, end.bytes };
|
|
||||||
array_push(self, range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ts_range_array_intersects(
|
|
||||||
const TSRangeArray *self,
|
|
||||||
unsigned start_index,
|
|
||||||
uint32_t start_byte,
|
|
||||||
uint32_t end_byte
|
|
||||||
) {
|
|
||||||
for (unsigned i = start_index; i < self->size; i++) {
|
|
||||||
TSRange *range = &self->contents[i];
|
|
||||||
if (range->end_byte > start_byte) {
|
|
||||||
if (range->start_byte >= end_byte) break;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ts_range_array_get_changed_ranges(
|
|
||||||
const TSRange *old_ranges, unsigned old_range_count,
|
|
||||||
const TSRange *new_ranges, unsigned new_range_count,
|
|
||||||
TSRangeArray *differences
|
|
||||||
) {
|
|
||||||
unsigned new_index = 0;
|
|
||||||
unsigned old_index = 0;
|
|
||||||
Length current_position = length_zero();
|
|
||||||
bool in_old_range = false;
|
|
||||||
bool in_new_range = false;
|
|
||||||
|
|
||||||
while (old_index < old_range_count || new_index < new_range_count) {
|
|
||||||
const TSRange *old_range = &old_ranges[old_index];
|
|
||||||
const TSRange *new_range = &new_ranges[new_index];
|
|
||||||
|
|
||||||
Length next_old_position;
|
|
||||||
if (in_old_range) {
|
|
||||||
next_old_position = (Length) {old_range->end_byte, old_range->end_point};
|
|
||||||
} else if (old_index < old_range_count) {
|
|
||||||
next_old_position = (Length) {old_range->start_byte, old_range->start_point};
|
|
||||||
} else {
|
|
||||||
next_old_position = LENGTH_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
Length next_new_position;
|
|
||||||
if (in_new_range) {
|
|
||||||
next_new_position = (Length) {new_range->end_byte, new_range->end_point};
|
|
||||||
} else if (new_index < new_range_count) {
|
|
||||||
next_new_position = (Length) {new_range->start_byte, new_range->start_point};
|
|
||||||
} else {
|
|
||||||
next_new_position = LENGTH_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_old_position.bytes < next_new_position.bytes) {
|
|
||||||
if (in_old_range != in_new_range) {
|
|
||||||
ts_range_array_add(differences, current_position, next_old_position);
|
|
||||||
}
|
|
||||||
if (in_old_range) old_index++;
|
|
||||||
current_position = next_old_position;
|
|
||||||
in_old_range = !in_old_range;
|
|
||||||
} else if (next_new_position.bytes < next_old_position.bytes) {
|
|
||||||
if (in_old_range != in_new_range) {
|
|
||||||
ts_range_array_add(differences, current_position, next_new_position);
|
|
||||||
}
|
|
||||||
if (in_new_range) new_index++;
|
|
||||||
current_position = next_new_position;
|
|
||||||
in_new_range = !in_new_range;
|
|
||||||
} else {
|
|
||||||
if (in_old_range != in_new_range) {
|
|
||||||
ts_range_array_add(differences, current_position, next_new_position);
|
|
||||||
}
|
|
||||||
if (in_old_range) old_index++;
|
|
||||||
if (in_new_range) new_index++;
|
|
||||||
in_old_range = !in_old_range;
|
|
||||||
in_new_range = !in_new_range;
|
|
||||||
current_position = next_new_position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
TreeCursor cursor;
|
|
||||||
const TSLanguage *language;
|
|
||||||
unsigned visible_depth;
|
|
||||||
bool in_padding;
|
|
||||||
} Iterator;
|
|
||||||
|
|
||||||
static Iterator iterator_new(
|
|
||||||
TreeCursor *cursor,
|
|
||||||
const Subtree *tree,
|
|
||||||
const TSLanguage *language
|
|
||||||
) {
|
|
||||||
array_clear(&cursor->stack);
|
|
||||||
array_push(&cursor->stack, ((TreeCursorEntry) {
|
|
||||||
.subtree = tree,
|
|
||||||
.position = length_zero(),
|
|
||||||
.child_index = 0,
|
|
||||||
.structural_child_index = 0,
|
|
||||||
}));
|
|
||||||
return (Iterator) {
|
|
||||||
.cursor = *cursor,
|
|
||||||
.language = language,
|
|
||||||
.visible_depth = 1,
|
|
||||||
.in_padding = false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool iterator_done(Iterator *self) {
|
|
||||||
return self->cursor.stack.size == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Length iterator_start_position(Iterator *self) {
|
|
||||||
TreeCursorEntry entry = *array_back(&self->cursor.stack);
|
|
||||||
if (self->in_padding) {
|
|
||||||
return entry.position;
|
|
||||||
} else {
|
|
||||||
return length_add(entry.position, ts_subtree_padding(*entry.subtree));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Length iterator_end_position(Iterator *self) {
|
|
||||||
TreeCursorEntry entry = *array_back(&self->cursor.stack);
|
|
||||||
Length result = length_add(entry.position, ts_subtree_padding(*entry.subtree));
|
|
||||||
if (self->in_padding) {
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
return length_add(result, ts_subtree_size(*entry.subtree));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool iterator_tree_is_visible(const Iterator *self) {
|
|
||||||
TreeCursorEntry entry = *array_back(&self->cursor.stack);
|
|
||||||
if (ts_subtree_visible(*entry.subtree)) return true;
|
|
||||||
if (self->cursor.stack.size > 1) {
|
|
||||||
Subtree parent = *self->cursor.stack.contents[self->cursor.stack.size - 2].subtree;
|
|
||||||
return ts_language_alias_at(
|
|
||||||
self->language,
|
|
||||||
parent.ptr->production_id,
|
|
||||||
entry.structural_child_index
|
|
||||||
) != 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iterator_get_visible_state(
|
|
||||||
const Iterator *self,
|
|
||||||
Subtree *tree,
|
|
||||||
TSSymbol *alias_symbol,
|
|
||||||
uint32_t *start_byte
|
|
||||||
) {
|
|
||||||
uint32_t i = self->cursor.stack.size - 1;
|
|
||||||
|
|
||||||
if (self->in_padding) {
|
|
||||||
if (i == 0) return;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i + 1 > 0; i--) {
|
|
||||||
TreeCursorEntry entry = self->cursor.stack.contents[i];
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
const Subtree *parent = self->cursor.stack.contents[i - 1].subtree;
|
|
||||||
*alias_symbol = ts_language_alias_at(
|
|
||||||
self->language,
|
|
||||||
parent->ptr->production_id,
|
|
||||||
entry.structural_child_index
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts_subtree_visible(*entry.subtree) || *alias_symbol) {
|
|
||||||
*tree = *entry.subtree;
|
|
||||||
*start_byte = entry.position.bytes;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iterator_ascend(Iterator *self) {
|
|
||||||
if (iterator_done(self)) return;
|
|
||||||
if (iterator_tree_is_visible(self) && !self->in_padding) self->visible_depth--;
|
|
||||||
if (array_back(&self->cursor.stack)->child_index > 0) self->in_padding = false;
|
|
||||||
self->cursor.stack.size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool iterator_descend(Iterator *self, uint32_t goal_position) {
|
|
||||||
if (self->in_padding) return false;
|
|
||||||
|
|
||||||
bool did_descend = false;
|
|
||||||
do {
|
|
||||||
did_descend = false;
|
|
||||||
TreeCursorEntry entry = *array_back(&self->cursor.stack);
|
|
||||||
Length position = entry.position;
|
|
||||||
uint32_t structural_child_index = 0;
|
|
||||||
for (uint32_t i = 0, n = ts_subtree_child_count(*entry.subtree); i < n; i++) {
|
|
||||||
const Subtree *child = &ts_subtree_children(*entry.subtree)[i];
|
|
||||||
Length child_left = length_add(position, ts_subtree_padding(*child));
|
|
||||||
Length child_right = length_add(child_left, ts_subtree_size(*child));
|
|
||||||
|
|
||||||
if (child_right.bytes > goal_position) {
|
|
||||||
array_push(&self->cursor.stack, ((TreeCursorEntry) {
|
|
||||||
.subtree = child,
|
|
||||||
.position = position,
|
|
||||||
.child_index = i,
|
|
||||||
.structural_child_index = structural_child_index,
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (iterator_tree_is_visible(self)) {
|
|
||||||
if (child_left.bytes > goal_position) {
|
|
||||||
self->in_padding = true;
|
|
||||||
} else {
|
|
||||||
self->visible_depth++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
did_descend = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
position = child_right;
|
|
||||||
if (!ts_subtree_extra(*child)) structural_child_index++;
|
|
||||||
}
|
|
||||||
} while (did_descend);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iterator_advance(Iterator *self) {
|
|
||||||
if (self->in_padding) {
|
|
||||||
self->in_padding = false;
|
|
||||||
if (iterator_tree_is_visible(self)) {
|
|
||||||
self->visible_depth++;
|
|
||||||
} else {
|
|
||||||
iterator_descend(self, 0);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (iterator_tree_is_visible(self)) self->visible_depth--;
|
|
||||||
TreeCursorEntry entry = array_pop(&self->cursor.stack);
|
|
||||||
if (iterator_done(self)) return;
|
|
||||||
|
|
||||||
const Subtree *parent = array_back(&self->cursor.stack)->subtree;
|
|
||||||
uint32_t child_index = entry.child_index + 1;
|
|
||||||
if (ts_subtree_child_count(*parent) > child_index) {
|
|
||||||
Length position = length_add(entry.position, ts_subtree_total_size(*entry.subtree));
|
|
||||||
uint32_t structural_child_index = entry.structural_child_index;
|
|
||||||
if (!ts_subtree_extra(*entry.subtree)) structural_child_index++;
|
|
||||||
const Subtree *next_child = &ts_subtree_children(*parent)[child_index];
|
|
||||||
|
|
||||||
array_push(&self->cursor.stack, ((TreeCursorEntry) {
|
|
||||||
.subtree = next_child,
|
|
||||||
.position = position,
|
|
||||||
.child_index = child_index,
|
|
||||||
.structural_child_index = structural_child_index,
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (iterator_tree_is_visible(self)) {
|
|
||||||
if (ts_subtree_padding(*next_child).bytes > 0) {
|
|
||||||
self->in_padding = true;
|
|
||||||
} else {
|
|
||||||
self->visible_depth++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iterator_descend(self, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
IteratorDiffers,
|
|
||||||
IteratorMayDiffer,
|
|
||||||
IteratorMatches,
|
|
||||||
} IteratorComparison;
|
|
||||||
|
|
||||||
static IteratorComparison iterator_compare(
|
|
||||||
const Iterator *old_iter,
|
|
||||||
const Iterator *new_iter
|
|
||||||
) {
|
|
||||||
Subtree old_tree = NULL_SUBTREE;
|
|
||||||
Subtree new_tree = NULL_SUBTREE;
|
|
||||||
uint32_t old_start = 0;
|
|
||||||
uint32_t new_start = 0;
|
|
||||||
TSSymbol old_alias_symbol = 0;
|
|
||||||
TSSymbol new_alias_symbol = 0;
|
|
||||||
iterator_get_visible_state(old_iter, &old_tree, &old_alias_symbol, &old_start);
|
|
||||||
iterator_get_visible_state(new_iter, &new_tree, &new_alias_symbol, &new_start);
|
|
||||||
|
|
||||||
if (!old_tree.ptr && !new_tree.ptr) return IteratorMatches;
|
|
||||||
if (!old_tree.ptr || !new_tree.ptr) return IteratorDiffers;
|
|
||||||
|
|
||||||
if (
|
|
||||||
old_alias_symbol == new_alias_symbol &&
|
|
||||||
ts_subtree_symbol(old_tree) == ts_subtree_symbol(new_tree)
|
|
||||||
) {
|
|
||||||
if (old_start == new_start &&
|
|
||||||
!ts_subtree_has_changes(old_tree) &&
|
|
||||||
ts_subtree_symbol(old_tree) != ts_builtin_sym_error &&
|
|
||||||
ts_subtree_size(old_tree).bytes == ts_subtree_size(new_tree).bytes &&
|
|
||||||
ts_subtree_parse_state(old_tree) != TS_TREE_STATE_NONE &&
|
|
||||||
ts_subtree_parse_state(new_tree) != TS_TREE_STATE_NONE &&
|
|
||||||
(ts_subtree_parse_state(old_tree) == ERROR_STATE) ==
|
|
||||||
(ts_subtree_parse_state(new_tree) == ERROR_STATE)) {
|
|
||||||
return IteratorMatches;
|
|
||||||
} else {
|
|
||||||
return IteratorMayDiffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IteratorDiffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_GET_CHANGED_RANGES
|
|
||||||
static inline void iterator_print_state(Iterator *self) {
|
|
||||||
TreeCursorEntry entry = *array_back(&self->cursor.stack);
|
|
||||||
TSPoint start = iterator_start_position(self).extent;
|
|
||||||
TSPoint end = iterator_end_position(self).extent;
|
|
||||||
const char *name = ts_language_symbol_name(self->language, ts_subtree_symbol(*entry.subtree));
|
|
||||||
printf(
|
|
||||||
"(%-25s %s\t depth:%u [%u, %u] - [%u, %u])",
|
|
||||||
name, self->in_padding ? "(p)" : " ",
|
|
||||||
self->visible_depth,
|
|
||||||
start.row + 1, start.column,
|
|
||||||
end.row + 1, end.column
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
unsigned ts_subtree_get_changed_ranges(
|
|
||||||
const Subtree *old_tree, const Subtree *new_tree,
|
|
||||||
TreeCursor *cursor1, TreeCursor *cursor2,
|
|
||||||
const TSLanguage *language,
|
|
||||||
const TSRangeArray *included_range_differences,
|
|
||||||
TSRange **ranges
|
|
||||||
) {
|
|
||||||
TSRangeArray results = array_new();
|
|
||||||
|
|
||||||
Iterator old_iter = iterator_new(cursor1, old_tree, language);
|
|
||||||
Iterator new_iter = iterator_new(cursor2, new_tree, language);
|
|
||||||
|
|
||||||
unsigned included_range_difference_index = 0;
|
|
||||||
|
|
||||||
Length position = iterator_start_position(&old_iter);
|
|
||||||
Length next_position = iterator_start_position(&new_iter);
|
|
||||||
if (position.bytes < next_position.bytes) {
|
|
||||||
ts_range_array_add(&results, position, next_position);
|
|
||||||
position = next_position;
|
|
||||||
} else if (position.bytes > next_position.bytes) {
|
|
||||||
ts_range_array_add(&results, next_position, position);
|
|
||||||
next_position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
#ifdef DEBUG_GET_CHANGED_RANGES
|
|
||||||
printf("At [%-2u, %-2u] Compare ", position.extent.row + 1, position.extent.column);
|
|
||||||
iterator_print_state(&old_iter);
|
|
||||||
printf("\tvs\t");
|
|
||||||
iterator_print_state(&new_iter);
|
|
||||||
puts("");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Compare the old and new subtrees.
|
|
||||||
IteratorComparison comparison = iterator_compare(&old_iter, &new_iter);
|
|
||||||
|
|
||||||
// Even if the two subtrees appear to be identical, they could differ
|
|
||||||
// internally if they contain a range of text that was previously
|
|
||||||
// excluded from the parse, and is now included, or vice-versa.
|
|
||||||
if (comparison == IteratorMatches && ts_range_array_intersects(
|
|
||||||
included_range_differences,
|
|
||||||
included_range_difference_index,
|
|
||||||
position.bytes,
|
|
||||||
iterator_end_position(&old_iter).bytes
|
|
||||||
)) {
|
|
||||||
comparison = IteratorMayDiffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_changed = false;
|
|
||||||
switch (comparison) {
|
|
||||||
// If the subtrees are definitely identical, move to the end
|
|
||||||
// of both subtrees.
|
|
||||||
case IteratorMatches:
|
|
||||||
next_position = iterator_end_position(&old_iter);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// If the subtrees might differ internally, descend into both
|
|
||||||
// subtrees, finding the first child that spans the current position.
|
|
||||||
case IteratorMayDiffer:
|
|
||||||
if (iterator_descend(&old_iter, position.bytes)) {
|
|
||||||
if (!iterator_descend(&new_iter, position.bytes)) {
|
|
||||||
is_changed = true;
|
|
||||||
next_position = iterator_end_position(&old_iter);
|
|
||||||
}
|
|
||||||
} else if (iterator_descend(&new_iter, position.bytes)) {
|
|
||||||
is_changed = true;
|
|
||||||
next_position = iterator_end_position(&new_iter);
|
|
||||||
} else {
|
|
||||||
next_position = length_min(
|
|
||||||
iterator_end_position(&old_iter),
|
|
||||||
iterator_end_position(&new_iter)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// If the subtrees are different, record a change and then move
|
|
||||||
// to the end of both subtrees.
|
|
||||||
case IteratorDiffers:
|
|
||||||
is_changed = true;
|
|
||||||
next_position = length_min(
|
|
||||||
iterator_end_position(&old_iter),
|
|
||||||
iterator_end_position(&new_iter)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that both iterators are caught up to the current position.
|
|
||||||
while (
|
|
||||||
!iterator_done(&old_iter) &&
|
|
||||||
iterator_end_position(&old_iter).bytes <= next_position.bytes
|
|
||||||
) iterator_advance(&old_iter);
|
|
||||||
while (
|
|
||||||
!iterator_done(&new_iter) &&
|
|
||||||
iterator_end_position(&new_iter).bytes <= next_position.bytes
|
|
||||||
) iterator_advance(&new_iter);
|
|
||||||
|
|
||||||
// Ensure that both iterators are at the same depth in the tree.
|
|
||||||
while (old_iter.visible_depth > new_iter.visible_depth) {
|
|
||||||
iterator_ascend(&old_iter);
|
|
||||||
}
|
|
||||||
while (new_iter.visible_depth > old_iter.visible_depth) {
|
|
||||||
iterator_ascend(&new_iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_changed) {
|
|
||||||
#ifdef DEBUG_GET_CHANGED_RANGES
|
|
||||||
printf(
|
|
||||||
" change: [[%u, %u] - [%u, %u]]\n",
|
|
||||||
position.extent.row + 1, position.extent.column,
|
|
||||||
next_position.extent.row + 1, next_position.extent.column
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ts_range_array_add(&results, position, next_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
position = next_position;
|
|
||||||
|
|
||||||
// Keep track of the current position in the included range differences
|
|
||||||
// array in order to avoid scanning the entire array on each iteration.
|
|
||||||
while (included_range_difference_index < included_range_differences->size) {
|
|
||||||
const TSRange *range = &included_range_differences->contents[
|
|
||||||
included_range_difference_index
|
|
||||||
];
|
|
||||||
if (range->end_byte <= position.bytes) {
|
|
||||||
included_range_difference_index++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!iterator_done(&old_iter) && !iterator_done(&new_iter));
|
|
||||||
|
|
||||||
Length old_size = ts_subtree_total_size(*old_tree);
|
|
||||||
Length new_size = ts_subtree_total_size(*new_tree);
|
|
||||||
if (old_size.bytes < new_size.bytes) {
|
|
||||||
ts_range_array_add(&results, old_size, new_size);
|
|
||||||
} else if (new_size.bytes < old_size.bytes) {
|
|
||||||
ts_range_array_add(&results, new_size, old_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
*cursor1 = old_iter.cursor;
|
|
||||||
*cursor2 = new_iter.cursor;
|
|
||||||
*ranges = results.contents;
|
|
||||||
return results.size;
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef TREE_SITTER_GET_CHANGED_RANGES_H_
|
|
||||||
#define TREE_SITTER_GET_CHANGED_RANGES_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "./tree_cursor.h"
|
|
||||||
#include "./subtree.h"
|
|
||||||
|
|
||||||
typedef Array(TSRange) TSRangeArray;
|
|
||||||
|
|
||||||
void ts_range_array_get_changed_ranges(
|
|
||||||
const TSRange *old_ranges, unsigned old_range_count,
|
|
||||||
const TSRange *new_ranges, unsigned new_range_count,
|
|
||||||
TSRangeArray *differences
|
|
||||||
);
|
|
||||||
|
|
||||||
bool ts_range_array_intersects(
|
|
||||||
const TSRangeArray *self, unsigned start_index,
|
|
||||||
uint32_t start_byte, uint32_t end_byte
|
|
||||||
);
|
|
||||||
|
|
||||||
unsigned ts_subtree_get_changed_ranges(
|
|
||||||
const Subtree *old_tree, const Subtree *new_tree,
|
|
||||||
TreeCursor *cursor1, TreeCursor *cursor2,
|
|
||||||
const TSLanguage *language,
|
|
||||||
const TSRangeArray *included_range_differences,
|
|
||||||
TSRange **ranges
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_GET_CHANGED_RANGES_H_
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
#define _POSIX_C_SOURCE 200112L
|
#define _POSIX_C_SOURCE 200112L
|
||||||
|
|
||||||
#include "./alloc.c"
|
#include "./alloc.c"
|
||||||
#include "./get_changed_ranges.c"
|
// #include "./get_changed_ranges.c"
|
||||||
#include "./language.c"
|
#include "./language.c"
|
||||||
#include "./lexer.c"
|
#include "./lexer.c"
|
||||||
#include "./node.c"
|
#include "./node.c"
|
||||||
#include "./parser.c"
|
#include "./parser.c"
|
||||||
#include "./query.c"
|
|
||||||
#include "./stack.c"
|
#include "./stack.c"
|
||||||
#include "./subtree.c"
|
#include "./subtree.c"
|
||||||
#include "./tree.c"
|
#include "./tree.c"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include "./atomic.h"
|
#include "./atomic.h"
|
||||||
#include "./clock.h"
|
#include "./clock.h"
|
||||||
#include "./error_costs.h"
|
#include "./error_costs.h"
|
||||||
#include "./get_changed_ranges.h"
|
|
||||||
#include "./language.h"
|
#include "./language.h"
|
||||||
#include "./length.h"
|
#include "./length.h"
|
||||||
#include "./lexer.h"
|
#include "./lexer.h"
|
||||||
|
|
@ -126,7 +125,6 @@ struct TSParser
|
||||||
unsigned operation_count;
|
unsigned operation_count;
|
||||||
const volatile size_t *cancellation_flag;
|
const volatile size_t *cancellation_flag;
|
||||||
Subtree old_tree;
|
Subtree old_tree;
|
||||||
TSRangeArray included_range_differences;
|
|
||||||
unsigned included_range_difference_index;
|
unsigned included_range_difference_index;
|
||||||
bool has_scanner_error;
|
bool has_scanner_error;
|
||||||
};
|
};
|
||||||
|
|
@ -709,11 +707,11 @@ static void ts_parser__set_cached_token(TSParser *self, uint32_t byte_index, Sub
|
||||||
cache->last_external_token = last_external_token;
|
cache->last_external_token = last_external_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ts_parser__has_included_range_difference(const TSParser *self, uint32_t start_position, uint32_t end_position)
|
// static bool ts_parser__has_included_range_difference(const TSParser *self, uint32_t start_position, uint32_t end_position)
|
||||||
{
|
// {
|
||||||
return ts_range_array_intersects(&self->included_range_differences, self->included_range_difference_index, start_position,
|
// return ts_range_array_intersects(&self->included_range_differences, self->included_range_difference_index, start_position,
|
||||||
end_position);
|
// end_position);
|
||||||
}
|
// }
|
||||||
|
|
||||||
static Subtree ts_parser__reuse_node(TSParser *self, StackVersion version, TSStateId *state, uint32_t position, Subtree last_external_token,
|
static Subtree ts_parser__reuse_node(TSParser *self, StackVersion version, TSStateId *state, uint32_t position, Subtree last_external_token,
|
||||||
TableEntry *table_entry)
|
TableEntry *table_entry)
|
||||||
|
|
@ -769,10 +767,10 @@ static Subtree ts_parser__reuse_node(TSParser *self, StackVersion version, TSSta
|
||||||
{
|
{
|
||||||
reason = "is_fragile";
|
reason = "is_fragile";
|
||||||
}
|
}
|
||||||
else if (ts_parser__has_included_range_difference(self, byte_offset, end_byte_offset))
|
// else if (ts_parser__has_included_range_difference(self, byte_offset, end_byte_offset))
|
||||||
{
|
// {
|
||||||
reason = "contains_different_included_range";
|
// reason = "contains_different_included_range";
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (reason)
|
if (reason)
|
||||||
{
|
{
|
||||||
|
|
@ -1857,7 +1855,6 @@ TSParser *ts_parser_new(void)
|
||||||
self->end_clock = clock_null();
|
self->end_clock = clock_null();
|
||||||
self->operation_count = 0;
|
self->operation_count = 0;
|
||||||
self->old_tree = NULL_SUBTREE;
|
self->old_tree = NULL_SUBTREE;
|
||||||
self->included_range_differences = (TSRangeArray)array_new();
|
|
||||||
self->included_range_difference_index = 0;
|
self->included_range_difference_index = 0;
|
||||||
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
||||||
return self;
|
return self;
|
||||||
|
|
@ -1874,10 +1871,6 @@ void ts_parser_delete(TSParser *self)
|
||||||
{
|
{
|
||||||
array_delete(&self->reduce_actions);
|
array_delete(&self->reduce_actions);
|
||||||
}
|
}
|
||||||
if (self->included_range_differences.contents)
|
|
||||||
{
|
|
||||||
array_delete(&self->included_range_differences);
|
|
||||||
}
|
|
||||||
if (self->old_tree.ptr)
|
if (self->old_tree.ptr)
|
||||||
{
|
{
|
||||||
ts_subtree_release(&self->tree_pool, self->old_tree);
|
ts_subtree_release(&self->tree_pool, self->old_tree);
|
||||||
|
|
@ -2011,6 +2004,7 @@ void ts_parser_reset(TSParser *self)
|
||||||
|
|
||||||
TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input)
|
TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input)
|
||||||
{
|
{
|
||||||
|
(void)(old_tree);
|
||||||
TSTree *result = NULL;
|
TSTree *result = NULL;
|
||||||
if (!self->language || !input.read)
|
if (!self->language || !input.read)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -2023,7 +2017,6 @@ TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input)
|
||||||
}
|
}
|
||||||
|
|
||||||
ts_lexer_set_input(&self->lexer, input);
|
ts_lexer_set_input(&self->lexer, input);
|
||||||
array_clear(&self->included_range_differences);
|
|
||||||
self->included_range_difference_index = 0;
|
self->included_range_difference_index = 0;
|
||||||
|
|
||||||
if (ts_parser_has_outstanding_parse(self))
|
if (ts_parser_has_outstanding_parse(self))
|
||||||
|
|
@ -2036,22 +2029,25 @@ TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input)
|
||||||
if (self->has_scanner_error)
|
if (self->has_scanner_error)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (old_tree)
|
// if (old_tree)
|
||||||
|
// {
|
||||||
|
// ts_subtree_retain(old_tree->root);
|
||||||
|
// self->old_tree = old_tree->root;
|
||||||
|
// ts_range_array_get_changed_ranges(old_tree->included_ranges, old_tree->included_range_count, self->lexer.included_ranges,
|
||||||
|
// self->lexer.included_range_count, &self->included_range_differences);
|
||||||
|
// reusable_node_reset(&self->reusable_node, old_tree->root);
|
||||||
|
// LOG("parse_after_edit");
|
||||||
|
// LOG_TREE(self->old_tree);
|
||||||
|
// for (unsigned i = 0; i < self->included_range_differences.size; i++)
|
||||||
|
// {
|
||||||
|
// TSRange *range = &self->included_range_differences.contents[i];
|
||||||
|
// LOG("different_included_range %u - %u", range->start_byte, range->end_byte);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
if (false)
|
||||||
{
|
{
|
||||||
ts_subtree_retain(old_tree->root);
|
|
||||||
self->old_tree = old_tree->root;
|
|
||||||
ts_range_array_get_changed_ranges(old_tree->included_ranges, old_tree->included_range_count, self->lexer.included_ranges,
|
|
||||||
self->lexer.included_range_count, &self->included_range_differences);
|
|
||||||
reusable_node_reset(&self->reusable_node, old_tree->root);
|
|
||||||
LOG("parse_after_edit");
|
|
||||||
LOG_TREE(self->old_tree);
|
|
||||||
for (unsigned i = 0; i < self->included_range_differences.size; i++)
|
|
||||||
{
|
|
||||||
TSRange *range = &self->included_range_differences.contents[i];
|
|
||||||
LOG("different_included_range %u - %u", range->start_byte, range->end_byte);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
{
|
||||||
reusable_node_clear(&self->reusable_node);
|
reusable_node_clear(&self->reusable_node);
|
||||||
LOG("new_parse");
|
LOG("new_parse");
|
||||||
|
|
@ -2112,18 +2108,6 @@ TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (self->included_range_difference_index < self->included_range_differences.size)
|
|
||||||
{
|
|
||||||
TSRange *range = &self->included_range_differences.contents[self->included_range_difference_index];
|
|
||||||
if (range->end_byte <= position)
|
|
||||||
{
|
|
||||||
self->included_range_difference_index++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (version_count != 0);
|
} while (version_count != 0);
|
||||||
|
|
||||||
assert(self->finished_tree.ptr);
|
assert(self->finished_tree.ptr);
|
||||||
|
|
|
||||||
4134
parser/src/query.c
4134
parser/src/query.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,165 +1,167 @@
|
||||||
#define _POSIX_C_SOURCE 200112L
|
#define _POSIX_C_SOURCE 200112L
|
||||||
|
|
||||||
#include "api.h"
|
#include "./tree.h"
|
||||||
#include "./array.h"
|
#include "./array.h"
|
||||||
#include "./get_changed_ranges.h"
|
|
||||||
#include "./length.h"
|
#include "./length.h"
|
||||||
#include "./subtree.h"
|
#include "./subtree.h"
|
||||||
#include "./tree_cursor.h"
|
#include "./tree_cursor.h"
|
||||||
#include "./tree.h"
|
#include "api.h"
|
||||||
|
|
||||||
TSTree *ts_tree_new(
|
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *included_ranges, unsigned included_range_count)
|
||||||
Subtree root, const TSLanguage *language,
|
{
|
||||||
const TSRange *included_ranges, unsigned included_range_count
|
TSTree *result = ts_malloc(sizeof(TSTree));
|
||||||
) {
|
result->root = root;
|
||||||
TSTree *result = ts_malloc(sizeof(TSTree));
|
result->language = ts_language_copy(language);
|
||||||
result->root = root;
|
result->included_ranges = ts_calloc(included_range_count, sizeof(TSRange));
|
||||||
result->language = ts_language_copy(language);
|
memcpy(result->included_ranges, included_ranges, included_range_count * sizeof(TSRange));
|
||||||
result->included_ranges = ts_calloc(included_range_count, sizeof(TSRange));
|
result->included_range_count = included_range_count;
|
||||||
memcpy(result->included_ranges, included_ranges, included_range_count * sizeof(TSRange));
|
return result;
|
||||||
result->included_range_count = included_range_count;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TSTree *ts_tree_copy(const TSTree *self) {
|
TSTree *ts_tree_copy(const TSTree *self)
|
||||||
ts_subtree_retain(self->root);
|
{
|
||||||
return ts_tree_new(self->root, self->language, self->included_ranges, self->included_range_count);
|
ts_subtree_retain(self->root);
|
||||||
|
return ts_tree_new(self->root, self->language, self->included_ranges, self->included_range_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_tree_delete(TSTree *self) {
|
void ts_tree_delete(TSTree *self)
|
||||||
if (!self) return;
|
{
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
SubtreePool pool = ts_subtree_pool_new(0);
|
SubtreePool pool = ts_subtree_pool_new(0);
|
||||||
ts_subtree_release(&pool, self->root);
|
ts_subtree_release(&pool, self->root);
|
||||||
ts_subtree_pool_delete(&pool);
|
ts_subtree_pool_delete(&pool);
|
||||||
ts_language_delete(self->language);
|
ts_language_delete(self->language);
|
||||||
ts_free(self->included_ranges);
|
ts_free(self->included_ranges);
|
||||||
ts_free(self);
|
ts_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSNode ts_tree_root_node(const TSTree *self) {
|
TSNode ts_tree_root_node(const TSTree *self)
|
||||||
return ts_node_new(self, &self->root, ts_subtree_padding(self->root), 0);
|
{
|
||||||
|
return ts_node_new(self, &self->root, ts_subtree_padding(self->root), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSNode ts_tree_root_node_with_offset(
|
TSNode ts_tree_root_node_with_offset(const TSTree *self, uint32_t offset_bytes, TSPoint offset_extent)
|
||||||
const TSTree *self,
|
{
|
||||||
uint32_t offset_bytes,
|
Length offset = {offset_bytes, offset_extent};
|
||||||
TSPoint offset_extent
|
return ts_node_new(self, &self->root, length_add(offset, ts_subtree_padding(self->root)), 0);
|
||||||
) {
|
|
||||||
Length offset = {offset_bytes, offset_extent};
|
|
||||||
return ts_node_new(self, &self->root, length_add(offset, ts_subtree_padding(self->root)), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TSLanguage *ts_tree_language(const TSTree *self) {
|
const TSLanguage *ts_tree_language(const TSTree *self)
|
||||||
return self->language;
|
{
|
||||||
|
return self->language;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_tree_edit(TSTree *self, const TSInputEdit *edit) {
|
void ts_tree_edit(TSTree *self, const TSInputEdit *edit)
|
||||||
for (unsigned i = 0; i < self->included_range_count; i++) {
|
{
|
||||||
TSRange *range = &self->included_ranges[i];
|
for (unsigned i = 0; i < self->included_range_count; i++)
|
||||||
if (range->end_byte >= edit->old_end_byte) {
|
{
|
||||||
if (range->end_byte != UINT32_MAX) {
|
TSRange *range = &self->included_ranges[i];
|
||||||
range->end_byte = edit->new_end_byte + (range->end_byte - edit->old_end_byte);
|
if (range->end_byte >= edit->old_end_byte)
|
||||||
range->end_point = point_add(
|
{
|
||||||
edit->new_end_point,
|
if (range->end_byte != UINT32_MAX)
|
||||||
point_sub(range->end_point, edit->old_end_point)
|
{
|
||||||
);
|
range->end_byte = edit->new_end_byte + (range->end_byte - edit->old_end_byte);
|
||||||
if (range->end_byte < edit->new_end_byte) {
|
range->end_point = point_add(edit->new_end_point, point_sub(range->end_point, edit->old_end_point));
|
||||||
range->end_byte = UINT32_MAX;
|
if (range->end_byte < edit->new_end_byte)
|
||||||
range->end_point = POINT_MAX;
|
{
|
||||||
}
|
range->end_byte = UINT32_MAX;
|
||||||
}
|
range->end_point = POINT_MAX;
|
||||||
} else if (range->end_byte > edit->start_byte) {
|
}
|
||||||
range->end_byte = edit->start_byte;
|
}
|
||||||
range->end_point = edit->start_point;
|
}
|
||||||
}
|
else if (range->end_byte > edit->start_byte)
|
||||||
if (range->start_byte >= edit->old_end_byte) {
|
{
|
||||||
range->start_byte = edit->new_end_byte + (range->start_byte - edit->old_end_byte);
|
range->end_byte = edit->start_byte;
|
||||||
range->start_point = point_add(
|
range->end_point = edit->start_point;
|
||||||
edit->new_end_point,
|
}
|
||||||
point_sub(range->start_point, edit->old_end_point)
|
if (range->start_byte >= edit->old_end_byte)
|
||||||
);
|
{
|
||||||
if (range->start_byte < edit->new_end_byte) {
|
range->start_byte = edit->new_end_byte + (range->start_byte - edit->old_end_byte);
|
||||||
range->start_byte = UINT32_MAX;
|
range->start_point = point_add(edit->new_end_point, point_sub(range->start_point, edit->old_end_point));
|
||||||
range->start_point = POINT_MAX;
|
if (range->start_byte < edit->new_end_byte)
|
||||||
}
|
{
|
||||||
} else if (range->start_byte > edit->start_byte) {
|
range->start_byte = UINT32_MAX;
|
||||||
range->start_byte = edit->start_byte;
|
range->start_point = POINT_MAX;
|
||||||
range->start_point = edit->start_point;
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (range->start_byte > edit->start_byte)
|
||||||
|
{
|
||||||
|
range->start_byte = edit->start_byte;
|
||||||
|
range->start_point = edit->start_point;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SubtreePool pool = ts_subtree_pool_new(0);
|
SubtreePool pool = ts_subtree_pool_new(0);
|
||||||
self->root = ts_subtree_edit(self->root, edit, &pool);
|
self->root = ts_subtree_edit(self->root, edit, &pool);
|
||||||
ts_subtree_pool_delete(&pool);
|
ts_subtree_pool_delete(&pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length) {
|
TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length)
|
||||||
*length = self->included_range_count;
|
{
|
||||||
TSRange *ranges = ts_calloc(self->included_range_count, sizeof(TSRange));
|
*length = self->included_range_count;
|
||||||
memcpy(ranges, self->included_ranges, self->included_range_count * sizeof(TSRange));
|
TSRange *ranges = ts_calloc(self->included_range_count, sizeof(TSRange));
|
||||||
return ranges;
|
memcpy(ranges, self->included_ranges, self->included_range_count * sizeof(TSRange));
|
||||||
|
return ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
TSRange *ts_tree_get_changed_ranges(const TSTree *old_tree, const TSTree *new_tree, uint32_t *length) {
|
// TSRange *ts_tree_get_changed_ranges(const TSTree *old_tree, const TSTree *new_tree, uint32_t *length)
|
||||||
TreeCursor cursor1 = {NULL, array_new(), 0};
|
// {
|
||||||
TreeCursor cursor2 = {NULL, array_new(), 0};
|
// TreeCursor cursor1 = {NULL, array_new(), 0};
|
||||||
ts_tree_cursor_init(&cursor1, ts_tree_root_node(old_tree));
|
// TreeCursor cursor2 = {NULL, array_new(), 0};
|
||||||
ts_tree_cursor_init(&cursor2, ts_tree_root_node(new_tree));
|
// ts_tree_cursor_init(&cursor1, ts_tree_root_node(old_tree));
|
||||||
|
// ts_tree_cursor_init(&cursor2, ts_tree_root_node(new_tree));
|
||||||
|
|
||||||
TSRangeArray included_range_differences = array_new();
|
// TSRangeArray included_range_differences = array_new();
|
||||||
ts_range_array_get_changed_ranges(
|
// ts_range_array_get_changed_ranges(old_tree->included_ranges, old_tree->included_range_count, new_tree->included_ranges,
|
||||||
old_tree->included_ranges, old_tree->included_range_count,
|
// new_tree->included_range_count, &included_range_differences);
|
||||||
new_tree->included_ranges, new_tree->included_range_count,
|
|
||||||
&included_range_differences
|
|
||||||
);
|
|
||||||
|
|
||||||
TSRange *result;
|
// TSRange *result;
|
||||||
*length = ts_subtree_get_changed_ranges(
|
// *length = ts_subtree_get_changed_ranges(&old_tree->root, &new_tree->root, &cursor1, &cursor2, old_tree->language,
|
||||||
&old_tree->root, &new_tree->root, &cursor1, &cursor2,
|
// &included_range_differences, &result);
|
||||||
old_tree->language, &included_range_differences, &result
|
|
||||||
);
|
|
||||||
|
|
||||||
array_delete(&included_range_differences);
|
// array_delete(&included_range_differences);
|
||||||
array_delete(&cursor1.stack);
|
// array_delete(&cursor1.stack);
|
||||||
array_delete(&cursor2.stack);
|
// array_delete(&cursor2.stack);
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include <io.h>
|
# include <io.h>
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
|
|
||||||
int _ts_dup(HANDLE handle) {
|
int _ts_dup(HANDLE handle)
|
||||||
HANDLE dup_handle;
|
{
|
||||||
if (!DuplicateHandle(
|
HANDLE dup_handle;
|
||||||
GetCurrentProcess(), handle,
|
if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &dup_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
GetCurrentProcess(), &dup_handle,
|
return -1;
|
||||||
0, FALSE, DUPLICATE_SAME_ACCESS
|
|
||||||
)) return -1;
|
|
||||||
|
|
||||||
return _open_osfhandle((intptr_t)dup_handle, 0);
|
return _open_osfhandle((intptr_t)dup_handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_tree_print_dot_graph(const TSTree *self, int fd) {
|
void ts_tree_print_dot_graph(const TSTree *self, int fd)
|
||||||
FILE *file = _fdopen(_ts_dup((HANDLE)_get_osfhandle(fd)), "a");
|
{
|
||||||
ts_subtree_print_dot_graph(self->root, self->language, file);
|
FILE *file = _fdopen(_ts_dup((HANDLE)_get_osfhandle(fd)), "a");
|
||||||
fclose(file);
|
ts_subtree_print_dot_graph(self->root, self->language, file);
|
||||||
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
|
|
||||||
int _ts_dup(int file_descriptor) {
|
int _ts_dup(int file_descriptor)
|
||||||
return dup(file_descriptor);
|
{
|
||||||
|
return dup(file_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor) {
|
void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor)
|
||||||
FILE *file = fdopen(_ts_dup(file_descriptor), "a");
|
{
|
||||||
ts_subtree_print_dot_graph(self->root, self->language, file);
|
FILE *file = fdopen(_ts_dup(file_descriptor), "a");
|
||||||
fclose(file);
|
ts_subtree_print_dot_graph(self->root, self->language, file);
|
||||||
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ static inline uint32_t ts_decode_ascii(const uint8_t *string, uint32_t length, i
|
||||||
|
|
||||||
static inline uint32_t ts_decode_utf8(const uint8_t *string, uint32_t length, int32_t *code_point)
|
static inline uint32_t ts_decode_utf8(const uint8_t *string, uint32_t length, int32_t *code_point)
|
||||||
{
|
{
|
||||||
return (ts_decode_ascii(string, length, code_point));
|
return (ts_decode_ascii(string, length, code_point));
|
||||||
/*
|
/*
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
U8_NEXT(string, i, length, *code_point);
|
U8_NEXT(string, i, length, *code_point);
|
||||||
return i;
|
return i;
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_decode_utf16(const uint8_t *string, uint32_t length, int32_t *code_point)
|
static inline uint32_t ts_decode_utf16(const uint8_t *string, uint32_t length, int32_t *code_point)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue