trimmed more fat
This commit is contained in:
parent
d9bf7fa721
commit
5898689697
14 changed files with 432 additions and 3151 deletions
|
|
@ -1,19 +1,13 @@
|
||||||
#include "./language.h"
|
#include "./language.h"
|
||||||
#include "./wasm_store.h"
|
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
const TSLanguage *ts_language_copy(const TSLanguage *self) {
|
const TSLanguage *ts_language_copy(const TSLanguage *self) {
|
||||||
if (self && ts_language_is_wasm(self)) {
|
|
||||||
ts_wasm_language_retain(self);
|
|
||||||
}
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_language_delete(const TSLanguage *self) {
|
void ts_language_delete(const TSLanguage *self) {
|
||||||
if (self && ts_language_is_wasm(self)) {
|
(void)(self);
|
||||||
ts_wasm_language_release(self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ts_language_symbol_count(const TSLanguage *self) {
|
uint32_t ts_language_symbol_count(const TSLanguage *self) {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,13 @@
|
||||||
#ifndef TREE_SITTER_LEXER_H_
|
#ifndef TREE_SITTER_LEXER_H_
|
||||||
#define TREE_SITTER_LEXER_H_
|
#define TREE_SITTER_LEXER_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "./length.h"
|
#include "./length.h"
|
||||||
#include "./subtree.h"
|
#include "./subtree.h"
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include "./parser.h"
|
#include "./parser.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Lexer{
|
||||||
TSLexer data;
|
TSLexer data;
|
||||||
Length current_position;
|
Length current_position;
|
||||||
Length token_start_position;
|
Length token_start_position;
|
||||||
|
|
@ -42,8 +39,5 @@ void ts_lexer_mark_end(Lexer *);
|
||||||
bool ts_lexer_set_included_ranges(Lexer *self, const TSRange *ranges, uint32_t count);
|
bool ts_lexer_set_included_ranges(Lexer *self, const TSRange *ranges, uint32_t count);
|
||||||
TSRange *ts_lexer_included_ranges(const Lexer *self, uint32_t *count);
|
TSRange *ts_lexer_included_ranges(const Lexer *self, uint32_t *count);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_LEXER_H_
|
#endif // TREE_SITTER_LEXER_H_
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#define _POSIX_C_SOURCE 200112L
|
#define _POSIX_C_SOURCE 200112L
|
||||||
|
|
||||||
#include "./alloc.c"
|
#include "./alloc.c"
|
||||||
// #include "./get_changed_ranges.c"
|
|
||||||
#include "./language.c"
|
#include "./language.c"
|
||||||
#include "./lexer.c"
|
#include "./lexer.c"
|
||||||
#include "./node.c"
|
#include "./node.c"
|
||||||
|
|
@ -9,8 +8,6 @@
|
||||||
#include "./stack.c"
|
#include "./stack.c"
|
||||||
#include "./subtree.c"
|
#include "./subtree.c"
|
||||||
#include "./tree.c"
|
#include "./tree.c"
|
||||||
#include "./tree_cursor.c"
|
|
||||||
#include "./wasm_store.c"
|
|
||||||
#include "./lex.c"
|
#include "./lex.c"
|
||||||
#include "./create_language.c"
|
#include "./create_language.c"
|
||||||
#include "./scanner.c"
|
#include "./scanner.c"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
#include "./stack.h"
|
#include "./stack.h"
|
||||||
#include "./subtree.h"
|
#include "./subtree.h"
|
||||||
#include "./tree.h"
|
#include "./tree.h"
|
||||||
#include "./wasm_store.h"
|
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
@ -96,7 +95,7 @@ static const unsigned MAX_SUMMARY_DEPTH = 16;
|
||||||
static const unsigned MAX_COST_DIFFERENCE = 16 * ERROR_COST_PER_SKIPPED_TREE;
|
static const unsigned MAX_COST_DIFFERENCE = 16 * ERROR_COST_PER_SKIPPED_TREE;
|
||||||
static const unsigned OP_COUNT_PER_TIMEOUT_CHECK = 100;
|
static const unsigned OP_COUNT_PER_TIMEOUT_CHECK = 100;
|
||||||
|
|
||||||
typedef struct
|
typedef struct TokenCache
|
||||||
{
|
{
|
||||||
Subtree token;
|
Subtree token;
|
||||||
Subtree last_external_token;
|
Subtree last_external_token;
|
||||||
|
|
@ -109,7 +108,6 @@ struct TSParser
|
||||||
Stack *stack;
|
Stack *stack;
|
||||||
SubtreePool tree_pool;
|
SubtreePool tree_pool;
|
||||||
const TSLanguage *language;
|
const TSLanguage *language;
|
||||||
TSWasmStore *wasm_store;
|
|
||||||
ReduceActionSet reduce_actions;
|
ReduceActionSet reduce_actions;
|
||||||
Subtree finished_tree;
|
Subtree finished_tree;
|
||||||
SubtreeArray trailing_extras;
|
SubtreeArray trailing_extras;
|
||||||
|
|
@ -129,7 +127,7 @@ struct TSParser
|
||||||
bool has_scanner_error;
|
bool has_scanner_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct ErrorStatus
|
||||||
{
|
{
|
||||||
unsigned cost;
|
unsigned cost;
|
||||||
unsigned node_count;
|
unsigned node_count;
|
||||||
|
|
@ -137,7 +135,7 @@ typedef struct
|
||||||
bool is_in_error;
|
bool is_in_error;
|
||||||
} ErrorStatus;
|
} ErrorStatus;
|
||||||
|
|
||||||
typedef enum
|
typedef enum ErrorComparison
|
||||||
{
|
{
|
||||||
ErrorComparisonTakeLeft,
|
ErrorComparisonTakeLeft,
|
||||||
ErrorComparisonPreferLeft,
|
ErrorComparisonPreferLeft,
|
||||||
|
|
@ -146,7 +144,7 @@ typedef enum
|
||||||
ErrorComparisonTakeRight,
|
ErrorComparisonTakeRight,
|
||||||
} ErrorComparison;
|
} ErrorComparison;
|
||||||
|
|
||||||
typedef struct
|
typedef struct TSStringInput
|
||||||
{
|
{
|
||||||
const char *string;
|
const char *string;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
|
|
@ -374,42 +372,22 @@ static bool ts_parser__better_version_exists(TSParser *self, StackVersion versio
|
||||||
|
|
||||||
static bool ts_parser__call_main_lex_fn(TSParser *self, TSLexMode lex_mode)
|
static bool ts_parser__call_main_lex_fn(TSParser *self, TSLexMode lex_mode)
|
||||||
{
|
{
|
||||||
if (ts_language_is_wasm(self->language))
|
return self->language->lex_fn(&self->lexer.data, lex_mode.lex_state);
|
||||||
{
|
|
||||||
return ts_wasm_store_call_lex_main(self->wasm_store, lex_mode.lex_state);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return self->language->lex_fn(&self->lexer.data, lex_mode.lex_state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ts_parser__call_keyword_lex_fn(TSParser *self, TSLexMode lex_mode)
|
static bool ts_parser__call_keyword_lex_fn(TSParser *self, TSLexMode lex_mode)
|
||||||
{
|
{
|
||||||
(void)(lex_mode);
|
(void)(lex_mode);
|
||||||
if (ts_language_is_wasm(self->language))
|
|
||||||
{
|
return self->language->keyword_lex_fn(&self->lexer.data, 0);
|
||||||
return ts_wasm_store_call_lex_keyword(self->wasm_store, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return self->language->keyword_lex_fn(&self->lexer.data, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ts_parser__external_scanner_create(TSParser *self)
|
static void ts_parser__external_scanner_create(TSParser *self)
|
||||||
{
|
{
|
||||||
if (self->language && self->language->external_scanner.states)
|
if (self->language && self->language->external_scanner.states)
|
||||||
{
|
{
|
||||||
if (ts_language_is_wasm(self->language))
|
|
||||||
{
|
if (self->language->external_scanner.create)
|
||||||
self->external_scanner_payload = (void *)(uintptr_t)ts_wasm_store_call_scanner_create(self->wasm_store);
|
|
||||||
if (ts_wasm_store_has_error(self->wasm_store))
|
|
||||||
{
|
|
||||||
self->has_scanner_error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (self->language->external_scanner.create)
|
|
||||||
{
|
{
|
||||||
self->external_scanner_payload = self->language->external_scanner.create();
|
self->external_scanner_payload = self->language->external_scanner.create();
|
||||||
}
|
}
|
||||||
|
|
@ -418,8 +396,7 @@ static void ts_parser__external_scanner_create(TSParser *self)
|
||||||
|
|
||||||
static void ts_parser__external_scanner_destroy(TSParser *self)
|
static void ts_parser__external_scanner_destroy(TSParser *self)
|
||||||
{
|
{
|
||||||
if (self->language && self->external_scanner_payload && self->language->external_scanner.destroy &&
|
if (self->language && self->external_scanner_payload && self->language->external_scanner.destroy)
|
||||||
!ts_language_is_wasm(self->language))
|
|
||||||
{
|
{
|
||||||
self->language->external_scanner.destroy(self->external_scanner_payload);
|
self->language->external_scanner.destroy(self->external_scanner_payload);
|
||||||
}
|
}
|
||||||
|
|
@ -428,16 +405,10 @@ static void ts_parser__external_scanner_destroy(TSParser *self)
|
||||||
|
|
||||||
static unsigned ts_parser__external_scanner_serialize(TSParser *self)
|
static unsigned ts_parser__external_scanner_serialize(TSParser *self)
|
||||||
{
|
{
|
||||||
if (ts_language_is_wasm(self->language))
|
|
||||||
{
|
uint32_t length = self->language->external_scanner.serialize(self->external_scanner_payload, self->lexer.debug_buffer);
|
||||||
return ts_wasm_store_call_scanner_serialize(self->wasm_store, (uintptr_t)self->external_scanner_payload, self->lexer.debug_buffer);
|
assert(length <= TREE_SITTER_SERIALIZATION_BUFFER_SIZE);
|
||||||
}
|
return length;
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t length = self->language->external_scanner.serialize(self->external_scanner_payload, self->lexer.debug_buffer);
|
|
||||||
assert(length <= TREE_SITTER_SERIALIZATION_BUFFER_SIZE);
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ts_parser__external_scanner_deserialize(TSParser *self, Subtree external_token)
|
static void ts_parser__external_scanner_deserialize(TSParser *self, Subtree external_token)
|
||||||
|
|
@ -450,37 +421,13 @@ static void ts_parser__external_scanner_deserialize(TSParser *self, Subtree exte
|
||||||
length = external_token.ptr->external_scanner_state.length;
|
length = external_token.ptr->external_scanner_state.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts_language_is_wasm(self->language))
|
self->language->external_scanner.deserialize(self->external_scanner_payload, data, length);
|
||||||
{
|
|
||||||
ts_wasm_store_call_scanner_deserialize(self->wasm_store, (uintptr_t)self->external_scanner_payload, data, length);
|
|
||||||
if (ts_wasm_store_has_error(self->wasm_store))
|
|
||||||
{
|
|
||||||
self->has_scanner_error = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->language->external_scanner.deserialize(self->external_scanner_payload, data, length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ts_parser__external_scanner_scan(TSParser *self, TSStateId external_lex_state)
|
static bool ts_parser__external_scanner_scan(TSParser *self, TSStateId external_lex_state)
|
||||||
{
|
{
|
||||||
if (ts_language_is_wasm(self->language))
|
const bool *valid_external_tokens = ts_language_enabled_external_tokens(self->language, external_lex_state);
|
||||||
{
|
return self->language->external_scanner.scan(self->external_scanner_payload, &self->lexer.data, valid_external_tokens);
|
||||||
bool result = ts_wasm_store_call_scanner_scan(self->wasm_store, (uintptr_t)self->external_scanner_payload,
|
|
||||||
external_lex_state * self->language->external_token_count);
|
|
||||||
if (ts_wasm_store_has_error(self->wasm_store))
|
|
||||||
{
|
|
||||||
self->has_scanner_error = true;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const bool *valid_external_tokens = ts_language_enabled_external_tokens(self->language, external_lex_state);
|
|
||||||
return self->language->external_scanner.scan(self->external_scanner_payload, &self->lexer.data, valid_external_tokens);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ts_parser__can_reuse_first_leaf(TSParser *self, TSStateId state, Subtree tree, TableEntry *table_entry)
|
static bool ts_parser__can_reuse_first_leaf(TSParser *self, TSStateId state, Subtree tree, TableEntry *table_entry)
|
||||||
|
|
@ -1876,7 +1823,6 @@ void ts_parser_delete(TSParser *self)
|
||||||
ts_subtree_release(&self->tree_pool, self->old_tree);
|
ts_subtree_release(&self->tree_pool, self->old_tree);
|
||||||
self->old_tree = NULL_SUBTREE;
|
self->old_tree = NULL_SUBTREE;
|
||||||
}
|
}
|
||||||
ts_wasm_store_delete(self->wasm_store);
|
|
||||||
ts_lexer_delete(&self->lexer);
|
ts_lexer_delete(&self->lexer);
|
||||||
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
||||||
ts_subtree_pool_delete(&self->tree_pool);
|
ts_subtree_pool_delete(&self->tree_pool);
|
||||||
|
|
@ -1902,12 +1848,6 @@ bool ts_parser_set_language(TSParser *self, const TSLanguage *language)
|
||||||
{
|
{
|
||||||
if (language->version > TREE_SITTER_LANGUAGE_VERSION || language->version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION)
|
if (language->version > TREE_SITTER_LANGUAGE_VERSION || language->version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ts_language_is_wasm(language))
|
|
||||||
{
|
|
||||||
if (!self->wasm_store || !ts_wasm_store_start(self->wasm_store, &self->lexer.data, language))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->language = ts_language_copy(language);
|
self->language = ts_language_copy(language);
|
||||||
|
|
@ -1978,11 +1918,6 @@ const TSRange *ts_parser_included_ranges(const TSParser *self, uint32_t *count)
|
||||||
void ts_parser_reset(TSParser *self)
|
void ts_parser_reset(TSParser *self)
|
||||||
{
|
{
|
||||||
ts_parser__external_scanner_destroy(self);
|
ts_parser__external_scanner_destroy(self);
|
||||||
if (self->wasm_store)
|
|
||||||
{
|
|
||||||
ts_wasm_store_reset(self->wasm_store);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -2009,13 +1944,6 @@ TSTree *ts_parser_parse(TSParser *self, const TSTree *old_tree, TSInput input)
|
||||||
if (!self->language || !input.read)
|
if (!self->language || !input.read)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ts_language_is_wasm(self->language))
|
|
||||||
{
|
|
||||||
if (!self->wasm_store)
|
|
||||||
return NULL;
|
|
||||||
ts_wasm_store_start(self->wasm_store, &self->lexer.data, self->language);
|
|
||||||
}
|
|
||||||
|
|
||||||
ts_lexer_set_input(&self->lexer, input);
|
ts_lexer_set_input(&self->lexer, input);
|
||||||
self->included_range_difference_index = 0;
|
self->included_range_difference_index = 0;
|
||||||
|
|
||||||
|
|
@ -2140,17 +2068,4 @@ TSTree *ts_parser_parse_string_encoding(TSParser *self, const TSTree *old_tree,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ts_parser_set_wasm_store(TSParser *self, TSWasmStore *store)
|
|
||||||
{
|
|
||||||
ts_wasm_store_delete(self->wasm_store);
|
|
||||||
self->wasm_store = store;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSWasmStore *ts_parser_take_wasm_store(TSParser *self)
|
|
||||||
{
|
|
||||||
TSWasmStore *result = self->wasm_store;
|
|
||||||
self->wasm_store = NULL;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef LOG
|
#undef LOG
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
#ifndef TREE_SITTER_REDUCE_ACTION_H_
|
#ifndef TREE_SITTER_REDUCE_ACTION_H_
|
||||||
#define TREE_SITTER_REDUCE_ACTION_H_
|
#define TREE_SITTER_REDUCE_ACTION_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "./array.h"
|
#include "./array.h"
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct ReduceAction {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
TSSymbol symbol;
|
TSSymbol symbol;
|
||||||
int dynamic_precedence;
|
int dynamic_precedence;
|
||||||
|
|
@ -27,8 +24,5 @@ static inline void ts_reduce_action_set_add(ReduceActionSet *self,
|
||||||
array_push(self, new_action);
|
array_push(self, new_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_REDUCE_ACTION_H_
|
#endif // TREE_SITTER_REDUCE_ACTION_H_
|
||||||
|
|
|
||||||
|
|
@ -1,95 +1,111 @@
|
||||||
#include "./subtree.h"
|
#include "./subtree.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct StackEntry
|
||||||
Subtree tree;
|
{
|
||||||
uint32_t child_index;
|
Subtree tree;
|
||||||
uint32_t byte_offset;
|
uint32_t child_index;
|
||||||
|
uint32_t byte_offset;
|
||||||
} StackEntry;
|
} StackEntry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct ReusableNode
|
||||||
Array(StackEntry) stack;
|
{
|
||||||
Subtree last_external_token;
|
Array(StackEntry) stack;
|
||||||
|
Subtree last_external_token;
|
||||||
} ReusableNode;
|
} ReusableNode;
|
||||||
|
|
||||||
static inline ReusableNode reusable_node_new(void) {
|
static inline ReusableNode reusable_node_new(void)
|
||||||
return (ReusableNode) {array_new(), NULL_SUBTREE};
|
{
|
||||||
|
return (ReusableNode){array_new(), NULL_SUBTREE};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reusable_node_clear(ReusableNode *self) {
|
static inline void reusable_node_clear(ReusableNode *self)
|
||||||
array_clear(&self->stack);
|
{
|
||||||
self->last_external_token = NULL_SUBTREE;
|
array_clear(&self->stack);
|
||||||
|
self->last_external_token = NULL_SUBTREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Subtree reusable_node_tree(ReusableNode *self) {
|
static inline Subtree reusable_node_tree(ReusableNode *self)
|
||||||
return self->stack.size > 0
|
{
|
||||||
? self->stack.contents[self->stack.size - 1].tree
|
return self->stack.size > 0 ? self->stack.contents[self->stack.size - 1].tree : NULL_SUBTREE;
|
||||||
: NULL_SUBTREE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t reusable_node_byte_offset(ReusableNode *self) {
|
static inline uint32_t reusable_node_byte_offset(ReusableNode *self)
|
||||||
return self->stack.size > 0
|
{
|
||||||
? self->stack.contents[self->stack.size - 1].byte_offset
|
return self->stack.size > 0 ? self->stack.contents[self->stack.size - 1].byte_offset : UINT32_MAX;
|
||||||
: UINT32_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reusable_node_delete(ReusableNode *self) {
|
static inline void reusable_node_delete(ReusableNode *self)
|
||||||
array_delete(&self->stack);
|
{
|
||||||
|
array_delete(&self->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reusable_node_advance(ReusableNode *self) {
|
static inline void reusable_node_advance(ReusableNode *self)
|
||||||
StackEntry last_entry = *array_back(&self->stack);
|
{
|
||||||
uint32_t byte_offset = last_entry.byte_offset + ts_subtree_total_bytes(last_entry.tree);
|
StackEntry last_entry = *array_back(&self->stack);
|
||||||
if (ts_subtree_has_external_tokens(last_entry.tree)) {
|
uint32_t byte_offset = last_entry.byte_offset + ts_subtree_total_bytes(last_entry.tree);
|
||||||
self->last_external_token = ts_subtree_last_external_token(last_entry.tree);
|
if (ts_subtree_has_external_tokens(last_entry.tree))
|
||||||
}
|
{
|
||||||
|
self->last_external_token = ts_subtree_last_external_token(last_entry.tree);
|
||||||
|
}
|
||||||
|
|
||||||
Subtree tree;
|
Subtree tree;
|
||||||
uint32_t next_index;
|
uint32_t next_index;
|
||||||
do {
|
do
|
||||||
StackEntry popped_entry = array_pop(&self->stack);
|
{
|
||||||
next_index = popped_entry.child_index + 1;
|
StackEntry popped_entry = array_pop(&self->stack);
|
||||||
if (self->stack.size == 0) return;
|
next_index = popped_entry.child_index + 1;
|
||||||
tree = array_back(&self->stack)->tree;
|
if (self->stack.size == 0)
|
||||||
} while (ts_subtree_child_count(tree) <= next_index);
|
return;
|
||||||
|
tree = array_back(&self->stack)->tree;
|
||||||
|
} while (ts_subtree_child_count(tree) <= next_index);
|
||||||
|
|
||||||
array_push(&self->stack, ((StackEntry) {
|
array_push(&self->stack, ((StackEntry){
|
||||||
.tree = ts_subtree_children(tree)[next_index],
|
.tree = ts_subtree_children(tree)[next_index],
|
||||||
.child_index = next_index,
|
.child_index = next_index,
|
||||||
.byte_offset = byte_offset,
|
.byte_offset = byte_offset,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool reusable_node_descend(ReusableNode *self) {
|
static inline bool reusable_node_descend(ReusableNode *self)
|
||||||
StackEntry last_entry = *array_back(&self->stack);
|
{
|
||||||
if (ts_subtree_child_count(last_entry.tree) > 0) {
|
StackEntry last_entry = *array_back(&self->stack);
|
||||||
array_push(&self->stack, ((StackEntry) {
|
if (ts_subtree_child_count(last_entry.tree) > 0)
|
||||||
.tree = ts_subtree_children(last_entry.tree)[0],
|
{
|
||||||
.child_index = 0,
|
array_push(&self->stack, ((StackEntry){
|
||||||
.byte_offset = last_entry.byte_offset,
|
.tree = ts_subtree_children(last_entry.tree)[0],
|
||||||
}));
|
.child_index = 0,
|
||||||
return true;
|
.byte_offset = last_entry.byte_offset,
|
||||||
} else {
|
}));
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reusable_node_advance_past_leaf(ReusableNode *self) {
|
static inline void reusable_node_advance_past_leaf(ReusableNode *self)
|
||||||
while (reusable_node_descend(self)) {}
|
{
|
||||||
reusable_node_advance(self);
|
while (reusable_node_descend(self))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
reusable_node_advance(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void reusable_node_reset(ReusableNode *self, Subtree tree) {
|
static inline void reusable_node_reset(ReusableNode *self, Subtree tree)
|
||||||
reusable_node_clear(self);
|
{
|
||||||
array_push(&self->stack, ((StackEntry) {
|
reusable_node_clear(self);
|
||||||
.tree = tree,
|
array_push(&self->stack, ((StackEntry){
|
||||||
.child_index = 0,
|
.tree = tree,
|
||||||
.byte_offset = 0,
|
.child_index = 0,
|
||||||
}));
|
.byte_offset = 0,
|
||||||
|
}));
|
||||||
|
|
||||||
// Never reuse the root node, because it has a non-standard internal structure
|
// Never reuse the root node, because it has a non-standard internal structure
|
||||||
// due to transformations that are applied when it is accepted: adding the EOF
|
// due to transformations that are applied when it is accepted: adding the EOF
|
||||||
// child and any extra children.
|
// child and any extra children.
|
||||||
if (!reusable_node_descend(self)) {
|
if (!reusable_node_descend(self))
|
||||||
reusable_node_clear(self);
|
{
|
||||||
}
|
reusable_node_clear(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
#ifndef TREE_SITTER_PARSE_STACK_H_
|
#ifndef TREE_SITTER_PARSE_STACK_H_
|
||||||
#define TREE_SITTER_PARSE_STACK_H_
|
#define TREE_SITTER_PARSE_STACK_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "./array.h"
|
#include "./array.h"
|
||||||
#include "./subtree.h"
|
|
||||||
#include "./error_costs.h"
|
#include "./error_costs.h"
|
||||||
|
#include "./subtree.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct Stack Stack;
|
typedef struct Stack Stack;
|
||||||
|
|
@ -15,19 +11,24 @@ typedef struct Stack Stack;
|
||||||
typedef unsigned StackVersion;
|
typedef unsigned StackVersion;
|
||||||
#define STACK_VERSION_NONE ((StackVersion)-1)
|
#define STACK_VERSION_NONE ((StackVersion)-1)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct StackSlice
|
||||||
SubtreeArray subtrees;
|
{
|
||||||
StackVersion version;
|
SubtreeArray subtrees;
|
||||||
|
StackVersion version;
|
||||||
} StackSlice;
|
} StackSlice;
|
||||||
typedef Array(StackSlice) StackSliceArray;
|
typedef Array(StackSlice) StackSliceArray;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct StackSummaryEntry
|
||||||
Length position;
|
{
|
||||||
unsigned depth;
|
Length position;
|
||||||
TSStateId state;
|
unsigned depth;
|
||||||
|
TSStateId state;
|
||||||
} StackSummaryEntry;
|
} StackSummaryEntry;
|
||||||
|
|
||||||
typedef Array(StackSummaryEntry) StackSummary;
|
typedef Array(StackSummaryEntry) StackSummary;
|
||||||
|
|
||||||
|
typedef void (*StackIterateCallback)(void *, TSStateId, uint32_t);
|
||||||
|
|
||||||
// Create a stack.
|
// Create a stack.
|
||||||
Stack *ts_stack_new(SubtreePool *);
|
Stack *ts_stack_new(SubtreePool *);
|
||||||
|
|
||||||
|
|
@ -45,7 +46,7 @@ TSStateId ts_stack_state(const Stack *, StackVersion);
|
||||||
Subtree ts_stack_last_external_token(const Stack *, StackVersion);
|
Subtree ts_stack_last_external_token(const Stack *, StackVersion);
|
||||||
|
|
||||||
// Set the last external token associated with a given version of the stack.
|
// Set the last external token associated with a given version of the stack.
|
||||||
void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree );
|
void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree);
|
||||||
|
|
||||||
// Get the position of the given version of the stack within the document.
|
// Get the position of the given version of the stack within the document.
|
||||||
Length ts_stack_position(const Stack *, StackVersion);
|
Length ts_stack_position(const Stack *, StackVersion);
|
||||||
|
|
@ -55,7 +56,7 @@ Length ts_stack_position(const Stack *, StackVersion);
|
||||||
// This transfers ownership of the tree to the Stack. Callers that
|
// This transfers ownership of the tree to the Stack. Callers that
|
||||||
// need to retain ownership of the tree for their own purposes should
|
// need to retain ownership of the tree for their own purposes should
|
||||||
// first retain the tree.
|
// first retain the tree.
|
||||||
void ts_stack_push(Stack *, StackVersion, Subtree , bool, TSStateId);
|
void ts_stack_push(Stack *, StackVersion, Subtree, bool, TSStateId);
|
||||||
|
|
||||||
// Pop the given number of entries from the given version of the stack. This
|
// Pop the given number of entries from the given version of the stack. This
|
||||||
// operation can increase the number of stack versions by revealing multiple
|
// operation can increase the number of stack versions by revealing multiple
|
||||||
|
|
@ -124,10 +125,4 @@ void ts_stack_clear(Stack *);
|
||||||
|
|
||||||
bool ts_stack_print_dot_graph(Stack *, const TSLanguage *, FILE *);
|
bool ts_stack_print_dot_graph(Stack *, const TSLanguage *, FILE *);
|
||||||
|
|
||||||
typedef void (*StackIterateCallback)(void *, TSStateId, uint32_t);
|
#endif // TREE_SITTER_PARSE_STACK_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_PARSE_STACK_H_
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,18 @@
|
||||||
#ifndef TREE_SITTER_SUBTREE_H_
|
#ifndef TREE_SITTER_SUBTREE_H_
|
||||||
#define TREE_SITTER_SUBTREE_H_
|
#define TREE_SITTER_SUBTREE_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "./length.h"
|
|
||||||
#include "./array.h"
|
#include "./array.h"
|
||||||
#include "./error_costs.h"
|
#include "./error_costs.h"
|
||||||
#include "./host.h"
|
#include "./host.h"
|
||||||
#include "api.h"
|
#include "./length.h"
|
||||||
#include "./parser.h"
|
#include "./parser.h"
|
||||||
|
#include "api.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define TS_TREE_STATE_NONE USHRT_MAX
|
#define TS_TREE_STATE_NONE USHRT_MAX
|
||||||
#define NULL_SUBTREE ((Subtree) {.ptr = NULL})
|
#define NULL_SUBTREE ((Subtree){.ptr = NULL})
|
||||||
|
|
||||||
// The serialized state of an external scanner.
|
// The serialized state of an external scanner.
|
||||||
//
|
//
|
||||||
|
|
@ -28,12 +24,13 @@ extern "C" {
|
||||||
//
|
//
|
||||||
// Small byte arrays are stored inline, and long ones are allocated
|
// Small byte arrays are stored inline, and long ones are allocated
|
||||||
// separately on the heap.
|
// separately on the heap.
|
||||||
typedef struct {
|
typedef struct ExternalScannerState
|
||||||
union {
|
{
|
||||||
char *long_data;
|
union {
|
||||||
char short_data[24];
|
char *long_data;
|
||||||
};
|
char short_data[24];
|
||||||
uint32_t length;
|
};
|
||||||
|
uint32_t length;
|
||||||
} ExternalScannerState;
|
} ExternalScannerState;
|
||||||
|
|
||||||
// A compact representation of a subtree.
|
// A compact representation of a subtree.
|
||||||
|
|
@ -49,53 +46,56 @@ typedef struct {
|
||||||
// the pointer or the inline struct.
|
// the pointer or the inline struct.
|
||||||
typedef struct SubtreeInlineData SubtreeInlineData;
|
typedef struct SubtreeInlineData SubtreeInlineData;
|
||||||
|
|
||||||
#define SUBTREE_BITS \
|
#define SUBTREE_BITS \
|
||||||
bool visible : 1; \
|
bool visible : 1; \
|
||||||
bool named : 1; \
|
bool named : 1; \
|
||||||
bool extra : 1; \
|
bool extra : 1; \
|
||||||
bool has_changes : 1; \
|
bool has_changes : 1; \
|
||||||
bool is_missing : 1; \
|
bool is_missing : 1; \
|
||||||
bool is_keyword : 1;
|
bool is_keyword : 1;
|
||||||
|
|
||||||
#define SUBTREE_SIZE \
|
#define SUBTREE_SIZE \
|
||||||
uint8_t padding_columns; \
|
uint8_t padding_columns; \
|
||||||
uint8_t padding_rows : 4; \
|
uint8_t padding_rows : 4; \
|
||||||
uint8_t lookahead_bytes : 4; \
|
uint8_t lookahead_bytes : 4; \
|
||||||
uint8_t padding_bytes; \
|
uint8_t padding_bytes; \
|
||||||
uint8_t size_bytes;
|
uint8_t size_bytes;
|
||||||
|
|
||||||
#if TS_BIG_ENDIAN
|
#if TS_BIG_ENDIAN
|
||||||
#if TS_PTR_SIZE == 32
|
# if TS_PTR_SIZE == 32
|
||||||
|
|
||||||
struct SubtreeInlineData {
|
struct SubtreeInlineData
|
||||||
uint16_t parse_state;
|
{
|
||||||
uint8_t symbol;
|
uint16_t parse_state;
|
||||||
SUBTREE_BITS
|
uint8_t symbol;
|
||||||
bool unused : 1;
|
SUBTREE_BITS
|
||||||
bool is_inline : 1;
|
bool unused : 1;
|
||||||
SUBTREE_SIZE
|
bool is_inline : 1;
|
||||||
|
SUBTREE_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
# else
|
||||||
|
|
||||||
struct SubtreeInlineData {
|
struct SubtreeInlineData
|
||||||
SUBTREE_SIZE
|
{
|
||||||
uint16_t parse_state;
|
SUBTREE_SIZE
|
||||||
uint8_t symbol;
|
uint16_t parse_state;
|
||||||
SUBTREE_BITS
|
uint8_t symbol;
|
||||||
bool unused : 1;
|
SUBTREE_BITS
|
||||||
bool is_inline : 1;
|
bool unused : 1;
|
||||||
|
bool is_inline : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
# endif
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct SubtreeInlineData {
|
struct SubtreeInlineData
|
||||||
bool is_inline : 1;
|
{
|
||||||
SUBTREE_BITS
|
bool is_inline : 1;
|
||||||
uint8_t symbol;
|
SUBTREE_BITS
|
||||||
uint16_t parse_state;
|
uint8_t symbol;
|
||||||
SUBTREE_SIZE
|
uint16_t parse_state;
|
||||||
|
SUBTREE_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -108,75 +108,79 @@ struct SubtreeInlineData {
|
||||||
// This representation is used for parent nodes, external tokens,
|
// This representation is used for parent nodes, external tokens,
|
||||||
// errors, and other leaf nodes whose data is too large to fit into
|
// errors, and other leaf nodes whose data is too large to fit into
|
||||||
// the inline representation.
|
// the inline representation.
|
||||||
typedef struct {
|
typedef struct SubtreeHeapData
|
||||||
volatile uint32_t ref_count;
|
{
|
||||||
Length padding;
|
volatile uint32_t ref_count;
|
||||||
Length size;
|
Length padding;
|
||||||
uint32_t lookahead_bytes;
|
Length size;
|
||||||
uint32_t error_cost;
|
uint32_t lookahead_bytes;
|
||||||
uint32_t child_count;
|
uint32_t error_cost;
|
||||||
TSSymbol symbol;
|
uint32_t child_count;
|
||||||
TSStateId parse_state;
|
TSSymbol symbol;
|
||||||
|
TSStateId parse_state;
|
||||||
|
|
||||||
bool visible : 1;
|
bool visible : 1;
|
||||||
bool named : 1;
|
bool named : 1;
|
||||||
bool extra : 1;
|
bool extra : 1;
|
||||||
bool fragile_left : 1;
|
bool fragile_left : 1;
|
||||||
bool fragile_right : 1;
|
bool fragile_right : 1;
|
||||||
bool has_changes : 1;
|
bool has_changes : 1;
|
||||||
bool has_external_tokens : 1;
|
bool has_external_tokens : 1;
|
||||||
bool has_external_scanner_state_change : 1;
|
bool has_external_scanner_state_change : 1;
|
||||||
bool depends_on_column: 1;
|
bool depends_on_column : 1;
|
||||||
bool is_missing : 1;
|
bool is_missing : 1;
|
||||||
bool is_keyword : 1;
|
bool is_keyword : 1;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
// Non-terminal subtrees (`child_count > 0`)
|
// Non-terminal subtrees (`child_count > 0`)
|
||||||
struct {
|
struct
|
||||||
uint32_t visible_child_count;
|
{
|
||||||
uint32_t named_child_count;
|
uint32_t visible_child_count;
|
||||||
uint32_t visible_descendant_count;
|
uint32_t named_child_count;
|
||||||
int32_t dynamic_precedence;
|
uint32_t visible_descendant_count;
|
||||||
uint16_t repeat_depth;
|
int32_t dynamic_precedence;
|
||||||
uint16_t production_id;
|
uint16_t repeat_depth;
|
||||||
struct {
|
uint16_t production_id;
|
||||||
TSSymbol symbol;
|
struct
|
||||||
TSStateId parse_state;
|
{
|
||||||
} first_leaf;
|
TSSymbol symbol;
|
||||||
};
|
TSStateId parse_state;
|
||||||
|
} first_leaf;
|
||||||
|
};
|
||||||
|
|
||||||
// External terminal subtrees (`child_count == 0 && has_external_tokens`)
|
// External terminal subtrees (`child_count == 0 && has_external_tokens`)
|
||||||
ExternalScannerState external_scanner_state;
|
ExternalScannerState external_scanner_state;
|
||||||
|
|
||||||
// Error terminal subtrees (`child_count == 0 && symbol == ts_builtin_sym_error`)
|
// Error terminal subtrees (`child_count == 0 && symbol == ts_builtin_sym_error`)
|
||||||
int32_t lookahead_char;
|
int32_t lookahead_char;
|
||||||
};
|
};
|
||||||
} SubtreeHeapData;
|
} SubtreeHeapData;
|
||||||
|
|
||||||
// The fundamental building block of a syntax tree.
|
// The fundamental building block of a syntax tree.
|
||||||
typedef union {
|
typedef union Subtree {
|
||||||
SubtreeInlineData data;
|
SubtreeInlineData data;
|
||||||
const SubtreeHeapData *ptr;
|
const SubtreeHeapData *ptr;
|
||||||
} Subtree;
|
} Subtree;
|
||||||
|
|
||||||
// Like Subtree, but mutable.
|
// Like Subtree, but mutable.
|
||||||
typedef union {
|
typedef union MutableSubtree {
|
||||||
SubtreeInlineData data;
|
SubtreeInlineData data;
|
||||||
SubtreeHeapData *ptr;
|
SubtreeHeapData *ptr;
|
||||||
} MutableSubtree;
|
} MutableSubtree;
|
||||||
|
|
||||||
typedef Array(Subtree) SubtreeArray;
|
typedef Array(Subtree) SubtreeArray;
|
||||||
typedef Array(MutableSubtree) MutableSubtreeArray;
|
typedef Array(MutableSubtree) MutableSubtreeArray;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct SubtreePool
|
||||||
MutableSubtreeArray free_trees;
|
{
|
||||||
MutableSubtreeArray tree_stack;
|
MutableSubtreeArray free_trees;
|
||||||
|
MutableSubtreeArray tree_stack;
|
||||||
} SubtreePool;
|
} SubtreePool;
|
||||||
|
|
||||||
void ts_external_scanner_state_init(ExternalScannerState *, const char *, unsigned);
|
void ts_external_scanner_state_init(ExternalScannerState *, const char *, unsigned);
|
||||||
const char *ts_external_scanner_state_data(const ExternalScannerState *);
|
const char *ts_external_scanner_state_data(const ExternalScannerState *);
|
||||||
bool ts_external_scanner_state_eq(const ExternalScannerState *self, const char *, unsigned);
|
bool ts_external_scanner_state_eq(const ExternalScannerState *self, const char *, unsigned);
|
||||||
void ts_external_scanner_state_delete(ExternalScannerState *self);
|
void ts_external_scanner_state_delete(ExternalScannerState *self);
|
||||||
|
|
||||||
void ts_subtree_array_copy(SubtreeArray, SubtreeArray *);
|
void ts_subtree_array_copy(SubtreeArray, SubtreeArray *);
|
||||||
void ts_subtree_array_clear(SubtreePool *, SubtreeArray *);
|
void ts_subtree_array_clear(SubtreePool *, SubtreeArray *);
|
||||||
|
|
@ -185,198 +189,263 @@ void ts_subtree_array_remove_trailing_extras(SubtreeArray *, SubtreeArray *);
|
||||||
void ts_subtree_array_reverse(SubtreeArray *);
|
void ts_subtree_array_reverse(SubtreeArray *);
|
||||||
|
|
||||||
SubtreePool ts_subtree_pool_new(uint32_t capacity);
|
SubtreePool ts_subtree_pool_new(uint32_t capacity);
|
||||||
void ts_subtree_pool_delete(SubtreePool *);
|
void ts_subtree_pool_delete(SubtreePool *);
|
||||||
|
|
||||||
Subtree ts_subtree_new_leaf(
|
Subtree ts_subtree_new_leaf(SubtreePool *, TSSymbol, Length, Length, uint32_t, TSStateId, bool, bool, bool, const TSLanguage *);
|
||||||
SubtreePool *, TSSymbol, Length, Length, uint32_t,
|
Subtree ts_subtree_new_error(SubtreePool *, int32_t, Length, Length, uint32_t, TSStateId, const TSLanguage *);
|
||||||
TSStateId, bool, bool, bool, const TSLanguage *
|
|
||||||
);
|
|
||||||
Subtree ts_subtree_new_error(
|
|
||||||
SubtreePool *, int32_t, Length, Length, uint32_t, TSStateId, const TSLanguage *
|
|
||||||
);
|
|
||||||
MutableSubtree ts_subtree_new_node(TSSymbol, SubtreeArray *, unsigned, const TSLanguage *);
|
MutableSubtree ts_subtree_new_node(TSSymbol, SubtreeArray *, unsigned, const TSLanguage *);
|
||||||
Subtree ts_subtree_new_error_node(SubtreeArray *, bool, const TSLanguage *);
|
Subtree ts_subtree_new_error_node(SubtreeArray *, bool, const TSLanguage *);
|
||||||
Subtree ts_subtree_new_missing_leaf(SubtreePool *, TSSymbol, Length, uint32_t, const TSLanguage *);
|
Subtree ts_subtree_new_missing_leaf(SubtreePool *, TSSymbol, Length, uint32_t, const TSLanguage *);
|
||||||
MutableSubtree ts_subtree_make_mut(SubtreePool *, Subtree);
|
MutableSubtree ts_subtree_make_mut(SubtreePool *, Subtree);
|
||||||
void ts_subtree_retain(Subtree);
|
void ts_subtree_retain(Subtree);
|
||||||
void ts_subtree_release(SubtreePool *, Subtree);
|
void ts_subtree_release(SubtreePool *, Subtree);
|
||||||
int ts_subtree_compare(Subtree, Subtree, SubtreePool *);
|
int ts_subtree_compare(Subtree, Subtree, SubtreePool *);
|
||||||
void ts_subtree_set_symbol(MutableSubtree *, TSSymbol, const TSLanguage *);
|
void ts_subtree_set_symbol(MutableSubtree *, TSSymbol, const TSLanguage *);
|
||||||
void ts_subtree_summarize(MutableSubtree, const Subtree *, uint32_t, const TSLanguage *);
|
void ts_subtree_summarize(MutableSubtree, const Subtree *, uint32_t, const TSLanguage *);
|
||||||
void ts_subtree_summarize_children(MutableSubtree, const TSLanguage *);
|
void ts_subtree_summarize_children(MutableSubtree, const TSLanguage *);
|
||||||
void ts_subtree_balance(Subtree, SubtreePool *, const TSLanguage *);
|
void ts_subtree_balance(Subtree, SubtreePool *, const TSLanguage *);
|
||||||
Subtree ts_subtree_edit(Subtree, const TSInputEdit *edit, SubtreePool *);
|
Subtree ts_subtree_edit(Subtree, const TSInputEdit *edit, SubtreePool *);
|
||||||
char *ts_subtree_string(Subtree, TSSymbol, bool, const TSLanguage *, bool include_all);
|
char *ts_subtree_string(Subtree, TSSymbol, bool, const TSLanguage *, bool include_all);
|
||||||
void ts_subtree_print_dot_graph(Subtree, const TSLanguage *, FILE *);
|
void ts_subtree_print_dot_graph(Subtree, const TSLanguage *, FILE *);
|
||||||
Subtree ts_subtree_last_external_token(Subtree);
|
Subtree ts_subtree_last_external_token(Subtree);
|
||||||
const ExternalScannerState *ts_subtree_external_scanner_state(Subtree self);
|
const ExternalScannerState *ts_subtree_external_scanner_state(Subtree self);
|
||||||
bool ts_subtree_external_scanner_state_eq(Subtree, Subtree);
|
bool ts_subtree_external_scanner_state_eq(Subtree, Subtree);
|
||||||
|
|
||||||
#define SUBTREE_GET(self, name) ((self).data.is_inline ? (self).data.name : (self).ptr->name)
|
#define SUBTREE_GET(self, name) ((self).data.is_inline ? (self).data.name : (self).ptr->name)
|
||||||
|
|
||||||
static inline TSSymbol ts_subtree_symbol(Subtree self) { return SUBTREE_GET(self, symbol); }
|
static inline TSSymbol ts_subtree_symbol(Subtree self)
|
||||||
static inline bool ts_subtree_visible(Subtree self) { return SUBTREE_GET(self, visible); }
|
{
|
||||||
static inline bool ts_subtree_named(Subtree self) { return SUBTREE_GET(self, named); }
|
return SUBTREE_GET(self, symbol);
|
||||||
static inline bool ts_subtree_extra(Subtree self) { return SUBTREE_GET(self, extra); }
|
}
|
||||||
static inline bool ts_subtree_has_changes(Subtree self) { return SUBTREE_GET(self, has_changes); }
|
static inline bool ts_subtree_visible(Subtree self)
|
||||||
static inline bool ts_subtree_missing(Subtree self) { return SUBTREE_GET(self, is_missing); }
|
{
|
||||||
static inline bool ts_subtree_is_keyword(Subtree self) { return SUBTREE_GET(self, is_keyword); }
|
return SUBTREE_GET(self, visible);
|
||||||
static inline TSStateId ts_subtree_parse_state(Subtree self) { return SUBTREE_GET(self, parse_state); }
|
}
|
||||||
static inline uint32_t ts_subtree_lookahead_bytes(Subtree self) { return SUBTREE_GET(self, lookahead_bytes); }
|
static inline bool ts_subtree_named(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, named);
|
||||||
|
}
|
||||||
|
static inline bool ts_subtree_extra(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, extra);
|
||||||
|
}
|
||||||
|
static inline bool ts_subtree_has_changes(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, has_changes);
|
||||||
|
}
|
||||||
|
static inline bool ts_subtree_missing(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, is_missing);
|
||||||
|
}
|
||||||
|
static inline bool ts_subtree_is_keyword(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, is_keyword);
|
||||||
|
}
|
||||||
|
static inline TSStateId ts_subtree_parse_state(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, parse_state);
|
||||||
|
}
|
||||||
|
static inline uint32_t ts_subtree_lookahead_bytes(Subtree self)
|
||||||
|
{
|
||||||
|
return SUBTREE_GET(self, lookahead_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
#undef SUBTREE_GET
|
#undef SUBTREE_GET
|
||||||
|
|
||||||
// Get the size needed to store a heap-allocated subtree with the given
|
// Get the size needed to store a heap-allocated subtree with the given
|
||||||
// number of children.
|
// number of children.
|
||||||
static inline size_t ts_subtree_alloc_size(uint32_t child_count) {
|
static inline size_t ts_subtree_alloc_size(uint32_t child_count)
|
||||||
return child_count * sizeof(Subtree) + sizeof(SubtreeHeapData);
|
{
|
||||||
|
return child_count * sizeof(Subtree) + sizeof(SubtreeHeapData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a subtree's children, which are allocated immediately before the
|
// Get a subtree's children, which are allocated immediately before the
|
||||||
// tree's own heap data.
|
// tree's own heap data.
|
||||||
#define ts_subtree_children(self) \
|
#define ts_subtree_children(self) ((self).data.is_inline ? NULL : (Subtree *)((self).ptr) - (self).ptr->child_count)
|
||||||
((self).data.is_inline ? NULL : (Subtree *)((self).ptr) - (self).ptr->child_count)
|
|
||||||
|
|
||||||
static inline void ts_subtree_set_extra(MutableSubtree *self, bool is_extra) {
|
static inline void ts_subtree_set_extra(MutableSubtree *self, bool is_extra)
|
||||||
if (self->data.is_inline) {
|
{
|
||||||
self->data.extra = is_extra;
|
if (self->data.is_inline)
|
||||||
} else {
|
{
|
||||||
self->ptr->extra = is_extra;
|
self->data.extra = is_extra;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->ptr->extra = is_extra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TSSymbol ts_subtree_leaf_symbol(Subtree self) {
|
static inline TSSymbol ts_subtree_leaf_symbol(Subtree self)
|
||||||
if (self.data.is_inline) return self.data.symbol;
|
{
|
||||||
if (self.ptr->child_count == 0) return self.ptr->symbol;
|
if (self.data.is_inline)
|
||||||
return self.ptr->first_leaf.symbol;
|
return self.data.symbol;
|
||||||
|
if (self.ptr->child_count == 0)
|
||||||
|
return self.ptr->symbol;
|
||||||
|
return self.ptr->first_leaf.symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline TSStateId ts_subtree_leaf_parse_state(Subtree self) {
|
static inline TSStateId ts_subtree_leaf_parse_state(Subtree self)
|
||||||
if (self.data.is_inline) return self.data.parse_state;
|
{
|
||||||
if (self.ptr->child_count == 0) return self.ptr->parse_state;
|
if (self.data.is_inline)
|
||||||
return self.ptr->first_leaf.parse_state;
|
return self.data.parse_state;
|
||||||
|
if (self.ptr->child_count == 0)
|
||||||
|
return self.ptr->parse_state;
|
||||||
|
return self.ptr->first_leaf.parse_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Length ts_subtree_padding(Subtree self) {
|
static inline Length ts_subtree_padding(Subtree self)
|
||||||
if (self.data.is_inline) {
|
{
|
||||||
Length result = {self.data.padding_bytes, {self.data.padding_rows, self.data.padding_columns}};
|
if (self.data.is_inline)
|
||||||
return result;
|
{
|
||||||
} else {
|
Length result = {self.data.padding_bytes, {self.data.padding_rows, self.data.padding_columns}};
|
||||||
return self.ptr->padding;
|
return result;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return self.ptr->padding;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Length ts_subtree_size(Subtree self) {
|
static inline Length ts_subtree_size(Subtree self)
|
||||||
if (self.data.is_inline) {
|
{
|
||||||
Length result = {self.data.size_bytes, {0, self.data.size_bytes}};
|
if (self.data.is_inline)
|
||||||
return result;
|
{
|
||||||
} else {
|
Length result = {self.data.size_bytes, {0, self.data.size_bytes}};
|
||||||
return self.ptr->size;
|
return result;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return self.ptr->size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Length ts_subtree_total_size(Subtree self) {
|
static inline Length ts_subtree_total_size(Subtree self)
|
||||||
return length_add(ts_subtree_padding(self), ts_subtree_size(self));
|
{
|
||||||
|
return length_add(ts_subtree_padding(self), ts_subtree_size(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_total_bytes(Subtree self) {
|
static inline uint32_t ts_subtree_total_bytes(Subtree self)
|
||||||
return ts_subtree_total_size(self).bytes;
|
{
|
||||||
|
return ts_subtree_total_size(self).bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_child_count(Subtree self) {
|
static inline uint32_t ts_subtree_child_count(Subtree self)
|
||||||
return self.data.is_inline ? 0 : self.ptr->child_count;
|
{
|
||||||
|
return self.data.is_inline ? 0 : self.ptr->child_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_repeat_depth(Subtree self) {
|
static inline uint32_t ts_subtree_repeat_depth(Subtree self)
|
||||||
return self.data.is_inline ? 0 : self.ptr->repeat_depth;
|
{
|
||||||
|
return self.data.is_inline ? 0 : self.ptr->repeat_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_is_repetition(Subtree self) {
|
static inline uint32_t ts_subtree_is_repetition(Subtree self)
|
||||||
return self.data.is_inline
|
{
|
||||||
? 0
|
return self.data.is_inline ? 0 : !self.ptr->named && !self.ptr->visible && self.ptr->child_count != 0;
|
||||||
: !self.ptr->named && !self.ptr->visible && self.ptr->child_count != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_visible_descendant_count(Subtree self) {
|
static inline uint32_t ts_subtree_visible_descendant_count(Subtree self)
|
||||||
return (self.data.is_inline || self.ptr->child_count == 0)
|
{
|
||||||
? 0
|
return (self.data.is_inline || self.ptr->child_count == 0) ? 0 : self.ptr->visible_descendant_count;
|
||||||
: self.ptr->visible_descendant_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_visible_child_count(Subtree self) {
|
static inline uint32_t ts_subtree_visible_child_count(Subtree self)
|
||||||
if (ts_subtree_child_count(self) > 0) {
|
{
|
||||||
return self.ptr->visible_child_count;
|
if (ts_subtree_child_count(self) > 0)
|
||||||
} else {
|
{
|
||||||
return 0;
|
return self.ptr->visible_child_count;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t ts_subtree_error_cost(Subtree self) {
|
static inline uint32_t ts_subtree_error_cost(Subtree self)
|
||||||
if (ts_subtree_missing(self)) {
|
{
|
||||||
return ERROR_COST_PER_MISSING_TREE + ERROR_COST_PER_RECOVERY;
|
if (ts_subtree_missing(self))
|
||||||
} else {
|
{
|
||||||
return self.data.is_inline ? 0 : self.ptr->error_cost;
|
return ERROR_COST_PER_MISSING_TREE + ERROR_COST_PER_RECOVERY;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return self.data.is_inline ? 0 : self.ptr->error_cost;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int32_t ts_subtree_dynamic_precedence(Subtree self) {
|
static inline int32_t ts_subtree_dynamic_precedence(Subtree self)
|
||||||
return (self.data.is_inline || self.ptr->child_count == 0) ? 0 : self.ptr->dynamic_precedence;
|
{
|
||||||
|
return (self.data.is_inline || self.ptr->child_count == 0) ? 0 : self.ptr->dynamic_precedence;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t ts_subtree_production_id(Subtree self) {
|
static inline uint16_t ts_subtree_production_id(Subtree self)
|
||||||
if (ts_subtree_child_count(self) > 0) {
|
{
|
||||||
return self.ptr->production_id;
|
if (ts_subtree_child_count(self) > 0)
|
||||||
} else {
|
{
|
||||||
return 0;
|
return self.ptr->production_id;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_fragile_left(Subtree self) {
|
static inline bool ts_subtree_fragile_left(Subtree self)
|
||||||
return self.data.is_inline ? false : self.ptr->fragile_left;
|
{
|
||||||
|
return self.data.is_inline ? false : self.ptr->fragile_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_fragile_right(Subtree self) {
|
static inline bool ts_subtree_fragile_right(Subtree self)
|
||||||
return self.data.is_inline ? false : self.ptr->fragile_right;
|
{
|
||||||
|
return self.data.is_inline ? false : self.ptr->fragile_right;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_has_external_tokens(Subtree self) {
|
static inline bool ts_subtree_has_external_tokens(Subtree self)
|
||||||
return self.data.is_inline ? false : self.ptr->has_external_tokens;
|
{
|
||||||
|
return self.data.is_inline ? false : self.ptr->has_external_tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_has_external_scanner_state_change(Subtree self) {
|
static inline bool ts_subtree_has_external_scanner_state_change(Subtree self)
|
||||||
return self.data.is_inline ? false : self.ptr->has_external_scanner_state_change;
|
{
|
||||||
|
return self.data.is_inline ? false : self.ptr->has_external_scanner_state_change;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_depends_on_column(Subtree self) {
|
static inline bool ts_subtree_depends_on_column(Subtree self)
|
||||||
return self.data.is_inline ? false : self.ptr->depends_on_column;
|
{
|
||||||
|
return self.data.is_inline ? false : self.ptr->depends_on_column;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_is_fragile(Subtree self) {
|
static inline bool ts_subtree_is_fragile(Subtree self)
|
||||||
return self.data.is_inline ? false : (self.ptr->fragile_left || self.ptr->fragile_right);
|
{
|
||||||
|
return self.data.is_inline ? false : (self.ptr->fragile_left || self.ptr->fragile_right);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_is_error(Subtree self) {
|
static inline bool ts_subtree_is_error(Subtree self)
|
||||||
return ts_subtree_symbol(self) == ts_builtin_sym_error;
|
{
|
||||||
|
return ts_subtree_symbol(self) == ts_builtin_sym_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ts_subtree_is_eof(Subtree self) {
|
static inline bool ts_subtree_is_eof(Subtree self)
|
||||||
return ts_subtree_symbol(self) == ts_builtin_sym_end;
|
{
|
||||||
|
return ts_subtree_symbol(self) == ts_builtin_sym_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Subtree ts_subtree_from_mut(MutableSubtree self) {
|
static inline Subtree ts_subtree_from_mut(MutableSubtree self)
|
||||||
Subtree result;
|
{
|
||||||
result.data = self.data;
|
Subtree result;
|
||||||
return result;
|
result.data = self.data;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline MutableSubtree ts_subtree_to_mut_unsafe(Subtree self) {
|
static inline MutableSubtree ts_subtree_to_mut_unsafe(Subtree self)
|
||||||
MutableSubtree result;
|
{
|
||||||
result.data = self.data;
|
MutableSubtree result;
|
||||||
return result;
|
result.data = self.data;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // TREE_SITTER_SUBTREE_H_
|
#endif // TREE_SITTER_SUBTREE_H_
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "./array.h"
|
#include "./array.h"
|
||||||
#include "./length.h"
|
#include "./length.h"
|
||||||
#include "./subtree.h"
|
#include "./subtree.h"
|
||||||
#include "./tree_cursor.h"
|
|
||||||
#include "api.h"
|
#include "api.h"
|
||||||
|
|
||||||
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *included_ranges, unsigned included_range_count)
|
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *included_ranges, unsigned included_range_count)
|
||||||
|
|
@ -106,51 +105,7 @@ TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length)
|
||||||
return ranges;
|
return ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSRange *ts_tree_get_changed_ranges(const TSTree *old_tree, const TSTree *new_tree, uint32_t *length)
|
#include <unistd.h>
|
||||||
// {
|
|
||||||
// TreeCursor cursor1 = {NULL, array_new(), 0};
|
|
||||||
// TreeCursor cursor2 = {NULL, array_new(), 0};
|
|
||||||
// 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();
|
|
||||||
// ts_range_array_get_changed_ranges(old_tree->included_ranges, old_tree->included_range_count, new_tree->included_ranges,
|
|
||||||
// new_tree->included_range_count, &included_range_differences);
|
|
||||||
|
|
||||||
// TSRange *result;
|
|
||||||
// *length = ts_subtree_get_changed_ranges(&old_tree->root, &new_tree->root, &cursor1, &cursor2, old_tree->language,
|
|
||||||
// &included_range_differences, &result);
|
|
||||||
|
|
||||||
// array_delete(&included_range_differences);
|
|
||||||
// array_delete(&cursor1.stack);
|
|
||||||
// array_delete(&cursor2.stack);
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
# include <io.h>
|
|
||||||
# include <windows.h>
|
|
||||||
|
|
||||||
int _ts_dup(HANDLE handle)
|
|
||||||
{
|
|
||||||
HANDLE dup_handle;
|
|
||||||
if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &dup_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return _open_osfhandle((intptr_t)dup_handle, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
# include <unistd.h>
|
|
||||||
|
|
||||||
int _ts_dup(int file_descriptor)
|
int _ts_dup(int file_descriptor)
|
||||||
{
|
{
|
||||||
|
|
@ -163,5 +118,3 @@ void ts_tree_print_dot_graph(const TSTree *self, int file_descriptor)
|
||||||
ts_subtree_print_dot_graph(self->root, self->language, file);
|
ts_subtree_print_dot_graph(self->root, self->language, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,23 @@
|
||||||
|
|
||||||
#include "./subtree.h"
|
#include "./subtree.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
typedef struct ParentCacheEntry
|
||||||
extern "C" {
|
{
|
||||||
#endif
|
const Subtree *child;
|
||||||
|
const Subtree *parent;
|
||||||
typedef struct {
|
Length position;
|
||||||
const Subtree *child;
|
TSSymbol alias_symbol;
|
||||||
const Subtree *parent;
|
|
||||||
Length position;
|
|
||||||
TSSymbol alias_symbol;
|
|
||||||
} ParentCacheEntry;
|
} ParentCacheEntry;
|
||||||
|
|
||||||
struct TSTree {
|
struct TSTree
|
||||||
Subtree root;
|
{
|
||||||
const TSLanguage *language;
|
Subtree root;
|
||||||
TSRange *included_ranges;
|
const TSLanguage *language;
|
||||||
unsigned included_range_count;
|
TSRange *included_ranges;
|
||||||
|
unsigned included_range_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *, unsigned);
|
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *, unsigned);
|
||||||
TSNode ts_node_new(const TSTree *, const Subtree *, Length, TSSymbol);
|
TSNode ts_node_new(const TSTree *, const Subtree *, Length, TSSymbol);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#endif // TREE_SITTER_TREE_H_
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_TREE_H_
|
|
||||||
|
|
|
||||||
|
|
@ -1,714 +0,0 @@
|
||||||
#include "api.h"
|
|
||||||
#include "./alloc.h"
|
|
||||||
#include "./tree_cursor.h"
|
|
||||||
#include "./language.h"
|
|
||||||
#include "./tree.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Subtree parent;
|
|
||||||
const TSTree *tree;
|
|
||||||
Length position;
|
|
||||||
uint32_t child_index;
|
|
||||||
uint32_t structural_child_index;
|
|
||||||
uint32_t descendant_index;
|
|
||||||
const TSSymbol *alias_sequence;
|
|
||||||
} CursorChildIterator;
|
|
||||||
|
|
||||||
// CursorChildIterator
|
|
||||||
|
|
||||||
static inline bool ts_tree_cursor_is_entry_visible(const TreeCursor *self, uint32_t index) {
|
|
||||||
TreeCursorEntry *entry = &self->stack.contents[index];
|
|
||||||
if (index == 0 || ts_subtree_visible(*entry->subtree)) {
|
|
||||||
return true;
|
|
||||||
} else if (!ts_subtree_extra(*entry->subtree)) {
|
|
||||||
TreeCursorEntry *parent_entry = &self->stack.contents[index - 1];
|
|
||||||
return ts_language_alias_at(
|
|
||||||
self->tree->language,
|
|
||||||
parent_entry->subtree->ptr->production_id,
|
|
||||||
entry->structural_child_index
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline CursorChildIterator ts_tree_cursor_iterate_children(const TreeCursor *self) {
|
|
||||||
TreeCursorEntry *last_entry = array_back(&self->stack);
|
|
||||||
if (ts_subtree_child_count(*last_entry->subtree) == 0) {
|
|
||||||
return (CursorChildIterator) {NULL_SUBTREE, self->tree, length_zero(), 0, 0, 0, NULL};
|
|
||||||
}
|
|
||||||
const TSSymbol *alias_sequence = ts_language_alias_sequence(
|
|
||||||
self->tree->language,
|
|
||||||
last_entry->subtree->ptr->production_id
|
|
||||||
);
|
|
||||||
|
|
||||||
uint32_t descendant_index = last_entry->descendant_index;
|
|
||||||
if (ts_tree_cursor_is_entry_visible(self, self->stack.size - 1)) {
|
|
||||||
descendant_index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (CursorChildIterator) {
|
|
||||||
.tree = self->tree,
|
|
||||||
.parent = *last_entry->subtree,
|
|
||||||
.position = last_entry->position,
|
|
||||||
.child_index = 0,
|
|
||||||
.structural_child_index = 0,
|
|
||||||
.descendant_index = descendant_index,
|
|
||||||
.alias_sequence = alias_sequence,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool ts_tree_cursor_child_iterator_next(
|
|
||||||
CursorChildIterator *self,
|
|
||||||
TreeCursorEntry *result,
|
|
||||||
bool *visible
|
|
||||||
) {
|
|
||||||
if (!self->parent.ptr || self->child_index == self->parent.ptr->child_count) return false;
|
|
||||||
const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
|
|
||||||
*result = (TreeCursorEntry) {
|
|
||||||
.subtree = child,
|
|
||||||
.position = self->position,
|
|
||||||
.child_index = self->child_index,
|
|
||||||
.structural_child_index = self->structural_child_index,
|
|
||||||
.descendant_index = self->descendant_index,
|
|
||||||
};
|
|
||||||
*visible = ts_subtree_visible(*child);
|
|
||||||
bool extra = ts_subtree_extra(*child);
|
|
||||||
if (!extra) {
|
|
||||||
if (self->alias_sequence) {
|
|
||||||
*visible |= self->alias_sequence[self->structural_child_index];
|
|
||||||
}
|
|
||||||
self->structural_child_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->descendant_index += ts_subtree_visible_descendant_count(*child);
|
|
||||||
if (*visible) {
|
|
||||||
self->descendant_index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->position = length_add(self->position, ts_subtree_size(*child));
|
|
||||||
self->child_index++;
|
|
||||||
|
|
||||||
if (self->child_index < self->parent.ptr->child_count) {
|
|
||||||
Subtree next_child = ts_subtree_children(self->parent)[self->child_index];
|
|
||||||
self->position = length_add(self->position, ts_subtree_padding(next_child));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a position that, when `b` is added to it, yields `a`. This
|
|
||||||
// can only be computed if `b` has zero rows. Otherwise, this function
|
|
||||||
// returns `LENGTH_UNDEFINED`, and the caller needs to recompute
|
|
||||||
// the position some other way.
|
|
||||||
static inline Length length_backtrack(Length a, Length b) {
|
|
||||||
if (length_is_undefined(a) || b.extent.row != 0) {
|
|
||||||
return LENGTH_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Length result;
|
|
||||||
result.bytes = a.bytes - b.bytes;
|
|
||||||
result.extent.row = a.extent.row;
|
|
||||||
result.extent.column = a.extent.column - b.extent.column;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool ts_tree_cursor_child_iterator_previous(
|
|
||||||
CursorChildIterator *self,
|
|
||||||
TreeCursorEntry *result,
|
|
||||||
bool *visible
|
|
||||||
) {
|
|
||||||
// this is mostly a reverse `ts_tree_cursor_child_iterator_next` taking into
|
|
||||||
// account unsigned underflow
|
|
||||||
if (!self->parent.ptr || (int8_t)self->child_index == -1) return false;
|
|
||||||
const Subtree *child = &ts_subtree_children(self->parent)[self->child_index];
|
|
||||||
*result = (TreeCursorEntry) {
|
|
||||||
.subtree = child,
|
|
||||||
.position = self->position,
|
|
||||||
.child_index = self->child_index,
|
|
||||||
.structural_child_index = self->structural_child_index,
|
|
||||||
};
|
|
||||||
*visible = ts_subtree_visible(*child);
|
|
||||||
bool extra = ts_subtree_extra(*child);
|
|
||||||
if (!extra && self->alias_sequence) {
|
|
||||||
*visible |= self->alias_sequence[self->structural_child_index];
|
|
||||||
self->structural_child_index--;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->position = length_backtrack(self->position, ts_subtree_padding(*child));
|
|
||||||
self->child_index--;
|
|
||||||
|
|
||||||
// unsigned can underflow so compare it to child_count
|
|
||||||
if (self->child_index < self->parent.ptr->child_count) {
|
|
||||||
Subtree previous_child = ts_subtree_children(self->parent)[self->child_index];
|
|
||||||
Length size = ts_subtree_size(previous_child);
|
|
||||||
self->position = length_backtrack(self->position, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TSTreeCursor - lifecycle
|
|
||||||
|
|
||||||
TSTreeCursor ts_tree_cursor_new(TSNode node) {
|
|
||||||
TSTreeCursor self = {NULL, NULL, {0, 0, 0}};
|
|
||||||
ts_tree_cursor_init((TreeCursor *)&self, node);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ts_tree_cursor_reset(TSTreeCursor *_self, TSNode node) {
|
|
||||||
ts_tree_cursor_init((TreeCursor *)_self, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ts_tree_cursor_init(TreeCursor *self, TSNode node) {
|
|
||||||
self->tree = node.tree;
|
|
||||||
self->root_alias_symbol = node.context[3];
|
|
||||||
array_clear(&self->stack);
|
|
||||||
array_push(&self->stack, ((TreeCursorEntry) {
|
|
||||||
.subtree = (const Subtree *)node.id,
|
|
||||||
.position = {
|
|
||||||
ts_node_start_byte(node),
|
|
||||||
ts_node_start_point(node)
|
|
||||||
},
|
|
||||||
.child_index = 0,
|
|
||||||
.structural_child_index = 0,
|
|
||||||
.descendant_index = 0,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ts_tree_cursor_delete(TSTreeCursor *_self) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
array_delete(&self->stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TSTreeCursor - walking the tree
|
|
||||||
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_first_child_internal(TSTreeCursor *_self) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
bool visible;
|
|
||||||
TreeCursorEntry entry;
|
|
||||||
CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
|
|
||||||
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
|
|
||||||
if (visible) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
return TreeCursorStepVisible;
|
|
||||||
}
|
|
||||||
if (ts_subtree_visible_child_count(*entry.subtree) > 0) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
return TreeCursorStepHidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TreeCursorStepNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
|
|
||||||
for (;;) {
|
|
||||||
switch (ts_tree_cursor_goto_first_child_internal(self)) {
|
|
||||||
case TreeCursorStepHidden:
|
|
||||||
continue;
|
|
||||||
case TreeCursorStepVisible:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_last_child_internal(TSTreeCursor *_self) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
bool visible;
|
|
||||||
TreeCursorEntry entry;
|
|
||||||
CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
|
|
||||||
if (!iterator.parent.ptr || iterator.parent.ptr->child_count == 0) return TreeCursorStepNone;
|
|
||||||
|
|
||||||
TreeCursorEntry last_entry = {0};
|
|
||||||
TreeCursorStep last_step = TreeCursorStepNone;
|
|
||||||
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
|
|
||||||
if (visible) {
|
|
||||||
last_entry = entry;
|
|
||||||
last_step = TreeCursorStepVisible;
|
|
||||||
}
|
|
||||||
else if (ts_subtree_visible_child_count(*entry.subtree) > 0) {
|
|
||||||
last_entry = entry;
|
|
||||||
last_step = TreeCursorStepHidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (last_entry.subtree) {
|
|
||||||
array_push(&self->stack, last_entry);
|
|
||||||
return last_step;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TreeCursorStepNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ts_tree_cursor_goto_last_child(TSTreeCursor *self) {
|
|
||||||
for (;;) {
|
|
||||||
switch (ts_tree_cursor_goto_last_child_internal(self)) {
|
|
||||||
case TreeCursorStepHidden:
|
|
||||||
continue;
|
|
||||||
case TreeCursorStepVisible:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int64_t ts_tree_cursor_goto_first_child_for_byte_and_point(
|
|
||||||
TSTreeCursor *_self,
|
|
||||||
uint32_t goal_byte,
|
|
||||||
TSPoint goal_point
|
|
||||||
) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
uint32_t initial_size = self->stack.size;
|
|
||||||
uint32_t visible_child_index = 0;
|
|
||||||
|
|
||||||
bool did_descend;
|
|
||||||
do {
|
|
||||||
did_descend = false;
|
|
||||||
|
|
||||||
bool visible;
|
|
||||||
TreeCursorEntry entry;
|
|
||||||
CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
|
|
||||||
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
|
|
||||||
Length entry_end = length_add(entry.position, ts_subtree_size(*entry.subtree));
|
|
||||||
bool at_goal = entry_end.bytes >= goal_byte && point_gte(entry_end.extent, goal_point);
|
|
||||||
uint32_t visible_child_count = ts_subtree_visible_child_count(*entry.subtree);
|
|
||||||
if (at_goal) {
|
|
||||||
if (visible) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
return visible_child_index;
|
|
||||||
}
|
|
||||||
if (visible_child_count > 0) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
did_descend = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (visible) {
|
|
||||||
visible_child_index++;
|
|
||||||
} else {
|
|
||||||
visible_child_index += visible_child_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (did_descend);
|
|
||||||
|
|
||||||
self->stack.size = initial_size;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t ts_tree_cursor_goto_first_child_for_byte(TSTreeCursor *self, uint32_t goal_byte) {
|
|
||||||
return ts_tree_cursor_goto_first_child_for_byte_and_point(self, goal_byte, POINT_ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t ts_tree_cursor_goto_first_child_for_point(TSTreeCursor *self, TSPoint goal_point) {
|
|
||||||
return ts_tree_cursor_goto_first_child_for_byte_and_point(self, 0, goal_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_sibling_internal(
|
|
||||||
TSTreeCursor *_self,
|
|
||||||
bool (*advance)(CursorChildIterator *, TreeCursorEntry *, bool *)) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
uint32_t initial_size = self->stack.size;
|
|
||||||
|
|
||||||
while (self->stack.size > 1) {
|
|
||||||
TreeCursorEntry entry = array_pop(&self->stack);
|
|
||||||
CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
|
|
||||||
iterator.child_index = entry.child_index;
|
|
||||||
iterator.structural_child_index = entry.structural_child_index;
|
|
||||||
iterator.position = entry.position;
|
|
||||||
iterator.descendant_index = entry.descendant_index;
|
|
||||||
|
|
||||||
bool visible = false;
|
|
||||||
advance(&iterator, &entry, &visible);
|
|
||||||
if (visible && self->stack.size + 1 < initial_size) break;
|
|
||||||
|
|
||||||
while (advance(&iterator, &entry, &visible)) {
|
|
||||||
if (visible) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
return TreeCursorStepVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ts_subtree_visible_child_count(*entry.subtree)) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
return TreeCursorStepHidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self->stack.size = initial_size;
|
|
||||||
return TreeCursorStepNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *_self) {
|
|
||||||
return ts_tree_cursor_goto_sibling_internal(_self, ts_tree_cursor_child_iterator_next);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
|
|
||||||
switch (ts_tree_cursor_goto_next_sibling_internal(self)) {
|
|
||||||
case TreeCursorStepHidden:
|
|
||||||
ts_tree_cursor_goto_first_child(self);
|
|
||||||
return true;
|
|
||||||
case TreeCursorStepVisible:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_previous_sibling_internal(TSTreeCursor *_self) {
|
|
||||||
// since subtracting across row loses column information, we may have to
|
|
||||||
// restore it
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
|
|
||||||
// for that, save current position before traversing
|
|
||||||
TreeCursorStep step = ts_tree_cursor_goto_sibling_internal(
|
|
||||||
_self, ts_tree_cursor_child_iterator_previous);
|
|
||||||
if (step == TreeCursorStepNone)
|
|
||||||
return step;
|
|
||||||
|
|
||||||
// if length is already valid, there's no need to recompute it
|
|
||||||
if (!length_is_undefined(array_back(&self->stack)->position))
|
|
||||||
return step;
|
|
||||||
|
|
||||||
// restore position from the parent node
|
|
||||||
const TreeCursorEntry *parent = &self->stack.contents[self->stack.size - 2];
|
|
||||||
Length position = parent->position;
|
|
||||||
uint32_t child_index = array_back(&self->stack)->child_index;
|
|
||||||
const Subtree *children = ts_subtree_children((*(parent->subtree)));
|
|
||||||
|
|
||||||
if (child_index > 0) {
|
|
||||||
// skip first child padding since its position should match the position of the parent
|
|
||||||
position = length_add(position, ts_subtree_size(children[0]));
|
|
||||||
for (uint32_t i = 1; i < child_index; ++i) {
|
|
||||||
position = length_add(position, ts_subtree_total_size(children[i]));
|
|
||||||
}
|
|
||||||
position = length_add(position, ts_subtree_padding(children[child_index]));
|
|
||||||
}
|
|
||||||
|
|
||||||
array_back(&self->stack)->position = position;
|
|
||||||
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ts_tree_cursor_goto_previous_sibling(TSTreeCursor *self) {
|
|
||||||
switch (ts_tree_cursor_goto_previous_sibling_internal(self)) {
|
|
||||||
case TreeCursorStepHidden:
|
|
||||||
ts_tree_cursor_goto_last_child(self);
|
|
||||||
return true;
|
|
||||||
case TreeCursorStepVisible:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ts_tree_cursor_goto_parent(TSTreeCursor *_self) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
|
|
||||||
if (ts_tree_cursor_is_entry_visible(self, i)) {
|
|
||||||
self->stack.size = i + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ts_tree_cursor_goto_descendant(
|
|
||||||
TSTreeCursor *_self,
|
|
||||||
uint32_t goal_descendant_index
|
|
||||||
) {
|
|
||||||
TreeCursor *self = (TreeCursor *)_self;
|
|
||||||
|
|
||||||
// Ascend to the lowest ancestor that contains the goal node.
|
|
||||||
for (;;) {
|
|
||||||
uint32_t i = self->stack.size - 1;
|
|
||||||
TreeCursorEntry *entry = &self->stack.contents[i];
|
|
||||||
uint32_t next_descendant_index =
|
|
||||||
entry->descendant_index +
|
|
||||||
(ts_tree_cursor_is_entry_visible(self, i) ? 1 : 0) +
|
|
||||||
ts_subtree_visible_descendant_count(*entry->subtree);
|
|
||||||
if (
|
|
||||||
(entry->descendant_index <= goal_descendant_index) &&
|
|
||||||
(next_descendant_index > goal_descendant_index)
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
} else if (self->stack.size <= 1) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
self->stack.size--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Descend to the goal node.
|
|
||||||
bool did_descend = true;
|
|
||||||
do {
|
|
||||||
did_descend = false;
|
|
||||||
bool visible;
|
|
||||||
TreeCursorEntry entry;
|
|
||||||
CursorChildIterator iterator = ts_tree_cursor_iterate_children(self);
|
|
||||||
if (iterator.descendant_index > goal_descendant_index) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ts_tree_cursor_child_iterator_next(&iterator, &entry, &visible)) {
|
|
||||||
if (iterator.descendant_index > goal_descendant_index) {
|
|
||||||
array_push(&self->stack, entry);
|
|
||||||
if (visible && entry.descendant_index == goal_descendant_index) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
did_descend = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (did_descend);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ts_tree_cursor_current_descendant_index(const TSTreeCursor *_self) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
TreeCursorEntry *last_entry = array_back(&self->stack);
|
|
||||||
return last_entry->descendant_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSNode ts_tree_cursor_current_node(const TSTreeCursor *_self) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
TreeCursorEntry *last_entry = array_back(&self->stack);
|
|
||||||
TSSymbol alias_symbol = self->root_alias_symbol;
|
|
||||||
if (self->stack.size > 1 && !ts_subtree_extra(*last_entry->subtree)) {
|
|
||||||
TreeCursorEntry *parent_entry = &self->stack.contents[self->stack.size - 2];
|
|
||||||
alias_symbol = ts_language_alias_at(
|
|
||||||
self->tree->language,
|
|
||||||
parent_entry->subtree->ptr->production_id,
|
|
||||||
last_entry->structural_child_index
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ts_node_new(
|
|
||||||
self->tree,
|
|
||||||
last_entry->subtree,
|
|
||||||
last_entry->position,
|
|
||||||
alias_symbol
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private - Get various facts about the current node that are needed
|
|
||||||
// when executing tree queries.
|
|
||||||
void ts_tree_cursor_current_status(
|
|
||||||
const TSTreeCursor *_self,
|
|
||||||
TSFieldId *field_id,
|
|
||||||
bool *has_later_siblings,
|
|
||||||
bool *has_later_named_siblings,
|
|
||||||
bool *can_have_later_siblings_with_this_field,
|
|
||||||
TSSymbol *supertypes,
|
|
||||||
unsigned *supertype_count
|
|
||||||
) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
unsigned max_supertypes = *supertype_count;
|
|
||||||
*field_id = 0;
|
|
||||||
*supertype_count = 0;
|
|
||||||
*has_later_siblings = false;
|
|
||||||
*has_later_named_siblings = false;
|
|
||||||
*can_have_later_siblings_with_this_field = false;
|
|
||||||
|
|
||||||
// Walk up the tree, visiting the current node and its invisible ancestors,
|
|
||||||
// because fields can refer to nodes through invisible *wrapper* nodes,
|
|
||||||
for (unsigned i = self->stack.size - 1; i > 0; i--) {
|
|
||||||
TreeCursorEntry *entry = &self->stack.contents[i];
|
|
||||||
TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
|
|
||||||
|
|
||||||
const TSSymbol *alias_sequence = ts_language_alias_sequence(
|
|
||||||
self->tree->language,
|
|
||||||
parent_entry->subtree->ptr->production_id
|
|
||||||
);
|
|
||||||
|
|
||||||
#define subtree_symbol(subtree, structural_child_index) \
|
|
||||||
(( \
|
|
||||||
!ts_subtree_extra(subtree) && \
|
|
||||||
alias_sequence && \
|
|
||||||
alias_sequence[structural_child_index] \
|
|
||||||
) ? \
|
|
||||||
alias_sequence[structural_child_index] : \
|
|
||||||
ts_subtree_symbol(subtree))
|
|
||||||
|
|
||||||
// Stop walking up when a visible ancestor is found.
|
|
||||||
TSSymbol entry_symbol = subtree_symbol(
|
|
||||||
*entry->subtree,
|
|
||||||
entry->structural_child_index
|
|
||||||
);
|
|
||||||
TSSymbolMetadata entry_metadata = ts_language_symbol_metadata(
|
|
||||||
self->tree->language,
|
|
||||||
entry_symbol
|
|
||||||
);
|
|
||||||
if (i != self->stack.size - 1 && entry_metadata.visible) break;
|
|
||||||
|
|
||||||
// Record any supertypes
|
|
||||||
if (entry_metadata.supertype && *supertype_count < max_supertypes) {
|
|
||||||
supertypes[*supertype_count] = entry_symbol;
|
|
||||||
(*supertype_count)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine if the current node has later siblings.
|
|
||||||
if (!*has_later_siblings) {
|
|
||||||
unsigned sibling_count = parent_entry->subtree->ptr->child_count;
|
|
||||||
unsigned structural_child_index = entry->structural_child_index;
|
|
||||||
if (!ts_subtree_extra(*entry->subtree)) structural_child_index++;
|
|
||||||
for (unsigned j = entry->child_index + 1; j < sibling_count; j++) {
|
|
||||||
Subtree sibling = ts_subtree_children(*parent_entry->subtree)[j];
|
|
||||||
TSSymbolMetadata sibling_metadata = ts_language_symbol_metadata(
|
|
||||||
self->tree->language,
|
|
||||||
subtree_symbol(sibling, structural_child_index)
|
|
||||||
);
|
|
||||||
if (sibling_metadata.visible) {
|
|
||||||
*has_later_siblings = true;
|
|
||||||
if (*has_later_named_siblings) break;
|
|
||||||
if (sibling_metadata.named) {
|
|
||||||
*has_later_named_siblings = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (ts_subtree_visible_child_count(sibling) > 0) {
|
|
||||||
*has_later_siblings = true;
|
|
||||||
if (*has_later_named_siblings) break;
|
|
||||||
if (sibling.ptr->named_child_count > 0) {
|
|
||||||
*has_later_named_siblings = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ts_subtree_extra(sibling)) structural_child_index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef subtree_symbol
|
|
||||||
|
|
||||||
if (!ts_subtree_extra(*entry->subtree)) {
|
|
||||||
const TSFieldMapEntry *field_map, *field_map_end;
|
|
||||||
ts_language_field_map(
|
|
||||||
self->tree->language,
|
|
||||||
parent_entry->subtree->ptr->production_id,
|
|
||||||
&field_map, &field_map_end
|
|
||||||
);
|
|
||||||
|
|
||||||
// Look for a field name associated with the current node.
|
|
||||||
if (!*field_id) {
|
|
||||||
for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) {
|
|
||||||
if (!map->inherited && map->child_index == entry->structural_child_index) {
|
|
||||||
*field_id = map->field_id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine if the current node can have later siblings with the same field name.
|
|
||||||
if (*field_id) {
|
|
||||||
for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) {
|
|
||||||
if (
|
|
||||||
map->field_id == *field_id &&
|
|
||||||
map->child_index > entry->structural_child_index
|
|
||||||
) {
|
|
||||||
*can_have_later_siblings_with_this_field = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t ts_tree_cursor_current_depth(const TSTreeCursor *_self) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
uint32_t depth = 0;
|
|
||||||
for (unsigned i = 1; i < self->stack.size; i++) {
|
|
||||||
if (ts_tree_cursor_is_entry_visible(self, i)) {
|
|
||||||
depth++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSNode ts_tree_cursor_parent_node(const TSTreeCursor *_self) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
for (int i = (int)self->stack.size - 2; i >= 0; i--) {
|
|
||||||
TreeCursorEntry *entry = &self->stack.contents[i];
|
|
||||||
bool is_visible = true;
|
|
||||||
TSSymbol alias_symbol = 0;
|
|
||||||
if (i > 0) {
|
|
||||||
TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
|
|
||||||
alias_symbol = ts_language_alias_at(
|
|
||||||
self->tree->language,
|
|
||||||
parent_entry->subtree->ptr->production_id,
|
|
||||||
entry->structural_child_index
|
|
||||||
);
|
|
||||||
is_visible = (alias_symbol != 0) || ts_subtree_visible(*entry->subtree);
|
|
||||||
}
|
|
||||||
if (is_visible) {
|
|
||||||
return ts_node_new(
|
|
||||||
self->tree,
|
|
||||||
entry->subtree,
|
|
||||||
entry->position,
|
|
||||||
alias_symbol
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ts_node_new(NULL, NULL, length_zero(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TSFieldId ts_tree_cursor_current_field_id(const TSTreeCursor *_self) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
|
|
||||||
// Walk up the tree, visiting the current node and its invisible ancestors.
|
|
||||||
for (unsigned i = self->stack.size - 1; i > 0; i--) {
|
|
||||||
TreeCursorEntry *entry = &self->stack.contents[i];
|
|
||||||
TreeCursorEntry *parent_entry = &self->stack.contents[i - 1];
|
|
||||||
|
|
||||||
// Stop walking up when another visible node is found.
|
|
||||||
if (
|
|
||||||
i != self->stack.size - 1 &&
|
|
||||||
ts_tree_cursor_is_entry_visible(self, i)
|
|
||||||
) break;
|
|
||||||
|
|
||||||
if (ts_subtree_extra(*entry->subtree)) break;
|
|
||||||
|
|
||||||
const TSFieldMapEntry *field_map, *field_map_end;
|
|
||||||
ts_language_field_map(
|
|
||||||
self->tree->language,
|
|
||||||
parent_entry->subtree->ptr->production_id,
|
|
||||||
&field_map, &field_map_end
|
|
||||||
);
|
|
||||||
for (const TSFieldMapEntry *map = field_map; map < field_map_end; map++) {
|
|
||||||
if (!map->inherited && map->child_index == entry->structural_child_index) {
|
|
||||||
return map->field_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ts_tree_cursor_current_field_name(const TSTreeCursor *_self) {
|
|
||||||
TSFieldId id = ts_tree_cursor_current_field_id(_self);
|
|
||||||
if (id) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
return self->tree->language->field_names[id];
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TSTreeCursor ts_tree_cursor_copy(const TSTreeCursor *_cursor) {
|
|
||||||
const TreeCursor *cursor = (const TreeCursor *)_cursor;
|
|
||||||
TSTreeCursor res = {NULL, NULL, {0, 0}};
|
|
||||||
TreeCursor *copy = (TreeCursor *)&res;
|
|
||||||
copy->tree = cursor->tree;
|
|
||||||
copy->root_alias_symbol = cursor->root_alias_symbol;
|
|
||||||
array_init(©->stack);
|
|
||||||
array_push_all(©->stack, &cursor->stack);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ts_tree_cursor_reset_to(TSTreeCursor *_dst, const TSTreeCursor *_src) {
|
|
||||||
const TreeCursor *cursor = (const TreeCursor *)_src;
|
|
||||||
TreeCursor *copy = (TreeCursor *)_dst;
|
|
||||||
copy->tree = cursor->tree;
|
|
||||||
copy->root_alias_symbol = cursor->root_alias_symbol;
|
|
||||||
array_clear(©->stack);
|
|
||||||
array_push_all(©->stack, &cursor->stack);
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
#ifndef TREE_SITTER_TREE_CURSOR_H_
|
|
||||||
#define TREE_SITTER_TREE_CURSOR_H_
|
|
||||||
|
|
||||||
#include "./subtree.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const Subtree *subtree;
|
|
||||||
Length position;
|
|
||||||
uint32_t child_index;
|
|
||||||
uint32_t structural_child_index;
|
|
||||||
uint32_t descendant_index;
|
|
||||||
} TreeCursorEntry;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const TSTree *tree;
|
|
||||||
Array(TreeCursorEntry) stack;
|
|
||||||
TSSymbol root_alias_symbol;
|
|
||||||
} TreeCursor;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TreeCursorStepNone,
|
|
||||||
TreeCursorStepHidden,
|
|
||||||
TreeCursorStepVisible,
|
|
||||||
} TreeCursorStep;
|
|
||||||
|
|
||||||
void ts_tree_cursor_init(TreeCursor *, TSNode);
|
|
||||||
void ts_tree_cursor_current_status(
|
|
||||||
const TSTreeCursor *,
|
|
||||||
TSFieldId *,
|
|
||||||
bool *,
|
|
||||||
bool *,
|
|
||||||
bool *,
|
|
||||||
TSSymbol *,
|
|
||||||
unsigned *
|
|
||||||
);
|
|
||||||
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_first_child_internal(TSTreeCursor *);
|
|
||||||
TreeCursorStep ts_tree_cursor_goto_next_sibling_internal(TSTreeCursor *);
|
|
||||||
|
|
||||||
static inline Subtree ts_tree_cursor_current_subtree(const TSTreeCursor *_self) {
|
|
||||||
const TreeCursor *self = (const TreeCursor *)_self;
|
|
||||||
TreeCursorEntry *last_entry = array_back(&self->stack);
|
|
||||||
return *last_entry->subtree;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSNode ts_tree_cursor_parent_node(const TSTreeCursor *);
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_TREE_CURSOR_H_
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef TREE_SITTER_WASM_H_
|
|
||||||
#define TREE_SITTER_WASM_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "api.h"
|
|
||||||
#include "./parser.h"
|
|
||||||
|
|
||||||
bool ts_wasm_store_start(TSWasmStore *, TSLexer *, const TSLanguage *);
|
|
||||||
void ts_wasm_store_reset(TSWasmStore *);
|
|
||||||
bool ts_wasm_store_has_error(const TSWasmStore *);
|
|
||||||
|
|
||||||
bool ts_wasm_store_call_lex_main(TSWasmStore *, TSStateId);
|
|
||||||
bool ts_wasm_store_call_lex_keyword(TSWasmStore *, TSStateId);
|
|
||||||
|
|
||||||
uint32_t ts_wasm_store_call_scanner_create(TSWasmStore *);
|
|
||||||
void ts_wasm_store_call_scanner_destroy(TSWasmStore *, uint32_t);
|
|
||||||
bool ts_wasm_store_call_scanner_scan(TSWasmStore *, uint32_t, uint32_t);
|
|
||||||
uint32_t ts_wasm_store_call_scanner_serialize(TSWasmStore *, uint32_t, char *);
|
|
||||||
void ts_wasm_store_call_scanner_deserialize(TSWasmStore *, uint32_t, const char *, unsigned);
|
|
||||||
|
|
||||||
void ts_wasm_language_retain(const TSLanguage *);
|
|
||||||
void ts_wasm_language_release(const TSLanguage *);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // TREE_SITTER_WASM_H_
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue