UNPKG

web-tree-sitter

Version:
36 lines 799 kB
{ "version": 3, "sources": [ "../lib/alloc.c", "../lib/get_changed_ranges.c", "../lib/length.h", "../lib/array.h", "../lib/point.h", "../lib/subtree.h", "../lib/subtree.c", "../lib/language.c", "../lib/wasm_store.c", "../lib/language.h", "../lib/lexer.c", "../lib/unicode.h", "../lib/node.c", "../lib/tree.c", "../lib/point.c", "../lib/parser.c", "../lib/stack.c", "../lib/reusable_node.h", "../lib/atomic.h", "../lib/query.c", "../lib/tree_cursor.c", "../lib/reduce_action.h", "../lib/tree_cursor.h", "../lib/tree-sitter.c" ], "sourcesContent": [ "#include \"alloc.h\"\n#include \"tree_sitter/api.h\"\n#include <stdlib.h>\n\nstatic void *ts_malloc_default(size_t size) {\n void *result = malloc(size);\n if (size > 0 && !result) {\n fprintf(stderr, \"tree-sitter failed to allocate %zu bytes\", size);\n abort();\n }\n return result;\n}\n\nstatic void *ts_calloc_default(size_t count, size_t size) {\n void *result = calloc(count, size);\n if (count > 0 && !result) {\n fprintf(stderr, \"tree-sitter failed to allocate %zu bytes\", count * size);\n abort();\n }\n return result;\n}\n\nstatic void *ts_realloc_default(void *buffer, size_t size) {\n void *result = realloc(buffer, size);\n if (size > 0 && !result) {\n fprintf(stderr, \"tree-sitter failed to reallocate %zu bytes\", size);\n abort();\n }\n return result;\n}\n\n// Allow clients to override allocation functions dynamically\nTS_PUBLIC void *(*ts_current_malloc)(size_t) = ts_malloc_default;\nTS_PUBLIC void *(*ts_current_calloc)(size_t, size_t) = ts_calloc_default;\nTS_PUBLIC void *(*ts_current_realloc)(void *, size_t) = ts_realloc_default;\nTS_PUBLIC void (*ts_current_free)(void *) = free;\n\nvoid ts_set_allocator(\n void *(*new_malloc)(size_t size),\n void *(*new_calloc)(size_t count, size_t size),\n void *(*new_realloc)(void *ptr, size_t size),\n void (*new_free)(void *ptr)\n) {\n ts_current_malloc = new_malloc ? new_malloc : ts_malloc_default;\n ts_current_calloc = new_calloc ? new_calloc : ts_calloc_default;\n ts_current_realloc = new_realloc ? new_realloc : ts_realloc_default;\n ts_current_free = new_free ? new_free : free;\n}\n", "#include \"./get_changed_ranges.h\"\n#include \"./subtree.h\"\n#include \"./language.h\"\n#include \"./error_costs.h\"\n#include \"./tree_cursor.h\"\n#include \"./ts_assert.h\"\n\n// #define DEBUG_GET_CHANGED_RANGES\n\nstatic void ts_range_array_add(\n TSRangeArray *self,\n Length start,\n Length end\n) {\n if (self->size > 0) {\n TSRange *last_range = array_back(self);\n if (start.bytes <= last_range->end_byte) {\n last_range->end_byte = end.bytes;\n last_range->end_point = end.extent;\n return;\n }\n }\n\n if (start.bytes < end.bytes) {\n TSRange range = { start.extent, end.extent, start.bytes, end.bytes };\n array_push(self, range);\n }\n}\n\nbool ts_range_array_intersects(\n const TSRangeArray *self,\n unsigned start_index,\n uint32_t start_byte,\n uint32_t end_byte\n) {\n for (unsigned i = start_index; i < self->size; i++) {\n TSRange *range = array_get(self, i);\n if (range->end_byte > start_byte) {\n if (range->start_byte >= end_byte) break;\n return true;\n }\n }\n return false;\n}\n\nvoid ts_range_array_get_changed_ranges(\n const TSRange *old_ranges, unsigned old_range_count,\n const TSRange *new_ranges, unsigned new_range_count,\n TSRangeArray *differences\n) {\n unsigned new_index = 0;\n unsigned old_index = 0;\n Length current_position = length_zero();\n bool in_old_range = false;\n bool in_new_range = false;\n\n while (old_index < old_range_count || new_index < new_range_count) {\n const TSRange *old_range = &old_ranges[old_index];\n const TSRange *new_range = &new_ranges[new_index];\n\n Length next_old_position;\n if (in_old_range) {\n next_old_position = (Length) {old_range->end_byte, old_range->end_point};\n } else if (old_index < old_range_count) {\n next_old_position = (Length) {old_range->start_byte, old_range->start_point};\n } else {\n next_old_position = LENGTH_MAX;\n }\n\n Length next_new_position;\n if (in_new_range) {\n next_new_position = (Length) {new_range->end_byte, new_range->end_point};\n } else if (new_index < new_range_count) {\n next_new_position = (Length) {new_range->start_byte, new_range->start_point};\n } else {\n next_new_position = LENGTH_MAX;\n }\n\n if (next_old_position.bytes < next_new_position.bytes) {\n if (in_old_range != in_new_range) {\n ts_range_array_add(differences, current_position, next_old_position);\n }\n if (in_old_range) old_index++;\n current_position = next_old_position;\n in_old_range = !in_old_range;\n } else if (next_new_position.bytes < next_old_position.bytes) {\n if (in_old_range != in_new_range) {\n ts_range_array_add(differences, current_position, next_new_position);\n }\n if (in_new_range) new_index++;\n current_position = next_new_position;\n in_new_range = !in_new_range;\n } else {\n if (in_old_range != in_new_range) {\n ts_range_array_add(differences, current_position, next_new_position);\n }\n if (in_old_range) old_index++;\n if (in_new_range) new_index++;\n in_old_range = !in_old_range;\n in_new_range = !in_new_range;\n current_position = next_new_position;\n }\n }\n}\n\nvoid ts_range_edit(TSRange *range, const TSInputEdit *edit) {\n if (range->end_byte >= edit->old_end_byte) {\n if (range->end_byte != UINT32_MAX) {\n range->end_byte = edit->new_end_byte + (range->end_byte - edit->old_end_byte);\n range->end_point = point_add(\n edit->new_end_point,\n point_sub(range->end_point, edit->old_end_point)\n );\n if (range->end_byte < edit->new_end_byte) {\n range->end_byte = UINT32_MAX;\n range->end_point = POINT_MAX;\n }\n }\n } else if (range->end_byte > edit->start_byte) {\n range->end_byte = edit->start_byte;\n range->end_point = edit->start_point;\n }\n\n if (range->start_byte >= edit->old_end_byte) {\n range->start_byte = edit->new_end_byte + (range->start_byte - edit->old_end_byte);\n range->start_point = point_add(\n edit->new_end_point,\n point_sub(range->start_point, edit->old_end_point)\n );\n if (range->start_byte < edit->new_end_byte) {\n range->start_byte = UINT32_MAX;\n range->start_point = POINT_MAX;\n }\n } else if (range->start_byte > edit->start_byte) {\n range->start_byte = edit->start_byte;\n range->start_point = edit->start_point;\n }\n}\n\ntypedef struct {\n TreeCursor cursor;\n const TSLanguage *language;\n unsigned visible_depth;\n bool in_padding;\n Subtree prev_external_token;\n} Iterator;\n\nstatic Iterator iterator_new(\n TreeCursor *cursor,\n const Subtree *tree,\n const TSLanguage *language\n) {\n array_clear(&cursor->stack);\n array_push(&cursor->stack, ((TreeCursorEntry) {\n .subtree = tree,\n .position = length_zero(),\n .child_index = 0,\n .structural_child_index = 0,\n }));\n return (Iterator) {\n .cursor = *cursor,\n .language = language,\n .visible_depth = 1,\n .in_padding = false,\n .prev_external_token = NULL_SUBTREE,\n };\n}\n\nstatic bool iterator_done(Iterator *self) {\n return self->cursor.stack.size == 0;\n}\n\nstatic Length iterator_start_position(Iterator *self) {\n TreeCursorEntry entry = *array_back(&self->cursor.stack);\n if (self->in_padding) {\n return entry.position;\n } else {\n return length_add(entry.position, ts_subtree_padding(*entry.subtree));\n }\n}\n\nstatic Length iterator_end_position(Iterator *self) {\n TreeCursorEntry entry = *array_back(&self->cursor.stack);\n Length result = length_add(entry.position, ts_subtree_padding(*entry.subtree));\n if (self->in_padding) {\n return result;\n } else {\n return length_add(result, ts_subtree_size(*entry.subtree));\n }\n}\n\nstatic bool iterator_tree_is_visible(const Iterator *self) {\n TreeCursorEntry entry = *array_back(&self->cursor.stack);\n if (ts_subtree_visible(*entry.subtree)) return true;\n if (self->cursor.stack.size > 1) {\n Subtree parent = *array_get(&self->cursor.stack, self->cursor.stack.size - 2)->subtree;\n return ts_language_alias_at(\n self->language,\n parent.ptr->production_id,\n entry.structural_child_index\n ) != 0;\n }\n return false;\n}\n\nstatic void iterator_get_visible_state(\n const Iterator *self,\n Subtree *tree,\n TSSymbol *alias_symbol,\n uint32_t *start_byte\n) {\n uint32_t i = self->cursor.stack.size - 1;\n\n if (self->in_padding) {\n if (i == 0) return;\n i--;\n }\n\n for (; i + 1 > 0; i--) {\n TreeCursorEntry entry = *array_get(&self->cursor.stack, i);\n\n if (i > 0) {\n const Subtree *parent = array_get(&self->cursor.stack, i - 1)->subtree;\n *alias_symbol = ts_language_alias_at(\n self->language,\n parent->ptr->production_id,\n entry.structural_child_index\n );\n }\n\n if (ts_subtree_visible(*entry.subtree) || *alias_symbol) {\n *tree = *entry.subtree;\n *start_byte = entry.position.bytes;\n break;\n }\n }\n}\n\nstatic void iterator_ascend(Iterator *self) {\n if (iterator_done(self)) return;\n if (iterator_tree_is_visible(self) && !self->in_padding) self->visible_depth--;\n if (array_back(&self->cursor.stack)->child_index > 0) self->in_padding = false;\n self->cursor.stack.size--;\n}\n\nstatic bool iterator_descend(Iterator *self, uint32_t goal_position) {\n if (self->in_padding) return false;\n\n bool did_descend = false;\n do {\n did_descend = false;\n TreeCursorEntry entry = *array_back(&self->cursor.stack);\n Length position = entry.position;\n uint32_t structural_child_index = 0;\n for (uint32_t i = 0, n = ts_subtree_child_count(*entry.subtree); i < n; i++) {\n const Subtree *child = &ts_subtree_children(*entry.subtree)[i];\n Length child_left = length_add(position, ts_subtree_padding(*child));\n Length child_right = length_add(child_left, ts_subtree_size(*child));\n\n if (child_right.bytes > goal_position) {\n array_push(&self->cursor.stack, ((TreeCursorEntry) {\n .subtree = child,\n .position = position,\n .child_index = i,\n .structural_child_index = structural_child_index,\n }));\n\n if (iterator_tree_is_visible(self)) {\n if (child_left.bytes > goal_position) {\n self->in_padding = true;\n } else {\n self->visible_depth++;\n }\n return true;\n }\n\n did_descend = true;\n break;\n }\n\n position = child_right;\n if (!ts_subtree_extra(*child)) structural_child_index++;\n Subtree last_external_token = ts_subtree_last_external_token(*child);\n if (last_external_token.ptr) {\n self->prev_external_token = last_external_token;\n }\n }\n } while (did_descend);\n\n return false;\n}\n\nstatic void iterator_advance(Iterator *self) {\n if (self->in_padding) {\n self->in_padding = false;\n if (iterator_tree_is_visible(self)) {\n self->visible_depth++;\n } else {\n iterator_descend(self, 0);\n }\n return;\n }\n\n for (;;) {\n if (iterator_tree_is_visible(self)) self->visible_depth--;\n TreeCursorEntry entry = array_pop(&self->cursor.stack);\n if (iterator_done(self)) return;\n\n const Subtree *parent = array_back(&self->cursor.stack)->subtree;\n uint32_t child_index = entry.child_index + 1;\n Subtree last_external_token = ts_subtree_last_external_token(*entry.subtree);\n if (last_external_token.ptr) {\n self->prev_external_token = last_external_token;\n }\n if (ts_subtree_child_count(*parent) > child_index) {\n Length position = length_add(entry.position, ts_subtree_total_size(*entry.subtree));\n uint32_t structural_child_index = entry.structural_child_index;\n if (!ts_subtree_extra(*entry.subtree)) structural_child_index++;\n const Subtree *next_child = &ts_subtree_children(*parent)[child_index];\n\n array_push(&self->cursor.stack, ((TreeCursorEntry) {\n .subtree = next_child,\n .position = position,\n .child_index = child_index,\n .structural_child_index = structural_child_index,\n }));\n\n if (iterator_tree_is_visible(self)) {\n if (ts_subtree_padding(*next_child).bytes > 0) {\n self->in_padding = true;\n } else {\n self->visible_depth++;\n }\n } else {\n iterator_descend(self, 0);\n }\n break;\n }\n }\n}\n\ntypedef enum {\n IteratorDiffers,\n IteratorMayDiffer,\n IteratorMatches,\n} IteratorComparison;\n\nstatic IteratorComparison iterator_compare(\n const Iterator *old_iter,\n const Iterator *new_iter\n) {\n Subtree old_tree = NULL_SUBTREE;\n Subtree new_tree = NULL_SUBTREE;\n uint32_t old_start = 0;\n uint32_t new_start = 0;\n TSSymbol old_alias_symbol = 0;\n TSSymbol new_alias_symbol = 0;\n iterator_get_visible_state(old_iter, &old_tree, &old_alias_symbol, &old_start);\n iterator_get_visible_state(new_iter, &new_tree, &new_alias_symbol, &new_start);\n TSSymbol old_symbol = ts_subtree_symbol(old_tree);\n TSSymbol new_symbol = ts_subtree_symbol(new_tree);\n\n if (!old_tree.ptr && !new_tree.ptr) return IteratorMatches;\n if (!old_tree.ptr || !new_tree.ptr) return IteratorDiffers;\n if (old_alias_symbol != new_alias_symbol || old_symbol != new_symbol) return IteratorDiffers;\n\n uint32_t old_size = ts_subtree_size(old_tree).bytes;\n uint32_t new_size = ts_subtree_size(new_tree).bytes;\n TSStateId old_state = ts_subtree_parse_state(old_tree);\n TSStateId new_state = ts_subtree_parse_state(new_tree);\n bool old_has_external_tokens = ts_subtree_has_external_tokens(old_tree);\n bool new_has_external_tokens = ts_subtree_has_external_tokens(new_tree);\n uint32_t old_error_cost = ts_subtree_error_cost(old_tree);\n uint32_t new_error_cost = ts_subtree_error_cost(new_tree);\n\n if (\n old_start != new_start ||\n old_symbol == ts_builtin_sym_error ||\n old_size != new_size ||\n old_state == TS_TREE_STATE_NONE ||\n new_state == TS_TREE_STATE_NONE ||\n ((old_state == ERROR_STATE) != (new_state == ERROR_STATE)) ||\n old_error_cost != new_error_cost ||\n old_has_external_tokens != new_has_external_tokens ||\n ts_subtree_has_changes(old_tree) ||\n (\n old_has_external_tokens &&\n !ts_subtree_external_scanner_state_eq(old_iter->prev_external_token, new_iter->prev_external_token)\n )\n ) {\n return IteratorMayDiffer;\n }\n\n return IteratorMatches;\n}\n\n#ifdef DEBUG_GET_CHANGED_RANGES\nstatic inline void iterator_print_state(Iterator *self) {\n TreeCursorEntry entry = *array_back(&self->cursor.stack);\n TSPoint start = iterator_start_position(self).extent;\n TSPoint end = iterator_end_position(self).extent;\n const char *name = ts_language_symbol_name(self->language, ts_subtree_symbol(*entry.subtree));\n printf(\n \"(%-25s %s\\t depth:%u [%u, %u] - [%u, %u])\",\n name, self->in_padding ? \"(p)\" : \" \",\n self->visible_depth,\n start.row, start.column,\n end.row, end.column\n );\n}\n#endif\n\nunsigned ts_subtree_get_changed_ranges(\n const Subtree *old_tree, const Subtree *new_tree,\n TreeCursor *cursor1, TreeCursor *cursor2,\n const TSLanguage *language,\n const TSRangeArray *included_range_differences,\n TSRange **ranges\n) {\n TSRangeArray results = array_new();\n\n Iterator old_iter = iterator_new(cursor1, old_tree, language);\n Iterator new_iter = iterator_new(cursor2, new_tree, language);\n\n unsigned included_range_difference_index = 0;\n\n Length position = iterator_start_position(&old_iter);\n Length next_position = iterator_start_position(&new_iter);\n if (position.bytes < next_position.bytes) {\n ts_range_array_add(&results, position, next_position);\n position = next_position;\n } else if (position.bytes > next_position.bytes) {\n ts_range_array_add(&results, next_position, position);\n next_position = position;\n }\n\n do {\n #ifdef DEBUG_GET_CHANGED_RANGES\n printf(\"At [%-2u, %-2u] Compare \", position.extent.row, position.extent.column);\n iterator_print_state(&old_iter);\n printf(\"\\tvs\\t\");\n iterator_print_state(&new_iter);\n puts(\"\");\n #endif\n\n // Compare the old and new subtrees.\n IteratorComparison comparison = iterator_compare(&old_iter, &new_iter);\n\n // Even if the two subtrees appear to be identical, they could differ\n // internally if they contain a range of text that was previously\n // excluded from the parse, and is now included, or vice-versa.\n if (comparison == IteratorMatches && ts_range_array_intersects(\n included_range_differences,\n included_range_difference_index,\n position.bytes,\n iterator_end_position(&old_iter).bytes\n )) {\n comparison = IteratorMayDiffer;\n }\n\n bool is_changed = false;\n switch (comparison) {\n // If the subtrees are definitely identical, move to the end\n // of both subtrees.\n case IteratorMatches:\n next_position = iterator_end_position(&old_iter);\n break;\n\n // If the subtrees might differ internally, descend into both\n // subtrees, finding the first child that spans the current position.\n case IteratorMayDiffer:\n if (iterator_descend(&old_iter, position.bytes)) {\n if (!iterator_descend(&new_iter, position.bytes)) {\n is_changed = true;\n next_position = iterator_end_position(&old_iter);\n }\n } else if (iterator_descend(&new_iter, position.bytes)) {\n is_changed = true;\n next_position = iterator_end_position(&new_iter);\n } else {\n next_position = length_min(\n iterator_end_position(&old_iter),\n iterator_end_position(&new_iter)\n );\n }\n break;\n\n // If the subtrees are different, record a change and then move\n // to the end of both subtrees.\n case IteratorDiffers:\n is_changed = true;\n next_position = length_min(\n iterator_end_position(&old_iter),\n iterator_end_position(&new_iter)\n );\n break;\n }\n\n // Ensure that both iterators are caught up to the current position.\n while (\n !iterator_done(&old_iter) &&\n iterator_end_position(&old_iter).bytes <= next_position.bytes\n ) iterator_advance(&old_iter);\n while (\n !iterator_done(&new_iter) &&\n iterator_end_position(&new_iter).bytes <= next_position.bytes\n ) iterator_advance(&new_iter);\n\n // Ensure that both iterators are at the same depth in the tree.\n while (old_iter.visible_depth > new_iter.visible_depth) {\n iterator_ascend(&old_iter);\n }\n while (new_iter.visible_depth > old_iter.visible_depth) {\n iterator_ascend(&new_iter);\n }\n\n if (is_changed) {\n #ifdef DEBUG_GET_CHANGED_RANGES\n printf(\n \" change: [[%u, %u] - [%u, %u]]\\n\",\n position.extent.row + 1, position.extent.column,\n next_position.extent.row + 1, next_position.extent.column\n );\n #endif\n\n ts_range_array_add(&results, position, next_position);\n }\n\n position = next_position;\n\n // Keep track of the current position in the included range differences\n // array in order to avoid scanning the entire array on each iteration.\n while (included_range_difference_index < included_range_differences->size) {\n const TSRange *range = array_get(included_range_differences,\n included_range_difference_index\n );\n if (range->end_byte <= position.bytes) {\n included_range_difference_index++;\n } else {\n break;\n }\n }\n } while (!iterator_done(&old_iter) && !iterator_done(&new_iter));\n\n Length old_size = ts_subtree_total_size(*old_tree);\n Length new_size = ts_subtree_total_size(*new_tree);\n if (old_size.bytes < new_size.bytes) {\n ts_range_array_add(&results, old_size, new_size);\n } else if (new_size.bytes < old_size.bytes) {\n ts_range_array_add(&results, new_size, old_size);\n }\n\n *cursor1 = old_iter.cursor;\n *cursor2 = new_iter.cursor;\n *ranges = results.contents;\n return results.size;\n}\n", "#ifndef TREE_SITTER_LENGTH_H_\n#define TREE_SITTER_LENGTH_H_\n\n#include <stdlib.h>\n#include <stdbool.h>\n#include \"./point.h\"\n#include \"tree_sitter/api.h\"\n\ntypedef struct {\n uint32_t bytes;\n TSPoint extent;\n} Length;\n\nstatic const Length LENGTH_UNDEFINED = {0, {0, 1}};\nstatic const Length LENGTH_MAX = {UINT32_MAX, {UINT32_MAX, UINT32_MAX}};\n\nstatic inline bool length_is_undefined(Length length) {\n return length.bytes == 0 && length.extent.column != 0;\n}\n\nstatic inline Length length_min(Length len1, Length len2) {\n return (len1.bytes < len2.bytes) ? len1 : len2;\n}\n\nstatic inline Length length_add(Length len1, Length len2) {\n Length result;\n result.bytes = len1.bytes + len2.bytes;\n result.extent = point_add(len1.extent, len2.extent);\n return result;\n}\n\nstatic inline Length length_sub(Length len1, Length len2) {\n Length result;\n result.bytes = (len1.bytes >= len2.bytes) ? len1.bytes - len2.bytes : 0;\n result.extent = point_sub(len1.extent, len2.extent);\n return result;\n}\n\nstatic inline Length length_zero(void) {\n Length result = {0, {0, 0}};\n return result;\n}\n\nstatic inline Length length_saturating_sub(Length len1, Length len2) {\n if (len1.bytes > len2.bytes) {\n return length_sub(len1, len2);\n } else {\n return length_zero();\n }\n}\n\n#endif\n", "#ifndef TREE_SITTER_ARRAY_H_\n#define TREE_SITTER_ARRAY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"./alloc.h\"\n#include \"./ts_assert.h\"\n\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifdef _MSC_VER\n#pragma warning(push)\n#pragma warning(disable : 4101)\n#elif defined(__GNUC__) || defined(__clang__)\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n#endif\n\n#define Array(T) \\\n struct { \\\n T *contents; \\\n uint32_t size; \\\n uint32_t capacity; \\\n }\n\n/// Initialize an array.\n#define array_init(self) \\\n ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL)\n\n/// Create an empty array.\n#define array_new() \\\n { NULL, 0, 0 }\n\n/// Get a pointer to the element at a given `index` in the array.\n#define array_get(self, _index) \\\n (ts_assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index])\n\n/// Get a pointer to the first element in the array.\n#define array_front(self) array_get(self, 0)\n\n/// Get a pointer to the last element in the array.\n#define array_back(self) array_get(self, (self)->size - 1)\n\n/// Clear the array, setting its size to zero. Note that this does not free any\n/// memory allocated for the array's contents.\n#define array_clear(self) ((self)->size = 0)\n\n/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is\n/// less than the array's current capacity, this function has no effect.\n#define array_reserve(self, new_capacity) \\\n _array__reserve((Array *)(self), array_elem_size(self), new_capacity)\n\n/// Free any memory allocated for this array. Note that this does not free any\n/// memory allocated for the array's contents.\n#define array_delete(self) _array__delete((Array *)(self))\n\n/// Push a new `element` onto the end of the array.\n#define array_push(self, element) \\\n (_array__grow((Array *)(self), 1, array_elem_size(self)), \\\n (self)->contents[(self)->size++] = (element))\n\n/// Increase the array's size by `count` elements.\n/// New elements are zero-initialized.\n#define array_grow_by(self, count) \\\n do { \\\n if ((count) == 0) break; \\\n _array__grow((Array *)(self), count, array_elem_size(self)); \\\n memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \\\n (self)->size += (count); \\\n } while (0)\n\n/// Append all elements from one array to the end of another.\n#define array_push_all(self, other) \\\n array_extend((self), (other)->size, (other)->contents)\n\n/// Append `count` elements to the end of the array, reading their values from the\n/// `contents` pointer.\n#define array_extend(self, count, contents) \\\n _array__splice( \\\n (Array *)(self), array_elem_size(self), (self)->size, \\\n 0, count, contents \\\n )\n\n/// Remove `old_count` elements from the array starting at the given `index`. At\n/// the same index, insert `new_count` new elements, reading their values from the\n/// `new_contents` pointer.\n#define array_splice(self, _index, old_count, new_count, new_contents) \\\n _array__splice( \\\n (Array *)(self), array_elem_size(self), _index, \\\n old_count, new_count, new_contents \\\n )\n\n/// Insert one `element` into the array at the given `index`.\n#define array_insert(self, _index, element) \\\n _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element))\n\n/// Remove one element from the array at the given `index`.\n#define array_erase(self, _index) \\\n _array__erase((Array *)(self), array_elem_size(self), _index)\n\n/// Pop the last element off the array, returning the element by value.\n#define array_pop(self) ((self)->contents[--(self)->size])\n\n/// Assign the contents of one array to another, reallocating if necessary.\n#define array_assign(self, other) \\\n _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self))\n\n/// Swap one array with another\n#define array_swap(self, other) \\\n _array__swap((Array *)(self), (Array *)(other))\n\n/// Get the size of the array contents\n#define array_elem_size(self) (sizeof *(self)->contents)\n\n/// Search a sorted array for a given `needle` value, using the given `compare`\n/// callback to determine the order.\n///\n/// If an existing element is found to be equal to `needle`, then the `index`\n/// out-parameter is set to the existing value's index, and the `exists`\n/// out-parameter is set to true. Otherwise, `index` is set to an index where\n/// `needle` should be inserted in order to preserve the sorting, and `exists`\n/// is set to false.\n#define array_search_sorted_with(self, compare, needle, _index, _exists) \\\n _array__search_sorted(self, 0, compare, , needle, _index, _exists)\n\n/// Search a sorted array for a given `needle` value, using integer comparisons\n/// of a given struct field (specified with a leading dot) to determine the order.\n///\n/// See also `array_search_sorted_with`.\n#define array_search_sorted_by(self, field, needle, _index, _exists) \\\n _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists)\n\n/// Insert a given `value` into a sorted array, using the given `compare`\n/// callback to determine the order.\n#define array_insert_sorted_with(self, compare, value) \\\n do { \\\n unsigned _index, _exists; \\\n array_search_sorted_with(self, compare, &(value), &_index, &_exists); \\\n if (!_exists) array_insert(self, _index, value); \\\n } while (0)\n\n/// Insert a given `value` into a sorted array, using integer comparisons of\n/// a given struct field (specified with a leading dot) to determine the order.\n///\n/// See also `array_search_sorted_by`.\n#define array_insert_sorted_by(self, field, value) \\\n do { \\\n unsigned _index, _exists; \\\n array_search_sorted_by(self, field, (value) field, &_index, &_exists); \\\n if (!_exists) array_insert(self, _index, value); \\\n } while (0)\n\n// Private\n\ntypedef Array(void) Array;\n\n/// This is not what you're looking for, see `array_delete`.\nstatic inline void _array__delete(Array *self) {\n if (self->contents) {\n ts_free(self->contents);\n self->contents = NULL;\n self->size = 0;\n self->capacity = 0;\n }\n}\n\n/// This is not what you're looking for, see `array_erase`.\nstatic inline void _array__erase(Array *self, size_t element_size,\n uint32_t index) {\n ts_assert(index < self->size);\n char *contents = (char *)self->contents;\n memmove(contents + index * element_size, contents + (index + 1) * element_size,\n (self->size - index - 1) * element_size);\n self->size--;\n}\n\n/// This is not what you're looking for, see `array_reserve`.\nstatic inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) {\n if (new_capacity > self->capacity) {\n if (self->contents) {\n self->contents = ts_realloc(self->contents, new_capacity * element_size);\n } else {\n self->contents = ts_malloc(new_capacity * element_size);\n }\n self->capacity = new_capacity;\n }\n}\n\n/// This is not what you're looking for, see `array_assign`.\nstatic inline void _array__assign(Array *self, const Array *other, size_t element_size) {\n _array__reserve(self, element_size, other->size);\n self->size = other->size;\n memcpy(self->contents, other->contents, self->size * element_size);\n}\n\n/// This is not what you're looking for, see `array_swap`.\nstatic inline void _array__swap(Array *self, Array *other) {\n Array swap = *other;\n *other = *self;\n *self = swap;\n}\n\n/// This is not what you're looking for, see `array_push` or `array_grow_by`.\nstatic inline void _array__grow(Array *self, uint32_t count, size_t element_size) {\n uint32_t new_size = self->size + count;\n if (new_size > self->capacity) {\n uint32_t new_capacity = self->capacity * 2;\n if (new_capacity < 8) new_capacity = 8;\n if (new_capacity < new_size) new_capacity = new_size;\n _array__reserve(self, element_size, new_capacity);\n }\n}\n\n/// This is not what you're looking for, see `array_splice`.\nstatic inline void _array__splice(Array *self, size_t element_size,\n uint32_t index, uint32_t old_count,\n uint32_t new_count, const void *elements) {\n uint32_t new_size = self->size + new_count - old_count;\n uint32_t old_end = index + old_count;\n uint32_t new_end = index + new_count;\n ts_assert(old_end <= self->size);\n\n _array__reserve(self, element_size, new_size);\n\n char *contents = (char *)self->contents;\n if (self->size > old_end) {\n memmove(\n contents + new_end * element_size,\n contents + old_end * element_size,\n (self->size - old_end) * element_size\n );\n }\n if (new_count > 0) {\n if (elements) {\n memcpy(\n (contents + index * element_size),\n elements,\n new_count * element_size\n );\n } else {\n memset(\n (contents + index * element_size),\n 0,\n new_count * element_size\n );\n }\n }\n self->size += new_count - old_count;\n}\n\n/// A binary search routine, based on Rust's `std::slice::binary_search_by`.\n/// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`.\n#define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \\\n do { \\\n *(_index) = start; \\\n *(_exists) = false; \\\n uint32_t size = (self)->size - *(_index); \\\n if (size == 0) break; \\\n int comparison; \\\n while (size > 1) { \\\n uint32_t half_size = size / 2; \\\n uint32_t mid_index = *(_index) + half_size; \\\n comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \\\n if (comparison <= 0) *(_index) = mid_index; \\\n size -= half_size; \\\n } \\\n comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \\\n if (comparison == 0) *(_exists) = true; \\\n else if (comparison < 0) *(_index) += 1; \\\n } while (0)\n\n/// Helper macro for the `_sorted_by` routines below. This takes the left (existing)\n/// parameter by reference in order to work with the generic sorting function above.\n#define _compare_int(a, b) ((int)*(a) - (int)(b))\n\n#ifdef _MSC_VER\n#pragma warning(pop)\n#elif defined(__GNUC__) || defined(__clang__)\n#pragma GCC diagnostic pop\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // TREE_SITTER_ARRAY_H_\n", "#ifndef TREE_SITTER_POINT_H_\n#define TREE_SITTER_POINT_H_\n\n#include \"tree_sitter/api.h\"\n\n#define POINT_ZERO ((TSPoint) {0, 0})\n#define POINT_MAX ((TSPoint) {UINT32_MAX, UINT32_MAX})\n\nstatic inline TSPoint point__new(unsigned row, unsigned column) {\n TSPoint result = {row, column};\n return result;\n}\n\nstatic inline TSPoint point_add(TSPoint a, TSPoint b) {\n if (b.row > 0)\n return point__new(a.row + b.row, b.column);\n else\n return point__new(a.row, a.column + b.column);\n}\n\nstatic inline TSPoint point_sub(TSPoint a, TSPoint b) {\n if (a.row > b.row)\n return point__new(a.row - b.row, a.column);\n else\n return point__new(0, (a.column >= b.column) ? a.column - b.column : 0);\n}\n\nstatic inline bool point_lte(TSPoint a, TSPoint b) {\n return (a.row < b.row) || (a.row == b.row && a.column <= b.column);\n}\n\nstatic inline bool point_lt(TSPoint a, TSPoint b) {\n return (a.row < b.row) || (a.row == b.row && a.column < b.column);\n}\n\nstatic inline bool point_gt(TSPoint a, TSPoint b) {\n return (a.row > b.row) || (a.row == b.row && a.column > b.column);\n}\n\nstatic inline bool point_gte(TSPoint a, TSPoint b) {\n return (a.row > b.row) || (a.row == b.row && a.column >= b.column);\n}\n\nstatic inline bool point_eq(TSPoint a, TSPoint b) {\n return a.row == b.row && a.column == b.column;\n}\n\n#endif\n", "#ifndef TREE_SITTER_SUBTREE_H_\n#define TREE_SITTER_SUBTREE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <limits.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include \"./length.h\"\n#include \"./array.h\"\n#include \"./error_costs.h\"\n#include \"./host.h\"\n#include \"tree_sitter/api.h\"\n#include \"./parser.h\"\n\n#define TS_TREE_STATE_NONE USHRT_MAX\n#define NULL_SUBTREE ((Subtree) {.ptr = NULL})\n\n// The serialized state of an external scanner.\n//\n// Every time an external token subtree is created after a call to an\n// external scanner, the scanner's `serialize` function is called to\n// retrieve a serialized copy of its state. The bytes are then copied\n// onto the subtree itself so that the scanner's state can later be\n// restored using its `deserialize` function.\n//\n// Small byte arrays are stored inline, and long ones are allocated\n// separately on the heap.\ntypedef struct {\n union {\n char *long_data;\n char short_data[24];\n };\n uint32_t length;\n} ExternalScannerState;\n\n// A compact representation of a subtree.\n//\n// This representation is used for small leaf nodes that are not\n// errors, and were not created by an external scanner.\n//\n// The idea behind the layout of this struct is that the `is_inline`\n// bit will fall exactly into the same location as the least significant\n// bit of the pointer in `Subtree` or `MutableSubtree`, respectively.\n// Because of alignment, for any valid pointer this will be 0, giving\n// us the opportunity to make use of this bit to signify whether to use\n// the pointer or the inline struct.\ntypedef struct SubtreeInlineData SubtreeInlineData;\n\n#define SUBTREE_BITS \\\n bool visible : 1; \\\n bool named : 1; \\\n bool extra : 1; \\\n bool has_changes : 1; \\\n bool is_missing : 1; \\\n bool is_keyword : 1;\n\n#define SUBTREE_SIZE \\\n uint8_t padding_columns; \\\n uint8_t padding_rows : 4; \\\n uint8_t lookahead_bytes : 4; \\\n uint8_t padding_bytes; \\\n uint8_t size_bytes;\n\n#if TS_BIG_ENDIAN\n#if TS_PTR_SIZE == 32\n\nstruct SubtreeInlineData {\n uint16_t parse_state;\n uint8_t symbol;\n SUBTREE_BITS\n bool unused : 1;\n bool is_inline : 1;\n SUBTREE_SIZE\n};\n\n#else\n\nstruct SubtreeInlineData {\n SUBTREE_SIZE\n uint16_t parse_state;\n uint8_t symbol;\n SUBTREE_BITS\n bool unused : 1;\n bool is_inline : 1;\n};\n\n#endif\n#else\n\nstruct SubtreeInlineData {\n bool is_inline : 1;\n SUBTREE_BITS\n uint8_t symbol;\n uint16_t parse_state;\n SUBTREE_SIZE\n};\n\n#endif\n\n#undef SUBTREE_BITS\n#undef SUBTREE_SIZE\n\n// A heap-allocated representation of a subtree.\n//\n// This representation is used for parent nodes, external tokens,\n// errors, and other leaf nodes whose data is too large to fit into\n// the inline representation.\ntypedef struct {\n volatile uint32_t ref_count;\n Length padding;\n Length size;\n uint32_t lookahead_bytes;\n uint32_t error_cost;\n uint32_t child_count;\n TSSymbol symbol;\n TSStateId parse_state;\n\n bool visible : 1;\n bool named : 1;\n bool extra : 1;\n bool fragile_left : 1;\n bool fragile_right : 1;\n bool has_changes : 1;\n bool has_external_tokens : 1;\n bool has_external_scanner_state_change : 1;\n bool depends_on_column: 1;\n bool is_missing : 1;\n bool is_keyword : 1;\n\n union {\n // Non-terminal subtrees (`child_count > 0`)\n struct {\n uint32_t visible_child_count;\n uint32_t named_child_count;\n uint32_t visible_descendant_count;\n int32_t dynamic_precedence;\n uint16_t repeat_depth;\n uint16_t production_id;\n struct {\n TSSymbol symbol;\n TSStateId parse_state;\n } first_leaf;\n };\n\n // External terminal subtrees (`child_count == 0 && has_external_tokens`)\n ExternalScannerState external_scanner_state;\n\n // Error terminal subtrees (`child_count == 0 && symbol == ts_builtin_sym_error`)\n int32_t lookahead_char;\n };\n} SubtreeHeapData;\n\n// The fundamental building block of a syntax tree.\ntypedef union {\n SubtreeInlineData data;\n const SubtreeHeapData *ptr;\n} Subtree;\n\n// Like Subtree, but mutable.\ntypedef union {\n SubtreeInlineData data;\n SubtreeHeapData *ptr;\n} MutableSubtree;\n\ntypedef Array(Subtree) SubtreeArray;\ntypedef Array(MutableSubtree) MutableSubtreeArray;\n\ntypedef struct {\n MutableSubtreeArray free_trees;\n MutableSubtreeArray tree_stack;\n} SubtreePool;\n\nvoid ts_external_scanner_state_init(ExternalScannerState *self, const char *data, unsigned length);\nconst char *ts_external_scanner_state_data(const ExternalScannerState *self);\nbool ts_external_scanner_state_eq(const ExternalScannerState *self, const char *buffer, unsigned length);\nvoid ts_external_scanner_state_delete(ExternalScannerState *self);\n\nvoid ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest);\nvoid ts_subtree_array_clear(SubtreePool *pool, SubtreeArray *self);\nvoid ts_subtree_array_delete(SubtreePool *pool, SubtreeArray *self);\nvoid ts_subtree_array_remove_trailing_extras(SubtreeArray *self, SubtreeArray *destination);\nvoid ts_subtree_array_reverse(SubtreeArray *self);\n\nSubtreePool ts_subtree_pool_new(uint32_t capacity);\nvoid ts_subtree_pool_delete(SubtreePool *self);\n\nSubtree ts_subtree_new_leaf(\n SubtreePool *pool, TSSymbol symbol, Length padding, Length size,\n uint32_t lookahead_bytes, TSStateId parse_state,\n bool has_external_tokens, bool depends_on_column,\n bool is_keyword, const TSLanguage *language\n);\nSubtree ts_subtree_new_error(\n SubtreePool *pool, int32_t lookahead_char, Length padding, Length size,\n uint32_t bytes_scanned, TSStateId parse_state, const TSLanguage *language\n);\nMutableSubtree ts_subtree_new_node(\n TSSymbol symbol,\n SubtreeArray *chiildren,\n unsigned production_id,\n const TSLanguage *language\n);\nSubtree ts_subtree_new_error_node(\n SubtreeArray *children,\n bool extra,\n const TSLanguage * language\n);\nSubtree ts_subtree_new_missing_leaf(\n SubtreePool *pool,\n TSSymbol symbol,\n Length padding,\n uint32_t lookahead_bytes,\n const TSLanguage *language\n);\nMutableSubtree ts_subtree_make_mut(SubtreePool *pool, Subtree self);\nvoid ts_subtree_retain(Subtree self);\nvoid ts_subtree_release(SubtreePool *pool, Subtree self);\nint ts_subtree_compare(Subtree left, Subtree right, SubtreePool *pool);\nvoid ts_subtree_set_symbol(MutableSubtree *self, TSSymbol symbol, const TSLanguage *language);\nvoid ts_subtree_compress(MutableSubtree self, unsigned count, const TSLanguage *language, MutableSubtreeArray *stack);\nvoid ts_subtree_summarize_children(MutableSubtree self, const TSLanguage *language);\nSubtree ts_subtree_edit(Subtree self, const TSInputEdit *edit, SubtreePool *pool);\nchar *ts_subtree_string(Subtree self, TSSymbol alias_symbol, bool alias_is_named, const TSLanguage *language, bool include_all);\nvoid ts_subtree_print_dot_graph(Subtree self, const TSLanguage *language, FILE *f);\nSubtree ts_subtree_last_external_token(Subtree tree);\nconst ExternalScannerState *ts_subtree_external_scanner_state(Subtree self);\nbool ts_subtree_external_scanner_state_eq(Subtree self, Subtree other);\n\n#define SUBTREE_GET(self, name) ((self).data.is_inline ? (self).data.name : (self).ptr->name)\n\nstatic inline TSSymbol ts_subtree_symbol(Subtree self) { return SUBTREE_GET(self, symbol); }\nstatic inline bool ts_subtree_visible(Subtree self) { return SUBTREE_GET(self, visible); }\nstatic inline bool ts_subtree_named(Subtree self) { return SUBTREE_GET(self, named); }\nstatic inline bool ts_subtree_extra(Subtree self) { return SUBTREE_GET(self, extra); }\nstatic inline bool ts_subtree_has_changes(Subtree self) { return SUBTREE_GET(self, has_changes); }\nstatic inline bool ts_subtree_missing(Subtree self) { return SUBTREE_GET(self, is_missing); }\nstatic inline bool ts_subtree_is_keyword(Subtree self) { return SUBTREE_GET(self, is_keyword); }\nstatic inline TSStateId ts_subtree_parse_state(Subtree self) { return SUBTREE_GET(self, parse_state); }\nstatic inline uint32_t ts_subtree_lookahead_bytes(Subtree self) { return SUBTREE_GET(self, lookahead_bytes); }\n\n#undef SUBTREE_GET\n\n// Get the size needed to store a heap-allocated subtree with the given\n// number of children.\nstatic inline size_t ts_subtree_alloc_size(uint32_t child_count) {\n return child_count * sizeof(Subtree) + sizeof(SubtreeHeapData);\n}\n\n// Get a subtree's children, which are allocated immediately before the\n// tree's own heap data.\n#define ts_subtree_children(self) \\\n ((self).data.is_inline ? NULL : (Subtree *)((self).ptr) - (self).ptr->child_count)\n\nstatic inline void ts_subtree_set_extra(MutableSubtree *self, bool is_extra) {\n if (self->data.is_inline) {\n self->data.extra = is_extra;\n } else {\n self->ptr->extra = is_extra;\n }\n}\n\nstatic inline TSSymbol ts_subtree_leaf_symbol(Subtree self) {\n if (self.data.is_inline) return self.data.symbol;\n if (self.ptr->child_count == 0) return self.ptr->symbol;\n return self.ptr->first_leaf.symbol;\n}\n\nstatic inline TSStateId ts_subtree_leaf_parse_state(Subtree self) {\n if (self.data.is_inline) return self.data.parse_state;\n if (self.ptr->child_count == 0) return self.ptr->parse_state;\n return self.ptr->first_leaf.parse_state;\n}\n\nstatic inline Length ts_subtree_padding(Subtree self) {\n if (self.data.is_inline) {\n Length result = {self.data.padding_bytes, {self.data.padding_rows, self.data.padding_columns}};\n return result;\n } else {\n return self.ptr->padding;\n }\n}\n\nstatic inline Length ts_subtree_size(Subtree self) {\n if (self.data.is_inline) {\n Length result = {self.data.size_bytes, {0, self.data.size_bytes}};\n return result;\n } else {\n return self.ptr->size;\n }\n}\n\nstatic inline Length ts_subtree_total_size(Subtree self) {\n return length_add(ts_subtree_padding(self), ts_subtree_size(self));\n}\n\nstatic inline uint32_t ts_subtree_total_bytes(Subtree self) {\n return ts_subtree_total_size(self).bytes;\n}\n\nstatic inline uint32_t ts_subtree_child_count(Subtree self) {\n return self.data.is_inline ? 0 : self.ptr->child_count;\n}\n\nstatic inline uint32_t ts_subtree_repeat_depth(Subtree self) {\n return self.data.is_inline ? 0 : self.ptr->repeat_depth;\n}\n\nstatic inline uint32_t ts_subtree_is_repetition(Subtree self) {\n return self.data.is_inline\n ? 0\n : !self.ptr->named && !self.ptr->visible && self.ptr->child_count != 0;\n}\n\nstatic inline uint32_t ts_subtree_visible_descendant_count(Subtree self) {\n return (self.data.is_inline || self.ptr->child_count == 0)\n ? 0\n : self.ptr->visible_descendant_count;\n}\n\nstatic inline uint32_t ts_subtree_visible_child_count(Subtree self) {\n if (ts_subtree_child_count(self) > 0) {\n return self.ptr->visible_child_count;\n } else {\n return 0;\n }\n}\n\nstatic inline uint32_t ts_subtree_error_cost(Subtree self) {\n if (ts_subtree_missing(self)) {\n return ERROR_COST_PER_MISSING_TREE + ERROR_COST_PER_RECOVERY;\n } else {\n return self.data.is_inline ? 0 : self.ptr->error_cost;\n }\n}\n\nstatic inline int32_t ts_subtree_dynamic_precedence(Subtree self) {\n return (self.data.is_inline || self.ptr->child_count == 0) ? 0 : self.ptr->dynamic_precedence;\n}\n\nstatic inline uint16_t ts_subtree_production_id(Subtree self) {\n if (ts_subtree_child_count(self) > 0) {\n return self.ptr->production_id;\n } else {\n return 0;\n }\n}\n\nstatic inline bool ts_subtree_fragile_left(Subtree self) {\n return self.data.is_inline ? false : self.ptr->fragile_left;\n}\n\nstatic inline bool ts_subtree_fragile_right(Subtree self) {\n return self.data.is_inline ? false : self.ptr->fragile_right;\n}\n\nstatic inline bool ts_subtree_has_external_tokens(Subtree self) {\n return self.data.is_inline ? false : self.ptr->has_external_tokens;\n}\n\nstatic inline bool ts_subtree_has_external_scanner_state_change(Subtree self) {\n return self.data.is_inline ? false : self.ptr->has_external_scanner_state_change;\n}\n\nstatic inline bool ts_subtree_depends_on_column(Subtree self) {\n return self.data.is_inline ? false : self.ptr->depends_on_column;\n}\n\nstatic inline bool ts_subtree_is_fragile(Subtree self) {\n return self.data.is_inline ? false : (self.ptr->fragile_left || self.ptr->fragile_right);\n}\n\nstatic inline bool ts_subtree_is_error(Subtree self) {\n return ts_subtree_symbol(self) == ts_builtin_sym_error;\n}\n\nstatic inline bool ts_subtree_is_eof(Subtree self) {\n return ts_subtree_symbol(self) == ts_builtin_sym_end;\n}\n\nstatic inline Subtree ts_subtree_from_mut(MutableSubtree self) {\n Subtree result;\n result.data = self.data;\n return result;\n}\n\nstatic inline MutableSubtree ts_subtree_to_mut_unsafe(Subtree self) {\n MutableSubtree result;\n result.data = self.data;\n return result;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // TREE_SITTER_SUBTREE_H_\n", "#include <ctype.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <string.h>\n#include <stdio.h>\n#include \"./alloc.h\"\n#include \"./array.h\"\n#include \"./atomic.h\"\n#include \"./subtree.h\"\n#include \"./length.h\"\n#include \"./language.h\"\n#include \"./error_costs.h\"\n#include \"./ts_assert.h\"\n#include <stddef.h>\n\ntypedef struct {\n Length start;\n Length old_end;\n Length new_end;\n} Edit;\n\n#define TS_MAX_INLINE_TREE_LENGTH UINT8_MAX\n#define TS_MAX_TREE_POOL_SIZE 32\n\n// ExternalScannerState\n\nvoid ts_external_scanner_state_init(ExternalScannerState *self, const char *data, unsigned length) {\n self->length = length;\n if (length > sizeof(self->short_data)) {\n self->long_data = ts_malloc(length);\n memcpy(self->long_data, data, length);\n } else {\n memcpy(self->short_data, data, length);\n }\n}\n\nExternalScannerState ts_external_scanner_state_copy(const ExternalScannerState *self) {\n ExternalScannerState result = *self;\n if (self->length > sizeof(self->short_data)) {\n result.long_data = ts_malloc(self->length);\n memcpy(result.long_data, self->long_data, self->length);\n }\n return result;\n}\n\nvoid ts_external_scanner_state_delete(ExternalScannerState *self) {\n if (self->length > sizeof(self->short_data)) {\n ts_free(self->long_data);\n }\n}\n\nconst char *ts_external_scanner_state_data(const ExternalScannerState *self) {\n if (self->length > sizeof(self->short_data)) {\n return self->long_data;\n } else {\n return self->short_data;\n }\n}\n\nbool ts_external_scanner_state_eq(const ExternalScannerState *self, const char *buffer, unsigned length) {\n return\n self->length == length &&\n memcmp(ts_external_scanner_state_data(self), buffer, length) == 0;\n}\n\n// SubtreeArray\n\nvoid ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest) {\n dest->size = self.size;\n dest->capacity = self.capacity;\n dest->contents = self.contents;\n if (self.capacity > 0) {\n dest->contents = ts_calloc(self.capacity, sizeof(Subtree));\n memcpy(dest->contents, self.contents, self.size * sizeof(Subtree));\n for (uint32_t i = 0; i < self.size; i++) {\n ts_subtree_retain(*array_get(dest, i));\n }\n }\n}\n\nvoid ts_subtree_array_clear(SubtreePool *pool, SubtreeArray *self) {\n for (uint32_t i = 0; i < self->size; i++) {\n ts_subtree_release(pool, *array_get(self, i));\n }\n array_clear(self);\n}\n\nvoid ts_subtree_array_delete(SubtreePool *pool, SubtreeArray *self) {\n ts_subtree_array_clear(pool, self);\n array_delete(self);\n}\n\nvoid ts_subtree_array_remove_trailing_extras(\n SubtreeArray *self,\n SubtreeArray *destination\n) {\n array_clear(destination);\n while (self->size > 0) {\n Subtree last = *array_get(self, self->size - 1);\n if (ts_subtree_extra(last)) {\n self->size--;\n array_push(destination, last);\n } else {\n break;\n }\n }\n ts_subtree_array_rev