Rework API completely

This commit is contained in:
Max Brunsfeld 2018-05-10 22:22:37 -07:00
parent 33f7643040
commit e75ecd1bb1
31 changed files with 841 additions and 1075 deletions

View file

@ -1,188 +0,0 @@
#include "runtime/alloc.h"
#include "runtime/subtree.h"
#include "runtime/parser.h"
#include "runtime/string_input.h"
#include "runtime/document.h"
#include "runtime/tree_cursor.h"
#include "runtime/get_changed_ranges.h"
#define LOG(...) \
snprintf(self->parser.lexer.debug_buffer, TREE_SITTER_SERIALIZATION_BUFFER_SIZE, __VA_ARGS__); \
self->parser.lexer.logger.log(self->parser.lexer.logger.payload, TSLogTypeLex, self->parser.lexer.debug_buffer); \
TSDocument *ts_document_new() {
TSDocument *self = ts_calloc(1, sizeof(TSDocument));
ts_parser_init(&self->parser);
array_init(&self->cursor1.stack);
array_init(&self->cursor2.stack);
return self;
}
void ts_document_free(TSDocument *self) {
if (self->tree) ts_subtree_release(&self->parser.tree_pool, self->tree);
if (self->cursor1.stack.contents) array_delete(&self->cursor1.stack);
if (self->cursor2.stack.contents) array_delete(&self->cursor2.stack);
ts_parser_destroy(&self->parser);
ts_document_set_input(self, (TSInput){
NULL,
NULL,
NULL,
TSInputEncodingUTF8,
});
ts_free(self);
}
const TSLanguage *ts_document_language(TSDocument *self) {
return self->parser.language;
}
void ts_document_set_language(TSDocument *self, const TSLanguage *language) {
if (language->version != TREE_SITTER_LANGUAGE_VERSION) return;
ts_document_invalidate(self);
ts_parser_set_language(&self->parser, language);
if (self->tree) {
ts_subtree_release(&self->parser.tree_pool, self->tree);
self->tree = NULL;
}
}
TSLogger ts_document_logger(const TSDocument *self) {
return self->parser.lexer.logger;
}
void ts_document_set_logger(TSDocument *self, TSLogger logger) {
self->parser.lexer.logger = logger;
}
void ts_document_print_debugging_graphs(TSDocument *self, bool should_print) {
self->parser.print_debugging_graphs = should_print;
}
TSInput ts_document_input(TSDocument *self) {
return self->input;
}
void ts_document_set_input(TSDocument *self, TSInput input) {
if (self->owns_input)
ts_free(self->input.payload);
self->input = input;
self->owns_input = false;
}
void ts_document_set_input_string(TSDocument *self, const char *text) {
ts_document_invalidate(self);
TSInput input = ts_string_input_make(text);
ts_document_set_input(self, input);
if (input.payload) {
self->owns_input = true;
}
}
void ts_document_set_input_string_with_length(TSDocument *self, const char *text, uint32_t length) {
ts_document_invalidate(self);
TSInput input = ts_string_input_make_with_length(text, length);
ts_document_set_input(self, input);
if (input.payload) {
self->owns_input = true;
}
}
void ts_document_edit(TSDocument *self, TSInputEdit edit) {
if (!self->tree)
return;
uint32_t max_bytes = ts_subtree_total_bytes(self->tree);
if (edit.start_byte > max_bytes)
return;
if (edit.bytes_removed > max_bytes - edit.start_byte)
edit.bytes_removed = max_bytes - edit.start_byte;
self->tree = ts_subtree_edit(self->tree, &edit, &self->parser.tree_pool);
if (self->parser.print_debugging_graphs) {
ts_subtree_print_dot_graph(self->tree, self->parser.language, stderr);
}
}
void ts_document_parse(TSDocument *self) {
ts_document_parse_with_options(self, (TSParseOptions){
.halt_on_error = false,
.changed_ranges = NULL,
.changed_range_count = NULL,
});
}
void ts_document_parse_and_get_changed_ranges(TSDocument *self, TSRange **ranges,
uint32_t *range_count) {
ts_document_parse_with_options(self, (TSParseOptions){
.halt_on_error = false,
.changed_ranges = ranges,
.changed_range_count = range_count,
});
}
void ts_document_parse_with_options(TSDocument *self, TSParseOptions options) {
if (options.changed_ranges && options.changed_range_count) {
*options.changed_ranges = NULL;
*options.changed_range_count = 0;
}
if (!self->input.read || !self->parser.language)
return;
Subtree *reusable_tree = self->valid ? self->tree : NULL;
if (reusable_tree && !reusable_tree->has_changes)
return;
Subtree *tree = ts_parser_parse(&self->parser, self->input, reusable_tree, options.halt_on_error);
if (self->tree) {
Subtree *old_tree = self->tree;
self->tree = tree;
if (options.changed_ranges && options.changed_range_count) {
*options.changed_range_count = ts_subtree_get_changed_ranges(
old_tree, tree, &self->cursor1, &self->cursor2,
self->parser.language, options.changed_ranges
);
if (self->parser.lexer.logger.log) {
for (unsigned i = 0; i < *options.changed_range_count; i++) {
TSRange range = (*options.changed_ranges)[i];
LOG(
"changed_range start:[%u %u], end:[%u %u]",
range.start.row, range.start.column,
range.end.row, range.end.column
);
}
}
}
ts_subtree_release(&self->parser.tree_pool, old_tree);
}
self->tree = tree;
self->parse_count++;
self->valid = true;
}
void ts_document_invalidate(TSDocument *self) {
self->valid = false;
}
TSNode ts_document_root_node(const TSDocument *self) {
return (TSNode) {
.subtree = self->tree,
.document = self,
.position = {0, 0},
.byte = 0,
};
}
uint32_t ts_document_parse_count(const TSDocument *self) {
return self->parse_count;
}
TSTreeCursor *ts_document_tree_cursor(const TSDocument *self) {
return ts_tree_cursor_new(self);
}

View file

@ -1,20 +0,0 @@
#ifndef RUNTIME_DOCUMENT_H_
#define RUNTIME_DOCUMENT_H_
#include "runtime/parser.h"
#include "runtime/subtree.h"
#include "runtime/tree_cursor.h"
#include <stdbool.h>
struct TSDocument {
TSParser parser;
TSInput input;
Subtree *tree;
TSTreeCursor cursor1;
TSTreeCursor cursor2;
size_t parse_count;
bool valid;
bool owns_input;
};
#endif

View file

@ -34,7 +34,7 @@ typedef struct {
static Iterator iterator_new(TSTreeCursor *cursor, Subtree *tree, const TSLanguage *language) {
array_clear(&cursor->stack);
array_push(&cursor->stack, ((TreeCursorEntry){
.tree = tree,
.subtree = tree,
.position = length_zero(),
.child_index = 0,
.structural_child_index = 0,
@ -56,25 +56,25 @@ Length iterator_start_position(Iterator *self) {
if (self->in_padding) {
return entry.position;
} else {
return length_add(entry.position, entry.tree->padding);
return length_add(entry.position, entry.subtree->padding);
}
}
Length iterator_end_position(Iterator *self) {
TreeCursorEntry entry = *array_back(&self->cursor.stack);
Length result = length_add(entry.position, entry.tree->padding);
Length result = length_add(entry.position, entry.subtree->padding);
if (self->in_padding) {
return result;
} else {
return length_add(result, entry.tree->size);
return length_add(result, entry.subtree->size);
}
}
static bool iterator_tree_is_visible(const Iterator *self) {
TreeCursorEntry entry = *array_back(&self->cursor.stack);
if (entry.tree->visible) return true;
if (entry.subtree->visible) return true;
if (self->cursor.stack.size > 1) {
Subtree *parent = self->cursor.stack.contents[self->cursor.stack.size - 2].tree;
Subtree *parent = self->cursor.stack.contents[self->cursor.stack.size - 2].subtree;
const TSSymbol *alias_sequence = ts_language_alias_sequence(self->language, parent->alias_sequence_id);
return alias_sequence && alias_sequence[entry.structural_child_index] != 0;
}
@ -94,7 +94,7 @@ static void iterator_get_visible_state(const Iterator *self, Subtree **tree,
TreeCursorEntry entry = self->cursor.stack.contents[i];
if (i > 0) {
Subtree *parent = self->cursor.stack.contents[i - 1].tree;
Subtree *parent = self->cursor.stack.contents[i - 1].subtree;
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->language,
parent->alias_sequence_id
@ -104,8 +104,8 @@ static void iterator_get_visible_state(const Iterator *self, Subtree **tree,
}
}
if (entry.tree->visible || *alias_symbol) {
*tree = entry.tree;
if (entry.subtree->visible || *alias_symbol) {
*tree = entry.subtree;
*start_byte = entry.position.bytes;
break;
}
@ -128,14 +128,14 @@ static bool iterator_descend(Iterator *self, uint32_t goal_position) {
TreeCursorEntry entry = *array_back(&self->cursor.stack);
Length position = entry.position;
uint32_t structural_child_index = 0;
for (uint32_t i = 0; i < entry.tree->children.size; i++) {
Subtree *child = entry.tree->children.contents[i];
for (uint32_t i = 0; i < entry.subtree->children.size; i++) {
Subtree *child = entry.subtree->children.contents[i];
Length child_left = length_add(position, child->padding);
Length child_right = length_add(child_left, child->size);
if (child_right.bytes > goal_position) {
array_push(&self->cursor.stack, ((TreeCursorEntry){
.tree = child,
.subtree = child,
.position = position,
.child_index = i,
.structural_child_index = structural_child_index,
@ -178,16 +178,16 @@ static void iterator_advance(Iterator *self) {
TreeCursorEntry entry = array_pop(&self->cursor.stack);
if (iterator_done(self)) return;
Subtree *parent = array_back(&self->cursor.stack)->tree;
Subtree *parent = array_back(&self->cursor.stack)->subtree;
uint32_t child_index = entry.child_index + 1;
if (parent->children.size > child_index) {
Length position = length_add(entry.position, ts_subtree_total_size(entry.tree));
Length position = length_add(entry.position, ts_subtree_total_size(entry.subtree));
uint32_t structural_child_index = entry.structural_child_index;
if (!entry.tree->extra) structural_child_index++;
if (!entry.subtree->extra) structural_child_index++;
Subtree *next_child = parent->children.contents[child_index];
array_push(&self->cursor.stack, ((TreeCursorEntry){
.tree = next_child,
.subtree = next_child,
.position = position,
.child_index = child_index,
.structural_child_index = structural_child_index,
@ -250,7 +250,7 @@ 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, entry.tree->symbol);
const char *name = ts_language_symbol_name(self->language, entry.subtree->symbol);
printf(
"(%-25s %s\t depth:%u [%u, %u] - [%u, %u])",
name, self->in_padding ? "(p)" : " ",

View file

@ -1,13 +1,13 @@
#include <stdbool.h>
#include "runtime/subtree.h"
#include "runtime/document.h"
#include "runtime/tree.h"
#include "runtime/language.h"
// NodeChildIterator
typedef struct {
const Subtree *parent;
const TSDocument *document;
const TSTree *tree;
Length position;
uint32_t child_index;
uint32_t structural_child_index;
@ -19,7 +19,7 @@ typedef struct {
static inline TSNode ts_node__null() {
return (TSNode) {
.subtree = NULL,
.document = NULL,
.tree = NULL,
.position = {0, 0},
.byte = 0,
};
@ -32,12 +32,12 @@ static inline const Subtree *ts_node__tree(TSNode self) {
static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) {
const Subtree *tree = ts_node__tree(*node);
const TSSymbol *alias_sequence = ts_language_alias_sequence(
node->document->parser.language,
node->tree->language,
tree->alias_sequence_id
);
return (NodeChildIterator) {
.parent = tree,
.document = node->document,
.tree = node->tree,
.position = {node->byte, node->position},
.child_index = 0,
.structural_child_index = 0,
@ -57,7 +57,7 @@ static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *
}
*result = (TSNode) {
.subtree = child,
.document = self->document,
.tree = self->tree,
.position = self->position.extent,
.byte = self->position.bytes,
.alias_symbol = alias_symbol,
@ -77,7 +77,7 @@ static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) {
(
self.alias_symbol &&
ts_language_symbol_metadata(
self.document->parser.language,
self.tree->language,
self.alias_symbol
).named
)
@ -343,11 +343,11 @@ TSSymbol ts_node_symbol(TSNode self) {
}
const char *ts_node_type(TSNode self) {
return ts_language_symbol_name(self.document->parser.language, ts_node_symbol(self));
return ts_language_symbol_name(self.tree->language, ts_node_symbol(self));
}
char *ts_node_string(TSNode self) {
return ts_subtree_string(ts_node__tree(self), self.document->parser.language, false);
return ts_subtree_string(ts_node__tree(self), self.tree->language, false);
}
bool ts_node_eq(TSNode self, TSNode other) {
@ -360,7 +360,7 @@ bool ts_node_eq(TSNode self, TSNode other) {
bool ts_node_is_named(TSNode self) {
const Subtree *tree = ts_node__tree(self);
return self.alias_symbol
? ts_language_symbol_metadata(self.document->parser.language, self.alias_symbol).named
? ts_language_symbol_metadata(self.tree->language, self.alias_symbol).named
: tree->named;
}
@ -378,7 +378,7 @@ bool ts_node_has_error(TSNode self) {
}
TSNode ts_node_parent(TSNode self) {
TSNode node = ts_document_root_node(self.document);
TSNode node = ts_tree_root_node(self.tree);
uint32_t end_byte = ts_node_end_byte(self);
if (node.subtree == self.subtree) return ts_node__null();

View file

@ -1,4 +1,3 @@
#include "runtime/parser.h"
#include <assert.h>
#include <stdio.h>
#include <limits.h>
@ -10,8 +9,12 @@
#include "runtime/array.h"
#include "runtime/language.h"
#include "runtime/alloc.h"
#include "runtime/stack.h"
#include "runtime/reusable_node.h"
#include "runtime/reduce_action.h"
#include "runtime/error_costs.h"
#include "runtime/string_input.h"
#include "runtime/tree.h"
#define LOG(...) \
if (self->lexer.logger.log || self->print_debugging_graphs) { \
@ -37,6 +40,29 @@ static const unsigned MAX_VERSION_COUNT = 6;
static const unsigned MAX_SUMMARY_DEPTH = 16;
static const unsigned MAX_COST_DIFFERENCE = 16 * ERROR_COST_PER_SKIPPED_TREE;
typedef struct {
Subtree *token;
Subtree *last_external_token;
uint32_t byte_index;
} TokenCache;
struct TSParser {
Lexer lexer;
Stack *stack;
SubtreePool tree_pool;
const TSLanguage *language;
ReduceActionSet reduce_actions;
Subtree *finished_tree;
Subtree scratch_tree;
TokenCache token_cache;
ReusableNode reusable_node;
void *external_scanner_payload;
bool in_ambiguity;
bool print_debugging_graphs;
bool halt_on_error;
unsigned accept_count;
};
typedef struct {
unsigned cost;
unsigned node_count;
@ -52,6 +78,8 @@ typedef enum {
ErrorComparisonTakeRight,
} ErrorComparison;
// Parser - Private
static void ts_parser__log(TSParser *self) {
if (self->lexer.logger.log) {
self->lexer.logger.log(
@ -670,7 +698,7 @@ static StackSliceArray ts_parser__reduce(TSParser *self, StackVersion version, T
return pop;
}
static void ts_parser__start(TSParser *self, TSInput input, Subtree *previous_tree) {
static void ts_parser__start(TSParser *self, TSInput input, const Subtree *previous_tree) {
if (previous_tree) {
LOG("parse_after_edit");
} else {
@ -1258,42 +1286,76 @@ static unsigned ts_parser__condense_stack(TSParser *self) {
return min_error_cost;
}
bool ts_parser_init(TSParser *self) {
// Parser - Public
TSParser *ts_parser_new() {
TSParser *self = ts_calloc(1, sizeof(TSParser));
ts_lexer_init(&self->lexer);
array_init(&self->reduce_actions);
array_reserve(&self->reduce_actions, 4);
ts_subtree_pool_init(&self->tree_pool);
self->tree_pool = ts_subtree_pool_new(32);
self->stack = ts_stack_new(&self->tree_pool);
self->finished_tree = NULL;
self->reusable_node = reusable_node_new();
self->print_debugging_graphs = false;
self->halt_on_error = false;
ts_parser__set_cached_token(self, 0, NULL, NULL);
return true;
return self;
}
void ts_parser_set_language(TSParser *self, const TSLanguage *language) {
if (self->external_scanner_payload && self->language->external_scanner.destroy)
self->language->external_scanner.destroy(self->external_scanner_payload);
if (language && language->external_scanner.create)
self->external_scanner_payload = language->external_scanner.create();
else
self->external_scanner_payload = NULL;
self->language = language;
}
void ts_parser_destroy(TSParser *self) {
if (self->stack)
void ts_parser_delete(TSParser *self) {
if (self->stack) {
ts_stack_delete(self->stack);
if (self->reduce_actions.contents)
}
if (self->reduce_actions.contents) {
array_delete(&self->reduce_actions);
}
ts_subtree_pool_delete(&self->tree_pool);
reusable_node_delete(&self->reusable_node);
ts_parser_set_language(self, NULL);
ts_free(self);
}
Subtree *ts_parser_parse(TSParser *self, TSInput input, Subtree *old_tree, bool halt_on_error) {
ts_parser__start(self, input, old_tree);
const TSLanguage *ts_parser_language(const TSParser *self) {
return self->language;
}
bool ts_parser_set_language(TSParser *self, const TSLanguage *language) {
if (language && language->version != TREE_SITTER_LANGUAGE_VERSION) return false;
if (self->external_scanner_payload && self->language->external_scanner.destroy) {
self->language->external_scanner.destroy(self->external_scanner_payload);
}
if (language && language->external_scanner.create) {
self->external_scanner_payload = language->external_scanner.create();
} else {
self->external_scanner_payload = NULL;
}
self->language = language;
return true;
}
TSLogger ts_parser_logger(const TSParser *self) {
return self->lexer.logger;
}
void ts_parser_set_logger(TSParser *self, TSLogger logger) {
self->lexer.logger = logger;
}
void ts_parser_print_debugging_graphs(TSParser *self, bool should_print) {
self->print_debugging_graphs = should_print;
}
void ts_parser_halt_on_error(TSParser *self, bool should_halt_on_error) {
self->halt_on_error = should_halt_on_error;
}
TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input) {
if (!self->language) return NULL;
ts_parser__start(self, input, old_tree ? old_tree->root : NULL);
StackVersion version = STACK_VERSION_NONE;
uint32_t position = 0, last_position = 0;
@ -1327,7 +1389,7 @@ Subtree *ts_parser_parse(TSParser *self, TSInput input, Subtree *old_tree, bool
unsigned min_error_cost = ts_parser__condense_stack(self);
if (self->finished_tree && self->finished_tree->error_cost < min_error_cost) {
break;
} else if (halt_on_error && min_error_cost > 0) {
} else if (self->halt_on_error && min_error_cost > 0) {
ts_parser__halt_parse(self);
break;
}
@ -1342,5 +1404,13 @@ Subtree *ts_parser_parse(TSParser *self, TSInput input, Subtree *old_tree, bool
LOG("done");
LOG_TREE();
return self->finished_tree;
return ts_tree_new(self->finished_tree, self->language);
}
TSTree *ts_parser_parse_string(TSParser *self, const TSTree *old_tree,
const char *string, uint32_t length) {
TSStringInput input;
ts_string_input_init(&input, string, length);
return ts_parser_parse(self, old_tree, input.input);
}

View file

@ -1,46 +0,0 @@
#ifndef RUNTIME_PARSER_H_
#define RUNTIME_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "runtime/stack.h"
#include "runtime/array.h"
#include "runtime/lexer.h"
#include "runtime/reusable_node.h"
#include "runtime/reduce_action.h"
#include "runtime/subtree.h"
typedef struct {
Subtree *token;
Subtree *last_external_token;
uint32_t byte_index;
} TokenCache;
typedef struct {
Lexer lexer;
Stack *stack;
SubtreePool tree_pool;
const TSLanguage *language;
ReduceActionSet reduce_actions;
Subtree *finished_tree;
Subtree scratch_tree;
TokenCache token_cache;
ReusableNode reusable_node;
void *external_scanner_payload;
bool in_ambiguity;
bool print_debugging_graphs;
unsigned accept_count;
} TSParser;
bool ts_parser_init(TSParser *);
void ts_parser_destroy(TSParser *);
Subtree *ts_parser_parse(TSParser *, TSInput, Subtree *, bool halt_on_error);
void ts_parser_set_language(TSParser *, const TSLanguage *);
#ifdef __cplusplus
}
#endif
#endif // RUNTIME_PARSER_H_

View file

@ -24,7 +24,7 @@ static inline void reusable_node_reset(ReusableNode *self, Subtree *tree) {
}));
}
static inline Subtree *reusable_node_tree(ReusableNode *self) {
static inline const Subtree *reusable_node_tree(ReusableNode *self) {
return self->stack.size > 0
? self->stack.contents[self->stack.size - 1].tree
: NULL;

View file

@ -1,13 +1,7 @@
#include "tree_sitter/runtime.h"
#include "runtime/string_input.h"
#include "runtime/alloc.h"
#include <string.h>
typedef struct {
const char *string;
uint32_t position;
uint32_t length;
} TSStringInput;
static const char *ts_string_input__read(void *payload, uint32_t *bytes_read) {
TSStringInput *input = (TSStringInput *)payload;
if (input->position >= input->length) {
@ -26,17 +20,12 @@ static int ts_string_input__seek(void *payload, uint32_t byte, TSPoint _) {
return (byte < input->length);
}
TSInput ts_string_input_make(const char *string) {
return ts_string_input_make_with_length(string, strlen(string));
}
TSInput ts_string_input_make_with_length(const char *string, uint32_t length) {
TSStringInput *input = ts_malloc(sizeof(TSStringInput));
input->string = string;
input->position = 0;
input->length = length;
return (TSInput){
.payload = input,
void ts_string_input_init(TSStringInput *self, const char *string, uint32_t length) {
self->string = string;
self->position = 0;
self->length = length;
self->input = (TSInput) {
.payload = self,
.read = ts_string_input__read,
.seek = ts_string_input__seek,
.encoding = TSInputEncodingUTF8,

View file

@ -7,8 +7,14 @@ extern "C" {
#include "tree_sitter/runtime.h"
TSInput ts_string_input_make(const char *);
TSInput ts_string_input_make_with_length(const char *, uint32_t);
typedef struct {
const char *string;
uint32_t position;
uint32_t length;
TSInput input;
} TSStringInput;
void ts_string_input_init(TSStringInput *, const char *, uint32_t);
#ifdef __cplusplus
}

View file

@ -19,6 +19,10 @@ typedef struct {
TSStateId TS_TREE_STATE_NONE = USHRT_MAX;
static const uint32_t MAX_TREE_POOL_SIZE = 1024;
static const TSExternalTokenState empty_state = {.length = 0, .short_data = {0}};
// ExternalTokenState
void ts_external_token_state_init(TSExternalTokenState *self, const char *content, unsigned length) {
@ -102,11 +106,10 @@ void ts_subtree_array_reverse(SubtreeArray *self) {
// SubtreePool
static const uint32_t MAX_TREE_POOL_SIZE = 1024;
void ts_subtree_pool_init(SubtreePool *self) {
array_init(&self->free_trees);
array_init(&self->tree_stack);
SubtreePool ts_subtree_pool_new(uint32_t capacity) {
SubtreePool self = {array_new(), array_new()};
array_reserve(&self.free_trees, capacity);
return self;
}
void ts_subtree_pool_delete(SubtreePool *self) {
@ -128,7 +131,7 @@ Subtree *ts_subtree_pool_allocate(SubtreePool *self) {
}
void ts_subtree_pool_free(SubtreePool *self, Subtree *tree) {
if (self->free_trees.size < MAX_TREE_POOL_SIZE) {
if (self->free_trees.capacity > 0 && self->free_trees.size < MAX_TREE_POOL_SIZE) {
array_push(&self->free_trees, tree);
} else {
ts_free(tree);
@ -691,8 +694,6 @@ void ts_subtree_print_dot_graph(const Subtree *self, const TSLanguage *language,
fprintf(f, "}\n");
}
static const TSExternalTokenState empty_state = {.length = 0, .short_data = {0}};
bool ts_subtree_external_token_state_eq(const Subtree *self, const Subtree *other) {
const TSExternalTokenState *state1 = &empty_state;
const TSExternalTokenState *state2 = &empty_state;

View file

@ -1,5 +1,5 @@
#ifndef RUNTIME_TREE_H_
#define RUNTIME_TREE_H_
#ifndef RUNTIME_SUBTREE_H_
#define RUNTIME_SUBTREE_H_
#ifdef __cplusplus
extern "C" {
@ -83,7 +83,7 @@ void ts_subtree_array_delete(SubtreePool *, SubtreeArray *);
SubtreeArray ts_subtree_array_remove_trailing_extras(SubtreeArray *);
void ts_subtree_array_reverse(SubtreeArray *);
void ts_subtree_pool_init(SubtreePool *);
SubtreePool ts_subtree_pool_new(uint32_t capacity);
void ts_subtree_pool_delete(SubtreePool *);
Subtree *ts_subtree_pool_allocate(SubtreePool *);
void ts_subtree_pool_free(SubtreePool *, Subtree *);
@ -122,4 +122,4 @@ static inline Length ts_subtree_total_size(const Subtree *self) {
}
#endif
#endif // RUNTIME_TREE_H_
#endif // RUNTIME_SUBTREE_H_

59
src/runtime/tree.c Normal file
View file

@ -0,0 +1,59 @@
#include "tree_sitter/runtime.h"
#include "runtime/array.h"
#include "runtime/get_changed_ranges.h"
#include "runtime/subtree.h"
#include "runtime/tree_cursor.h"
#include "runtime/tree.h"
TSTree *ts_tree_new(const Subtree *root, const TSLanguage *language) {
TSTree *result = ts_malloc(sizeof(TSTree));
result->root = root;
result->language = language;
return result;
}
TSTree *ts_tree_copy(const TSTree *self) {
ts_subtree_retain(self->root);
return ts_tree_new(self->root, self->language);
}
void ts_tree_delete(const TSTree *self) {
SubtreePool pool = ts_subtree_pool_new(0);
ts_subtree_release(&pool, self->root);
ts_subtree_pool_delete(&pool);
ts_free(self);
}
TSNode ts_tree_root_node(const TSTree *self) {
return (TSNode) {
.subtree = self->root,
.tree = self,
.position = {0, 0},
.byte = 0,
.alias_symbol = 0,
};
}
void ts_tree_edit(TSTree *self, const TSInputEdit *edit) {
SubtreePool pool = ts_subtree_pool_new(0);
self->root = ts_subtree_edit(self->root, edit, &pool);
assert(pool.tree_stack.capacity == 0 && pool.free_trees.capacity == 0);
}
TSRange *ts_tree_get_changed_ranges(const TSTree *self, const TSTree *other, uint32_t *count) {
TSRange *result;
TSTreeCursor cursor1, cursor2;
ts_tree_cursor_init(&cursor1, self);
ts_tree_cursor_init(&cursor2, self);
*count = ts_subtree_get_changed_ranges(
self->root, other->root, &cursor1, &cursor2,
self->language, &result
);
array_delete(&cursor1.stack);
array_delete(&cursor2.stack);
return result;
}
void ts_tree_print_dot_graph(const TSTree *self, FILE *file) {
ts_subtree_print_dot_graph(self->root, self->language, file);
}

19
src/runtime/tree.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef RUNTIME_TREE_H_
#define RUNTIME_TREE_H_
#ifdef __cplusplus
extern "C" {
#endif
struct TSTree {
const Subtree *root;
const TSLanguage *language;
};
TSTree *ts_tree_new(const Subtree *root, const TSLanguage *language);
#ifdef __cplusplus
}
#endif
#endif // RUNTIME_TREE_H_

View file

@ -1,20 +1,24 @@
#include "tree_sitter/runtime.h"
#include "runtime/alloc.h"
#include "runtime/tree_cursor.h"
#include "runtime/document.h"
#include "runtime/language.h"
#include "runtime/tree.h"
TSTreeCursor *ts_tree_cursor_new(const TSDocument *document) {
TSTreeCursor *ts_tree_cursor_new(const TSTree *tree) {
TSTreeCursor *self = ts_malloc(sizeof(TSTreeCursor));
self->document = document;
ts_tree_cursor_init(self, tree);
return self;
}
void ts_tree_cursor_init(TSTreeCursor *self, const TSTree *tree) {
self->tree = tree;
array_init(&self->stack);
array_push(&self->stack, ((TreeCursorEntry) {
.tree = document->tree,
.subtree = tree->root,
.position = length_zero(),
.child_index = 0,
.structural_child_index = 0,
}));
return self;
}
void ts_tree_cursor_delete(TSTreeCursor *self) {
@ -24,7 +28,7 @@ void ts_tree_cursor_delete(TSTreeCursor *self) {
bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
TreeCursorEntry *last_entry = array_back(&self->stack);
Subtree *tree = last_entry->tree;
Subtree *tree = last_entry->subtree;
Length position = last_entry->position;
bool did_descend;
@ -36,7 +40,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
Subtree *child = tree->children.contents[i];
if (child->visible || child->visible_child_count > 0) {
array_push(&self->stack, ((TreeCursorEntry) {
.tree = child,
.subtree = child,
.child_index = i,
.structural_child_index = structural_child_index,
.position = position,
@ -64,7 +68,7 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
TreeCursorEntry *parent_entry = &self->stack.contents[i];
Subtree *parent = parent_entry->tree;
Subtree *parent = parent_entry->subtree;
uint32_t child_index = child_entry->child_index;
uint32_t structural_child_index = child_entry->structural_child_index;
Length position = child_entry->position;
@ -77,7 +81,7 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
if (child->visible || child->visible_child_count > 0) {
self->stack.contents[i + 1] = (TreeCursorEntry) {
.tree = child,
.subtree = child,
.child_index = child_index,
.structural_child_index = structural_child_index,
.position = position,
@ -103,7 +107,7 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
bool ts_tree_cursor_goto_parent(TSTreeCursor *self) {
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
TreeCursorEntry *entry = &self->stack.contents[i];
if (entry->tree->visible) {
if (entry->subtree->visible) {
self->stack.size = i + 1;
return true;
}
@ -117,16 +121,16 @@ TSNode ts_tree_cursor_current_node(TSTreeCursor *self) {
if (self->stack.size > 1) {
TreeCursorEntry *parent_entry = &self->stack.contents[self->stack.size - 2];
const TSSymbol *alias_sequence = ts_language_alias_sequence(
self->document->parser.language,
parent_entry->tree->alias_sequence_id
self->tree->language,
parent_entry->subtree->alias_sequence_id
);
if (alias_sequence) {
alias_symbol = alias_sequence[last_entry->structural_child_index];
}
}
return (TSNode) {
.document = self->document,
.subtree = last_entry->tree,
.tree = self->tree,
.subtree = last_entry->subtree,
.position = last_entry->position.extent,
.byte = last_entry->position.bytes,
.alias_symbol = alias_symbol,

View file

@ -4,17 +4,17 @@
#include "runtime/subtree.h"
typedef struct {
Subtree *tree;
Subtree *subtree;
Length position;
uint32_t child_index;
uint32_t structural_child_index;
} TreeCursorEntry;
struct TSTreeCursor {
const TSDocument *document;
const TSTree *tree;
Array(TreeCursorEntry) stack;
};
TSTreeCursor *ts_tree_cursor_new(const TSDocument *);
void ts_tree_cursor_init(TSTreeCursor *, const TSTree *);
#endif // RUNTIME_TREE_CURSOR_H_