Rename Tree -> Subtree
This commit is contained in:
parent
61327b627a
commit
35510a612d
25 changed files with 724 additions and 719 deletions
|
|
@ -95,7 +95,7 @@
|
|||
'src/runtime/stack.c',
|
||||
'src/runtime/parser.c',
|
||||
'src/runtime/string_input.c',
|
||||
'src/runtime/tree.c',
|
||||
'src/runtime/subtree.c',
|
||||
'src/runtime/tree_cursor.c',
|
||||
'src/runtime/utf16.c',
|
||||
'externals/utf8proc/utf8proc.c',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "runtime/alloc.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/parser.h"
|
||||
#include "runtime/string_input.h"
|
||||
#include "runtime/document.h"
|
||||
|
|
@ -19,7 +19,7 @@ TSDocument *ts_document_new() {
|
|||
}
|
||||
|
||||
void ts_document_free(TSDocument *self) {
|
||||
if (self->tree) ts_tree_release(&self->parser.tree_pool, self->tree);
|
||||
if (self->tree) ts_subtree_release(&self->parser.tree_pool, self->tree);
|
||||
if (self->cursor1.stack.contents) array_delete(&self->cursor1.stack);
|
||||
if (self->cursor2.stack.contents) array_delete(&self->cursor2.stack);
|
||||
parser_destroy(&self->parser);
|
||||
|
|
@ -41,7 +41,7 @@ void ts_document_set_language(TSDocument *self, const TSLanguage *language) {
|
|||
ts_document_invalidate(self);
|
||||
parser_set_language(&self->parser, language);
|
||||
if (self->tree) {
|
||||
ts_tree_release(&self->parser.tree_pool, self->tree);
|
||||
ts_subtree_release(&self->parser.tree_pool, self->tree);
|
||||
self->tree = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -91,16 +91,16 @@ void ts_document_edit(TSDocument *self, TSInputEdit edit) {
|
|||
if (!self->tree)
|
||||
return;
|
||||
|
||||
uint32_t max_bytes = ts_tree_total_bytes(self->tree);
|
||||
uint32_t max_bytes = ts_subtree_total_bytes(self->tree);
|
||||
if (edit.start_byte > max_bytes)
|
||||
return;
|
||||
if (edit.bytes_removed > max_bytes - edit.start_byte)
|
||||
edit.bytes_removed = max_bytes - edit.start_byte;
|
||||
|
||||
self->tree = ts_tree_edit(self->tree, &edit, &self->parser.tree_pool);
|
||||
self->tree = ts_subtree_edit(self->tree, &edit, &self->parser.tree_pool);
|
||||
|
||||
if (self->parser.print_debugging_graphs) {
|
||||
ts_tree_print_dot_graph(self->tree, self->parser.language, stderr);
|
||||
ts_subtree_print_dot_graph(self->tree, self->parser.language, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,18 +130,18 @@ void ts_document_parse_with_options(TSDocument *self, TSParseOptions options) {
|
|||
if (!self->input.read || !self->parser.language)
|
||||
return;
|
||||
|
||||
Tree *reusable_tree = self->valid ? self->tree : NULL;
|
||||
Subtree *reusable_tree = self->valid ? self->tree : NULL;
|
||||
if (reusable_tree && !reusable_tree->has_changes)
|
||||
return;
|
||||
|
||||
Tree *tree = parser_parse(&self->parser, self->input, reusable_tree, options.halt_on_error);
|
||||
Subtree *tree = parser_parse(&self->parser, self->input, reusable_tree, options.halt_on_error);
|
||||
|
||||
if (self->tree) {
|
||||
Tree *old_tree = self->tree;
|
||||
Subtree *old_tree = self->tree;
|
||||
self->tree = tree;
|
||||
|
||||
if (options.changed_ranges && options.changed_range_count) {
|
||||
*options.changed_range_count = ts_tree_get_changed_ranges(
|
||||
*options.changed_range_count = ts_subtree_get_changed_ranges(
|
||||
old_tree, tree, &self->cursor1, &self->cursor2,
|
||||
self->parser.language, options.changed_ranges
|
||||
);
|
||||
|
|
@ -158,7 +158,7 @@ void ts_document_parse_with_options(TSDocument *self, TSParseOptions options) {
|
|||
}
|
||||
}
|
||||
|
||||
ts_tree_release(&self->parser.tree_pool, old_tree);
|
||||
ts_subtree_release(&self->parser.tree_pool, old_tree);
|
||||
}
|
||||
|
||||
self->tree = tree;
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
#define RUNTIME_DOCUMENT_H_
|
||||
|
||||
#include "runtime/parser.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/tree_cursor.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
struct TSDocument {
|
||||
Parser parser;
|
||||
TSInput input;
|
||||
Tree *tree;
|
||||
Subtree *tree;
|
||||
TSTreeCursor cursor1;
|
||||
TSTreeCursor cursor2;
|
||||
size_t parse_count;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "runtime/get_changed_ranges.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/language.h"
|
||||
#include "runtime/error_costs.h"
|
||||
#include "runtime/tree_cursor.h"
|
||||
|
|
@ -31,7 +31,7 @@ typedef struct {
|
|||
bool in_padding;
|
||||
} Iterator;
|
||||
|
||||
static Iterator iterator_new(TSTreeCursor *cursor, Tree *tree, const TSLanguage *language) {
|
||||
static Iterator iterator_new(TSTreeCursor *cursor, Subtree *tree, const TSLanguage *language) {
|
||||
array_clear(&cursor->stack);
|
||||
array_push(&cursor->stack, ((TreeCursorEntry){
|
||||
.tree = tree,
|
||||
|
|
@ -74,14 +74,14 @@ static bool iterator_tree_is_visible(const Iterator *self) {
|
|||
TreeCursorEntry entry = *array_back(&self->cursor.stack);
|
||||
if (entry.tree->visible) return true;
|
||||
if (self->cursor.stack.size > 1) {
|
||||
Tree *parent = self->cursor.stack.contents[self->cursor.stack.size - 2].tree;
|
||||
Subtree *parent = self->cursor.stack.contents[self->cursor.stack.size - 2].tree;
|
||||
const TSSymbol *alias_sequence = ts_language_alias_sequence(self->language, parent->alias_sequence_id);
|
||||
return alias_sequence && alias_sequence[entry.structural_child_index] != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void iterator_get_visible_state(const Iterator *self, Tree **tree,
|
||||
static void iterator_get_visible_state(const Iterator *self, Subtree **tree,
|
||||
TSSymbol *alias_symbol, uint32_t *start_byte) {
|
||||
uint32_t i = self->cursor.stack.size - 1;
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ static void iterator_get_visible_state(const Iterator *self, Tree **tree,
|
|||
TreeCursorEntry entry = self->cursor.stack.contents[i];
|
||||
|
||||
if (i > 0) {
|
||||
Tree *parent = self->cursor.stack.contents[i - 1].tree;
|
||||
Subtree *parent = self->cursor.stack.contents[i - 1].tree;
|
||||
const TSSymbol *alias_sequence = ts_language_alias_sequence(
|
||||
self->language,
|
||||
parent->alias_sequence_id
|
||||
|
|
@ -129,7 +129,7 @@ static bool iterator_descend(Iterator *self, uint32_t goal_position) {
|
|||
Length position = entry.position;
|
||||
uint32_t structural_child_index = 0;
|
||||
for (uint32_t i = 0; i < entry.tree->children.size; i++) {
|
||||
Tree *child = entry.tree->children.contents[i];
|
||||
Subtree *child = entry.tree->children.contents[i];
|
||||
Length child_left = length_add(position, child->padding);
|
||||
Length child_right = length_add(child_left, child->size);
|
||||
|
||||
|
|
@ -178,13 +178,13 @@ static void iterator_advance(Iterator *self) {
|
|||
TreeCursorEntry entry = array_pop(&self->cursor.stack);
|
||||
if (iterator_done(self)) return;
|
||||
|
||||
Tree *parent = array_back(&self->cursor.stack)->tree;
|
||||
Subtree *parent = array_back(&self->cursor.stack)->tree;
|
||||
uint32_t child_index = entry.child_index + 1;
|
||||
if (parent->children.size > child_index) {
|
||||
Length position = length_add(entry.position, ts_tree_total_size(entry.tree));
|
||||
Length position = length_add(entry.position, ts_subtree_total_size(entry.tree));
|
||||
uint32_t structural_child_index = entry.structural_child_index;
|
||||
if (!entry.tree->extra) structural_child_index++;
|
||||
Tree *next_child = parent->children.contents[child_index];
|
||||
Subtree *next_child = parent->children.contents[child_index];
|
||||
|
||||
array_push(&self->cursor.stack, ((TreeCursorEntry){
|
||||
.tree = next_child,
|
||||
|
|
@ -214,7 +214,7 @@ typedef enum {
|
|||
} IteratorComparison;
|
||||
|
||||
IteratorComparison iterator_compare(const Iterator *old_iter, const Iterator *new_iter) {
|
||||
Tree *old_tree = NULL, *new_tree = NULL;
|
||||
Subtree *old_tree = NULL, *new_tree = NULL;
|
||||
uint32_t old_start = 0, new_start = 0;
|
||||
TSSymbol old_alias_symbol = 0, new_alias_symbol = 0;
|
||||
iterator_get_visible_state(old_iter, &old_tree, &old_alias_symbol, &old_start);
|
||||
|
|
@ -261,7 +261,7 @@ static inline void iterator_print_state(Iterator *self) {
|
|||
}
|
||||
#endif
|
||||
|
||||
unsigned ts_tree_get_changed_ranges(Tree *old_tree, Tree *new_tree,
|
||||
unsigned ts_subtree_get_changed_ranges(Subtree *old_tree, Subtree *new_tree,
|
||||
TSTreeCursor *cursor1, TSTreeCursor *cursor2,
|
||||
const TSLanguage *language, TSRange **ranges) {
|
||||
RangeArray results = array_new();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef RUNTIME_GET_CHANGED_RANGES_H_
|
||||
#define RUNTIME_GET_CHANGED_RANGES_H_
|
||||
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
|
||||
unsigned ts_tree_get_changed_ranges(
|
||||
Tree *old_tree, Tree *new_tree, TSTreeCursor *cursor1, TSTreeCursor *cursor2,
|
||||
unsigned ts_subtree_get_changed_ranges(
|
||||
Subtree *old_tree, Subtree *new_tree, TSTreeCursor *cursor1, TSTreeCursor *cursor2,
|
||||
const TSLanguage *language, TSRange **ranges
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "runtime/language.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/error_costs.h"
|
||||
|
||||
void ts_language_table_entry(const TSLanguage *self, TSStateId state,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include "tree_sitter/parser.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
|
||||
#define ts_builtin_sym_error_repeat (ts_builtin_sym_error - 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include "runtime/lexer.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/utf16.h"
|
||||
#include "utf8proc.h"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
#include "tree_sitter/parser.h"
|
||||
#include "tree_sitter/runtime.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
|
||||
typedef struct {
|
||||
TSLexer data;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#include <stdbool.h>
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/document.h"
|
||||
#include "runtime/language.h"
|
||||
|
||||
// NodeChildIterator
|
||||
|
||||
typedef struct {
|
||||
const Tree *parent;
|
||||
const Subtree *parent;
|
||||
const TSDocument *document;
|
||||
Length position;
|
||||
uint32_t child_index;
|
||||
|
|
@ -25,12 +25,12 @@ static inline TSNode ts_node__null() {
|
|||
};
|
||||
}
|
||||
|
||||
static inline const Tree *ts_node__tree(TSNode self) {
|
||||
static inline const Subtree *ts_node__tree(TSNode self) {
|
||||
return self.subtree;
|
||||
}
|
||||
|
||||
static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node) {
|
||||
const Tree *tree = ts_node__tree(*node);
|
||||
const Subtree *tree = ts_node__tree(*node);
|
||||
const TSSymbol *alias_sequence = ts_language_alias_sequence(
|
||||
node->document->parser.language,
|
||||
tree->alias_sequence_id
|
||||
|
|
@ -47,7 +47,7 @@ static inline NodeChildIterator ts_node_child_iterator_begin(const TSNode *node)
|
|||
|
||||
static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) {
|
||||
if (self->child_index == self->parent->children.size) return false;
|
||||
Tree *child = self->parent->children.contents[self->child_index];
|
||||
Subtree *child = self->parent->children.contents[self->child_index];
|
||||
TSSymbol alias_symbol = 0;
|
||||
if (!child->extra) {
|
||||
if (self->alias_sequence) {
|
||||
|
|
@ -62,13 +62,13 @@ static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *
|
|||
.byte = self->position.bytes,
|
||||
.alias_symbol = alias_symbol,
|
||||
};
|
||||
self->position = length_add(self->position, ts_tree_total_size(child));
|
||||
self->position = length_add(self->position, ts_subtree_total_size(child));
|
||||
self->child_index++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
if (include_anonymous) {
|
||||
return tree->visible || self.alias_symbol;
|
||||
} else {
|
||||
|
|
@ -86,7 +86,7 @@ static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) {
|
|||
}
|
||||
|
||||
static inline uint32_t ts_node__relevant_child_count(TSNode self, bool include_anonymous) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
if (tree->children.size > 0) {
|
||||
if (include_anonymous) {
|
||||
return tree->visible_child_count;
|
||||
|
|
@ -300,7 +300,7 @@ static inline TSNode ts_node__descendant_for_point_range(TSNode self, TSPoint mi
|
|||
TSNode child;
|
||||
NodeChildIterator iterator = ts_node_child_iterator_begin(&node);
|
||||
while (ts_node_child_iterator_next(&iterator, &child)) {
|
||||
const Tree *child_tree = ts_node__tree(child);
|
||||
const Subtree *child_tree = ts_node__tree(child);
|
||||
if (iterator.child_index != 1) {
|
||||
start_position = point_add(start_position, child_tree->padding.extent);
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ TSPoint ts_node_end_point(TSNode self) {
|
|||
}
|
||||
|
||||
TSSymbol ts_node_symbol(TSNode self) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
return self.alias_symbol ? self.alias_symbol : tree->symbol;
|
||||
}
|
||||
|
||||
|
|
@ -347,25 +347,25 @@ const char *ts_node_type(TSNode self) {
|
|||
}
|
||||
|
||||
char *ts_node_string(TSNode self) {
|
||||
return ts_tree_string(ts_node__tree(self), self.document->parser.language, false);
|
||||
return ts_subtree_string(ts_node__tree(self), self.document->parser.language, false);
|
||||
}
|
||||
|
||||
bool ts_node_eq(TSNode self, TSNode other) {
|
||||
return (
|
||||
ts_tree_eq(ts_node__tree(self), ts_node__tree(other)) &&
|
||||
ts_subtree_eq(ts_node__tree(self), ts_node__tree(other)) &&
|
||||
self.byte == other.byte
|
||||
);
|
||||
}
|
||||
|
||||
bool ts_node_is_named(TSNode self) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
return self.alias_symbol
|
||||
? ts_language_symbol_metadata(self.document->parser.language, self.alias_symbol).named
|
||||
: tree->named;
|
||||
}
|
||||
|
||||
bool ts_node_is_missing(TSNode self) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
return tree->is_missing;
|
||||
}
|
||||
|
||||
|
|
@ -414,7 +414,7 @@ TSNode ts_node_named_child(TSNode self, uint32_t child_index) {
|
|||
}
|
||||
|
||||
uint32_t ts_node_child_count(TSNode self) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
if (tree->children.size > 0) {
|
||||
return tree->visible_child_count;
|
||||
} else {
|
||||
|
|
@ -423,7 +423,7 @@ uint32_t ts_node_child_count(TSNode self) {
|
|||
}
|
||||
|
||||
uint32_t ts_node_named_child_count(TSNode self) {
|
||||
const Tree *tree = ts_node__tree(self);
|
||||
const Subtree *tree = ts_node__tree(self);
|
||||
if (tree->children.size > 0) {
|
||||
return tree->named_child_count;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include "tree_sitter/runtime.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/lexer.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/array.h"
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#define LOG_TREE() \
|
||||
if (self->print_debugging_graphs) { \
|
||||
ts_tree_print_dot_graph(self->finished_tree, self->language, stderr); \
|
||||
ts_subtree_print_dot_graph(self->finished_tree, self->language, stderr); \
|
||||
fputs("\n", stderr); \
|
||||
}
|
||||
|
||||
|
|
@ -84,10 +84,10 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
|
|||
for (uint32_t i = 0; i < pop.size; i++) {
|
||||
StackSlice slice = pop.contents[i];
|
||||
TSStateId state = ts_stack_state(self->stack, slice.version);
|
||||
Tree *parent = *array_front(&slice.trees);
|
||||
Subtree *parent = *array_front(&slice.subtrees);
|
||||
|
||||
for (uint32_t j = 0; j < parent->children.size; j++) {
|
||||
Tree *child = parent->children.contents[j];
|
||||
Subtree *child = parent->children.contents[j];
|
||||
pending = child->children.size > 0;
|
||||
|
||||
if (child->symbol == ts_builtin_sym_error) {
|
||||
|
|
@ -96,17 +96,17 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
|
|||
state = ts_language_next_state(self->language, state, child->symbol);
|
||||
}
|
||||
|
||||
ts_tree_retain(child);
|
||||
ts_subtree_retain(child);
|
||||
ts_stack_push(self->stack, slice.version, child, pending, state);
|
||||
}
|
||||
|
||||
for (uint32_t j = 1; j < slice.trees.size; j++) {
|
||||
Tree *tree = slice.trees.contents[j];
|
||||
for (uint32_t j = 1; j < slice.subtrees.size; j++) {
|
||||
Subtree *tree = slice.subtrees.contents[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, state);
|
||||
}
|
||||
|
||||
ts_tree_release(&self->tree_pool, parent);
|
||||
array_delete(&slice.trees);
|
||||
ts_subtree_release(&self->tree_pool, parent);
|
||||
array_delete(&slice.subtrees);
|
||||
|
||||
LOG("breakdown_top_of_stack tree:%s", SYM_NAME(parent->symbol));
|
||||
LOG_STACK();
|
||||
|
|
@ -116,11 +116,11 @@ static bool parser__breakdown_top_of_stack(Parser *self, StackVersion version) {
|
|||
return did_break_down;
|
||||
}
|
||||
|
||||
static void parser__breakdown_lookahead(Parser *self, Tree **lookahead,
|
||||
static void parser__breakdown_lookahead(Parser *self, Subtree **lookahead,
|
||||
TSStateId state,
|
||||
ReusableNode *reusable_node) {
|
||||
bool did_descend = false;
|
||||
Tree *tree = reusable_node_tree(reusable_node);
|
||||
Subtree *tree = reusable_node_tree(reusable_node);
|
||||
while (tree->children.size > 0 && tree->parse_state != state) {
|
||||
LOG("state_mismatch sym:%s", SYM_NAME(tree->symbol));
|
||||
reusable_node_descend(reusable_node);
|
||||
|
|
@ -129,9 +129,9 @@ static void parser__breakdown_lookahead(Parser *self, Tree **lookahead,
|
|||
}
|
||||
|
||||
if (did_descend) {
|
||||
ts_tree_release(&self->tree_pool, *lookahead);
|
||||
ts_subtree_release(&self->tree_pool, *lookahead);
|
||||
*lookahead = tree;
|
||||
ts_tree_retain(*lookahead);
|
||||
ts_subtree_retain(*lookahead);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ static bool parser__better_version_exists(Parser *self, StackVersion version,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void parser__restore_external_scanner(Parser *self, Tree *external_token) {
|
||||
static void parser__restore_external_scanner(Parser *self, Subtree *external_token) {
|
||||
if (external_token) {
|
||||
self->language->external_scanner.deserialize(
|
||||
self->external_scanner_payload,
|
||||
|
|
@ -227,9 +227,9 @@ static void parser__restore_external_scanner(Parser *self, Tree *external_token)
|
|||
}
|
||||
}
|
||||
|
||||
static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_state) {
|
||||
static Subtree *parser__lex(Parser *self, StackVersion version, TSStateId parse_state) {
|
||||
Length start_position = ts_stack_position(self->stack, version);
|
||||
Tree *external_token = ts_stack_last_external_token(self->stack, version);
|
||||
Subtree *external_token = ts_stack_last_external_token(self->stack, version);
|
||||
TSLexMode lex_mode = self->language->lex_modes[parse_state];
|
||||
const bool *valid_external_tokens = ts_language_enabled_external_tokens(
|
||||
self->language,
|
||||
|
|
@ -326,11 +326,11 @@ static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_sta
|
|||
last_byte_scanned = self->lexer.current_position.bytes;
|
||||
}
|
||||
|
||||
Tree *result;
|
||||
Subtree *result;
|
||||
if (skipped_error) {
|
||||
Length padding = length_sub(error_start_position, start_position);
|
||||
Length size = length_sub(error_end_position, error_start_position);
|
||||
result = ts_tree_make_error(&self->tree_pool, size, padding, first_error_character, self->language);
|
||||
result = ts_subtree_make_error(&self->tree_pool, size, padding, first_error_character, self->language);
|
||||
} else {
|
||||
if (self->lexer.token_end_position.bytes < self->lexer.token_start_position.bytes) {
|
||||
self->lexer.token_start_position = self->lexer.token_end_position;
|
||||
|
|
@ -355,7 +355,7 @@ static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_sta
|
|||
}
|
||||
}
|
||||
|
||||
result = ts_tree_make_leaf(&self->tree_pool, symbol, padding, size, self->language);
|
||||
result = ts_subtree_make_leaf(&self->tree_pool, symbol, padding, size, self->language);
|
||||
|
||||
if (found_external_token) {
|
||||
result->has_external_tokens = true;
|
||||
|
|
@ -375,30 +375,30 @@ static Tree *parser__lex(Parser *self, StackVersion version, TSStateId parse_sta
|
|||
return result;
|
||||
}
|
||||
|
||||
static Tree *parser__get_cached_token(Parser *self, size_t byte_index, Tree *last_external_token) {
|
||||
static Subtree *parser__get_cached_token(Parser *self, size_t byte_index, Subtree *last_external_token) {
|
||||
TokenCache *cache = &self->token_cache;
|
||||
if (cache->token &&
|
||||
cache->byte_index == byte_index &&
|
||||
ts_tree_external_token_state_eq(cache->last_external_token, last_external_token)) {
|
||||
ts_subtree_external_token_state_eq(cache->last_external_token, last_external_token)) {
|
||||
return cache->token;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void parser__set_cached_token(Parser *self, size_t byte_index, Tree *last_external_token,
|
||||
Tree *token) {
|
||||
static void parser__set_cached_token(Parser *self, size_t byte_index, Subtree *last_external_token,
|
||||
Subtree *token) {
|
||||
TokenCache *cache = &self->token_cache;
|
||||
if (token) ts_tree_retain(token);
|
||||
if (last_external_token) ts_tree_retain(last_external_token);
|
||||
if (cache->token) ts_tree_release(&self->tree_pool, cache->token);
|
||||
if (cache->last_external_token) ts_tree_release(&self->tree_pool, cache->last_external_token);
|
||||
if (token) ts_subtree_retain(token);
|
||||
if (last_external_token) ts_subtree_retain(last_external_token);
|
||||
if (cache->token) ts_subtree_release(&self->tree_pool, cache->token);
|
||||
if (cache->last_external_token) ts_subtree_release(&self->tree_pool, cache->last_external_token);
|
||||
cache->token = token;
|
||||
cache->byte_index = byte_index;
|
||||
cache->last_external_token = last_external_token;
|
||||
}
|
||||
|
||||
static bool parser__can_reuse_first_leaf(Parser *self, TSStateId state, Tree *tree,
|
||||
static bool parser__can_reuse_first_leaf(Parser *self, TSStateId state, Subtree *tree,
|
||||
TableEntry *table_entry) {
|
||||
TSLexMode current_lex_mode = self->language->lex_modes[state];
|
||||
|
||||
|
|
@ -416,12 +416,12 @@ static bool parser__can_reuse_first_leaf(Parser *self, TSStateId state, Tree *tr
|
|||
return current_lex_mode.external_lex_state == 0 && table_entry->is_reusable;
|
||||
}
|
||||
|
||||
static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId *state,
|
||||
static Subtree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId *state,
|
||||
ReusableNode *reusable_node, TableEntry *table_entry) {
|
||||
Length position = ts_stack_position(self->stack, version);
|
||||
Tree *last_external_token = ts_stack_last_external_token(self->stack, version);
|
||||
Subtree *last_external_token = ts_stack_last_external_token(self->stack, version);
|
||||
|
||||
Tree *result;
|
||||
Subtree *result;
|
||||
while ((result = reusable_node_tree(reusable_node))) {
|
||||
uint32_t byte_offset = reusable_node_byte_offset(reusable_node);
|
||||
if (byte_offset > position.bytes) {
|
||||
|
|
@ -435,7 +435,7 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!ts_tree_external_token_state_eq(reusable_node->last_external_token, last_external_token)) {
|
||||
if (!ts_subtree_external_token_state_eq(reusable_node->last_external_token, last_external_token)) {
|
||||
LOG("reusable_node_has_different_external_scanner_state symbol:%s", SYM_NAME(result->symbol));
|
||||
reusable_node_advance(reusable_node);
|
||||
continue;
|
||||
|
|
@ -476,14 +476,14 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
|
|||
}
|
||||
|
||||
LOG("reuse_node symbol:%s", SYM_NAME(result->symbol));
|
||||
ts_tree_retain(result);
|
||||
ts_subtree_retain(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((result = parser__get_cached_token(self, position.bytes, last_external_token))) {
|
||||
ts_language_table_entry(self->language, *state, result->first_leaf.symbol, table_entry);
|
||||
if (parser__can_reuse_first_leaf(self, *state, result, table_entry)) {
|
||||
ts_tree_retain(result);
|
||||
ts_subtree_retain(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -494,7 +494,7 @@ static Tree *parser__get_lookahead(Parser *self, StackVersion version, TSStateId
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool parser__select_tree(Parser *self, Tree *left, Tree *right) {
|
||||
static bool parser__select_tree(Parser *self, Subtree *left, Subtree *right) {
|
||||
if (!left) return true;
|
||||
if (!right) return false;
|
||||
|
||||
|
|
@ -526,7 +526,7 @@ static bool parser__select_tree(Parser *self, Tree *left, Tree *right) {
|
|||
|
||||
if (left->error_cost > 0) return true;
|
||||
|
||||
int comparison = ts_tree_compare(left, right);
|
||||
int comparison = ts_subtree_compare(left, right);
|
||||
switch (comparison) {
|
||||
case -1:
|
||||
LOG("select_earlier symbol:%s, over_symbol:%s", SYM_NAME(left->symbol),
|
||||
|
|
@ -545,31 +545,31 @@ static bool parser__select_tree(Parser *self, Tree *left, Tree *right) {
|
|||
}
|
||||
|
||||
static void parser__shift(Parser *self, StackVersion version, TSStateId state,
|
||||
Tree *lookahead, bool extra) {
|
||||
Subtree *lookahead, bool extra) {
|
||||
if (extra != lookahead->extra) {
|
||||
if (ts_stack_version_count(self->stack) > 1) {
|
||||
lookahead = ts_tree_make_copy(&self->tree_pool, lookahead);
|
||||
lookahead = ts_subtree_make_copy(&self->tree_pool, lookahead);
|
||||
} else {
|
||||
ts_tree_retain(lookahead);
|
||||
ts_subtree_retain(lookahead);
|
||||
}
|
||||
lookahead->extra = extra;
|
||||
} else {
|
||||
ts_tree_retain(lookahead);
|
||||
ts_subtree_retain(lookahead);
|
||||
}
|
||||
|
||||
bool is_pending = lookahead->children.size > 0;
|
||||
ts_stack_push(self->stack, version, lookahead, is_pending, state);
|
||||
if (lookahead->has_external_tokens) {
|
||||
ts_stack_set_last_external_token(
|
||||
self->stack, version, ts_tree_last_external_token(lookahead)
|
||||
self->stack, version, ts_subtree_last_external_token(lookahead)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static bool parser__replace_children(Parser *self, Tree *tree, TreeArray *children) {
|
||||
static bool parser__replace_children(Parser *self, Subtree *tree, SubtreeArray *children) {
|
||||
self->scratch_tree = *tree;
|
||||
self->scratch_tree.children.size = 0;
|
||||
ts_tree_set_children(&self->scratch_tree, children, self->language);
|
||||
ts_subtree_set_children(&self->scratch_tree, children, self->language);
|
||||
if (parser__select_tree(self, tree, &self->scratch_tree)) {
|
||||
*tree = self->scratch_tree;
|
||||
return true;
|
||||
|
|
@ -591,12 +591,12 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
|
|||
// Extra tokens on top of the stack should not be included in this new parent
|
||||
// node. They will be re-pushed onto the stack after the parent node is
|
||||
// created and pushed.
|
||||
TreeArray children = slice.trees;
|
||||
SubtreeArray children = slice.subtrees;
|
||||
while (children.size > 0 && children.contents[children.size - 1]->extra) {
|
||||
children.size--;
|
||||
}
|
||||
|
||||
Tree *parent = ts_tree_make_node(&self->tree_pool,
|
||||
Subtree *parent = ts_subtree_make_node(&self->tree_pool,
|
||||
symbol, &children, alias_sequence_id, self->language
|
||||
);
|
||||
|
||||
|
|
@ -609,16 +609,16 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
|
|||
if (next_slice.version != slice.version) break;
|
||||
i++;
|
||||
|
||||
TreeArray children = next_slice.trees;
|
||||
SubtreeArray children = next_slice.subtrees;
|
||||
while (children.size > 0 && children.contents[children.size - 1]->extra) {
|
||||
children.size--;
|
||||
}
|
||||
|
||||
if (parser__replace_children(self, parent, &children)) {
|
||||
ts_tree_array_delete(&self->tree_pool, &slice.trees);
|
||||
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
||||
slice = next_slice;
|
||||
} else {
|
||||
ts_tree_array_delete(&self->tree_pool, &next_slice.trees);
|
||||
ts_subtree_array_delete(&self->tree_pool, &next_slice.subtrees);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -638,15 +638,15 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
|
|||
// Push the parent node onto the stack, along with any extra tokens that
|
||||
// were previously on top of the stack.
|
||||
ts_stack_push(self->stack, slice.version, parent, false, next_state);
|
||||
for (uint32_t j = parent->children.size; j < slice.trees.size; j++) {
|
||||
ts_stack_push(self->stack, slice.version, slice.trees.contents[j], false, next_state);
|
||||
for (uint32_t j = parent->children.size; j < slice.subtrees.size; j++) {
|
||||
ts_stack_push(self->stack, slice.version, slice.subtrees.contents[j], false, next_state);
|
||||
}
|
||||
|
||||
if (ts_stack_version_count(self->stack) > MAX_VERSION_COUNT) {
|
||||
i++;
|
||||
while (i < pop.size) {
|
||||
StackSlice slice = pop.contents[i];
|
||||
ts_tree_array_delete(&self->tree_pool, &slice.trees);
|
||||
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
||||
ts_stack_halt(self->stack, slice.version);
|
||||
i++;
|
||||
}
|
||||
|
|
@ -669,7 +669,7 @@ static StackSliceArray parser__reduce(Parser *self, StackVersion version, TSSymb
|
|||
return pop;
|
||||
}
|
||||
|
||||
static void parser__start(Parser *self, TSInput input, Tree *previous_tree) {
|
||||
static void parser__start(Parser *self, TSInput input, Subtree *previous_tree) {
|
||||
if (previous_tree) {
|
||||
LOG("parse_after_edit");
|
||||
} else {
|
||||
|
|
@ -688,29 +688,29 @@ static void parser__start(Parser *self, TSInput input, Tree *previous_tree) {
|
|||
self->in_ambiguity = false;
|
||||
}
|
||||
|
||||
static void parser__accept(Parser *self, StackVersion version, Tree *lookahead) {
|
||||
static void parser__accept(Parser *self, StackVersion version, Subtree *lookahead) {
|
||||
lookahead->extra = true;
|
||||
assert(lookahead->symbol == ts_builtin_sym_end);
|
||||
ts_tree_retain(lookahead);
|
||||
ts_subtree_retain(lookahead);
|
||||
ts_stack_push(self->stack, version, lookahead, false, 1);
|
||||
|
||||
StackSliceArray pop = ts_stack_pop_all(self->stack, version);
|
||||
for (uint32_t i = 0; i < pop.size; i++) {
|
||||
TreeArray trees = pop.contents[i].trees;
|
||||
SubtreeArray trees = pop.contents[i].subtrees;
|
||||
|
||||
Tree *root = NULL;
|
||||
Subtree *root = NULL;
|
||||
for (uint32_t j = trees.size - 1; j + 1 > 0; j--) {
|
||||
Tree *child = trees.contents[j];
|
||||
Subtree *child = trees.contents[j];
|
||||
if (!child->extra) {
|
||||
for (uint32_t k = 0; k < child->children.size; k++) {
|
||||
ts_tree_retain(child->children.contents[k]);
|
||||
ts_subtree_retain(child->children.contents[k]);
|
||||
}
|
||||
array_splice(&trees, j, 1, &child->children);
|
||||
root = ts_tree_make_node(
|
||||
root = ts_subtree_make_node(
|
||||
&self->tree_pool, child->symbol, &trees,
|
||||
child->alias_sequence_id, self->language
|
||||
);
|
||||
ts_tree_release(&self->tree_pool, child);
|
||||
ts_subtree_release(&self->tree_pool, child);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -720,10 +720,10 @@ static void parser__accept(Parser *self, StackVersion version, Tree *lookahead)
|
|||
|
||||
if (self->finished_tree) {
|
||||
if (parser__select_tree(self, self->finished_tree, root)) {
|
||||
ts_tree_release(&self->tree_pool, self->finished_tree);
|
||||
ts_subtree_release(&self->tree_pool, self->finished_tree);
|
||||
self->finished_tree = root;
|
||||
} else {
|
||||
ts_tree_release(&self->tree_pool, root);
|
||||
ts_subtree_release(&self->tree_pool, root);
|
||||
}
|
||||
} else {
|
||||
self->finished_tree = root;
|
||||
|
|
@ -845,7 +845,7 @@ static void parser__handle_error(Parser *self, StackVersion version, TSSymbol lo
|
|||
lookahead_symbol
|
||||
)) {
|
||||
StackVersion version_with_missing_tree = ts_stack_copy_version(self->stack, v);
|
||||
Tree *missing_tree = ts_tree_make_missing_leaf(&self->tree_pool, missing_symbol, self->language);
|
||||
Subtree *missing_tree = ts_subtree_make_missing_leaf(&self->tree_pool, missing_symbol, self->language);
|
||||
ts_stack_push(
|
||||
self->stack, version_with_missing_tree,
|
||||
missing_tree, false,
|
||||
|
|
@ -890,17 +890,17 @@ static void parser__halt_parse(Parser *self) {
|
|||
ts_stack_position(self->stack, 0)
|
||||
);
|
||||
|
||||
Tree *filler_node = ts_tree_make_error(&self->tree_pool, remaining_length, length_zero(), 0, self->language);
|
||||
Subtree *filler_node = ts_subtree_make_error(&self->tree_pool, remaining_length, length_zero(), 0, self->language);
|
||||
filler_node->visible = false;
|
||||
ts_stack_push(self->stack, 0, filler_node, false, 0);
|
||||
|
||||
TreeArray children = array_new();
|
||||
Tree *root_error = ts_tree_make_error_node(&self->tree_pool, &children, self->language);
|
||||
SubtreeArray children = array_new();
|
||||
Subtree *root_error = ts_subtree_make_error_node(&self->tree_pool, &children, self->language);
|
||||
ts_stack_push(self->stack, 0, root_error, false, 0);
|
||||
|
||||
Tree *eof = ts_tree_make_leaf(&self->tree_pool, ts_builtin_sym_end, length_zero(), length_zero(), self->language);
|
||||
Subtree *eof = ts_subtree_make_leaf(&self->tree_pool, ts_builtin_sym_end, length_zero(), length_zero(), self->language);
|
||||
parser__accept(self, 0, eof);
|
||||
ts_tree_release(&self->tree_pool, eof);
|
||||
ts_subtree_release(&self->tree_pool, eof);
|
||||
}
|
||||
|
||||
static bool parser__recover_to_state(Parser *self, StackVersion version, unsigned depth,
|
||||
|
|
@ -912,40 +912,40 @@ static bool parser__recover_to_state(Parser *self, StackVersion version, unsigne
|
|||
StackSlice slice = pop.contents[i];
|
||||
|
||||
if (slice.version == previous_version) {
|
||||
ts_tree_array_delete(&self->tree_pool, &slice.trees);
|
||||
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
||||
array_erase(&pop, i--);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ts_stack_state(self->stack, slice.version) != goal_state) {
|
||||
ts_stack_halt(self->stack, slice.version);
|
||||
ts_tree_array_delete(&self->tree_pool, &slice.trees);
|
||||
ts_subtree_array_delete(&self->tree_pool, &slice.subtrees);
|
||||
array_erase(&pop, i--);
|
||||
continue;
|
||||
}
|
||||
|
||||
TreeArray error_trees = ts_stack_pop_error(self->stack, slice.version);
|
||||
SubtreeArray error_trees = ts_stack_pop_error(self->stack, slice.version);
|
||||
if (error_trees.size > 0) {
|
||||
assert(error_trees.size == 1);
|
||||
array_splice(&slice.trees, 0, 0, &error_trees.contents[0]->children);
|
||||
array_splice(&slice.subtrees, 0, 0, &error_trees.contents[0]->children);
|
||||
for (unsigned j = 0; j < error_trees.contents[0]->children.size; j++) {
|
||||
ts_tree_retain(slice.trees.contents[j]);
|
||||
ts_subtree_retain(slice.subtrees.contents[j]);
|
||||
}
|
||||
ts_tree_array_delete(&self->tree_pool, &error_trees);
|
||||
ts_subtree_array_delete(&self->tree_pool, &error_trees);
|
||||
}
|
||||
|
||||
TreeArray trailing_extras = ts_tree_array_remove_trailing_extras(&slice.trees);
|
||||
SubtreeArray trailing_extras = ts_subtree_array_remove_trailing_extras(&slice.subtrees);
|
||||
|
||||
if (slice.trees.size > 0) {
|
||||
Tree *error = ts_tree_make_error_node(&self->tree_pool, &slice.trees, self->language);
|
||||
if (slice.subtrees.size > 0) {
|
||||
Subtree *error = ts_subtree_make_error_node(&self->tree_pool, &slice.subtrees, self->language);
|
||||
error->extra = true;
|
||||
ts_stack_push(self->stack, slice.version, error, false, goal_state);
|
||||
} else {
|
||||
array_delete(&slice.trees);
|
||||
array_delete(&slice.subtrees);
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < trailing_extras.size; j++) {
|
||||
Tree *tree = trailing_extras.contents[j];
|
||||
Subtree *tree = trailing_extras.contents[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, goal_state);
|
||||
}
|
||||
|
||||
|
|
@ -956,7 +956,7 @@ static bool parser__recover_to_state(Parser *self, StackVersion version, unsigne
|
|||
return previous_version != STACK_VERSION_NONE;
|
||||
}
|
||||
|
||||
static void parser__recover(Parser *self, StackVersion version, Tree *lookahead) {
|
||||
static void parser__recover(Parser *self, StackVersion version, Subtree *lookahead) {
|
||||
bool did_recover = false;
|
||||
unsigned previous_version_count = ts_stack_version_count(self->stack);
|
||||
Length position = ts_stack_position(self->stack, version);
|
||||
|
|
@ -1017,8 +1017,8 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
|
||||
if (lookahead->symbol == ts_builtin_sym_end) {
|
||||
LOG("recover_eof");
|
||||
TreeArray children = array_new();
|
||||
Tree *parent = ts_tree_make_error_node(&self->tree_pool, &children, self->language);
|
||||
SubtreeArray children = array_new();
|
||||
Subtree *parent = ts_subtree_make_error_node(&self->tree_pool, &children, self->language);
|
||||
ts_stack_push(self->stack, version, parent, false, 1);
|
||||
parser__accept(self, version, lookahead);
|
||||
return;
|
||||
|
|
@ -1026,8 +1026,8 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
|
||||
unsigned new_cost =
|
||||
current_error_cost + ERROR_COST_PER_SKIPPED_TREE +
|
||||
ts_tree_total_bytes(lookahead) * ERROR_COST_PER_SKIPPED_CHAR +
|
||||
ts_tree_total_size(lookahead).extent.row * ERROR_COST_PER_SKIPPED_LINE;
|
||||
ts_subtree_total_bytes(lookahead) * ERROR_COST_PER_SKIPPED_CHAR +
|
||||
ts_subtree_total_size(lookahead).extent.row * ERROR_COST_PER_SKIPPED_LINE;
|
||||
|
||||
if (parser__better_version_exists(self, version, false, new_cost)) {
|
||||
ts_stack_halt(self->stack, version);
|
||||
|
|
@ -1041,11 +1041,11 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
}
|
||||
|
||||
LOG("skip_token symbol:%s", SYM_NAME(lookahead->symbol));
|
||||
ts_tree_retain(lookahead);
|
||||
TreeArray children = array_new();
|
||||
ts_subtree_retain(lookahead);
|
||||
SubtreeArray children = array_new();
|
||||
array_reserve(&children, 1);
|
||||
array_push(&children, lookahead);
|
||||
Tree *error_repeat = ts_tree_make_node(
|
||||
Subtree *error_repeat = ts_subtree_make_node(
|
||||
&self->tree_pool,
|
||||
ts_builtin_sym_error_repeat,
|
||||
&children,
|
||||
|
|
@ -1056,13 +1056,13 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
if (node_count_since_error > 0) {
|
||||
StackSliceArray pop = ts_stack_pop_count(self->stack, version, 1);
|
||||
assert(pop.size == 1);
|
||||
assert(pop.contents[0].trees.size == 1);
|
||||
assert(pop.contents[0].subtrees.size == 1);
|
||||
ts_stack_renumber_version(self->stack, pop.contents[0].version, version);
|
||||
array_push(&pop.contents[0].trees, error_repeat);
|
||||
error_repeat = ts_tree_make_node(
|
||||
array_push(&pop.contents[0].subtrees, error_repeat);
|
||||
error_repeat = ts_subtree_make_node(
|
||||
&self->tree_pool,
|
||||
ts_builtin_sym_error_repeat,
|
||||
&pop.contents[0].trees,
|
||||
&pop.contents[0].subtrees,
|
||||
0,
|
||||
self->language
|
||||
);
|
||||
|
|
@ -1072,7 +1072,7 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
|
||||
if (lookahead->has_external_tokens) {
|
||||
ts_stack_set_last_external_token(
|
||||
self->stack, version, ts_tree_last_external_token(lookahead)
|
||||
self->stack, version, ts_subtree_last_external_token(lookahead)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1080,7 +1080,7 @@ static void parser__recover(Parser *self, StackVersion version, Tree *lookahead)
|
|||
static void parser__advance(Parser *self, StackVersion version, ReusableNode *reusable_node) {
|
||||
TSStateId state = ts_stack_state(self->stack, version);
|
||||
TableEntry table_entry;
|
||||
Tree *lookahead = parser__get_lookahead(self, version, &state, reusable_node, &table_entry);
|
||||
Subtree *lookahead = parser__get_lookahead(self, version, &state, reusable_node, &table_entry);
|
||||
|
||||
for (;;) {
|
||||
StackVersion last_reduction_version = STACK_VERSION_NONE;
|
||||
|
|
@ -1113,7 +1113,7 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
|
|||
if (lookahead == reusable_node_tree(reusable_node)) {
|
||||
reusable_node_advance(reusable_node);
|
||||
}
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
ts_subtree_release(&self->tree_pool, lookahead);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1133,7 +1133,7 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
|
|||
case TSParseActionTypeAccept: {
|
||||
LOG("accept");
|
||||
parser__accept(self, version, lookahead);
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
ts_subtree_release(&self->tree_pool, lookahead);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1145,7 +1145,7 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
|
|||
if (lookahead == reusable_node_tree(reusable_node)) {
|
||||
reusable_node_advance(reusable_node);
|
||||
}
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
ts_subtree_release(&self->tree_pool, lookahead);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1156,12 +1156,12 @@ static void parser__advance(Parser *self, StackVersion version, ReusableNode *re
|
|||
LOG_STACK();
|
||||
} else if (state == ERROR_STATE) {
|
||||
parser__recover(self, version, lookahead);
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
ts_subtree_release(&self->tree_pool, lookahead);
|
||||
return;
|
||||
} else if (!parser__breakdown_top_of_stack(self, version)) {
|
||||
LOG("detect_error");
|
||||
ts_stack_pause(self->stack, version, lookahead->first_leaf.symbol);
|
||||
ts_tree_release(&self->tree_pool, lookahead);
|
||||
ts_subtree_release(&self->tree_pool, lookahead);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1260,7 +1260,7 @@ bool parser_init(Parser *self) {
|
|||
ts_lexer_init(&self->lexer);
|
||||
array_init(&self->reduce_actions);
|
||||
array_reserve(&self->reduce_actions, 4);
|
||||
ts_tree_pool_init(&self->tree_pool);
|
||||
ts_subtree_pool_init(&self->tree_pool);
|
||||
self->stack = ts_stack_new(&self->tree_pool);
|
||||
self->finished_tree = NULL;
|
||||
self->reusable_node = reusable_node_new();
|
||||
|
|
@ -1285,12 +1285,12 @@ void parser_destroy(Parser *self) {
|
|||
ts_stack_delete(self->stack);
|
||||
if (self->reduce_actions.contents)
|
||||
array_delete(&self->reduce_actions);
|
||||
ts_tree_pool_delete(&self->tree_pool);
|
||||
ts_subtree_pool_delete(&self->tree_pool);
|
||||
reusable_node_delete(&self->reusable_node);
|
||||
parser_set_language(self, NULL);
|
||||
}
|
||||
|
||||
Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_error) {
|
||||
Subtree *parser_parse(Parser *self, TSInput input, Subtree *old_tree, bool halt_on_error) {
|
||||
parser__start(self, input, old_tree);
|
||||
|
||||
StackVersion version = STACK_VERSION_NONE;
|
||||
|
|
@ -1336,7 +1336,7 @@ Tree *parser_parse(Parser *self, TSInput input, Tree *old_tree, bool halt_on_err
|
|||
reusable_node_delete(&reusable_node);
|
||||
ts_stack_clear(self->stack);
|
||||
parser__set_cached_token(self, 0, NULL, NULL);
|
||||
ts_tree_balance(self->finished_tree, &self->tree_pool, self->language);
|
||||
ts_subtree_balance(self->finished_tree, &self->tree_pool, self->language);
|
||||
|
||||
LOG("done");
|
||||
LOG_TREE();
|
||||
|
|
|
|||
|
|
@ -10,22 +10,22 @@ extern "C" {
|
|||
#include "runtime/lexer.h"
|
||||
#include "runtime/reusable_node.h"
|
||||
#include "runtime/reduce_action.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
|
||||
typedef struct {
|
||||
Tree *token;
|
||||
Tree *last_external_token;
|
||||
Subtree *token;
|
||||
Subtree *last_external_token;
|
||||
uint32_t byte_index;
|
||||
} TokenCache;
|
||||
|
||||
typedef struct {
|
||||
Lexer lexer;
|
||||
Stack *stack;
|
||||
TreePool tree_pool;
|
||||
SubtreePool tree_pool;
|
||||
const TSLanguage *language;
|
||||
ReduceActionSet reduce_actions;
|
||||
Tree *finished_tree;
|
||||
Tree scratch_tree;
|
||||
Subtree *finished_tree;
|
||||
Subtree scratch_tree;
|
||||
TokenCache token_cache;
|
||||
ReusableNode reusable_node;
|
||||
void *external_scanner_payload;
|
||||
|
|
@ -36,7 +36,7 @@ typedef struct {
|
|||
|
||||
bool parser_init(Parser *);
|
||||
void parser_destroy(Parser *);
|
||||
Tree *parser_parse(Parser *, TSInput, Tree *, bool halt_on_error);
|
||||
Subtree *parser_parse(Parser *, TSInput, Subtree *, bool halt_on_error);
|
||||
void parser_set_language(Parser *, const TSLanguage *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
|
||||
typedef struct {
|
||||
Tree *tree;
|
||||
Subtree *tree;
|
||||
uint32_t child_index;
|
||||
uint32_t byte_offset;
|
||||
} StackEntry;
|
||||
|
||||
typedef struct {
|
||||
Array(StackEntry) stack;
|
||||
Tree *last_external_token;
|
||||
Subtree *last_external_token;
|
||||
} ReusableNode;
|
||||
|
||||
static inline ReusableNode reusable_node_new() {
|
||||
return (ReusableNode) {array_new(), NULL};
|
||||
}
|
||||
|
||||
static inline void reusable_node_reset(ReusableNode *self, Tree *tree) {
|
||||
static inline void reusable_node_reset(ReusableNode *self, Subtree *tree) {
|
||||
array_clear(&self->stack);
|
||||
array_push(&self->stack, ((StackEntry) {
|
||||
.tree = tree,
|
||||
|
|
@ -24,7 +24,7 @@ static inline void reusable_node_reset(ReusableNode *self, Tree *tree) {
|
|||
}));
|
||||
}
|
||||
|
||||
static inline Tree *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
|
||||
: NULL;
|
||||
|
|
@ -46,12 +46,12 @@ static inline void reusable_node_assign(ReusableNode *self, const ReusableNode *
|
|||
|
||||
static inline void reusable_node_advance(ReusableNode *self) {
|
||||
StackEntry last_entry = *array_back(&self->stack);
|
||||
uint32_t byte_offset = last_entry.byte_offset + ts_tree_total_bytes(last_entry.tree);
|
||||
uint32_t byte_offset = last_entry.byte_offset + ts_subtree_total_bytes(last_entry.tree);
|
||||
if (last_entry.tree->has_external_tokens) {
|
||||
self->last_external_token = ts_tree_last_external_token(last_entry.tree);
|
||||
self->last_external_token = ts_subtree_last_external_token(last_entry.tree);
|
||||
}
|
||||
|
||||
Tree *tree;
|
||||
Subtree *tree;
|
||||
uint32_t next_index;
|
||||
do {
|
||||
StackEntry popped_entry = array_pop(&self->stack);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "runtime/alloc.h"
|
||||
#include "runtime/language.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/array.h"
|
||||
#include "runtime/stack.h"
|
||||
#include "runtime/length.h"
|
||||
|
|
@ -21,7 +21,7 @@ typedef struct StackNode StackNode;
|
|||
|
||||
typedef struct {
|
||||
StackNode *node;
|
||||
Tree *tree;
|
||||
Subtree *subtree;
|
||||
bool is_pending;
|
||||
} StackLink;
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ struct StackNode {
|
|||
|
||||
typedef struct {
|
||||
StackNode *node;
|
||||
TreeArray trees;
|
||||
uint32_t tree_count;
|
||||
SubtreeArray subtrees;
|
||||
uint32_t subtree_count;
|
||||
bool is_pending;
|
||||
} Iterator;
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
StackNode *node;
|
||||
Tree *last_external_token;
|
||||
Subtree *last_external_token;
|
||||
StackSummary *summary;
|
||||
unsigned node_count_at_last_error;
|
||||
TSSymbol lookahead_when_paused;
|
||||
|
|
@ -71,7 +71,7 @@ struct Stack {
|
|||
Array(Iterator) iterators;
|
||||
StackNodeArray node_pool;
|
||||
StackNode *base_node;
|
||||
TreePool *tree_pool;
|
||||
SubtreePool *subtree_pool;
|
||||
};
|
||||
|
||||
typedef unsigned StackAction;
|
||||
|
|
@ -91,7 +91,7 @@ static void stack_node_retain(StackNode *self) {
|
|||
assert(self->ref_count != 0);
|
||||
}
|
||||
|
||||
static void stack_node_release(StackNode *self, StackNodeArray *pool, TreePool *tree_pool) {
|
||||
static void stack_node_release(StackNode *self, StackNodeArray *pool, SubtreePool *subtree_pool) {
|
||||
recur:
|
||||
assert(self->ref_count != 0);
|
||||
self->ref_count--;
|
||||
|
|
@ -100,10 +100,10 @@ recur:
|
|||
StackNode *first_predecessor = NULL;
|
||||
if (self->link_count > 0) {
|
||||
for (unsigned i = self->link_count - 1; i > 0; i--) {
|
||||
if (self->links[i].tree) ts_tree_release(tree_pool, self->links[i].tree);
|
||||
stack_node_release(self->links[i].node, pool, tree_pool);
|
||||
if (self->links[i].subtree) ts_subtree_release(subtree_pool, self->links[i].subtree);
|
||||
stack_node_release(self->links[i].node, pool, subtree_pool);
|
||||
}
|
||||
if (self->links[0].tree) ts_tree_release(tree_pool, self->links[0].tree);
|
||||
if (self->links[0].subtree) ts_subtree_release(subtree_pool, self->links[0].subtree);
|
||||
first_predecessor = self->links[0].node;
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ recur:
|
|||
}
|
||||
}
|
||||
|
||||
static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_pending,
|
||||
static StackNode *stack_node_new(StackNode *previous_node, Subtree *subtree, bool is_pending,
|
||||
TSStateId state, StackNodeArray *pool) {
|
||||
StackNode *node = pool->size > 0 ?
|
||||
array_pop(pool) :
|
||||
|
|
@ -130,7 +130,7 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
|
|||
node->link_count = 1;
|
||||
node->links[0] = (StackLink){
|
||||
.node = previous_node,
|
||||
.tree = tree,
|
||||
.subtree = subtree,
|
||||
.is_pending = is_pending,
|
||||
};
|
||||
|
||||
|
|
@ -139,11 +139,11 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
|
|||
node->dynamic_precedence = previous_node->dynamic_precedence;
|
||||
node->node_count = previous_node->node_count;
|
||||
|
||||
if (tree) {
|
||||
node->error_cost += tree->error_cost;
|
||||
node->position = length_add(node->position, ts_tree_total_size(tree));
|
||||
node->dynamic_precedence += tree->dynamic_precedence;
|
||||
if (!tree->extra) node->node_count += tree->node_count;
|
||||
if (subtree) {
|
||||
node->error_cost += subtree->error_cost;
|
||||
node->position = length_add(node->position, ts_subtree_total_size(subtree));
|
||||
node->dynamic_precedence += subtree->dynamic_precedence;
|
||||
if (!subtree->extra) node->node_count += subtree->node_count;
|
||||
}
|
||||
} else {
|
||||
node->position = length_zero();
|
||||
|
|
@ -153,7 +153,7 @@ static StackNode *stack_node_new(StackNode *previous_node, Tree *tree, bool is_p
|
|||
return node;
|
||||
}
|
||||
|
||||
static bool stack__tree_is_equivalent(const Tree *left, const Tree *right) {
|
||||
static bool stack__subtree_is_equivalent(const Subtree *left, const Subtree *right) {
|
||||
return
|
||||
left == right ||
|
||||
(left &&
|
||||
|
|
@ -164,7 +164,7 @@ static bool stack__tree_is_equivalent(const Tree *left, const Tree *right) {
|
|||
left->padding.bytes == right->padding.bytes &&
|
||||
left->size.bytes == right->size.bytes &&
|
||||
left->extra == right->extra &&
|
||||
ts_tree_external_token_state_eq(left, right))));
|
||||
ts_subtree_external_token_state_eq(left, right))));
|
||||
}
|
||||
|
||||
static void stack_node_add_link(StackNode *self, StackLink link) {
|
||||
|
|
@ -172,7 +172,7 @@ static void stack_node_add_link(StackNode *self, StackLink link) {
|
|||
|
||||
for (int i = 0; i < self->link_count; i++) {
|
||||
StackLink existing_link = self->links[i];
|
||||
if (stack__tree_is_equivalent(existing_link.tree, link.tree)) {
|
||||
if (stack__subtree_is_equivalent(existing_link.subtree, link.subtree)) {
|
||||
if (existing_link.node == link.node) return;
|
||||
if (existing_link.node->state == link.node->state &&
|
||||
existing_link.node->position.bytes == link.node->position.bytes) {
|
||||
|
|
@ -187,24 +187,24 @@ static void stack_node_add_link(StackNode *self, StackLink link) {
|
|||
if (self->link_count == MAX_LINK_COUNT) return;
|
||||
|
||||
stack_node_retain(link.node);
|
||||
if (link.tree) ts_tree_retain(link.tree);
|
||||
if (link.subtree) ts_subtree_retain(link.subtree);
|
||||
self->links[self->link_count++] = link;
|
||||
|
||||
unsigned node_count = link.node->node_count;
|
||||
if (link.tree) node_count += link.tree->node_count;
|
||||
if (link.subtree) node_count += link.subtree->node_count;
|
||||
if (node_count > self->node_count) self->node_count = node_count;
|
||||
}
|
||||
|
||||
static void stack_head_delete(StackHead *self, StackNodeArray *pool, TreePool *tree_pool) {
|
||||
static void stack_head_delete(StackHead *self, StackNodeArray *pool, SubtreePool *subtree_pool) {
|
||||
if (self->node) {
|
||||
if (self->last_external_token) {
|
||||
ts_tree_release(tree_pool, self->last_external_token);
|
||||
ts_subtree_release(subtree_pool, self->last_external_token);
|
||||
}
|
||||
if (self->summary) {
|
||||
array_delete(self->summary);
|
||||
ts_free(self->summary);
|
||||
}
|
||||
stack_node_release(self->node, pool, tree_pool);
|
||||
stack_node_release(self->node, pool, subtree_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -219,44 +219,44 @@ static StackVersion ts_stack__add_version(Stack *self, StackVersion original_ver
|
|||
};
|
||||
array_push(&self->heads, head);
|
||||
stack_node_retain(node);
|
||||
if (head.last_external_token) ts_tree_retain(head.last_external_token);
|
||||
if (head.last_external_token) ts_subtree_retain(head.last_external_token);
|
||||
return (StackVersion)(self->heads.size - 1);
|
||||
}
|
||||
|
||||
static void ts_stack__add_slice(Stack *self, StackVersion original_version,
|
||||
StackNode *node, TreeArray *trees) {
|
||||
StackNode *node, SubtreeArray *subtrees) {
|
||||
for (uint32_t i = self->slices.size - 1; i + 1 > 0; i--) {
|
||||
StackVersion version = self->slices.contents[i].version;
|
||||
if (self->heads.contents[version].node == node) {
|
||||
StackSlice slice = {*trees, version};
|
||||
StackSlice slice = {*subtrees, version};
|
||||
array_insert(&self->slices, i + 1, slice);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StackVersion version = ts_stack__add_version(self, original_version, node);
|
||||
StackSlice slice = { *trees, version };
|
||||
StackSlice slice = { *subtrees, version };
|
||||
array_push(&self->slices, slice);
|
||||
}
|
||||
|
||||
inline StackSliceArray stack__iter(Stack *self, StackVersion version,
|
||||
StackCallback callback, void *payload,
|
||||
int goal_tree_count) {
|
||||
int goal_subtree_count) {
|
||||
array_clear(&self->slices);
|
||||
array_clear(&self->iterators);
|
||||
|
||||
StackHead *head = array_get(&self->heads, version);
|
||||
Iterator iterator = {
|
||||
.node = head->node,
|
||||
.trees = array_new(),
|
||||
.tree_count = 0,
|
||||
.subtrees = array_new(),
|
||||
.subtree_count = 0,
|
||||
.is_pending = true,
|
||||
};
|
||||
|
||||
bool include_trees = false;
|
||||
if (goal_tree_count >= 0) {
|
||||
include_trees = true;
|
||||
array_reserve(&iterator.trees, goal_tree_count);
|
||||
bool include_subtrees = false;
|
||||
if (goal_subtree_count >= 0) {
|
||||
include_subtrees = true;
|
||||
array_reserve(&iterator.subtrees, goal_subtree_count);
|
||||
}
|
||||
|
||||
array_push(&self->iterators, iterator);
|
||||
|
|
@ -271,21 +271,21 @@ inline StackSliceArray stack__iter(Stack *self, StackVersion version,
|
|||
bool should_stop = action & StackActionStop || node->link_count == 0;
|
||||
|
||||
if (should_pop) {
|
||||
TreeArray trees = iterator->trees;
|
||||
SubtreeArray subtrees = iterator->subtrees;
|
||||
if (!should_stop)
|
||||
ts_tree_array_copy(trees, &trees);
|
||||
ts_tree_array_reverse(&trees);
|
||||
ts_subtree_array_copy(subtrees, &subtrees);
|
||||
ts_subtree_array_reverse(&subtrees);
|
||||
ts_stack__add_slice(
|
||||
self,
|
||||
version,
|
||||
node,
|
||||
&trees
|
||||
&subtrees
|
||||
);
|
||||
}
|
||||
|
||||
if (should_stop) {
|
||||
if (!should_pop)
|
||||
ts_tree_array_delete(self->tree_pool, &iterator->trees);
|
||||
ts_subtree_array_delete(self->subtree_pool, &iterator->subtrees);
|
||||
array_erase(&self->iterators, i);
|
||||
i--, size--;
|
||||
continue;
|
||||
|
|
@ -303,24 +303,24 @@ inline StackSliceArray stack__iter(Stack *self, StackVersion version,
|
|||
Iterator current_iterator = self->iterators.contents[i];
|
||||
array_push(&self->iterators, current_iterator);
|
||||
next_iterator = array_back(&self->iterators);
|
||||
ts_tree_array_copy(next_iterator->trees, &next_iterator->trees);
|
||||
ts_subtree_array_copy(next_iterator->subtrees, &next_iterator->subtrees);
|
||||
}
|
||||
|
||||
next_iterator->node = link.node;
|
||||
if (link.tree) {
|
||||
if (include_trees) {
|
||||
array_push(&next_iterator->trees, link.tree);
|
||||
ts_tree_retain(link.tree);
|
||||
if (link.subtree) {
|
||||
if (include_subtrees) {
|
||||
array_push(&next_iterator->subtrees, link.subtree);
|
||||
ts_subtree_retain(link.subtree);
|
||||
}
|
||||
|
||||
if (!link.tree->extra) {
|
||||
next_iterator->tree_count++;
|
||||
if (!link.subtree->extra) {
|
||||
next_iterator->subtree_count++;
|
||||
if (!link.is_pending) {
|
||||
next_iterator->is_pending = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
next_iterator->tree_count++;
|
||||
next_iterator->subtree_count++;
|
||||
next_iterator->is_pending = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -330,7 +330,7 @@ inline StackSliceArray stack__iter(Stack *self, StackVersion version,
|
|||
return self->slices;
|
||||
}
|
||||
|
||||
Stack *ts_stack_new(TreePool *tree_pool) {
|
||||
Stack *ts_stack_new(SubtreePool *subtree_pool) {
|
||||
Stack *self = ts_calloc(1, sizeof(Stack));
|
||||
|
||||
array_init(&self->heads);
|
||||
|
|
@ -342,7 +342,7 @@ Stack *ts_stack_new(TreePool *tree_pool) {
|
|||
array_reserve(&self->iterators, 4);
|
||||
array_reserve(&self->node_pool, MAX_NODE_POOL_SIZE);
|
||||
|
||||
self->tree_pool = tree_pool;
|
||||
self->subtree_pool = subtree_pool;
|
||||
self->base_node = stack_node_new(NULL, NULL, false, 1, &self->node_pool);
|
||||
ts_stack_clear(self);
|
||||
|
||||
|
|
@ -354,9 +354,9 @@ void ts_stack_delete(Stack *self) {
|
|||
array_delete(&self->slices);
|
||||
if (self->iterators.contents)
|
||||
array_delete(&self->iterators);
|
||||
stack_node_release(self->base_node, &self->node_pool, self->tree_pool);
|
||||
stack_node_release(self->base_node, &self->node_pool, self->subtree_pool);
|
||||
for (uint32_t i = 0; i < self->heads.size; i++) {
|
||||
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->tree_pool);
|
||||
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->subtree_pool);
|
||||
}
|
||||
array_clear(&self->heads);
|
||||
if (self->node_pool.contents) {
|
||||
|
|
@ -380,14 +380,14 @@ Length ts_stack_position(const Stack *self, StackVersion version) {
|
|||
return array_get(&self->heads, version)->node->position;
|
||||
}
|
||||
|
||||
Tree *ts_stack_last_external_token(const Stack *self, StackVersion version) {
|
||||
Subtree *ts_stack_last_external_token(const Stack *self, StackVersion version) {
|
||||
return array_get(&self->heads, version)->last_external_token;
|
||||
}
|
||||
|
||||
void ts_stack_set_last_external_token(Stack *self, StackVersion version, Tree *token) {
|
||||
void ts_stack_set_last_external_token(Stack *self, StackVersion version, Subtree *token) {
|
||||
StackHead *head = array_get(&self->heads, version);
|
||||
if (token) ts_tree_retain(token);
|
||||
if (head->last_external_token) ts_tree_release(self->tree_pool, head->last_external_token);
|
||||
if (token) ts_subtree_retain(token);
|
||||
if (head->last_external_token) ts_subtree_release(self->subtree_pool, head->last_external_token);
|
||||
head->last_external_token = token;
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +396,7 @@ unsigned ts_stack_error_cost(const Stack *self, StackVersion version) {
|
|||
unsigned result = head->node->error_cost;
|
||||
if (
|
||||
head->status == StackStatusPaused ||
|
||||
(head->node->state == ERROR_STATE && !head->node->links[0].tree)) {
|
||||
(head->node->state == ERROR_STATE && !head->node->links[0].subtree)) {
|
||||
result += ERROR_COST_PER_RECOVERY;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -410,10 +410,10 @@ unsigned ts_stack_node_count_since_error(const Stack *self, StackVersion version
|
|||
return head->node->node_count - head->node_count_at_last_error;
|
||||
}
|
||||
|
||||
void ts_stack_push(Stack *self, StackVersion version, Tree *tree, bool pending, TSStateId state) {
|
||||
void ts_stack_push(Stack *self, StackVersion version, Subtree *subtree, bool pending, TSStateId state) {
|
||||
StackHead *head = array_get(&self->heads, version);
|
||||
StackNode *new_node = stack_node_new(head->node, tree, pending, state, &self->node_pool);
|
||||
if (!tree) head->node_count_at_last_error = new_node->node_count;
|
||||
StackNode *new_node = stack_node_new(head->node, subtree, pending, state, &self->node_pool);
|
||||
if (!subtree) head->node_count_at_last_error = new_node->node_count;
|
||||
head->node = new_node;
|
||||
}
|
||||
|
||||
|
|
@ -422,7 +422,7 @@ inline StackAction iterate_callback(void *payload, const Iterator *iterator) {
|
|||
session->callback(
|
||||
session->payload,
|
||||
iterator->node->state,
|
||||
iterator->tree_count
|
||||
iterator->subtree_count
|
||||
);
|
||||
return StackActionNone;
|
||||
}
|
||||
|
|
@ -434,8 +434,8 @@ void ts_stack_iterate(Stack *self, StackVersion version,
|
|||
}
|
||||
|
||||
inline StackAction pop_count_callback(void *payload, const Iterator *iterator) {
|
||||
unsigned *goal_tree_count = payload;
|
||||
if (iterator->tree_count == *goal_tree_count) {
|
||||
unsigned *goal_subtree_count = payload;
|
||||
if (iterator->subtree_count == *goal_subtree_count) {
|
||||
return StackActionPop | StackActionStop;
|
||||
} else {
|
||||
return StackActionNone;
|
||||
|
|
@ -447,7 +447,7 @@ StackSliceArray ts_stack_pop_count(Stack *self, StackVersion version, uint32_t c
|
|||
}
|
||||
|
||||
inline StackAction pop_pending_callback(void *payload, const Iterator *iterator) {
|
||||
if (iterator->tree_count >= 1) {
|
||||
if (iterator->subtree_count >= 1) {
|
||||
if (iterator->is_pending) {
|
||||
return StackActionPop | StackActionStop;
|
||||
} else {
|
||||
|
|
@ -468,9 +468,9 @@ StackSliceArray ts_stack_pop_pending(Stack *self, StackVersion version) {
|
|||
}
|
||||
|
||||
inline StackAction pop_error_callback(void *payload, const Iterator *iterator) {
|
||||
if (iterator->trees.size > 0) {
|
||||
if (iterator->subtrees.size > 0) {
|
||||
bool *found_error = payload;
|
||||
if (!*found_error && iterator->trees.contents[0]->symbol == ts_builtin_sym_error) {
|
||||
if (!*found_error && iterator->subtrees.contents[0]->symbol == ts_builtin_sym_error) {
|
||||
*found_error = true;
|
||||
return StackActionPop | StackActionStop;
|
||||
} else {
|
||||
|
|
@ -481,21 +481,21 @@ inline StackAction pop_error_callback(void *payload, const Iterator *iterator) {
|
|||
}
|
||||
}
|
||||
|
||||
TreeArray ts_stack_pop_error(Stack *self, StackVersion version) {
|
||||
SubtreeArray ts_stack_pop_error(Stack *self, StackVersion version) {
|
||||
StackNode *node = array_get(&self->heads, version)->node;
|
||||
for (unsigned i = 0; i < node->link_count; i++) {
|
||||
if (node->links[i].tree && node->links[i].tree->symbol == ts_builtin_sym_error) {
|
||||
if (node->links[i].subtree && node->links[i].subtree->symbol == ts_builtin_sym_error) {
|
||||
bool found_error = false;
|
||||
StackSliceArray pop = stack__iter(self, version, pop_error_callback, &found_error, 1);
|
||||
if (pop.size > 0) {
|
||||
assert(pop.size == 1);
|
||||
ts_stack_renumber_version(self, pop.contents[0].version, version);
|
||||
return pop.contents[0].trees;
|
||||
return pop.contents[0].subtrees;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (TreeArray){.size = 0};
|
||||
return (SubtreeArray){.size = 0};
|
||||
}
|
||||
|
||||
inline StackAction pop_all_callback(void *payload, const Iterator *iterator) {
|
||||
|
|
@ -514,7 +514,7 @@ typedef struct {
|
|||
inline StackAction summarize_stack_callback(void *payload, const Iterator *iterator) {
|
||||
SummarizeStackSession *session = payload;
|
||||
TSStateId state = iterator->node->state;
|
||||
unsigned depth = iterator->tree_count;
|
||||
unsigned depth = iterator->subtree_count;
|
||||
if (depth > session->max_depth) return StackActionStop;
|
||||
for (unsigned i = session->summary->size - 1; i + 1 > 0; i--) {
|
||||
StackSummaryEntry entry = session->summary->contents[i];
|
||||
|
|
@ -548,7 +548,7 @@ int ts_stack_dynamic_precedence(Stack *self, StackVersion version) {
|
|||
}
|
||||
|
||||
void ts_stack_remove_version(Stack *self, StackVersion version) {
|
||||
stack_head_delete(array_get(&self->heads, version), &self->node_pool, self->tree_pool);
|
||||
stack_head_delete(array_get(&self->heads, version), &self->node_pool, self->subtree_pool);
|
||||
array_erase(&self->heads, version);
|
||||
}
|
||||
|
||||
|
|
@ -561,7 +561,7 @@ void ts_stack_renumber_version(Stack *self, StackVersion v1, StackVersion v2) {
|
|||
source_head->summary = target_head->summary;
|
||||
target_head->summary = NULL;
|
||||
}
|
||||
stack_head_delete(target_head, &self->node_pool, self->tree_pool);
|
||||
stack_head_delete(target_head, &self->node_pool, self->subtree_pool);
|
||||
*target_head = *source_head;
|
||||
array_erase(&self->heads, v1);
|
||||
}
|
||||
|
|
@ -577,7 +577,7 @@ StackVersion ts_stack_copy_version(Stack *self, StackVersion version) {
|
|||
array_push(&self->heads, self->heads.contents[version]);
|
||||
StackHead *head = array_back(&self->heads);
|
||||
stack_node_retain(head->node);
|
||||
if (head->last_external_token) ts_tree_retain(head->last_external_token);
|
||||
if (head->last_external_token) ts_subtree_retain(head->last_external_token);
|
||||
head->summary = NULL;
|
||||
return self->heads.size - 1;
|
||||
}
|
||||
|
|
@ -605,7 +605,7 @@ bool ts_stack_can_merge(Stack *self, StackVersion version1, StackVersion version
|
|||
head1->node->state == head2->node->state &&
|
||||
head1->node->position.bytes == head2->node->position.bytes &&
|
||||
head1->node->error_cost == head2->node->error_cost &&
|
||||
ts_tree_external_token_state_eq(head1->last_external_token, head2->last_external_token);
|
||||
ts_subtree_external_token_state_eq(head1->last_external_token, head2->last_external_token);
|
||||
}
|
||||
|
||||
void ts_stack_halt(Stack *self, StackVersion version) {
|
||||
|
|
@ -643,7 +643,7 @@ TSSymbol ts_stack_resume(Stack *self, StackVersion version) {
|
|||
void ts_stack_clear(Stack *self) {
|
||||
stack_node_retain(self->base_node);
|
||||
for (uint32_t i = 0; i < self->heads.size; i++) {
|
||||
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->tree_pool);
|
||||
stack_head_delete(&self->heads.contents[i], &self->node_pool, self->subtree_pool);
|
||||
}
|
||||
array_clear(&self->heads);
|
||||
array_push(&self->heads, ((StackHead){
|
||||
|
|
@ -715,8 +715,8 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
|
|||
fprintf(f, "node_%p [", node);
|
||||
if (node->state == ERROR_STATE)
|
||||
fprintf(f, "label=\"?\"");
|
||||
else if (node->link_count == 1 && node->links[0].tree &&
|
||||
node->links[0].tree->extra)
|
||||
else if (node->link_count == 1 && node->links[0].subtree &&
|
||||
node->links[0].subtree->extra)
|
||||
fprintf(f, "shape=point margin=0 label=\"\"");
|
||||
else
|
||||
fprintf(f, "label=\"%d\"", node->state);
|
||||
|
|
@ -736,24 +736,24 @@ bool ts_stack_print_dot_graph(Stack *self, const TSLanguage *language, FILE *f)
|
|||
fprintf(f, "node_%p -> node_%p [", node, link.node);
|
||||
if (link.is_pending)
|
||||
fprintf(f, "style=dashed ");
|
||||
if (link.tree && link.tree->extra)
|
||||
if (link.subtree && link.subtree->extra)
|
||||
fprintf(f, "fontcolor=gray ");
|
||||
|
||||
if (!link.tree) {
|
||||
if (!link.subtree) {
|
||||
fprintf(f, "color=red");
|
||||
} else {
|
||||
fprintf(f, "label=\"");
|
||||
if (link.tree->visible && !link.tree->named) fprintf(f, "'");
|
||||
const char *name = ts_language_symbol_name(language, link.tree->symbol);
|
||||
if (link.subtree->visible && !link.subtree->named) fprintf(f, "'");
|
||||
const char *name = ts_language_symbol_name(language, link.subtree->symbol);
|
||||
for (const char *c = name; *c; c++) {
|
||||
if (*c == '\"' || *c == '\\') fprintf(f, "\\");
|
||||
fprintf(f, "%c", *c);
|
||||
}
|
||||
if (link.tree->visible && !link.tree->named) fprintf(f, "'");
|
||||
if (link.subtree->visible && !link.subtree->named) fprintf(f, "'");
|
||||
fprintf(f, "\"");
|
||||
fprintf(f, "labeltooltip=\"error_cost: %u\ndynamic_precedence: %u\"",
|
||||
link.tree->error_cost,
|
||||
link.tree->dynamic_precedence);
|
||||
link.subtree->error_cost,
|
||||
link.subtree->dynamic_precedence);
|
||||
}
|
||||
|
||||
fprintf(f, "];\n");
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include "runtime/array.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/error_costs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ typedef unsigned StackVersion;
|
|||
#define STACK_VERSION_NONE ((StackVersion)-1)
|
||||
|
||||
typedef struct {
|
||||
TreeArray trees;
|
||||
SubtreeArray subtrees;
|
||||
StackVersion version;
|
||||
} StackSlice;
|
||||
typedef Array(StackSlice) StackSliceArray;
|
||||
|
|
@ -29,7 +29,7 @@ typedef struct {
|
|||
typedef Array(StackSummaryEntry) StackSummary;
|
||||
|
||||
// Create a stack.
|
||||
Stack *ts_stack_new(TreePool *);
|
||||
Stack *ts_stack_new(SubtreePool *);
|
||||
|
||||
// Release the memory reserved for a given stack.
|
||||
void ts_stack_delete(Stack *);
|
||||
|
|
@ -42,10 +42,10 @@ uint32_t ts_stack_version_count(const Stack *);
|
|||
TSStateId ts_stack_state(const Stack *, StackVersion);
|
||||
|
||||
// Get the last external token associated with a given version of the stack.
|
||||
Tree *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.
|
||||
void ts_stack_set_last_external_token(Stack *, StackVersion, Tree *);
|
||||
void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree *);
|
||||
|
||||
// Get the position of the given version of the stack within the document.
|
||||
Length ts_stack_position(const Stack *, StackVersion);
|
||||
|
|
@ -55,7 +55,7 @@ Length ts_stack_position(const Stack *, StackVersion);
|
|||
// This transfers ownership of the tree to the Stack. Callers that
|
||||
// need to retain ownership of the tree for their own purposes should
|
||||
// first retain the tree.
|
||||
void ts_stack_push(Stack *, StackVersion, Tree *, 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
|
||||
// operation can increase the number of stack versions by revealing multiple
|
||||
|
|
@ -65,7 +65,7 @@ void ts_stack_push(Stack *, StackVersion, Tree *, bool, TSStateId);
|
|||
StackSliceArray ts_stack_pop_count(Stack *, StackVersion, uint32_t count);
|
||||
|
||||
// Remove an error at the top of the given version of the stack.
|
||||
TreeArray ts_stack_pop_error(Stack *, StackVersion);
|
||||
SubtreeArray ts_stack_pop_error(Stack *, StackVersion);
|
||||
|
||||
// Remove any pending trees from the top of the given version of the stack.
|
||||
StackSliceArray ts_stack_pop_pending(Stack *, StackVersion);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <stdio.h>
|
||||
#include "runtime/alloc.h"
|
||||
#include "runtime/atomic.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/language.h"
|
||||
#include "runtime/error_costs.h"
|
||||
|
|
@ -51,15 +51,15 @@ bool ts_external_token_state_eq(const TSExternalTokenState *a, const TSExternalT
|
|||
memcmp(ts_external_token_state_data(a), ts_external_token_state_data(b), a->length) == 0);
|
||||
}
|
||||
|
||||
// TreeArray
|
||||
// SubtreeArray
|
||||
|
||||
bool ts_tree_array_copy(TreeArray self, TreeArray *dest) {
|
||||
Tree **contents = NULL;
|
||||
bool ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest) {
|
||||
Subtree **contents = NULL;
|
||||
if (self.capacity > 0) {
|
||||
contents = ts_calloc(self.capacity, sizeof(Tree *));
|
||||
memcpy(contents, self.contents, self.size * sizeof(Tree *));
|
||||
contents = ts_calloc(self.capacity, sizeof(Subtree *));
|
||||
memcpy(contents, self.contents, self.size * sizeof(Subtree *));
|
||||
for (uint32_t i = 0; i < self.size; i++) {
|
||||
ts_tree_retain(contents[i]);
|
||||
ts_subtree_retain(contents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,47 +69,47 @@ bool ts_tree_array_copy(TreeArray self, TreeArray *dest) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ts_tree_array_delete(TreePool *pool, TreeArray *self) {
|
||||
void ts_subtree_array_delete(SubtreePool *pool, SubtreeArray *self) {
|
||||
for (uint32_t i = 0; i < self->size; i++) {
|
||||
ts_tree_release(pool, self->contents[i]);
|
||||
ts_subtree_release(pool, self->contents[i]);
|
||||
}
|
||||
array_delete(self);
|
||||
}
|
||||
|
||||
TreeArray ts_tree_array_remove_trailing_extras(TreeArray *self) {
|
||||
TreeArray result = array_new();
|
||||
SubtreeArray ts_subtree_array_remove_trailing_extras(SubtreeArray *self) {
|
||||
SubtreeArray result = array_new();
|
||||
|
||||
uint32_t i = self->size - 1;
|
||||
for (; i + 1 > 0; i--) {
|
||||
Tree *child = self->contents[i];
|
||||
Subtree *child = self->contents[i];
|
||||
if (!child->extra) break;
|
||||
array_push(&result, child);
|
||||
}
|
||||
|
||||
self->size = i + 1;
|
||||
ts_tree_array_reverse(&result);
|
||||
ts_subtree_array_reverse(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ts_tree_array_reverse(TreeArray *self) {
|
||||
void ts_subtree_array_reverse(SubtreeArray *self) {
|
||||
for (uint32_t i = 0, limit = self->size / 2; i < limit; i++) {
|
||||
size_t reverse_index = self->size - 1 - i;
|
||||
Tree *swap = self->contents[i];
|
||||
Subtree *swap = self->contents[i];
|
||||
self->contents[i] = self->contents[reverse_index];
|
||||
self->contents[reverse_index] = swap;
|
||||
}
|
||||
}
|
||||
|
||||
// TreePool
|
||||
// SubtreePool
|
||||
|
||||
static const uint32_t MAX_TREE_POOL_SIZE = 1024;
|
||||
|
||||
void ts_tree_pool_init(TreePool *self) {
|
||||
void ts_subtree_pool_init(SubtreePool *self) {
|
||||
array_init(&self->free_trees);
|
||||
array_init(&self->tree_stack);
|
||||
}
|
||||
|
||||
void ts_tree_pool_delete(TreePool *self) {
|
||||
void ts_subtree_pool_delete(SubtreePool *self) {
|
||||
if (self->free_trees.contents) {
|
||||
for (unsigned i = 0; i < self->free_trees.size; i++) {
|
||||
ts_free(self->free_trees.contents[i]);
|
||||
|
|
@ -119,15 +119,15 @@ void ts_tree_pool_delete(TreePool *self) {
|
|||
if (self->tree_stack.contents) array_delete(&self->tree_stack);
|
||||
}
|
||||
|
||||
Tree *ts_tree_pool_allocate(TreePool *self) {
|
||||
Subtree *ts_subtree_pool_allocate(SubtreePool *self) {
|
||||
if (self->free_trees.size > 0) {
|
||||
return array_pop(&self->free_trees);
|
||||
} else {
|
||||
return ts_malloc(sizeof(Tree));
|
||||
return ts_malloc(sizeof(Subtree));
|
||||
}
|
||||
}
|
||||
|
||||
void ts_tree_pool_free(TreePool *self, Tree *tree) {
|
||||
void ts_subtree_pool_free(SubtreePool *self, Subtree *tree) {
|
||||
if (self->free_trees.size < MAX_TREE_POOL_SIZE) {
|
||||
array_push(&self->free_trees, tree);
|
||||
} else {
|
||||
|
|
@ -135,12 +135,13 @@ void ts_tree_pool_free(TreePool *self, Tree *tree) {
|
|||
}
|
||||
}
|
||||
|
||||
// Tree
|
||||
// Subtree
|
||||
|
||||
Tree *ts_tree_make_leaf(TreePool *pool, TSSymbol symbol, Length padding, Length size, const TSLanguage *language) {
|
||||
Subtree *ts_subtree_make_leaf(SubtreePool *pool, TSSymbol symbol, Length padding, Length size,
|
||||
const TSLanguage *language) {
|
||||
TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
|
||||
Tree *result = ts_tree_pool_allocate(pool);
|
||||
*result = (Tree){
|
||||
Subtree *result = ts_subtree_pool_allocate(pool);
|
||||
*result = (Subtree){
|
||||
.ref_count = 1,
|
||||
.symbol = symbol,
|
||||
.size = size,
|
||||
|
|
@ -161,50 +162,51 @@ Tree *ts_tree_make_leaf(TreePool *pool, TSSymbol symbol, Length padding, Length
|
|||
return result;
|
||||
}
|
||||
|
||||
Tree *ts_tree_make_error(TreePool *pool, Length size, Length padding, int32_t lookahead_char,
|
||||
const TSLanguage *language) {
|
||||
Tree *result = ts_tree_make_leaf(pool, ts_builtin_sym_error, padding, size, language);
|
||||
Subtree *ts_subtree_make_error(SubtreePool *pool, Length size, Length padding,
|
||||
int32_t lookahead_char, const TSLanguage *language) {
|
||||
Subtree *result = ts_subtree_make_leaf(pool, ts_builtin_sym_error, padding, size, language);
|
||||
result->fragile_left = true;
|
||||
result->fragile_right = true;
|
||||
result->lookahead_char = lookahead_char;
|
||||
return result;
|
||||
}
|
||||
|
||||
Tree *ts_tree_make_copy(TreePool *pool, Tree *self) {
|
||||
Tree *result = ts_tree_pool_allocate(pool);
|
||||
Subtree *ts_subtree_make_copy(SubtreePool *pool, Subtree *self) {
|
||||
Subtree *result = ts_subtree_pool_allocate(pool);
|
||||
*result = *self;
|
||||
if (result->children.size > 0) {
|
||||
ts_tree_array_copy(self->children, &result->children);
|
||||
ts_subtree_array_copy(self->children, &result->children);
|
||||
}
|
||||
result->ref_count = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static Tree *ts_tree_make_mut(TreePool *pool, Tree *self) {
|
||||
static Subtree *ts_subtree_make_mut(SubtreePool *pool, Subtree *self) {
|
||||
if (self->ref_count == 1) {
|
||||
return self;
|
||||
} else {
|
||||
Tree *result = ts_tree_make_copy(pool, self);
|
||||
ts_tree_release(pool, self);
|
||||
Subtree *result = ts_subtree_make_copy(pool, self);
|
||||
ts_subtree_release(pool, self);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *language, TreeArray *stack) {
|
||||
static void ts_subtree__compress(Subtree *self, unsigned count, const TSLanguage *language,
|
||||
SubtreeArray *stack) {
|
||||
unsigned initial_stack_size = stack->size;
|
||||
|
||||
Tree *tree = self;
|
||||
Subtree *tree = self;
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
if (tree->ref_count > 1 || tree->children.size != 2) break;
|
||||
|
||||
Tree *child = tree->children.contents[0];
|
||||
Subtree *child = tree->children.contents[0];
|
||||
if (
|
||||
child->ref_count > 1 ||
|
||||
child->children.size != 2 ||
|
||||
child->symbol != tree->symbol
|
||||
) break;
|
||||
|
||||
Tree *grandchild = child->children.contents[0];
|
||||
Subtree *grandchild = child->children.contents[0];
|
||||
if (
|
||||
grandchild->ref_count > 1 ||
|
||||
grandchild->children.size != 2 ||
|
||||
|
|
@ -221,19 +223,19 @@ static void ts_tree__compress(Tree *self, unsigned count, const TSLanguage *lang
|
|||
while (stack->size > initial_stack_size) {
|
||||
tree = array_pop(stack);
|
||||
assert(tree);
|
||||
Tree *child = tree->children.contents[0];
|
||||
Tree *grandchild = child->children.contents[1];
|
||||
ts_tree_set_children(grandchild, &grandchild->children, language);
|
||||
ts_tree_set_children(child, &child->children, language);
|
||||
ts_tree_set_children(tree, &tree->children, language);
|
||||
Subtree *child = tree->children.contents[0];
|
||||
Subtree *grandchild = child->children.contents[1];
|
||||
ts_subtree_set_children(grandchild, &grandchild->children, language);
|
||||
ts_subtree_set_children(child, &child->children, language);
|
||||
ts_subtree_set_children(tree, &tree->children, language);
|
||||
}
|
||||
}
|
||||
|
||||
void ts_tree_balance(Tree *self, TreePool *pool, const TSLanguage *language) {
|
||||
void ts_subtree_balance(Subtree *self, SubtreePool *pool, const TSLanguage *language) {
|
||||
array_clear(&pool->tree_stack);
|
||||
array_push(&pool->tree_stack, self);
|
||||
while (pool->tree_stack.size > 0) {
|
||||
Tree *tree = array_pop(&pool->tree_stack);
|
||||
Subtree *tree = array_pop(&pool->tree_stack);
|
||||
assert(tree);
|
||||
|
||||
if (tree->repeat_depth > 0) {
|
||||
|
|
@ -243,14 +245,14 @@ void ts_tree_balance(Tree *self, TreePool *pool, const TSLanguage *language) {
|
|||
tree->children.contents[1]->repeat_depth
|
||||
);
|
||||
for (unsigned i = n / 2; i > 0; i /= 2) {
|
||||
ts_tree__compress(tree, i, language, &pool->tree_stack);
|
||||
ts_subtree__compress(tree, i, language, &pool->tree_stack);
|
||||
n -= i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < tree->children.size; i++) {
|
||||
Tree *child = tree->children.contents[i];
|
||||
Subtree *child = tree->children.contents[i];
|
||||
if (child->ref_count == 1) {
|
||||
array_push(&pool->tree_stack, child);
|
||||
}
|
||||
|
|
@ -258,7 +260,7 @@ void ts_tree_balance(Tree *self, TreePool *pool, const TSLanguage *language) {
|
|||
}
|
||||
}
|
||||
|
||||
void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *language) {
|
||||
void ts_subtree_set_children(Subtree *self, SubtreeArray *children, const TSLanguage *language) {
|
||||
if (self->children.size > 0 && children->contents != self->children.contents) {
|
||||
array_delete(&self->children);
|
||||
}
|
||||
|
|
@ -276,16 +278,16 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
|
|||
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id);
|
||||
|
||||
for (uint32_t i = 0; i < self->children.size; i++) {
|
||||
Tree *child = self->children.contents[i];
|
||||
Subtree *child = self->children.contents[i];
|
||||
|
||||
if (i == 0) {
|
||||
self->padding = child->padding;
|
||||
self->size = child->size;
|
||||
self->bytes_scanned = child->bytes_scanned;
|
||||
} else {
|
||||
uint32_t bytes_scanned = ts_tree_total_bytes(self) + child->bytes_scanned;
|
||||
uint32_t bytes_scanned = ts_subtree_total_bytes(self) + child->bytes_scanned;
|
||||
if (bytes_scanned > self->bytes_scanned) self->bytes_scanned = bytes_scanned;
|
||||
self->size = length_add(self->size, ts_tree_total_size(child));
|
||||
self->size = length_add(self->size, ts_subtree_total_size(child));
|
||||
}
|
||||
|
||||
if (child->symbol != ts_builtin_sym_error_repeat) {
|
||||
|
|
@ -322,7 +324,7 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
|
|||
ERROR_COST_PER_SKIPPED_CHAR * self->size.bytes +
|
||||
ERROR_COST_PER_SKIPPED_LINE * self->size.extent.row;
|
||||
for (uint32_t i = 0; i < self->children.size; i++) {
|
||||
Tree *child = self->children.contents[i];
|
||||
Subtree *child = self->children.contents[i];
|
||||
if (child->extra) continue;
|
||||
if (child->symbol == ts_builtin_sym_error && child->children.size == 0) continue;
|
||||
if (child->visible) {
|
||||
|
|
@ -334,8 +336,8 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
|
|||
}
|
||||
|
||||
if (self->children.size > 0) {
|
||||
Tree *first_child = self->children.contents[0];
|
||||
Tree *last_child = self->children.contents[self->children.size - 1];
|
||||
Subtree *first_child = self->children.contents[0];
|
||||
Subtree *last_child = self->children.contents[self->children.size - 1];
|
||||
self->first_leaf = first_child->first_leaf;
|
||||
if (first_child->fragile_left) self->fragile_left = true;
|
||||
if (last_child->fragile_right) self->fragile_right = true;
|
||||
|
|
@ -354,40 +356,42 @@ void ts_tree_set_children(Tree *self, TreeArray *children, const TSLanguage *lan
|
|||
}
|
||||
}
|
||||
|
||||
Tree *ts_tree_make_node(TreePool *pool, TSSymbol symbol, TreeArray *children,
|
||||
Subtree *ts_subtree_make_node(SubtreePool *pool, TSSymbol symbol, SubtreeArray *children,
|
||||
unsigned alias_sequence_id, const TSLanguage *language) {
|
||||
Tree *result = ts_tree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
|
||||
Subtree *result = ts_subtree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
|
||||
result->alias_sequence_id = alias_sequence_id;
|
||||
if (symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat) {
|
||||
result->fragile_left = true;
|
||||
result->fragile_right = true;
|
||||
}
|
||||
ts_tree_set_children(result, children, language);
|
||||
ts_subtree_set_children(result, children, language);
|
||||
return result;
|
||||
}
|
||||
|
||||
Tree *ts_tree_make_error_node(TreePool *pool, TreeArray *children, const TSLanguage *language) {
|
||||
return ts_tree_make_node(pool, ts_builtin_sym_error, children, 0, language);
|
||||
Subtree *ts_subtree_make_error_node(SubtreePool *pool, SubtreeArray *children,
|
||||
const TSLanguage *language) {
|
||||
return ts_subtree_make_node(pool, ts_builtin_sym_error, children, 0, language);
|
||||
}
|
||||
|
||||
Tree *ts_tree_make_missing_leaf(TreePool *pool, TSSymbol symbol, const TSLanguage *language) {
|
||||
Tree *result = ts_tree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
|
||||
Subtree *ts_subtree_make_missing_leaf(SubtreePool *pool, TSSymbol symbol,
|
||||
const TSLanguage *language) {
|
||||
Subtree *result = ts_subtree_make_leaf(pool, symbol, length_zero(), length_zero(), language);
|
||||
result->is_missing = true;
|
||||
result->error_cost = ERROR_COST_PER_MISSING_TREE + ERROR_COST_PER_RECOVERY;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ts_tree_retain(Tree *self) {
|
||||
void ts_subtree_retain(Subtree *self) {
|
||||
assert(self->ref_count > 0);
|
||||
atomic_inc(&self->ref_count);
|
||||
assert(self->ref_count != 0);
|
||||
}
|
||||
|
||||
void ts_tree_release(TreePool *pool, Tree *self) {
|
||||
void ts_subtree_release(SubtreePool *pool, Subtree *self) {
|
||||
array_clear(&pool->tree_stack);
|
||||
array_push(&pool->tree_stack, self);
|
||||
while (pool->tree_stack.size > 0) {
|
||||
Tree *tree = array_pop(&pool->tree_stack);
|
||||
Subtree *tree = array_pop(&pool->tree_stack);
|
||||
assert(tree->ref_count > 0);
|
||||
if (atomic_dec(&tree->ref_count) == 0) {
|
||||
if (tree->children.size > 0) {
|
||||
|
|
@ -398,12 +402,12 @@ void ts_tree_release(TreePool *pool, Tree *self) {
|
|||
} else if (tree->has_external_tokens) {
|
||||
ts_external_token_state_delete(&tree->external_token_state);
|
||||
}
|
||||
ts_tree_pool_free(pool, tree);
|
||||
ts_subtree_pool_free(pool, tree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ts_tree_eq(const Tree *self, const Tree *other) {
|
||||
bool ts_subtree_eq(const Subtree *self, const Subtree *other) {
|
||||
if (self) {
|
||||
if (!other) return false;
|
||||
} else {
|
||||
|
|
@ -421,14 +425,14 @@ bool ts_tree_eq(const Tree *self, const Tree *other) {
|
|||
if (self->named_child_count != other->named_child_count) return false;
|
||||
|
||||
for (uint32_t i = 0; i < self->children.size; i++) {
|
||||
if (!ts_tree_eq(self->children.contents[i], other->children.contents[i])) {
|
||||
if (!ts_subtree_eq(self->children.contents[i], other->children.contents[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ts_tree_compare(const Tree *left, const Tree *right) {
|
||||
int ts_subtree_compare(const Subtree *left, const Subtree *right) {
|
||||
if (left->symbol < right->symbol)
|
||||
return -1;
|
||||
if (right->symbol < left->symbol)
|
||||
|
|
@ -438,9 +442,9 @@ int ts_tree_compare(const Tree *left, const Tree *right) {
|
|||
if (right->children.size < left->children.size)
|
||||
return 1;
|
||||
for (uint32_t i = 0; i < left->children.size; i++) {
|
||||
Tree *left_child = left->children.contents[i];
|
||||
Tree *right_child = right->children.contents[i];
|
||||
switch (ts_tree_compare(left_child, right_child)) {
|
||||
Subtree *left_child = left->children.contents[i];
|
||||
Subtree *right_child = right->children.contents[i];
|
||||
switch (ts_subtree_compare(left_child, right_child)) {
|
||||
case -1:
|
||||
return -1;
|
||||
case 1:
|
||||
|
|
@ -452,30 +456,31 @@ int ts_tree_compare(const Tree *left, const Tree *right) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Tree *ts_tree_invalidate_lookahead(Tree *self, uint32_t edit_byte_offset, TreePool *pool) {
|
||||
Subtree *ts_subtree_invalidate_lookahead(Subtree *self, uint32_t edit_byte_offset,
|
||||
SubtreePool *pool) {
|
||||
if (edit_byte_offset >= self->bytes_scanned) return self;
|
||||
|
||||
Tree *result = ts_tree_make_mut(pool, self);
|
||||
Subtree *result = ts_subtree_make_mut(pool, self);
|
||||
result->has_changes = true;
|
||||
|
||||
if (result->children.size > 0) {
|
||||
uint32_t child_start_byte = 0;
|
||||
for (uint32_t i = 0; i < result->children.size; i++) {
|
||||
Tree **child = &result->children.contents[i];
|
||||
Subtree **child = &result->children.contents[i];
|
||||
if (child_start_byte > edit_byte_offset) break;
|
||||
*child = ts_tree_invalidate_lookahead(*child, edit_byte_offset - child_start_byte, pool);
|
||||
child_start_byte += ts_tree_total_bytes(*child);
|
||||
*child = ts_subtree_invalidate_lookahead(*child, edit_byte_offset - child_start_byte, pool);
|
||||
child_start_byte += ts_subtree_total_bytes(*child);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Tree *ts_tree__edit(Tree *self, Edit edit, TreePool *pool) {
|
||||
Subtree *ts_subtree__edit(Subtree *self, Edit edit, SubtreePool *pool) {
|
||||
Length new_end = length_add(edit.start, edit.added);
|
||||
Length old_end = length_add(edit.start, edit.removed);
|
||||
|
||||
Tree *result = ts_tree_make_mut(pool, self);
|
||||
Subtree *result = ts_subtree_make_mut(pool, self);
|
||||
result->has_changes = true;
|
||||
|
||||
if (old_end.bytes <= result->padding.bytes) {
|
||||
|
|
@ -486,14 +491,14 @@ Tree *ts_tree__edit(Tree *self, Edit edit, TreePool *pool) {
|
|||
} else if (edit.start.bytes == result->padding.bytes && edit.removed.bytes == 0) {
|
||||
result->padding = length_add(result->padding, edit.added);
|
||||
} else {
|
||||
Length new_total_size = length_add(new_end, length_sub(ts_tree_total_size(result), old_end));
|
||||
Length new_total_size = length_add(new_end, length_sub(ts_subtree_total_size(result), old_end));
|
||||
result->size = length_sub(new_total_size, result->padding);
|
||||
}
|
||||
|
||||
Length child_left, child_right = length_zero();
|
||||
for (uint32_t i = 0; i < result->children.size; i++) {
|
||||
Tree **child = &result->children.contents[i];
|
||||
Length child_size = ts_tree_total_size(*child);
|
||||
Subtree **child = &result->children.contents[i];
|
||||
Length child_size = ts_subtree_total_size(*child);
|
||||
child_left = child_right;
|
||||
child_right = length_add(child_left, child_size);
|
||||
|
||||
|
|
@ -519,28 +524,28 @@ Tree *ts_tree__edit(Tree *self, Edit edit, TreePool *pool) {
|
|||
edit.added = length_zero();
|
||||
edit.removed = length_sub(edit.removed, child_edit.removed);
|
||||
|
||||
*child = ts_tree__edit(*child, child_edit, pool);
|
||||
*child = ts_subtree__edit(*child, child_edit, pool);
|
||||
} else if (child_left.bytes <= edit.start.bytes) {
|
||||
*child = ts_tree_invalidate_lookahead(*child, edit.start.bytes - child_left.bytes, pool);
|
||||
*child = ts_subtree_invalidate_lookahead(*child, edit.start.bytes - child_left.bytes, pool);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Tree *ts_tree_edit(Tree *self, const TSInputEdit *edit, TreePool *pool) {
|
||||
return ts_tree__edit(self, (Edit) {
|
||||
Subtree *ts_subtree_edit(Subtree *self, const TSInputEdit *edit, SubtreePool *pool) {
|
||||
return ts_subtree__edit(self, (Edit) {
|
||||
.start = {edit->start_byte, edit->start_point},
|
||||
.added = {edit->bytes_added, edit->extent_added},
|
||||
.removed = {edit->bytes_removed, edit->extent_removed},
|
||||
}, pool);
|
||||
}
|
||||
|
||||
Tree *ts_tree_last_external_token(Tree *tree) {
|
||||
Subtree *ts_subtree_last_external_token(Subtree *tree) {
|
||||
if (!tree->has_external_tokens) return NULL;
|
||||
while (tree->children.size > 0) {
|
||||
for (uint32_t i = tree->children.size - 1; i + 1 > 0; i--) {
|
||||
Tree *child = tree->children.contents[i];
|
||||
Subtree *child = tree->children.contents[i];
|
||||
if (child->has_external_tokens) {
|
||||
tree = child;
|
||||
break;
|
||||
|
|
@ -550,7 +555,7 @@ Tree *ts_tree_last_external_token(Tree *tree) {
|
|||
return tree;
|
||||
}
|
||||
|
||||
static size_t ts_tree__write_char_to_string(char *s, size_t n, int32_t c) {
|
||||
static size_t ts_subtree__write_char_to_string(char *s, size_t n, int32_t c) {
|
||||
if (c == 0)
|
||||
return snprintf(s, n, "EOF");
|
||||
if (c == -1)
|
||||
|
|
@ -567,7 +572,7 @@ static size_t ts_tree__write_char_to_string(char *s, size_t n, int32_t c) {
|
|||
return snprintf(s, n, "%d", c);
|
||||
}
|
||||
|
||||
static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t limit,
|
||||
static size_t ts_subtree__write_to_string(const Subtree *self, char *string, size_t limit,
|
||||
const TSLanguage *language, bool is_root,
|
||||
bool include_all, TSSymbol alias_symbol,
|
||||
bool alias_is_named) {
|
||||
|
|
@ -589,7 +594,7 @@ static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t li
|
|||
if (visible) {
|
||||
if (self->symbol == ts_builtin_sym_error && self->children.size == 0 && self->size.bytes > 0) {
|
||||
cursor += snprintf(*writer, limit, "(UNEXPECTED ");
|
||||
cursor += ts_tree__write_char_to_string(*writer, limit, self->lookahead_char);
|
||||
cursor += ts_subtree__write_char_to_string(*writer, limit, self->lookahead_char);
|
||||
} else if (self->is_missing) {
|
||||
cursor += snprintf(*writer, limit, "(MISSING");
|
||||
} else {
|
||||
|
|
@ -602,16 +607,16 @@ static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t li
|
|||
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id);
|
||||
uint32_t structural_child_index = 0;
|
||||
for (uint32_t i = 0; i < self->children.size; i++) {
|
||||
Tree *child = self->children.contents[i];
|
||||
Subtree *child = self->children.contents[i];
|
||||
if (child->extra) {
|
||||
cursor += ts_tree__write_to_string(
|
||||
cursor += ts_subtree__write_to_string(
|
||||
child, *writer, limit,
|
||||
language, false, include_all,
|
||||
0, false
|
||||
);
|
||||
} else {
|
||||
TSSymbol alias_symbol = alias_sequence ? alias_sequence[structural_child_index] : 0;
|
||||
cursor += ts_tree__write_to_string(
|
||||
cursor += ts_subtree__write_to_string(
|
||||
child, *writer, limit,
|
||||
language, false, include_all,
|
||||
alias_symbol,
|
||||
|
|
@ -626,19 +631,19 @@ static size_t ts_tree__write_to_string(const Tree *self, char *string, size_t li
|
|||
return cursor - string;
|
||||
}
|
||||
|
||||
char *ts_tree_string(const Tree *self, const TSLanguage *language, bool include_all) {
|
||||
char *ts_subtree_string(const Subtree *self, const TSLanguage *language, bool include_all) {
|
||||
char scratch_string[1];
|
||||
size_t size = ts_tree__write_to_string(
|
||||
size_t size = ts_subtree__write_to_string(
|
||||
self, scratch_string, 0,
|
||||
language, true,
|
||||
include_all, 0, false
|
||||
) + 1;
|
||||
char *result = ts_malloc(size * sizeof(char));
|
||||
ts_tree__write_to_string(self, result, size, language, true, include_all, 0, false);
|
||||
ts_subtree__write_to_string(self, result, size, language, true, include_all, 0, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
|
||||
void ts_subtree__print_dot_graph(const Subtree *self, uint32_t byte_offset,
|
||||
const TSLanguage *language, TSSymbol alias_symbol, FILE *f) {
|
||||
TSSymbol symbol = alias_symbol ? alias_symbol : self->symbol;
|
||||
fprintf(f, "tree_%p [label=\"%s\"", self, ts_language_symbol_name(language, symbol));
|
||||
|
|
@ -656,7 +661,7 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
|
|||
"repeat-depth:%u\n"
|
||||
"bytes-scanned:%u\"]\n",
|
||||
self,
|
||||
byte_offset, byte_offset + ts_tree_total_bytes(self),
|
||||
byte_offset, byte_offset + ts_subtree_total_bytes(self),
|
||||
self->parse_state,
|
||||
self->error_cost,
|
||||
self->repeat_depth,
|
||||
|
|
@ -666,29 +671,29 @@ void ts_tree__print_dot_graph(const Tree *self, uint32_t byte_offset,
|
|||
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->alias_sequence_id);
|
||||
uint32_t structural_child_index = 0;
|
||||
for (uint32_t i = 0; i < self->children.size; i++) {
|
||||
const Tree *child = self->children.contents[i];
|
||||
const Subtree *child = self->children.contents[i];
|
||||
if (child->extra) {
|
||||
ts_tree__print_dot_graph(child, byte_offset, language, 0, f);
|
||||
ts_subtree__print_dot_graph(child, byte_offset, language, 0, f);
|
||||
} else {
|
||||
TSSymbol alias_symbol = alias_sequence ? alias_sequence[structural_child_index] : 0;
|
||||
ts_tree__print_dot_graph(child, byte_offset, language, alias_symbol, f);
|
||||
ts_subtree__print_dot_graph(child, byte_offset, language, alias_symbol, f);
|
||||
structural_child_index++;
|
||||
}
|
||||
fprintf(f, "tree_%p -> tree_%p [tooltip=%u]\n", self, child, i);
|
||||
byte_offset += ts_tree_total_bytes(child);
|
||||
byte_offset += ts_subtree_total_bytes(child);
|
||||
}
|
||||
}
|
||||
|
||||
void ts_tree_print_dot_graph(const Tree *self, const TSLanguage *language, FILE *f) {
|
||||
void ts_subtree_print_dot_graph(const Subtree *self, const TSLanguage *language, FILE *f) {
|
||||
fprintf(f, "digraph tree {\n");
|
||||
fprintf(f, "edge [arrowhead=none]\n");
|
||||
ts_tree__print_dot_graph(self, 0, language, 0, f);
|
||||
ts_subtree__print_dot_graph(self, 0, language, 0, f);
|
||||
fprintf(f, "}\n");
|
||||
}
|
||||
|
||||
static const TSExternalTokenState empty_state = {.length = 0, .short_data = {0}};
|
||||
|
||||
bool ts_tree_external_token_state_eq(const Tree *self, const Tree *other) {
|
||||
bool ts_subtree_external_token_state_eq(const Subtree *self, const Subtree *other) {
|
||||
const TSExternalTokenState *state1 = &empty_state;
|
||||
const TSExternalTokenState *state2 = &empty_state;
|
||||
if (self && self->has_external_tokens) state1 = &self->external_token_state;
|
||||
125
src/runtime/subtree.h
Normal file
125
src/runtime/subtree.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#ifndef RUNTIME_TREE_H_
|
||||
#define RUNTIME_TREE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "tree_sitter/parser.h"
|
||||
#include "tree_sitter/runtime.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/array.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern TSStateId TS_TREE_STATE_NONE;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
char *long_data;
|
||||
char short_data[sizeof(char *) + sizeof(uint32_t)];
|
||||
};
|
||||
uint32_t length;
|
||||
} TSExternalTokenState;
|
||||
|
||||
typedef struct Subtree Subtree;
|
||||
|
||||
typedef Array(Subtree *) SubtreeArray;
|
||||
|
||||
struct Subtree {
|
||||
Length padding;
|
||||
Length size;
|
||||
volatile uint32_t ref_count;
|
||||
uint32_t bytes_scanned;
|
||||
uint32_t error_cost;
|
||||
uint32_t node_count;
|
||||
uint32_t repeat_depth;
|
||||
uint32_t child_count;
|
||||
int32_t dynamic_precedence;
|
||||
|
||||
bool visible : 1;
|
||||
bool named : 1;
|
||||
bool extra : 1;
|
||||
bool fragile_left : 1;
|
||||
bool fragile_right : 1;
|
||||
bool has_changes : 1;
|
||||
bool has_external_tokens : 1;
|
||||
bool is_missing : 1;
|
||||
TSSymbol symbol;
|
||||
TSStateId parse_state;
|
||||
struct {
|
||||
TSSymbol symbol;
|
||||
TSLexMode lex_mode;
|
||||
} first_leaf;
|
||||
|
||||
union {
|
||||
struct {
|
||||
SubtreeArray children;
|
||||
uint32_t visible_child_count;
|
||||
uint32_t named_child_count;
|
||||
uint16_t alias_sequence_id;
|
||||
};
|
||||
struct {
|
||||
uint32_t _2;
|
||||
TSExternalTokenState external_token_state;
|
||||
};
|
||||
struct {
|
||||
uint32_t _1;
|
||||
int32_t lookahead_char;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
SubtreeArray free_trees;
|
||||
SubtreeArray tree_stack;
|
||||
} SubtreePool;
|
||||
|
||||
void ts_external_token_state_init(TSExternalTokenState *, const char *, unsigned);
|
||||
const char *ts_external_token_state_data(const TSExternalTokenState *);
|
||||
|
||||
bool ts_subtree_array_copy(SubtreeArray, SubtreeArray *);
|
||||
void ts_subtree_array_delete(SubtreePool *, SubtreeArray *);
|
||||
SubtreeArray ts_subtree_array_remove_trailing_extras(SubtreeArray *);
|
||||
void ts_subtree_array_reverse(SubtreeArray *);
|
||||
|
||||
void ts_subtree_pool_init(SubtreePool *);
|
||||
void ts_subtree_pool_delete(SubtreePool *);
|
||||
Subtree *ts_subtree_pool_allocate(SubtreePool *);
|
||||
void ts_subtree_pool_free(SubtreePool *, Subtree *);
|
||||
|
||||
Subtree *ts_subtree_make_leaf(SubtreePool *, TSSymbol, Length, Length, const TSLanguage *);
|
||||
Subtree *ts_subtree_make_node(SubtreePool *, TSSymbol, SubtreeArray *, unsigned, const TSLanguage *);
|
||||
Subtree *ts_subtree_make_copy(SubtreePool *, Subtree *child);
|
||||
Subtree *ts_subtree_make_error_node(SubtreePool *, SubtreeArray *, const TSLanguage *);
|
||||
Subtree *ts_subtree_make_error(SubtreePool *, Length, Length, int32_t, const TSLanguage *);
|
||||
Subtree *ts_subtree_make_missing_leaf(SubtreePool *, TSSymbol, const TSLanguage *);
|
||||
void ts_subtree_retain(Subtree *tree);
|
||||
void ts_subtree_release(SubtreePool *, Subtree *tree);
|
||||
bool ts_subtree_eq(const Subtree *tree1, const Subtree *tree2);
|
||||
int ts_subtree_compare(const Subtree *tree1, const Subtree *tree2);
|
||||
void ts_subtree_set_children(Subtree *, SubtreeArray *, const TSLanguage *);
|
||||
void ts_subtree_balance(Subtree *, SubtreePool *, const TSLanguage *);
|
||||
Subtree *ts_subtree_edit(Subtree *, const TSInputEdit *edit, SubtreePool *);
|
||||
char *ts_subtree_string(const Subtree *, const TSLanguage *, bool include_all);
|
||||
void ts_subtree_print_dot_graph(const Subtree *, const TSLanguage *, FILE *);
|
||||
Subtree *ts_subtree_last_external_token(Subtree *);
|
||||
bool ts_subtree_external_token_state_eq(const Subtree *, const Subtree *);
|
||||
|
||||
static inline uint32_t ts_subtree_total_bytes(const Subtree *self) {
|
||||
return self->padding.bytes + self->size.bytes;
|
||||
}
|
||||
|
||||
static inline uint32_t ts_subtree_total_rows(const Subtree *self) {
|
||||
return self->padding.extent.row + self->size.extent.row;
|
||||
}
|
||||
|
||||
static inline Length ts_subtree_total_size(const Subtree *self) {
|
||||
return length_add(self->padding, self->size);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RUNTIME_TREE_H_
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
#ifndef RUNTIME_TREE_H_
|
||||
#define RUNTIME_TREE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "tree_sitter/parser.h"
|
||||
#include "tree_sitter/runtime.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/array.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern TSStateId TS_TREE_STATE_NONE;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
char *long_data;
|
||||
char short_data[sizeof(char *) + sizeof(uint32_t)];
|
||||
};
|
||||
uint32_t length;
|
||||
} TSExternalTokenState;
|
||||
|
||||
typedef struct Tree Tree;
|
||||
|
||||
typedef Array(Tree *) TreeArray;
|
||||
|
||||
struct Tree {
|
||||
Length padding;
|
||||
Length size;
|
||||
volatile uint32_t ref_count;
|
||||
uint32_t bytes_scanned;
|
||||
uint32_t error_cost;
|
||||
uint32_t node_count;
|
||||
uint32_t repeat_depth;
|
||||
uint32_t child_count;
|
||||
int32_t dynamic_precedence;
|
||||
|
||||
bool visible : 1;
|
||||
bool named : 1;
|
||||
bool extra : 1;
|
||||
bool fragile_left : 1;
|
||||
bool fragile_right : 1;
|
||||
bool has_changes : 1;
|
||||
bool has_external_tokens : 1;
|
||||
bool is_missing : 1;
|
||||
TSSymbol symbol;
|
||||
TSStateId parse_state;
|
||||
struct {
|
||||
TSSymbol symbol;
|
||||
TSLexMode lex_mode;
|
||||
} first_leaf;
|
||||
|
||||
union {
|
||||
struct {
|
||||
TreeArray children;
|
||||
uint32_t visible_child_count;
|
||||
uint32_t named_child_count;
|
||||
uint16_t alias_sequence_id;
|
||||
};
|
||||
struct {
|
||||
uint32_t _2;
|
||||
TSExternalTokenState external_token_state;
|
||||
};
|
||||
struct {
|
||||
uint32_t _1;
|
||||
int32_t lookahead_char;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
TreeArray free_trees;
|
||||
TreeArray tree_stack;
|
||||
} TreePool;
|
||||
|
||||
void ts_external_token_state_init(TSExternalTokenState *, const char *, unsigned);
|
||||
const char *ts_external_token_state_data(const TSExternalTokenState *);
|
||||
|
||||
bool ts_tree_array_copy(TreeArray, TreeArray *);
|
||||
void ts_tree_array_delete(TreePool *, TreeArray *);
|
||||
TreeArray ts_tree_array_remove_trailing_extras(TreeArray *);
|
||||
void ts_tree_array_reverse(TreeArray *);
|
||||
|
||||
void ts_tree_pool_init(TreePool *);
|
||||
void ts_tree_pool_delete(TreePool *);
|
||||
Tree *ts_tree_pool_allocate(TreePool *);
|
||||
void ts_tree_pool_free(TreePool *, Tree *);
|
||||
|
||||
Tree *ts_tree_make_leaf(TreePool *, TSSymbol, Length, Length, const TSLanguage *);
|
||||
Tree *ts_tree_make_node(TreePool *, TSSymbol, TreeArray *, unsigned, const TSLanguage *);
|
||||
Tree *ts_tree_make_copy(TreePool *, Tree *child);
|
||||
Tree *ts_tree_make_error_node(TreePool *, TreeArray *, const TSLanguage *);
|
||||
Tree *ts_tree_make_error(TreePool *, Length, Length, int32_t, const TSLanguage *);
|
||||
Tree *ts_tree_make_missing_leaf(TreePool *, TSSymbol, const TSLanguage *);
|
||||
void ts_tree_retain(Tree *tree);
|
||||
void ts_tree_release(TreePool *, Tree *tree);
|
||||
bool ts_tree_eq(const Tree *tree1, const Tree *tree2);
|
||||
int ts_tree_compare(const Tree *tree1, const Tree *tree2);
|
||||
void ts_tree_set_children(Tree *, TreeArray *, const TSLanguage *);
|
||||
void ts_tree_balance(Tree *, TreePool *, const TSLanguage *);
|
||||
Tree *ts_tree_edit(Tree *, const TSInputEdit *edit, TreePool *);
|
||||
char *ts_tree_string(const Tree *, const TSLanguage *, bool include_all);
|
||||
void ts_tree_print_dot_graph(const Tree *, const TSLanguage *, FILE *);
|
||||
Tree *ts_tree_last_external_token(Tree *);
|
||||
bool ts_tree_external_token_state_eq(const Tree *, const Tree *);
|
||||
|
||||
static inline uint32_t ts_tree_total_bytes(const Tree *self) {
|
||||
return self->padding.bytes + self->size.bytes;
|
||||
}
|
||||
|
||||
static inline uint32_t ts_tree_total_rows(const Tree *self) {
|
||||
return self->padding.extent.row + self->size.extent.row;
|
||||
}
|
||||
|
||||
static inline Length ts_tree_total_size(const Tree *self) {
|
||||
return length_add(self->padding, self->size);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RUNTIME_TREE_H_
|
||||
|
|
@ -24,7 +24,7 @@ void ts_tree_cursor_delete(TSTreeCursor *self) {
|
|||
|
||||
bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
|
||||
TreeCursorEntry *last_entry = array_back(&self->stack);
|
||||
Tree *tree = last_entry->tree;
|
||||
Subtree *tree = last_entry->tree;
|
||||
Length position = last_entry->position;
|
||||
|
||||
bool did_descend;
|
||||
|
|
@ -33,7 +33,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
|
|||
|
||||
uint32_t structural_child_index = 0;
|
||||
for (uint32_t i = 0; i < tree->children.size; i++) {
|
||||
Tree *child = tree->children.contents[i];
|
||||
Subtree *child = tree->children.contents[i];
|
||||
if (child->visible || child->visible_child_count > 0) {
|
||||
array_push(&self->stack, ((TreeCursorEntry) {
|
||||
.tree = child,
|
||||
|
|
@ -51,7 +51,7 @@ bool ts_tree_cursor_goto_first_child(TSTreeCursor *self) {
|
|||
}
|
||||
}
|
||||
if (!child->extra) structural_child_index++;
|
||||
position = length_add(position, ts_tree_total_size(child));
|
||||
position = length_add(position, ts_subtree_total_size(child));
|
||||
}
|
||||
} while (did_descend);
|
||||
|
||||
|
|
@ -64,15 +64,15 @@ bool ts_tree_cursor_goto_next_sibling(TSTreeCursor *self) {
|
|||
for (unsigned i = self->stack.size - 2; i + 1 > 0; i--) {
|
||||
TreeCursorEntry *parent_entry = &self->stack.contents[i];
|
||||
|
||||
Tree *parent = parent_entry->tree;
|
||||
Subtree *parent = parent_entry->tree;
|
||||
uint32_t child_index = child_entry->child_index;
|
||||
uint32_t structural_child_index = child_entry->structural_child_index;
|
||||
Length position = child_entry->position;
|
||||
Tree *child = parent->children.contents[child_index];
|
||||
Subtree *child = parent->children.contents[child_index];
|
||||
|
||||
while (++child_index < parent->children.size) {
|
||||
if (!child->extra) structural_child_index++;
|
||||
position = length_add(position, ts_tree_total_size(child));
|
||||
position = length_add(position, ts_subtree_total_size(child));
|
||||
child = parent->children.contents[child_index];
|
||||
|
||||
if (child->visible || child->visible_child_count > 0) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#ifndef RUNTIME_TREE_CURSOR_H_
|
||||
#define RUNTIME_TREE_CURSOR_H_
|
||||
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
|
||||
typedef struct {
|
||||
Tree *tree;
|
||||
Subtree *tree;
|
||||
Length position;
|
||||
uint32_t child_index;
|
||||
uint32_t structural_child_index;
|
||||
|
|
|
|||
|
|
@ -14,21 +14,21 @@ const char *symbol_names[24] = {
|
|||
"twenty-two", "twenty-three"
|
||||
};
|
||||
|
||||
TreeArray *tree_array(std::vector<Tree *> trees) {
|
||||
static TreeArray result;
|
||||
SubtreeArray *tree_array(std::vector<Subtree *> trees) {
|
||||
static SubtreeArray result;
|
||||
result.capacity = trees.size();
|
||||
result.size = trees.size();
|
||||
result.contents = (Tree **)calloc(trees.size(), sizeof(Tree *));
|
||||
result.contents = (Subtree **)calloc(trees.size(), sizeof(Subtree *));
|
||||
for (size_t i = 0; i < trees.size(); i++) {
|
||||
result.contents[i] = trees[i];
|
||||
}
|
||||
return &result;
|
||||
}
|
||||
|
||||
ostream &operator<<(std::ostream &stream, const Tree *tree) {
|
||||
ostream &operator<<(std::ostream &stream, const Subtree *tree) {
|
||||
static TSLanguage DUMMY_LANGUAGE = {};
|
||||
DUMMY_LANGUAGE.symbol_names = symbol_names;
|
||||
char *string = ts_tree_string(tree, &DUMMY_LANGUAGE, false);
|
||||
char *string = ts_subtree_string(tree, &DUMMY_LANGUAGE, false);
|
||||
stream << string;
|
||||
ts_free(string);
|
||||
return stream;
|
||||
|
|
@ -49,7 +49,7 @@ bool operator==(const TSNode &left, const TSNode &right) {
|
|||
return ts_node_eq(left, right);
|
||||
}
|
||||
|
||||
bool operator==(const std::vector<Tree *> &vec, const TreeArray &array) {
|
||||
bool operator==(const std::vector<Subtree *> &vec, const SubtreeArray &array) {
|
||||
if (vec.size() != array.size)
|
||||
return false;
|
||||
for (size_t i = 0; i < array.size; i++)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
#ifndef HELPERS_TREE_HELPERS_H_
|
||||
#define HELPERS_TREE_HELPERS_H_
|
||||
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
extern const char *symbol_names[24];
|
||||
TreeArray *tree_array(std::vector<Tree *> trees);
|
||||
SubtreeArray *tree_array(std::vector<Subtree *> trees);
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const Tree *tree);
|
||||
std::ostream &operator<<(std::ostream &stream, const Subtree *tree);
|
||||
std::ostream &operator<<(std::ostream &stream, const TSNode &node);
|
||||
bool operator==(const TSNode &left, const TSNode &right);
|
||||
bool operator==(const std::vector<Tree *> &right, const TreeArray &array);
|
||||
bool operator==(const std::vector<Subtree *> &right, const SubtreeArray &array);
|
||||
|
||||
void assert_consistent_tree_sizes(TSNode node);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "helpers/record_alloc.h"
|
||||
#include "helpers/stream_methods.h"
|
||||
#include "runtime/stack.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/length.h"
|
||||
#include "runtime/alloc.h"
|
||||
|
||||
|
|
@ -23,23 +23,23 @@ Length operator*(const Length &length, uint32_t factor) {
|
|||
return {length.bytes * factor, {0, length.extent.column * factor}};
|
||||
}
|
||||
|
||||
void free_slice_array(TreePool *pool, StackSliceArray *slices) {
|
||||
void free_slice_array(SubtreePool *pool, StackSliceArray *slices) {
|
||||
for (size_t i = 0; i < slices->size; i++) {
|
||||
StackSlice slice = slices->contents[i];
|
||||
|
||||
bool matches_prior_trees = false;
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
StackSlice prior_slice = slices->contents[j];
|
||||
if (slice.trees.contents == prior_slice.trees.contents) {
|
||||
if (slice.subtrees.contents == prior_slice.subtrees.contents) {
|
||||
matches_prior_trees = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matches_prior_trees) {
|
||||
for (size_t j = 0; j < slice.trees.size; j++)
|
||||
ts_tree_release(pool, slice.trees.contents[j]);
|
||||
array_delete(&slice.trees);
|
||||
for (size_t j = 0; j < slice.subtrees.size; j++)
|
||||
ts_subtree_release(pool, slice.subtrees.contents[j]);
|
||||
array_delete(&slice.subtrees);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -54,9 +54,9 @@ vector<StackEntry> get_stack_entries(Stack *stack, StackVersion version) {
|
|||
ts_stack_iterate(
|
||||
stack,
|
||||
version,
|
||||
[](void *payload, TSStateId state, uint32_t tree_count) {
|
||||
[](void *payload, TSStateId state, uint32_t subtree_count) {
|
||||
auto entries = static_cast<vector<StackEntry> *>(payload);
|
||||
StackEntry entry = {state, tree_count};
|
||||
StackEntry entry = {state, subtree_count};
|
||||
if (find(entries->begin(), entries->end(), entry) == entries->end()) {
|
||||
entries->push_back(entry);
|
||||
}
|
||||
|
|
@ -68,39 +68,39 @@ START_TEST
|
|||
|
||||
describe("Stack", [&]() {
|
||||
Stack *stack;
|
||||
const size_t tree_count = 11;
|
||||
Tree *trees[tree_count];
|
||||
const size_t subtree_count = 11;
|
||||
Subtree *subtrees[subtree_count];
|
||||
Length tree_len = {3, {0, 3}};
|
||||
TreePool pool;
|
||||
SubtreePool pool;
|
||||
|
||||
before_each([&]() {
|
||||
record_alloc::start();
|
||||
|
||||
ts_tree_pool_init(&pool);
|
||||
ts_subtree_pool_init(&pool);
|
||||
stack = ts_stack_new(&pool);
|
||||
|
||||
TSLanguage dummy_language;
|
||||
TSSymbolMetadata symbol_metadata[50] = {};
|
||||
dummy_language.symbol_metadata = symbol_metadata;
|
||||
|
||||
for (size_t i = 0; i < tree_count; i++) {
|
||||
trees[i] = ts_tree_make_leaf(&pool, i, length_zero(), tree_len, &dummy_language);
|
||||
for (size_t i = 0; i < subtree_count; i++) {
|
||||
subtrees[i] = ts_subtree_make_leaf(&pool, i, length_zero(), tree_len, &dummy_language);
|
||||
}
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_stack_delete(stack);
|
||||
for (size_t i = 0; i < tree_count; i++) {
|
||||
ts_tree_release(&pool, trees[i]);
|
||||
for (size_t i = 0; i < subtree_count; i++) {
|
||||
ts_subtree_release(&pool, subtrees[i]);
|
||||
}
|
||||
ts_tree_pool_delete(&pool);
|
||||
ts_subtree_pool_delete(&pool);
|
||||
|
||||
record_alloc::stop();
|
||||
AssertThat(record_alloc::outstanding_allocation_indices(), IsEmpty());
|
||||
});
|
||||
|
||||
auto push = [&](StackVersion version, Tree *tree, TSStateId state) {
|
||||
ts_tree_retain(tree);
|
||||
auto push = [&](StackVersion version, Subtree *tree, TSStateId state) {
|
||||
ts_subtree_retain(tree);
|
||||
ts_stack_push(stack, version, tree, false, state);
|
||||
};
|
||||
|
||||
|
|
@ -111,17 +111,17 @@ describe("Stack", [&]() {
|
|||
AssertThat(ts_stack_position(stack, 0), Equals(length_zero()));
|
||||
|
||||
// . <──0── A*
|
||||
push(0, trees[0], stateA);
|
||||
push(0, subtrees[0], stateA);
|
||||
AssertThat(ts_stack_state(stack, 0), Equals(stateA));
|
||||
AssertThat(ts_stack_position(stack, 0), Equals(tree_len));
|
||||
|
||||
// . <──0── A <──1── B*
|
||||
push(0, trees[1], stateB);
|
||||
push(0, subtrees[1], stateB);
|
||||
AssertThat(ts_stack_state(stack, 0), Equals(stateB));
|
||||
AssertThat(ts_stack_position(stack, 0), Equals(tree_len * 2));
|
||||
|
||||
// . <──0── A <──1── B <──2── C*
|
||||
push(0, trees[2], stateC);
|
||||
push(0, subtrees[2], stateC);
|
||||
AssertThat(ts_stack_state(stack, 0), Equals(stateC));
|
||||
AssertThat(ts_stack_position(stack, 0), Equals(tree_len * 3));
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <─*
|
||||
// ↑
|
||||
// └───*
|
||||
push(0, trees[0], stateA);
|
||||
push(0, subtrees[0], stateA);
|
||||
ts_stack_copy_version(stack, 0);
|
||||
});
|
||||
|
||||
|
|
@ -147,10 +147,10 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <──3── D*
|
||||
// ↑
|
||||
// └───2─── C <──4── D*
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, trees[3], stateD);
|
||||
push(1, trees[4], stateD);
|
||||
push(0, subtrees[1], stateB);
|
||||
push(1, subtrees[2], stateC);
|
||||
push(0, subtrees[3], stateD);
|
||||
push(1, subtrees[4], stateD);
|
||||
|
||||
// . <──0── A <──1── B <──3── D*
|
||||
// ↑ |
|
||||
|
|
@ -170,8 +170,8 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B*
|
||||
// ↑
|
||||
// └───2─── C*
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, subtrees[1], stateB);
|
||||
push(1, subtrees[2], stateC);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
|
||||
|
|
@ -181,11 +181,11 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <────3──── D*
|
||||
// ↑
|
||||
// └───2─── C <──4── D*
|
||||
trees[3]->size = tree_len * 3;
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, trees[3], stateD);
|
||||
push(1, trees[4], stateD);
|
||||
subtrees[3]->size = tree_len * 3;
|
||||
push(0, subtrees[1], stateB);
|
||||
push(1, subtrees[2], stateC);
|
||||
push(0, subtrees[3], stateD);
|
||||
push(1, subtrees[4], stateD);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
|
||||
|
|
@ -196,12 +196,12 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <──3── D <──5── E*
|
||||
// ↑
|
||||
// └───2─── C <──4── D <──5── E*
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateC);
|
||||
push(0, trees[3], stateD);
|
||||
push(1, trees[4], stateD);
|
||||
push(0, trees[5], stateE);
|
||||
push(1, trees[5], stateE);
|
||||
push(0, subtrees[1], stateB);
|
||||
push(1, subtrees[2], stateC);
|
||||
push(0, subtrees[3], stateD);
|
||||
push(1, subtrees[4], stateD);
|
||||
push(0, subtrees[5], stateE);
|
||||
push(1, subtrees[5], stateE);
|
||||
|
||||
// . <──0── A <──1── B <──3── D <──5── E*
|
||||
// ↑ |
|
||||
|
|
@ -224,12 +224,12 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <────1──── B*
|
||||
// ↑
|
||||
// └2─ A <──1── B*
|
||||
trees[2]->extra = true;
|
||||
trees[2]->size = tree_len * 0;
|
||||
subtrees[2]->extra = true;
|
||||
subtrees[2]->size = tree_len * 0;
|
||||
|
||||
push(0, trees[1], stateB);
|
||||
push(1, trees[2], stateA);
|
||||
push(1, trees[1], stateB);
|
||||
push(0, subtrees[1], stateB);
|
||||
push(1, subtrees[2], stateA);
|
||||
push(1, subtrees[1], stateB);
|
||||
|
||||
// . <──0── A <──1── B*
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
|
||||
|
|
@ -246,9 +246,9 @@ describe("Stack", [&]() {
|
|||
describe("pop_count(version, count)", [&]() {
|
||||
before_each([&]() {
|
||||
// . <──0── A <──1── B <──2── C*
|
||||
push(0, trees[0], stateA);
|
||||
push(0, trees[1], stateB);
|
||||
push(0, trees[2], stateC);
|
||||
push(0, subtrees[0], stateA);
|
||||
push(0, subtrees[1], stateB);
|
||||
push(0, subtrees[2], stateC);
|
||||
});
|
||||
|
||||
it("creates a new version with the given number of entries removed", [&]() {
|
||||
|
|
@ -261,14 +261,14 @@ describe("Stack", [&]() {
|
|||
|
||||
StackSlice slice = pop.contents[0];
|
||||
AssertThat(slice.version, Equals<StackVersion>(1));
|
||||
AssertThat(slice.trees, Equals(vector<Tree *>({ trees[1], trees[2] })));
|
||||
AssertThat(slice.subtrees, Equals(vector<Subtree *>({ subtrees[1], subtrees[2] })));
|
||||
AssertThat(ts_stack_state(stack, 1), Equals(stateA));
|
||||
|
||||
free_slice_array(&pool,&pop);
|
||||
});
|
||||
|
||||
it("does not count 'extra' trees toward the given count", [&]() {
|
||||
trees[1]->extra = true;
|
||||
it("does not count 'extra' subtrees toward the given count", [&]() {
|
||||
subtrees[1]->extra = true;
|
||||
|
||||
// . <──0── A <──1── B <──2── C*
|
||||
// ↑
|
||||
|
|
@ -277,7 +277,7 @@ describe("Stack", [&]() {
|
|||
AssertThat(pop.size, Equals<size_t>(1));
|
||||
|
||||
StackSlice slice = pop.contents[0];
|
||||
AssertThat(slice.trees, Equals(vector<Tree *>({ trees[0], trees[1], trees[2] })));
|
||||
AssertThat(slice.subtrees, Equals(vector<Subtree *>({ subtrees[0], subtrees[1], subtrees[2] })));
|
||||
AssertThat(ts_stack_state(stack, 1), Equals(1));
|
||||
|
||||
free_slice_array(&pool,&pop);
|
||||
|
|
@ -288,14 +288,14 @@ describe("Stack", [&]() {
|
|||
// . <──0── A <──1── B <──2── C <──3── D <──10── I*
|
||||
// ↑ |
|
||||
// └───4─── E <──5── F <──6───┘
|
||||
push(0, trees[3], stateD);
|
||||
push(0, subtrees[3], stateD);
|
||||
StackSliceArray pop = ts_stack_pop_count(stack, 0, 3);
|
||||
free_slice_array(&pool,&pop);
|
||||
push(1, trees[4], stateE);
|
||||
push(1, trees[5], stateF);
|
||||
push(1, trees[6], stateD);
|
||||
push(1, subtrees[4], stateE);
|
||||
push(1, subtrees[5], stateF);
|
||||
push(1, subtrees[6], stateD);
|
||||
ts_stack_merge(stack, 0, 1);
|
||||
push(0, trees[10], stateI);
|
||||
push(0, subtrees[10], stateI);
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
|
||||
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
|
||||
|
|
@ -322,11 +322,11 @@ describe("Stack", [&]() {
|
|||
|
||||
StackSlice slice1 = pop.contents[0];
|
||||
AssertThat(slice1.version, Equals<StackVersion>(1));
|
||||
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[2], trees[3], trees[10] })));
|
||||
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[2], subtrees[3], subtrees[10] })));
|
||||
|
||||
StackSlice slice2 = pop.contents[1];
|
||||
AssertThat(slice2.version, Equals<StackVersion>(2));
|
||||
AssertThat(slice2.trees, Equals(vector<Tree *>({ trees[5], trees[6], trees[10] })));
|
||||
AssertThat(slice2.subtrees, Equals(vector<Subtree *>({ subtrees[5], subtrees[6], subtrees[10] })));
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(3));
|
||||
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
|
||||
|
|
@ -366,7 +366,7 @@ describe("Stack", [&]() {
|
|||
|
||||
StackSlice slice1 = pop.contents[0];
|
||||
AssertThat(slice1.version, Equals<StackVersion>(1));
|
||||
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[10] })));
|
||||
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[10] })));
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
|
||||
AssertThat(ts_stack_state(stack, 0), Equals(stateI));
|
||||
|
|
@ -388,11 +388,11 @@ describe("Stack", [&]() {
|
|||
|
||||
StackSlice slice1 = pop.contents[0];
|
||||
AssertThat(slice1.version, Equals<StackVersion>(1));
|
||||
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[1], trees[2], trees[3], trees[10] })));
|
||||
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[1], subtrees[2], subtrees[3], subtrees[10] })));
|
||||
|
||||
StackSlice slice2 = pop.contents[1];
|
||||
AssertThat(slice2.version, Equals<StackVersion>(1));
|
||||
AssertThat(slice2.trees, Equals(vector<Tree *>({ trees[4], trees[5], trees[6], trees[10] })));
|
||||
AssertThat(slice2.subtrees, Equals(vector<Subtree *>({ subtrees[4], subtrees[5], subtrees[6], subtrees[10] })));
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(2));
|
||||
AssertThat(ts_stack_state(stack, 0), Equals(stateI));
|
||||
|
|
@ -403,7 +403,7 @@ describe("Stack", [&]() {
|
|||
});
|
||||
|
||||
describe("when there are three paths that lead to three different versions", [&]() {
|
||||
it("returns three entries with different arrays of trees", [&]() {
|
||||
it("returns three entries with different arrays of subtrees", [&]() {
|
||||
// . <──0── A <──1── B <──2── C <──3── D <──10── I*
|
||||
// ↑ |
|
||||
// ├───4─── E <──5── F <──6───┘
|
||||
|
|
@ -411,10 +411,10 @@ describe("Stack", [&]() {
|
|||
// └───7─── G <──8── H <──9───┘
|
||||
StackSliceArray pop = ts_stack_pop_count(stack, 0, 4);
|
||||
free_slice_array(&pool,&pop);
|
||||
push(1, trees[7], stateG);
|
||||
push(1, trees[8], stateH);
|
||||
push(1, trees[9], stateD);
|
||||
push(1, trees[10], stateI);
|
||||
push(1, subtrees[7], stateG);
|
||||
push(1, subtrees[8], stateH);
|
||||
push(1, subtrees[9], stateD);
|
||||
push(1, subtrees[10], stateI);
|
||||
ts_stack_merge(stack, 0, 1);
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(1));
|
||||
|
|
@ -443,15 +443,15 @@ describe("Stack", [&]() {
|
|||
|
||||
StackSlice slice1 = pop.contents[0];
|
||||
AssertThat(slice1.version, Equals<StackVersion>(1));
|
||||
AssertThat(slice1.trees, Equals(vector<Tree *>({ trees[3], trees[10] })));
|
||||
AssertThat(slice1.subtrees, Equals(vector<Subtree *>({ subtrees[3], subtrees[10] })));
|
||||
|
||||
StackSlice slice2 = pop.contents[1];
|
||||
AssertThat(slice2.version, Equals<StackVersion>(2));
|
||||
AssertThat(slice2.trees, Equals(vector<Tree *>({ trees[6], trees[10] })));
|
||||
AssertThat(slice2.subtrees, Equals(vector<Subtree *>({ subtrees[6], subtrees[10] })));
|
||||
|
||||
StackSlice slice3 = pop.contents[2];
|
||||
AssertThat(slice3.version, Equals<StackVersion>(3));
|
||||
AssertThat(slice3.trees, Equals(vector<Tree *>({ trees[9], trees[10] })));
|
||||
AssertThat(slice3.subtrees, Equals(vector<Subtree *>({ subtrees[9], subtrees[10] })));
|
||||
|
||||
AssertThat(ts_stack_version_count(stack), Equals<size_t>(4));
|
||||
AssertThat(ts_stack_state(stack, 0), Equals(stateI));
|
||||
|
|
@ -467,12 +467,12 @@ describe("Stack", [&]() {
|
|||
|
||||
describe("pop_pending(version)", [&]() {
|
||||
before_each([&]() {
|
||||
push(0, trees[0], stateA);
|
||||
push(0, subtrees[0], stateA);
|
||||
});
|
||||
|
||||
it("removes the top node from the stack if it was pushed in pending mode", [&]() {
|
||||
ts_stack_push(stack, 0, trees[1], true, stateB);
|
||||
ts_tree_retain(trees[1]);
|
||||
ts_stack_push(stack, 0, subtrees[1], true, stateB);
|
||||
ts_subtree_retain(subtrees[1]);
|
||||
|
||||
StackSliceArray pop = ts_stack_pop_pending(stack, 0);
|
||||
AssertThat(pop.size, Equals<size_t>(1));
|
||||
|
|
@ -485,20 +485,20 @@ describe("Stack", [&]() {
|
|||
free_slice_array(&pool,&pop);
|
||||
});
|
||||
|
||||
it("skips entries whose trees are extra", [&]() {
|
||||
ts_stack_push(stack, 0, trees[1], true, stateB);
|
||||
ts_tree_retain(trees[1]);
|
||||
it("skips entries whose subtrees are extra", [&]() {
|
||||
ts_stack_push(stack, 0, subtrees[1], true, stateB);
|
||||
ts_subtree_retain(subtrees[1]);
|
||||
|
||||
trees[2]->extra = true;
|
||||
trees[3]->extra = true;
|
||||
subtrees[2]->extra = true;
|
||||
subtrees[3]->extra = true;
|
||||
|
||||
push(0, trees[2], stateB);
|
||||
push(0, trees[3], stateB);
|
||||
push(0, subtrees[2], stateB);
|
||||
push(0, subtrees[3], stateB);
|
||||
|
||||
StackSliceArray pop = ts_stack_pop_pending(stack, 0);
|
||||
AssertThat(pop.size, Equals<size_t>(1));
|
||||
|
||||
AssertThat(pop.contents[0].trees, Equals(vector<Tree *>({ trees[1], trees[2], trees[3] })));
|
||||
AssertThat(pop.contents[0].subtrees, Equals(vector<Subtree *>({ subtrees[1], subtrees[2], subtrees[3] })));
|
||||
|
||||
AssertThat(get_stack_entries(stack, 0), Equals(vector<StackEntry>({
|
||||
{stateA, 0},
|
||||
|
|
@ -509,7 +509,7 @@ describe("Stack", [&]() {
|
|||
});
|
||||
|
||||
it("does nothing if the top node was not pushed in pending mode", [&]() {
|
||||
push(0, trees[1], stateB);
|
||||
push(0, subtrees[1], stateB);
|
||||
|
||||
StackSliceArray pop = ts_stack_pop_pending(stack, 0);
|
||||
AssertThat(pop.size, Equals<size_t>(0));
|
||||
|
|
@ -526,59 +526,59 @@ describe("Stack", [&]() {
|
|||
|
||||
describe("setting external token state", [&]() {
|
||||
before_each([&]() {
|
||||
trees[1]->has_external_tokens = true;
|
||||
trees[2]->has_external_tokens = true;
|
||||
ts_external_token_state_init(&trees[1]->external_token_state, NULL, 0);
|
||||
ts_external_token_state_init(&trees[2]->external_token_state, NULL, 0);
|
||||
subtrees[1]->has_external_tokens = true;
|
||||
subtrees[2]->has_external_tokens = true;
|
||||
ts_external_token_state_init(&subtrees[1]->external_token_state, NULL, 0);
|
||||
ts_external_token_state_init(&subtrees[2]->external_token_state, NULL, 0);
|
||||
});
|
||||
|
||||
it("allows the state to be retrieved", [&]() {
|
||||
AssertThat(ts_stack_last_external_token(stack, 0), Equals<Tree *>(nullptr));
|
||||
AssertThat(ts_stack_last_external_token(stack, 0), Equals<Subtree *>(nullptr));
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
AssertThat(ts_stack_last_external_token(stack, 0), Equals(trees[1]));
|
||||
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
|
||||
AssertThat(ts_stack_last_external_token(stack, 0), Equals(subtrees[1]));
|
||||
|
||||
ts_stack_copy_version(stack, 0);
|
||||
AssertThat(ts_stack_last_external_token(stack, 1), Equals(trees[1]));
|
||||
AssertThat(ts_stack_last_external_token(stack, 1), Equals(subtrees[1]));
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[2]);
|
||||
AssertThat(ts_stack_last_external_token(stack, 0), Equals(trees[2]));
|
||||
ts_stack_set_last_external_token(stack, 0, subtrees[2]);
|
||||
AssertThat(ts_stack_last_external_token(stack, 0), Equals(subtrees[2]));
|
||||
});
|
||||
|
||||
it("does not merge stack versions with different external token states", [&]() {
|
||||
ts_external_token_state_init(&trees[1]->external_token_state, "abcd", 2);
|
||||
ts_external_token_state_init(&trees[2]->external_token_state, "ABCD", 2);
|
||||
ts_external_token_state_init(&subtrees[1]->external_token_state, "abcd", 2);
|
||||
ts_external_token_state_init(&subtrees[2]->external_token_state, "ABCD", 2);
|
||||
|
||||
ts_stack_copy_version(stack, 0);
|
||||
push(0, trees[0], 5);
|
||||
push(1, trees[0], 5);
|
||||
push(0, subtrees[0], 5);
|
||||
push(1, subtrees[0], 5);
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
ts_stack_set_last_external_token(stack, 1, trees[2]);
|
||||
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
|
||||
ts_stack_set_last_external_token(stack, 1, subtrees[2]);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsFalse());
|
||||
});
|
||||
|
||||
it("merges stack versions with identical external token states", [&]() {
|
||||
ts_external_token_state_init(&trees[1]->external_token_state, "abcd", 2);
|
||||
ts_external_token_state_init(&trees[2]->external_token_state, "abcd", 2);
|
||||
ts_external_token_state_init(&subtrees[1]->external_token_state, "abcd", 2);
|
||||
ts_external_token_state_init(&subtrees[2]->external_token_state, "abcd", 2);
|
||||
|
||||
ts_stack_copy_version(stack, 0);
|
||||
push(0, trees[0], 5);
|
||||
push(1, trees[0], 5);
|
||||
push(0, subtrees[0], 5);
|
||||
push(1, subtrees[0], 5);
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
ts_stack_set_last_external_token(stack, 1, trees[2]);
|
||||
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
|
||||
ts_stack_set_last_external_token(stack, 1, subtrees[2]);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
|
||||
});
|
||||
|
||||
it("does not distinguish between an *empty* external token state and *no* external token state", [&]() {
|
||||
ts_stack_copy_version(stack, 0);
|
||||
push(0, trees[0], 5);
|
||||
push(1, trees[0], 5);
|
||||
push(0, subtrees[0], 5);
|
||||
push(1, subtrees[0], 5);
|
||||
|
||||
ts_stack_set_last_external_token(stack, 0, trees[1]);
|
||||
ts_stack_set_last_external_token(stack, 0, subtrees[1]);
|
||||
|
||||
AssertThat(ts_stack_merge(stack, 0, 1), IsTrue());
|
||||
});
|
||||
|
|
@ -595,7 +595,7 @@ std::ostream &operator<<(std::ostream &stream, const StackEntry &entry) {
|
|||
return stream << "{" << entry.state << ", " << entry.depth << "}";
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const TreeArray &array) {
|
||||
std::ostream &operator<<(std::ostream &stream, const SubtreeArray &array) {
|
||||
stream << "[";
|
||||
bool first = true;
|
||||
for (size_t i = 0; i < array.size; i++) {
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
#include "test_helper.h"
|
||||
#include "helpers/tree_helpers.h"
|
||||
#include "helpers/point_helpers.h"
|
||||
#include "runtime/tree.h"
|
||||
#include "runtime/subtree.h"
|
||||
#include "runtime/length.h"
|
||||
|
||||
void assert_consistent(const Tree *tree) {
|
||||
void assert_consistent(const Subtree *tree) {
|
||||
if (tree->child_count == 0) return;
|
||||
AssertThat(tree->children.contents[0]->padding, Equals<Length>(tree->padding));
|
||||
|
||||
Length total_children_size = length_zero();
|
||||
for (size_t i = 0; i < tree->children.size; i++) {
|
||||
Tree *child = tree->children.contents[i];
|
||||
Subtree *child = tree->children.contents[i];
|
||||
assert_consistent(child);
|
||||
total_children_size = length_add(total_children_size, ts_tree_total_size(child));
|
||||
total_children_size = length_add(total_children_size, ts_subtree_total_size(child));
|
||||
}
|
||||
|
||||
AssertThat(total_children_size, Equals<Length>(ts_tree_total_size(tree)));
|
||||
AssertThat(total_children_size, Equals<Length>(ts_subtree_total_size(tree)));
|
||||
};
|
||||
|
||||
START_TEST
|
||||
|
||||
describe("Tree", []() {
|
||||
describe("Subtree", []() {
|
||||
enum {
|
||||
symbol1 = 1,
|
||||
symbol2,
|
||||
|
|
@ -38,29 +38,29 @@ describe("Tree", []() {
|
|||
TSLanguage language;
|
||||
language.symbol_metadata = metadata_list;
|
||||
|
||||
TreePool pool;
|
||||
SubtreePool pool;
|
||||
|
||||
before_each([&]() {
|
||||
ts_tree_pool_init(&pool);
|
||||
ts_subtree_pool_init(&pool);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_pool_delete(&pool);
|
||||
ts_subtree_pool_delete(&pool);
|
||||
});
|
||||
|
||||
describe("make_leaf", [&]() {
|
||||
it("does not mark the tree as fragile", [&]() {
|
||||
Tree *tree = ts_tree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
|
||||
Subtree *tree = ts_subtree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
|
||||
AssertThat(tree->fragile_left, IsFalse());
|
||||
AssertThat(tree->fragile_right, IsFalse());
|
||||
|
||||
ts_tree_release(&pool, tree);
|
||||
ts_subtree_release(&pool, tree);
|
||||
});
|
||||
});
|
||||
|
||||
describe("make_error", [&]() {
|
||||
it("marks the tree as fragile", [&]() {
|
||||
Tree *error_tree = ts_tree_make_error(
|
||||
Subtree *error_tree = ts_subtree_make_error(
|
||||
&pool,
|
||||
length_zero(),
|
||||
length_zero(),
|
||||
|
|
@ -71,29 +71,29 @@ describe("Tree", []() {
|
|||
AssertThat(error_tree->fragile_left, IsTrue());
|
||||
AssertThat(error_tree->fragile_right, IsTrue());
|
||||
|
||||
ts_tree_release(&pool, error_tree);
|
||||
ts_subtree_release(&pool, error_tree);
|
||||
});
|
||||
});
|
||||
|
||||
describe("make_node", [&]() {
|
||||
Tree *tree1, *tree2, *parent1;
|
||||
Subtree *tree1, *tree2, *parent1;
|
||||
|
||||
before_each([&]() {
|
||||
tree1 = ts_tree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
|
||||
tree2 = ts_tree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
|
||||
tree1 = ts_subtree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
|
||||
tree2 = ts_subtree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
|
||||
|
||||
ts_tree_retain(tree1);
|
||||
ts_tree_retain(tree2);
|
||||
parent1 = ts_tree_make_node(&pool, symbol3, tree_array({
|
||||
ts_subtree_retain(tree1);
|
||||
ts_subtree_retain(tree2);
|
||||
parent1 = ts_subtree_make_node(&pool, symbol3, tree_array({
|
||||
tree1,
|
||||
tree2,
|
||||
}), 0, &language);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_release(&pool, tree1);
|
||||
ts_tree_release(&pool, tree2);
|
||||
ts_tree_release(&pool, parent1);
|
||||
ts_subtree_release(&pool, tree1);
|
||||
ts_subtree_release(&pool, tree2);
|
||||
ts_subtree_release(&pool, parent1);
|
||||
});
|
||||
|
||||
it("computes its size and padding based on its child nodes", [&]() {
|
||||
|
|
@ -104,22 +104,22 @@ describe("Tree", []() {
|
|||
});
|
||||
|
||||
describe("when the first node is fragile on the left side", [&]() {
|
||||
Tree *parent;
|
||||
Subtree *parent;
|
||||
|
||||
before_each([&]() {
|
||||
tree1->fragile_left = true;
|
||||
tree1->extra = true;
|
||||
|
||||
ts_tree_retain(tree1);
|
||||
ts_tree_retain(tree2);
|
||||
parent = ts_tree_make_node(&pool, symbol3, tree_array({
|
||||
ts_subtree_retain(tree1);
|
||||
ts_subtree_retain(tree2);
|
||||
parent = ts_subtree_make_node(&pool, symbol3, tree_array({
|
||||
tree1,
|
||||
tree2,
|
||||
}), 0, &language);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_release(&pool, parent);
|
||||
ts_subtree_release(&pool, parent);
|
||||
});
|
||||
|
||||
it("records that it is fragile on the left side", [&]() {
|
||||
|
|
@ -128,22 +128,22 @@ describe("Tree", []() {
|
|||
});
|
||||
|
||||
describe("when the last node is fragile on the right side", [&]() {
|
||||
Tree *parent;
|
||||
Subtree *parent;
|
||||
|
||||
before_each([&]() {
|
||||
tree2->fragile_right = true;
|
||||
tree2->extra = true;
|
||||
|
||||
ts_tree_retain(tree1);
|
||||
ts_tree_retain(tree2);
|
||||
parent = ts_tree_make_node(&pool, symbol3, tree_array({
|
||||
ts_subtree_retain(tree1);
|
||||
ts_subtree_retain(tree2);
|
||||
parent = ts_subtree_make_node(&pool, symbol3, tree_array({
|
||||
tree1,
|
||||
tree2,
|
||||
}), 0, &language);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_release(&pool, parent);
|
||||
ts_subtree_release(&pool, parent);
|
||||
});
|
||||
|
||||
it("records that it is fragile on the right side", [&]() {
|
||||
|
|
@ -152,22 +152,22 @@ describe("Tree", []() {
|
|||
});
|
||||
|
||||
describe("when the outer nodes aren't fragile on their outer side", [&]() {
|
||||
Tree *parent;
|
||||
Subtree *parent;
|
||||
|
||||
before_each([&]() {
|
||||
tree1->fragile_right = true;
|
||||
tree2->fragile_left = true;
|
||||
|
||||
ts_tree_retain(tree1);
|
||||
ts_tree_retain(tree2);
|
||||
parent = ts_tree_make_node(&pool, symbol3, tree_array({
|
||||
ts_subtree_retain(tree1);
|
||||
ts_subtree_retain(tree2);
|
||||
parent = ts_subtree_make_node(&pool, symbol3, tree_array({
|
||||
tree1,
|
||||
tree2,
|
||||
}), 0, &language);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_release(&pool, parent);
|
||||
ts_subtree_release(&pool, parent);
|
||||
});
|
||||
|
||||
it("records that it is not fragile", [&]() {
|
||||
|
|
@ -178,13 +178,13 @@ describe("Tree", []() {
|
|||
});
|
||||
|
||||
describe("edit", [&]() {
|
||||
Tree *tree;
|
||||
Subtree *tree;
|
||||
|
||||
before_each([&]() {
|
||||
tree = ts_tree_make_node(&pool, symbol1, tree_array({
|
||||
ts_tree_make_leaf(&pool, symbol2, {2, {0, 2}}, {3, {0, 3}}, &language),
|
||||
ts_tree_make_leaf(&pool, symbol3, {2, {0, 2}}, {3, {0, 3}}, &language),
|
||||
ts_tree_make_leaf(&pool, symbol4, {2, {0, 2}}, {3, {0, 3}}, &language),
|
||||
tree = ts_subtree_make_node(&pool, symbol1, tree_array({
|
||||
ts_subtree_make_leaf(&pool, symbol2, {2, {0, 2}}, {3, {0, 3}}, &language),
|
||||
ts_subtree_make_leaf(&pool, symbol3, {2, {0, 2}}, {3, {0, 3}}, &language),
|
||||
ts_subtree_make_leaf(&pool, symbol4, {2, {0, 2}}, {3, {0, 3}}, &language),
|
||||
}), 0, &language);
|
||||
|
||||
AssertThat(tree->padding, Equals<Length>({2, {0, 2}}));
|
||||
|
|
@ -192,7 +192,7 @@ describe("Tree", []() {
|
|||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_release(&pool, tree);
|
||||
ts_subtree_release(&pool, tree);
|
||||
});
|
||||
|
||||
it("does not mutate the argument", [&]() {
|
||||
|
|
@ -204,8 +204,8 @@ describe("Tree", []() {
|
|||
edit.extent_removed = {0, 0};
|
||||
edit.extent_added = {0, 1};
|
||||
|
||||
ts_tree_retain(tree);
|
||||
Tree *new_tree = ts_tree_edit(tree, &edit, &pool);
|
||||
ts_subtree_retain(tree);
|
||||
Subtree *new_tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
assert_consistent(new_tree);
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ describe("Tree", []() {
|
|||
AssertThat(tree->children.contents[1]->padding, Equals<Length>({2, {0, 2}}));
|
||||
AssertThat(tree->children.contents[1]->size, Equals<Length>({3, {0, 3}}));
|
||||
|
||||
ts_tree_release(&pool, new_tree);
|
||||
ts_subtree_release(&pool, new_tree);
|
||||
});
|
||||
|
||||
describe("edits within a tree's padding", [&]() {
|
||||
|
|
@ -233,7 +233,7 @@ describe("Tree", []() {
|
|||
edit.start_point = {0, 1};
|
||||
edit.extent_removed = {0, 0};
|
||||
edit.extent_added = {0, 1};
|
||||
tree = ts_tree_edit(tree, &edit, &pool);
|
||||
tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
|
||||
AssertThat(tree->has_changes, IsTrue());
|
||||
|
|
@ -259,7 +259,7 @@ describe("Tree", []() {
|
|||
edit.start_point = {0, 1};
|
||||
edit.extent_removed = {0, 3};
|
||||
edit.extent_added = {0, 4};
|
||||
tree = ts_tree_edit(tree, &edit, &pool);
|
||||
tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
|
||||
AssertThat(tree->has_changes, IsTrue());
|
||||
|
|
@ -281,7 +281,7 @@ describe("Tree", []() {
|
|||
edit.start_point = {0, 2};
|
||||
edit.extent_removed = {0, 0};
|
||||
edit.extent_added = {0, 2};
|
||||
tree = ts_tree_edit(tree, &edit, &pool);
|
||||
tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
|
||||
AssertThat(tree->has_changes, IsTrue());
|
||||
|
|
@ -305,7 +305,7 @@ describe("Tree", []() {
|
|||
edit.start_point = {0, 2};
|
||||
edit.extent_removed = {0, 2};
|
||||
edit.extent_added = {0, 5};
|
||||
tree = ts_tree_edit(tree, &edit, &pool);
|
||||
tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
|
||||
AssertThat(tree->has_changes, IsTrue());
|
||||
|
|
@ -329,7 +329,7 @@ describe("Tree", []() {
|
|||
edit.start_point = {0, 1};
|
||||
edit.extent_removed = {0, 10};
|
||||
edit.extent_added = {0, 3};
|
||||
tree = ts_tree_edit(tree, &edit, &pool);
|
||||
tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
|
||||
AssertThat(tree->has_changes, IsTrue());
|
||||
|
|
@ -361,7 +361,7 @@ describe("Tree", []() {
|
|||
edit.start_point = {0, 6};
|
||||
edit.extent_removed = {0, 1};
|
||||
edit.extent_added = {0, 1};
|
||||
tree = ts_tree_edit(tree, &edit, &pool);
|
||||
tree = ts_subtree_edit(tree, &edit, &pool);
|
||||
assert_consistent(tree);
|
||||
|
||||
AssertThat(tree->children.contents[0]->has_changes, IsTrue());
|
||||
|
|
@ -370,43 +370,43 @@ describe("Tree", []() {
|
|||
});
|
||||
|
||||
describe("eq", [&]() {
|
||||
Tree *leaf;
|
||||
Subtree *leaf;
|
||||
|
||||
before_each([&]() {
|
||||
leaf = ts_tree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
|
||||
leaf = ts_subtree_make_leaf(&pool, symbol1, {2, {0, 1}}, {5, {0, 4}}, &language);
|
||||
});
|
||||
|
||||
after_each([&]() {
|
||||
ts_tree_release(&pool, leaf);
|
||||
ts_subtree_release(&pool, leaf);
|
||||
});
|
||||
|
||||
it("returns true for identical trees", [&]() {
|
||||
Tree *leaf_copy = ts_tree_make_leaf(&pool, symbol1, {2, {1, 1}}, {5, {1, 4}}, &language);
|
||||
AssertThat(ts_tree_eq(leaf, leaf_copy), IsTrue());
|
||||
Subtree *leaf_copy = ts_subtree_make_leaf(&pool, symbol1, {2, {1, 1}}, {5, {1, 4}}, &language);
|
||||
AssertThat(ts_subtree_eq(leaf, leaf_copy), IsTrue());
|
||||
|
||||
Tree *parent = ts_tree_make_node(&pool, symbol2, tree_array({
|
||||
Subtree *parent = ts_subtree_make_node(&pool, symbol2, tree_array({
|
||||
leaf,
|
||||
leaf_copy,
|
||||
}), 0, &language);
|
||||
ts_tree_retain(leaf);
|
||||
ts_tree_retain(leaf_copy);
|
||||
ts_subtree_retain(leaf);
|
||||
ts_subtree_retain(leaf_copy);
|
||||
|
||||
Tree *parent_copy = ts_tree_make_node(&pool, symbol2, tree_array({
|
||||
Subtree *parent_copy = ts_subtree_make_node(&pool, symbol2, tree_array({
|
||||
leaf,
|
||||
leaf_copy,
|
||||
}), 0, &language);
|
||||
ts_tree_retain(leaf);
|
||||
ts_tree_retain(leaf_copy);
|
||||
ts_subtree_retain(leaf);
|
||||
ts_subtree_retain(leaf_copy);
|
||||
|
||||
AssertThat(ts_tree_eq(parent, parent_copy), IsTrue());
|
||||
AssertThat(ts_subtree_eq(parent, parent_copy), IsTrue());
|
||||
|
||||
ts_tree_release(&pool, leaf_copy);
|
||||
ts_tree_release(&pool, parent);
|
||||
ts_tree_release(&pool, parent_copy);
|
||||
ts_subtree_release(&pool, leaf_copy);
|
||||
ts_subtree_release(&pool, parent);
|
||||
ts_subtree_release(&pool, parent_copy);
|
||||
});
|
||||
|
||||
it("returns false for trees with different symbols", [&]() {
|
||||
Tree *different_leaf = ts_tree_make_leaf(
|
||||
Subtree *different_leaf = ts_subtree_make_leaf(
|
||||
&pool,
|
||||
leaf->symbol + 1,
|
||||
leaf->padding,
|
||||
|
|
@ -414,50 +414,50 @@ describe("Tree", []() {
|
|||
&language
|
||||
);
|
||||
|
||||
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_tree_release(&pool, different_leaf);
|
||||
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_subtree_release(&pool, different_leaf);
|
||||
});
|
||||
|
||||
it("returns false for trees with different options", [&]() {
|
||||
Tree *different_leaf = ts_tree_make_leaf(&pool, leaf->symbol, leaf->padding, leaf->size, &language);
|
||||
Subtree *different_leaf = ts_subtree_make_leaf(&pool, leaf->symbol, leaf->padding, leaf->size, &language);
|
||||
different_leaf->visible = !leaf->visible;
|
||||
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_tree_release(&pool, different_leaf);
|
||||
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_subtree_release(&pool, different_leaf);
|
||||
});
|
||||
|
||||
it("returns false for trees with different paddings or sizes", [&]() {
|
||||
Tree *different_leaf = ts_tree_make_leaf(&pool, leaf->symbol, {}, leaf->size, &language);
|
||||
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_tree_release(&pool, different_leaf);
|
||||
Subtree *different_leaf = ts_subtree_make_leaf(&pool, leaf->symbol, {}, leaf->size, &language);
|
||||
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_subtree_release(&pool, different_leaf);
|
||||
|
||||
different_leaf = ts_tree_make_leaf(&pool, symbol1, leaf->padding, {}, &language);
|
||||
AssertThat(ts_tree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_tree_release(&pool, different_leaf);
|
||||
different_leaf = ts_subtree_make_leaf(&pool, symbol1, leaf->padding, {}, &language);
|
||||
AssertThat(ts_subtree_eq(leaf, different_leaf), IsFalse());
|
||||
ts_subtree_release(&pool, different_leaf);
|
||||
});
|
||||
|
||||
it("returns false for trees with different children", [&]() {
|
||||
Tree *leaf2 = ts_tree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
|
||||
Subtree *leaf2 = ts_subtree_make_leaf(&pool, symbol2, {1, {0, 1}}, {3, {0, 3}}, &language);
|
||||
|
||||
Tree *parent = ts_tree_make_node(&pool, symbol2, tree_array({
|
||||
Subtree *parent = ts_subtree_make_node(&pool, symbol2, tree_array({
|
||||
leaf,
|
||||
leaf2,
|
||||
}), 0, &language);
|
||||
ts_tree_retain(leaf);
|
||||
ts_tree_retain(leaf2);
|
||||
ts_subtree_retain(leaf);
|
||||
ts_subtree_retain(leaf2);
|
||||
|
||||
Tree *different_parent = ts_tree_make_node(&pool, symbol2, tree_array({
|
||||
Subtree *different_parent = ts_subtree_make_node(&pool, symbol2, tree_array({
|
||||
leaf2,
|
||||
leaf,
|
||||
}), 0, &language);
|
||||
ts_tree_retain(leaf2);
|
||||
ts_tree_retain(leaf);
|
||||
ts_subtree_retain(leaf2);
|
||||
ts_subtree_retain(leaf);
|
||||
|
||||
AssertThat(ts_tree_eq(different_parent, parent), IsFalse());
|
||||
AssertThat(ts_tree_eq(parent, different_parent), IsFalse());
|
||||
AssertThat(ts_subtree_eq(different_parent, parent), IsFalse());
|
||||
AssertThat(ts_subtree_eq(parent, different_parent), IsFalse());
|
||||
|
||||
ts_tree_release(&pool, leaf2);
|
||||
ts_tree_release(&pool, parent);
|
||||
ts_tree_release(&pool, different_parent);
|
||||
ts_subtree_release(&pool, leaf2);
|
||||
ts_subtree_release(&pool, parent);
|
||||
ts_subtree_release(&pool, different_parent);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -465,32 +465,32 @@ describe("Tree", []() {
|
|||
Length padding = {1, {0, 1}};
|
||||
Length size = {2, {0, 2}};
|
||||
|
||||
auto make_external = [](Tree *tree) {
|
||||
auto make_external = [](Subtree *tree) {
|
||||
tree->has_external_tokens = true;
|
||||
return tree;
|
||||
};
|
||||
|
||||
it("returns the last serialized external token state in the given tree", [&]() {
|
||||
Tree *tree1, *tree2, *tree3, *tree4, *tree5, *tree6, *tree7, *tree8, *tree9;
|
||||
Subtree *tree1, *tree2, *tree3, *tree4, *tree5, *tree6, *tree7, *tree8, *tree9;
|
||||
|
||||
tree1 = ts_tree_make_node(&pool, symbol1, tree_array({
|
||||
(tree2 = ts_tree_make_node(&pool, symbol2, tree_array({
|
||||
(tree3 = make_external(ts_tree_make_leaf(&pool, symbol3, padding, size, &language))),
|
||||
(tree4 = ts_tree_make_leaf(&pool, symbol4, padding, size, &language)),
|
||||
(tree5 = ts_tree_make_leaf(&pool, symbol5, padding, size, &language)),
|
||||
tree1 = ts_subtree_make_node(&pool, symbol1, tree_array({
|
||||
(tree2 = ts_subtree_make_node(&pool, symbol2, tree_array({
|
||||
(tree3 = make_external(ts_subtree_make_leaf(&pool, symbol3, padding, size, &language))),
|
||||
(tree4 = ts_subtree_make_leaf(&pool, symbol4, padding, size, &language)),
|
||||
(tree5 = ts_subtree_make_leaf(&pool, symbol5, padding, size, &language)),
|
||||
}), 0, &language)),
|
||||
(tree6 = ts_tree_make_node(&pool, symbol6, tree_array({
|
||||
(tree7 = ts_tree_make_node(&pool, symbol7, tree_array({
|
||||
(tree8 = ts_tree_make_leaf(&pool, symbol8, padding, size, &language)),
|
||||
(tree6 = ts_subtree_make_node(&pool, symbol6, tree_array({
|
||||
(tree7 = ts_subtree_make_node(&pool, symbol7, tree_array({
|
||||
(tree8 = ts_subtree_make_leaf(&pool, symbol8, padding, size, &language)),
|
||||
}), 0, &language)),
|
||||
(tree9 = ts_tree_make_leaf(&pool, symbol9, padding, size, &language)),
|
||||
(tree9 = ts_subtree_make_leaf(&pool, symbol9, padding, size, &language)),
|
||||
}), 0, &language)),
|
||||
}), 0, &language);
|
||||
|
||||
auto token = ts_tree_last_external_token(tree1);
|
||||
auto token = ts_subtree_last_external_token(tree1);
|
||||
AssertThat(token, Equals(tree3));
|
||||
|
||||
ts_tree_release(&pool, tree1);
|
||||
ts_subtree_release(&pool, tree1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
'test/runtime/node_test.cc',
|
||||
'test/runtime/parser_test.cc',
|
||||
'test/runtime/stack_test.cc',
|
||||
'test/runtime/tree_test.cc',
|
||||
'test/runtime/subtree_test.cc',
|
||||
'test/tests.cc',
|
||||
],
|
||||
'cflags': [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue