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 "./wasm_store.h"
|
||||
#include "api.h"
|
||||
#include <string.h>
|
||||
|
||||
const TSLanguage *ts_language_copy(const TSLanguage *self) {
|
||||
if (self && ts_language_is_wasm(self)) {
|
||||
ts_wasm_language_retain(self);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
void ts_language_delete(const TSLanguage *self) {
|
||||
if (self && ts_language_is_wasm(self)) {
|
||||
ts_wasm_language_release(self);
|
||||
}
|
||||
(void)(self);
|
||||
}
|
||||
|
||||
uint32_t ts_language_symbol_count(const TSLanguage *self) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
#ifndef TREE_SITTER_LEXER_H_
|
||||
#define TREE_SITTER_LEXER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "./length.h"
|
||||
#include "./subtree.h"
|
||||
#include "api.h"
|
||||
#include "./parser.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct Lexer{
|
||||
TSLexer data;
|
||||
Length current_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);
|
||||
TSRange *ts_lexer_included_ranges(const Lexer *self, uint32_t *count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_LEXER_H_
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
#include "./alloc.c"
|
||||
// #include "./get_changed_ranges.c"
|
||||
#include "./language.c"
|
||||
#include "./lexer.c"
|
||||
#include "./node.c"
|
||||
|
|
@ -9,8 +8,6 @@
|
|||
#include "./stack.c"
|
||||
#include "./subtree.c"
|
||||
#include "./tree.c"
|
||||
#include "./tree_cursor.c"
|
||||
#include "./wasm_store.c"
|
||||
#include "./lex.c"
|
||||
#include "./create_language.c"
|
||||
#include "./scanner.c"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include "./stack.h"
|
||||
#include "./subtree.h"
|
||||
#include "./tree.h"
|
||||
#include "./wasm_store.h"
|
||||
#include "api.h"
|
||||
#include <assert.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 OP_COUNT_PER_TIMEOUT_CHECK = 100;
|
||||
|
||||
typedef struct
|
||||
typedef struct TokenCache
|
||||
{
|
||||
Subtree token;
|
||||
Subtree last_external_token;
|
||||
|
|
@ -109,7 +108,6 @@ struct TSParser
|
|||
Stack *stack;
|
||||
SubtreePool tree_pool;
|
||||
const TSLanguage *language;
|
||||
TSWasmStore *wasm_store;
|
||||
ReduceActionSet reduce_actions;
|
||||
Subtree finished_tree;
|
||||
SubtreeArray trailing_extras;
|
||||
|
|
@ -129,7 +127,7 @@ struct TSParser
|
|||
bool has_scanner_error;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
typedef struct ErrorStatus
|
||||
{
|
||||
unsigned cost;
|
||||
unsigned node_count;
|
||||
|
|
@ -137,7 +135,7 @@ typedef struct
|
|||
bool is_in_error;
|
||||
} ErrorStatus;
|
||||
|
||||
typedef enum
|
||||
typedef enum ErrorComparison
|
||||
{
|
||||
ErrorComparisonTakeLeft,
|
||||
ErrorComparisonPreferLeft,
|
||||
|
|
@ -146,7 +144,7 @@ typedef enum
|
|||
ErrorComparisonTakeRight,
|
||||
} ErrorComparison;
|
||||
|
||||
typedef struct
|
||||
typedef struct TSStringInput
|
||||
{
|
||||
const char *string;
|
||||
uint32_t length;
|
||||
|
|
@ -373,43 +371,23 @@ static bool ts_parser__better_version_exists(TSParser *self, StackVersion versio
|
|||
}
|
||||
|
||||
static bool ts_parser__call_main_lex_fn(TSParser *self, TSLexMode lex_mode)
|
||||
{
|
||||
if (ts_language_is_wasm(self->language))
|
||||
{
|
||||
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)
|
||||
{
|
||||
(void)(lex_mode);
|
||||
if (ts_language_is_wasm(self->language))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (self->language && self->language->external_scanner.states)
|
||||
{
|
||||
if (ts_language_is_wasm(self->language))
|
||||
{
|
||||
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)
|
||||
|
||||
if (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)
|
||||
{
|
||||
if (self->language && self->external_scanner_payload && self->language->external_scanner.destroy &&
|
||||
!ts_language_is_wasm(self->language))
|
||||
if (self->language && self->external_scanner_payload && self->language->external_scanner.destroy)
|
||||
{
|
||||
self->language->external_scanner.destroy(self->external_scanner_payload);
|
||||
}
|
||||
|
|
@ -428,17 +405,11 @@ static void ts_parser__external_scanner_destroy(TSParser *self)
|
|||
|
||||
static unsigned ts_parser__external_scanner_serialize(TSParser *self)
|
||||
{
|
||||
if (ts_language_is_wasm(self->language))
|
||||
{
|
||||
return ts_wasm_store_call_scanner_serialize(self->wasm_store, (uintptr_t)self->external_scanner_payload, self->lexer.debug_buffer);
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
|
@ -450,38 +421,14 @@ static void ts_parser__external_scanner_deserialize(TSParser *self, Subtree exte
|
|||
length = external_token.ptr->external_scanner_state.length;
|
||||
}
|
||||
|
||||
if (ts_language_is_wasm(self->language))
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (ts_language_is_wasm(self->language))
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
@ -1876,7 +1823,6 @@ void ts_parser_delete(TSParser *self)
|
|||
ts_subtree_release(&self->tree_pool, self->old_tree);
|
||||
self->old_tree = NULL_SUBTREE;
|
||||
}
|
||||
ts_wasm_store_delete(self->wasm_store);
|
||||
ts_lexer_delete(&self->lexer);
|
||||
ts_parser__set_cached_token(self, 0, NULL_SUBTREE, NULL_SUBTREE);
|
||||
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)
|
||||
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);
|
||||
|
|
@ -1978,11 +1918,6 @@ const TSRange *ts_parser_included_ranges(const TSParser *self, uint32_t *count)
|
|||
void ts_parser_reset(TSParser *self)
|
||||
{
|
||||
ts_parser__external_scanner_destroy(self);
|
||||
if (self->wasm_store)
|
||||
{
|
||||
ts_wasm_store_reset(self->wasm_store);
|
||||
}
|
||||
|
||||
if (self->old_tree.ptr)
|
||||
{
|
||||
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)
|
||||
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);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
#ifndef TREE_SITTER_REDUCE_ACTION_H_
|
||||
#define TREE_SITTER_REDUCE_ACTION_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "./array.h"
|
||||
#include "api.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct ReduceAction {
|
||||
uint32_t count;
|
||||
TSSymbol symbol;
|
||||
int dynamic_precedence;
|
||||
|
|
@ -27,8 +24,5 @@ static inline void ts_reduce_action_set_add(ReduceActionSet *self,
|
|||
array_push(self, new_action);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_REDUCE_ACTION_H_
|
||||
|
|
|
|||
|
|
@ -1,54 +1,61 @@
|
|||
#include "./subtree.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct StackEntry
|
||||
{
|
||||
Subtree tree;
|
||||
uint32_t child_index;
|
||||
uint32_t byte_offset;
|
||||
} StackEntry;
|
||||
|
||||
typedef struct {
|
||||
typedef struct ReusableNode
|
||||
{
|
||||
Array(StackEntry) stack;
|
||||
Subtree last_external_token;
|
||||
} ReusableNode;
|
||||
|
||||
static inline ReusableNode reusable_node_new(void) {
|
||||
static inline ReusableNode reusable_node_new(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static inline Subtree reusable_node_tree(ReusableNode *self) {
|
||||
return self->stack.size > 0
|
||||
? self->stack.contents[self->stack.size - 1].tree
|
||||
: NULL_SUBTREE;
|
||||
static inline Subtree reusable_node_tree(ReusableNode *self)
|
||||
{
|
||||
return self->stack.size > 0 ? self->stack.contents[self->stack.size - 1].tree : NULL_SUBTREE;
|
||||
}
|
||||
|
||||
static inline uint32_t reusable_node_byte_offset(ReusableNode *self) {
|
||||
return self->stack.size > 0
|
||||
? self->stack.contents[self->stack.size - 1].byte_offset
|
||||
: UINT32_MAX;
|
||||
static inline uint32_t reusable_node_byte_offset(ReusableNode *self)
|
||||
{
|
||||
return self->stack.size > 0 ? self->stack.contents[self->stack.size - 1].byte_offset : UINT32_MAX;
|
||||
}
|
||||
|
||||
static inline void reusable_node_delete(ReusableNode *self) {
|
||||
static inline void reusable_node_delete(ReusableNode *self)
|
||||
{
|
||||
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);
|
||||
if (ts_subtree_has_external_tokens(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;
|
||||
uint32_t next_index;
|
||||
do {
|
||||
do
|
||||
{
|
||||
StackEntry popped_entry = array_pop(&self->stack);
|
||||
next_index = popped_entry.child_index + 1;
|
||||
if (self->stack.size == 0) return;
|
||||
if (self->stack.size == 0)
|
||||
return;
|
||||
tree = array_back(&self->stack)->tree;
|
||||
} while (ts_subtree_child_count(tree) <= next_index);
|
||||
|
||||
|
|
@ -59,26 +66,34 @@ static inline void reusable_node_advance(ReusableNode *self) {
|
|||
}));
|
||||
}
|
||||
|
||||
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) {
|
||||
if (ts_subtree_child_count(last_entry.tree) > 0)
|
||||
{
|
||||
array_push(&self->stack, ((StackEntry){
|
||||
.tree = ts_subtree_children(last_entry.tree)[0],
|
||||
.child_index = 0,
|
||||
.byte_offset = last_entry.byte_offset,
|
||||
}));
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void reusable_node_advance_past_leaf(ReusableNode *self) {
|
||||
while (reusable_node_descend(self)) {}
|
||||
static inline void reusable_node_advance_past_leaf(ReusableNode *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){
|
||||
.tree = tree,
|
||||
|
|
@ -89,7 +104,8 @@ static inline void reusable_node_reset(ReusableNode *self, Subtree tree) {
|
|||
// 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
|
||||
// child and any extra children.
|
||||
if (!reusable_node_descend(self)) {
|
||||
if (!reusable_node_descend(self))
|
||||
{
|
||||
reusable_node_clear(self);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
#ifndef TREE_SITTER_PARSE_STACK_H_
|
||||
#define TREE_SITTER_PARSE_STACK_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "./array.h"
|
||||
#include "./subtree.h"
|
||||
#include "./error_costs.h"
|
||||
#include "./subtree.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct Stack Stack;
|
||||
|
|
@ -15,19 +11,24 @@ typedef struct Stack Stack;
|
|||
typedef unsigned StackVersion;
|
||||
#define STACK_VERSION_NONE ((StackVersion)-1)
|
||||
|
||||
typedef struct {
|
||||
typedef struct StackSlice
|
||||
{
|
||||
SubtreeArray subtrees;
|
||||
StackVersion version;
|
||||
} StackSlice;
|
||||
typedef Array(StackSlice) StackSliceArray;
|
||||
|
||||
typedef struct {
|
||||
typedef struct StackSummaryEntry
|
||||
{
|
||||
Length position;
|
||||
unsigned depth;
|
||||
TSStateId state;
|
||||
} StackSummaryEntry;
|
||||
|
||||
typedef Array(StackSummaryEntry) StackSummary;
|
||||
|
||||
typedef void (*StackIterateCallback)(void *, TSStateId, uint32_t);
|
||||
|
||||
// Create a stack.
|
||||
Stack *ts_stack_new(SubtreePool *);
|
||||
|
||||
|
|
@ -124,10 +125,4 @@ void ts_stack_clear(Stack *);
|
|||
|
||||
bool ts_stack_print_dot_graph(Stack *, const TSLanguage *, FILE *);
|
||||
|
||||
typedef void (*StackIterateCallback)(void *, TSStateId, uint32_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TREE_SITTER_PARSE_STACK_H_
|
||||
|
|
|
|||
|
|
@ -1,19 +1,15 @@
|
|||
#ifndef 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 "./error_costs.h"
|
||||
#include "./host.h"
|
||||
#include "api.h"
|
||||
#include "./length.h"
|
||||
#include "./parser.h"
|
||||
#include "api.h"
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define TS_TREE_STATE_NONE USHRT_MAX
|
||||
#define NULL_SUBTREE ((Subtree){.ptr = NULL})
|
||||
|
|
@ -28,7 +24,8 @@ extern "C" {
|
|||
//
|
||||
// Small byte arrays are stored inline, and long ones are allocated
|
||||
// separately on the heap.
|
||||
typedef struct {
|
||||
typedef struct ExternalScannerState
|
||||
{
|
||||
union {
|
||||
char *long_data;
|
||||
char short_data[24];
|
||||
|
|
@ -67,7 +64,8 @@ typedef struct SubtreeInlineData SubtreeInlineData;
|
|||
#if TS_BIG_ENDIAN
|
||||
# if TS_PTR_SIZE == 32
|
||||
|
||||
struct SubtreeInlineData {
|
||||
struct SubtreeInlineData
|
||||
{
|
||||
uint16_t parse_state;
|
||||
uint8_t symbol;
|
||||
SUBTREE_BITS
|
||||
|
|
@ -78,7 +76,8 @@ struct SubtreeInlineData {
|
|||
|
||||
# else
|
||||
|
||||
struct SubtreeInlineData {
|
||||
struct SubtreeInlineData
|
||||
{
|
||||
SUBTREE_SIZE
|
||||
uint16_t parse_state;
|
||||
uint8_t symbol;
|
||||
|
|
@ -90,7 +89,8 @@ struct SubtreeInlineData {
|
|||
# endif
|
||||
#else
|
||||
|
||||
struct SubtreeInlineData {
|
||||
struct SubtreeInlineData
|
||||
{
|
||||
bool is_inline : 1;
|
||||
SUBTREE_BITS
|
||||
uint8_t symbol;
|
||||
|
|
@ -108,7 +108,8 @@ struct SubtreeInlineData {
|
|||
// This representation is used for parent nodes, external tokens,
|
||||
// errors, and other leaf nodes whose data is too large to fit into
|
||||
// the inline representation.
|
||||
typedef struct {
|
||||
typedef struct SubtreeHeapData
|
||||
{
|
||||
volatile uint32_t ref_count;
|
||||
Length padding;
|
||||
Length size;
|
||||
|
|
@ -132,14 +133,16 @@ typedef struct {
|
|||
|
||||
union {
|
||||
// Non-terminal subtrees (`child_count > 0`)
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
uint32_t visible_child_count;
|
||||
uint32_t named_child_count;
|
||||
uint32_t visible_descendant_count;
|
||||
int32_t dynamic_precedence;
|
||||
uint16_t repeat_depth;
|
||||
uint16_t production_id;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
TSSymbol symbol;
|
||||
TSStateId parse_state;
|
||||
} first_leaf;
|
||||
|
|
@ -154,13 +157,13 @@ typedef struct {
|
|||
} SubtreeHeapData;
|
||||
|
||||
// The fundamental building block of a syntax tree.
|
||||
typedef union {
|
||||
typedef union Subtree {
|
||||
SubtreeInlineData data;
|
||||
const SubtreeHeapData *ptr;
|
||||
} Subtree;
|
||||
|
||||
// Like Subtree, but mutable.
|
||||
typedef union {
|
||||
typedef union MutableSubtree {
|
||||
SubtreeInlineData data;
|
||||
SubtreeHeapData *ptr;
|
||||
} MutableSubtree;
|
||||
|
|
@ -168,7 +171,8 @@ typedef union {
|
|||
typedef Array(Subtree) SubtreeArray;
|
||||
typedef Array(MutableSubtree) MutableSubtreeArray;
|
||||
|
||||
typedef struct {
|
||||
typedef struct SubtreePool
|
||||
{
|
||||
MutableSubtreeArray free_trees;
|
||||
MutableSubtreeArray tree_stack;
|
||||
} SubtreePool;
|
||||
|
|
@ -187,13 +191,8 @@ void ts_subtree_array_reverse(SubtreeArray *);
|
|||
SubtreePool ts_subtree_pool_new(uint32_t capacity);
|
||||
void ts_subtree_pool_delete(SubtreePool *);
|
||||
|
||||
Subtree ts_subtree_new_leaf(
|
||||
SubtreePool *, TSSymbol, Length, Length, uint32_t,
|
||||
TSStateId, bool, bool, bool, const TSLanguage *
|
||||
);
|
||||
Subtree ts_subtree_new_error(
|
||||
SubtreePool *, int32_t, Length, Length, uint32_t, TSStateId, const TSLanguage *
|
||||
);
|
||||
Subtree ts_subtree_new_leaf(SubtreePool *, TSSymbol, Length, Length, uint32_t, 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 *);
|
||||
Subtree ts_subtree_new_error_node(SubtreeArray *, bool, const TSLanguage *);
|
||||
Subtree ts_subtree_new_missing_leaf(SubtreePool *, TSSymbol, Length, uint32_t, const TSLanguage *);
|
||||
|
|
@ -214,162 +213,232 @@ bool ts_subtree_external_scanner_state_eq(Subtree, Subtree);
|
|||
|
||||
#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 bool ts_subtree_visible(Subtree self) { return SUBTREE_GET(self, visible); }
|
||||
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); }
|
||||
static inline TSSymbol ts_subtree_symbol(Subtree self)
|
||||
{
|
||||
return SUBTREE_GET(self, symbol);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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
|
||||
|
||||
// Get the size needed to store a heap-allocated subtree with the given
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Get a subtree's children, which are allocated immediately before the
|
||||
// tree's own heap data.
|
||||
#define ts_subtree_children(self) \
|
||||
((self).data.is_inline ? NULL : (Subtree *)((self).ptr) - (self).ptr->child_count)
|
||||
#define ts_subtree_children(self) ((self).data.is_inline ? NULL : (Subtree *)((self).ptr) - (self).ptr->child_count)
|
||||
|
||||
static inline void ts_subtree_set_extra(MutableSubtree *self, bool is_extra) {
|
||||
if (self->data.is_inline) {
|
||||
static inline void ts_subtree_set_extra(MutableSubtree *self, bool is_extra)
|
||||
{
|
||||
if (self->data.is_inline)
|
||||
{
|
||||
self->data.extra = is_extra;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
self->ptr->extra = is_extra;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
return self.ptr->first_leaf.symbol;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
return self.ptr->first_leaf.parse_state;
|
||||
}
|
||||
|
||||
static inline Length ts_subtree_padding(Subtree self) {
|
||||
if (self.data.is_inline) {
|
||||
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}};
|
||||
return result;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return self.ptr->padding;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Length ts_subtree_size(Subtree self) {
|
||||
if (self.data.is_inline) {
|
||||
static inline Length ts_subtree_size(Subtree self)
|
||||
{
|
||||
if (self.data.is_inline)
|
||||
{
|
||||
Length result = {self.data.size_bytes, {0, self.data.size_bytes}};
|
||||
return result;
|
||||
} else {
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline uint32_t ts_subtree_is_repetition(Subtree self) {
|
||||
return self.data.is_inline
|
||||
? 0
|
||||
: !self.ptr->named && !self.ptr->visible && self.ptr->child_count != 0;
|
||||
static inline uint32_t ts_subtree_is_repetition(Subtree self)
|
||||
{
|
||||
return self.data.is_inline ? 0 : !self.ptr->named && !self.ptr->visible && self.ptr->child_count != 0;
|
||||
}
|
||||
|
||||
static inline uint32_t ts_subtree_visible_descendant_count(Subtree self) {
|
||||
return (self.data.is_inline || self.ptr->child_count == 0)
|
||||
? 0
|
||||
: self.ptr->visible_descendant_count;
|
||||
static inline uint32_t ts_subtree_visible_descendant_count(Subtree self)
|
||||
{
|
||||
return (self.data.is_inline || self.ptr->child_count == 0) ? 0 : self.ptr->visible_descendant_count;
|
||||
}
|
||||
|
||||
static inline uint32_t ts_subtree_visible_child_count(Subtree self) {
|
||||
if (ts_subtree_child_count(self) > 0) {
|
||||
static inline uint32_t ts_subtree_visible_child_count(Subtree self)
|
||||
{
|
||||
if (ts_subtree_child_count(self) > 0)
|
||||
{
|
||||
return self.ptr->visible_child_count;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t ts_subtree_error_cost(Subtree self) {
|
||||
if (ts_subtree_missing(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;
|
||||
} else {
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static inline uint16_t ts_subtree_production_id(Subtree self) {
|
||||
if (ts_subtree_child_count(self) > 0) {
|
||||
static inline uint16_t ts_subtree_production_id(Subtree self)
|
||||
{
|
||||
if (ts_subtree_child_count(self) > 0)
|
||||
{
|
||||
return self.ptr->production_id;
|
||||
} else {
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline Subtree ts_subtree_from_mut(MutableSubtree self) {
|
||||
static inline Subtree ts_subtree_from_mut(MutableSubtree self)
|
||||
{
|
||||
Subtree 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;
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include "./array.h"
|
||||
#include "./length.h"
|
||||
#include "./subtree.h"
|
||||
#include "./tree_cursor.h"
|
||||
#include "api.h"
|
||||
|
||||
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *included_ranges, unsigned included_range_count)
|
||||
|
|
@ -106,50 +105,6 @@ TSRange *ts_tree_included_ranges(const TSTree *self, uint32_t *length)
|
|||
return ranges;
|
||||
}
|
||||
|
||||
// TSRange *ts_tree_get_changed_ranges(const TSTree *old_tree, const TSTree *new_tree, uint32_t *length)
|
||||
// {
|
||||
// TreeCursor cursor1 = {NULL, array_new(), 0};
|
||||
// TreeCursor cursor2 = {NULL, array_new(), 0};
|
||||
// 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)
|
||||
|
|
@ -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);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,18 +3,16 @@
|
|||
|
||||
#include "./subtree.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
typedef struct ParentCacheEntry
|
||||
{
|
||||
const Subtree *child;
|
||||
const Subtree *parent;
|
||||
Length position;
|
||||
TSSymbol alias_symbol;
|
||||
} ParentCacheEntry;
|
||||
|
||||
struct TSTree {
|
||||
struct TSTree
|
||||
{
|
||||
Subtree root;
|
||||
const TSLanguage *language;
|
||||
TSRange *included_ranges;
|
||||
|
|
@ -24,8 +22,4 @@ struct TSTree {
|
|||
TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *, unsigned);
|
||||
TSNode ts_node_new(const TSTree *, const Subtree *, Length, TSSymbol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#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