Updated stuff to be more normed
This commit is contained in:
parent
2247d3662e
commit
f6d6589a3a
39 changed files with 1838 additions and 1288 deletions
|
|
@ -1,5 +1,18 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* parser.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/09/02 20:48:07 by maiboyer #+# #+# */
|
||||
/* Updated: 2024/09/02 21:14:40 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "me/mem/mem.h"
|
||||
#include "me/types.h"
|
||||
#include "me/vec/vec_subtree.h"
|
||||
#include "parser/api.h"
|
||||
#include "parser/array.h"
|
||||
#include "parser/language.h"
|
||||
|
|
@ -30,9 +43,9 @@ struct TSParser
|
|||
const TSLanguage *language;
|
||||
ReduceActionSet reduce_actions;
|
||||
t_subtree finished_tree;
|
||||
SubtreeArray trailing_extras;
|
||||
SubtreeArray trailing_extras2;
|
||||
SubtreeArray scratch_trees;
|
||||
t_vec_subtree trailing_extras;
|
||||
t_vec_subtree trailing_extras2;
|
||||
t_vec_subtree scratch_trees;
|
||||
void *external_scanner_payload;
|
||||
t_u32 accept_count;
|
||||
t_u32 operation_count;
|
||||
|
|
@ -101,7 +114,7 @@ static bool ts_parser__breakdown_top_of_stack(TSParser *self, t_stack_version ve
|
|||
{
|
||||
t_stack_slice slice = pop.contents[i];
|
||||
TSStateId state = ts_stack_state(self->stack, slice.version);
|
||||
t_subtree parent = *array_front(&slice.subtrees);
|
||||
t_subtree parent = *slice.subtrees.buffer;
|
||||
|
||||
for (t_u32 j = 0, n = ts_subtree_child_count(parent); j < n; j++)
|
||||
{
|
||||
|
|
@ -121,9 +134,9 @@ static bool ts_parser__breakdown_top_of_stack(TSParser *self, t_stack_version ve
|
|||
ts_stack_push(self->stack, slice.version, child, pending, state);
|
||||
}
|
||||
|
||||
for (t_u32 j = 1; j < slice.subtrees.size; j++)
|
||||
for (t_u32 j = 1; j < slice.subtrees.len; j++)
|
||||
{
|
||||
t_subtree tree = slice.subtrees.contents[j];
|
||||
t_subtree tree = slice.subtrees.buffer[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, state);
|
||||
}
|
||||
|
||||
|
|
@ -505,17 +518,13 @@ static bool ts_parser__select_tree(TSParser *self, t_subtree left, t_subtree rig
|
|||
|
||||
// Determine if a given tree's children should be replaced by an alternative
|
||||
// array of children.
|
||||
static bool ts_parser__select_children(TSParser *self, t_subtree left, const SubtreeArray *children)
|
||||
static bool ts_parser__select_children(TSParser *self, t_subtree left, const t_vec_subtree *children)
|
||||
{
|
||||
array_assign(&self->scratch_trees, children);
|
||||
t_subtree scratch_tree;
|
||||
|
||||
// Create a temporary subtree using the scratch trees array. This node does
|
||||
// not perform any allocation except for possibly growing the array to make
|
||||
// room for its own heap data. The scratch tree is never explicitly released,
|
||||
// so the same 'scratch trees' array can be reused again later.
|
||||
t_subtree scratch_tree = ts_subtree_new_node(ts_subtree_symbol(left), &self->scratch_trees, 0, self->language);
|
||||
|
||||
return ts_parser__select_tree(self, left, (scratch_tree));
|
||||
vec_subtree_copy_into(&self->scratch_trees, (void *)children);
|
||||
scratch_tree = ts_subtree_new_node(ts_subtree_symbol(left), &self->scratch_trees, 0, self->language);
|
||||
return (ts_parser__select_tree(self, left, (scratch_tree)));
|
||||
}
|
||||
|
||||
static void ts_parser__shift(TSParser *self, t_stack_version version, TSStateId state, t_subtree lookahead, bool extra)
|
||||
|
|
@ -524,7 +533,7 @@ static void ts_parser__shift(TSParser *self, t_stack_version version, TSStateId
|
|||
t_subtree subtree_to_push = lookahead;
|
||||
if (extra != ts_subtree_extra(lookahead) && is_leaf)
|
||||
{
|
||||
t_subtree result = ts_subtree_make_mut(/*&self->tree_pool,*/ lookahead);
|
||||
t_subtree result = ts_subtree_ensure_owner(/*&self->tree_pool,*/ lookahead);
|
||||
ts_subtree_set_extra(&result, extra);
|
||||
subtree_to_push = (result);
|
||||
}
|
||||
|
|
@ -576,7 +585,7 @@ static t_stack_version ts_parser__reduce(TSParser *self, t_stack_version version
|
|||
// 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.
|
||||
SubtreeArray children = slice.subtrees;
|
||||
t_vec_subtree children = slice.subtrees;
|
||||
ts_subtree_array_remove_trailing_extras(&children, &self->trailing_extras);
|
||||
|
||||
t_subtree parent = ts_subtree_new_node(symbol, &children, production_id, self->language);
|
||||
|
|
@ -592,7 +601,7 @@ static t_stack_version ts_parser__reduce(TSParser *self, t_stack_version version
|
|||
break;
|
||||
i++;
|
||||
|
||||
SubtreeArray next_slice_children = next_slice.subtrees;
|
||||
t_vec_subtree next_slice_children = next_slice.subtrees;
|
||||
ts_subtree_array_remove_trailing_extras(&next_slice_children, &self->trailing_extras2);
|
||||
|
||||
if (ts_parser__select_children(self, (parent), &next_slice_children))
|
||||
|
|
@ -604,7 +613,7 @@ static t_stack_version ts_parser__reduce(TSParser *self, t_stack_version version
|
|||
}
|
||||
else
|
||||
{
|
||||
array_clear(&self->trailing_extras2);
|
||||
self->trailing_extras2.len = 0;
|
||||
ts_subtree_array_delete(/*&self->tree_pool,*/ &next_slice.subtrees);
|
||||
}
|
||||
}
|
||||
|
|
@ -630,9 +639,9 @@ static t_stack_version ts_parser__reduce(TSParser *self, t_stack_version version
|
|||
// 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 (t_u32 j = 0; j < self->trailing_extras.size; j++)
|
||||
for (t_u32 j = 0; j < self->trailing_extras.len; j++)
|
||||
{
|
||||
ts_stack_push(self->stack, slice_version, self->trailing_extras.contents[j], false, next_state);
|
||||
ts_stack_push(self->stack, slice_version, self->trailing_extras.buffer[j], false, next_state);
|
||||
}
|
||||
|
||||
for (t_stack_version j = 0; j < slice_version; j++)
|
||||
|
|
@ -659,46 +668,37 @@ static void ts_parser__accept(TSParser *self, t_stack_version version, t_subtree
|
|||
t_stack_slice_array pop = ts_stack_pop_all(self->stack, version);
|
||||
for (t_u32 i = 0; i < pop.size; i++)
|
||||
{
|
||||
SubtreeArray trees = pop.contents[i].subtrees;
|
||||
t_vec_subtree trees = pop.contents[i].subtrees;
|
||||
t_subtree root = NULL;
|
||||
|
||||
t_subtree root = NULL;
|
||||
for (t_u32 j = trees.size - 1; j + 1 > 0; j--)
|
||||
for (t_u32 j = trees.len - 1; j + 1 > 0; j--)
|
||||
{
|
||||
t_subtree tree = trees.contents[j];
|
||||
t_subtree tree = trees.buffer[j];
|
||||
if (!ts_subtree_extra(tree))
|
||||
{
|
||||
t_u32 child_count = ts_subtree_child_count(tree);
|
||||
const t_subtree *children = ts_subtree_children(tree);
|
||||
for (t_u32 k = 0; k < child_count; k++)
|
||||
{
|
||||
(children[k]->ref_count++);
|
||||
}
|
||||
array_splice(&trees, j, 1, child_count, children);
|
||||
children[k]->ref_count++;
|
||||
vec_subtree_splice(&trees, vec_subtree_splice_args(j, 1, child_count, children));
|
||||
root = (ts_subtree_new_node(ts_subtree_symbol(tree), &trees, tree->production_id, self->language));
|
||||
ts_subtree_release(/*&self->tree_pool, */ tree);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(root);
|
||||
self->accept_count++;
|
||||
|
||||
if (self->finished_tree)
|
||||
{
|
||||
if (ts_parser__select_tree(self, self->finished_tree, root))
|
||||
{
|
||||
ts_subtree_release(/*&self->tree_pool,*/ self->finished_tree);
|
||||
ts_subtree_release(self->finished_tree);
|
||||
self->finished_tree = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
ts_subtree_release(/*&self->tree_pool,*/ root);
|
||||
}
|
||||
ts_subtree_release(root);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->finished_tree = root;
|
||||
}
|
||||
}
|
||||
|
||||
ts_stack_remove_version(self->stack, pop.contents[0].version);
|
||||
|
|
@ -834,18 +834,17 @@ static bool ts_parser__recover_to_state(TSParser *self, t_stack_version version,
|
|||
continue;
|
||||
}
|
||||
|
||||
SubtreeArray error_trees = ts_stack_pop_error(self->stack, slice.version);
|
||||
if (error_trees.size > 0)
|
||||
t_vec_subtree error_trees = ts_stack_pop_error(self->stack, slice.version);
|
||||
if (error_trees.len > 0)
|
||||
{
|
||||
assert(error_trees.size == 1);
|
||||
t_subtree error_tree = error_trees.contents[0];
|
||||
t_subtree error_tree = error_trees.buffer[0];
|
||||
t_u32 error_child_count = ts_subtree_child_count(error_tree);
|
||||
if (error_child_count > 0)
|
||||
{
|
||||
array_splice(&slice.subtrees, 0, 0, error_child_count, ts_subtree_children(error_tree));
|
||||
vec_subtree_splice(&slice.subtrees, vec_subtree_splice_args(0, 0, error_child_count, ts_subtree_children(error_tree)));
|
||||
for (t_u32 j = 0; j < error_child_count; j++)
|
||||
{
|
||||
(slice.subtrees.contents[j]->ref_count++);
|
||||
(slice.subtrees.buffer[j]->ref_count++);
|
||||
}
|
||||
}
|
||||
ts_subtree_array_delete(/*&self->tree_pool,*/ &error_trees);
|
||||
|
|
@ -853,19 +852,19 @@ static bool ts_parser__recover_to_state(TSParser *self, t_stack_version version,
|
|||
|
||||
ts_subtree_array_remove_trailing_extras(&slice.subtrees, &self->trailing_extras);
|
||||
|
||||
if (slice.subtrees.size > 0)
|
||||
if (slice.subtrees.len > 0)
|
||||
{
|
||||
t_subtree error = ts_subtree_new_error_node(&slice.subtrees, true, self->language);
|
||||
ts_stack_push(self->stack, slice.version, error, false, goal_state);
|
||||
}
|
||||
else
|
||||
{
|
||||
array_delete(&slice.subtrees);
|
||||
vec_subtree_free(slice.subtrees);
|
||||
}
|
||||
|
||||
for (t_u32 j = 0; j < self->trailing_extras.size; j++)
|
||||
for (t_u32 j = 0; j < self->trailing_extras.len; j++)
|
||||
{
|
||||
t_subtree tree = self->trailing_extras.contents[j];
|
||||
t_subtree tree = self->trailing_extras.buffer[j];
|
||||
ts_stack_push(self->stack, slice.version, tree, false, goal_state);
|
||||
}
|
||||
|
||||
|
|
@ -976,7 +975,7 @@ static void ts_parser__recover(TSParser *self, t_stack_version version, t_subtre
|
|||
// in an ERROR node and terminate.
|
||||
if (ts_subtree_is_eof(lookahead))
|
||||
{
|
||||
SubtreeArray children = array_new();
|
||||
t_vec_subtree children = vec_subtree_new(16, NULL);
|
||||
t_subtree parent = ts_subtree_new_error_node(&children, false, self->language);
|
||||
ts_stack_push(self->stack, version, parent, false, 1);
|
||||
ts_parser__accept(self, version, lookahead);
|
||||
|
|
@ -999,15 +998,14 @@ static void ts_parser__recover(TSParser *self, t_stack_version version, t_subtre
|
|||
const TSParseAction *actions = ts_language_actions(self->language, 1, ts_subtree_symbol(lookahead), &n);
|
||||
if (n > 0 && actions[n - 1].type == TSParseActionTypeShift && actions[n - 1].shift.extra)
|
||||
{
|
||||
t_subtree mutable_lookahead = ts_subtree_make_mut(/*&self->tree_pool,*/ lookahead);
|
||||
t_subtree mutable_lookahead = ts_subtree_ensure_owner(/*&self->tree_pool,*/ lookahead);
|
||||
ts_subtree_set_extra(&mutable_lookahead, true);
|
||||
lookahead = (mutable_lookahead);
|
||||
}
|
||||
|
||||
// Wrap the lookahead token in an ERROR.
|
||||
SubtreeArray children = array_new();
|
||||
array_reserve(&children, 1);
|
||||
array_push(&children, lookahead);
|
||||
t_vec_subtree children = vec_subtree_new(1, NULL);
|
||||
vec_subtree_push(&children, lookahead);
|
||||
t_subtree error_repeat = ts_subtree_new_node(ts_builtin_sym_error_repeat, &children, 0, self->language);
|
||||
|
||||
// If other tokens have already been skipped, so there is already an ERROR at the top of the
|
||||
|
|
@ -1034,7 +1032,7 @@ static void ts_parser__recover(TSParser *self, t_stack_version version, t_subtre
|
|||
}
|
||||
|
||||
ts_stack_renumber_version(self->stack, pop.contents[0].version, version);
|
||||
array_push(&pop.contents[0].subtrees, (error_repeat));
|
||||
vec_subtree_push(&pop.contents[0].subtrees, (error_repeat));
|
||||
error_repeat = ts_subtree_new_node(ts_builtin_sym_error_repeat, &pop.contents[0].subtrees, 0, self->language);
|
||||
}
|
||||
|
||||
|
|
@ -1248,7 +1246,7 @@ static bool ts_parser__advance(TSParser *self, t_stack_version version, bool all
|
|||
ts_language_table_entry(self->language, state, self->language->keyword_capture_token, &table_entry);
|
||||
if (table_entry.action_count > 0)
|
||||
{
|
||||
t_subtree mutable_lookahead = ts_subtree_make_mut(/*&self->tree_pool,*/ lookahead);
|
||||
t_subtree mutable_lookahead = ts_subtree_ensure_owner(/*&self->tree_pool,*/ lookahead);
|
||||
ts_subtree_set_symbol(&mutable_lookahead, self->language->keyword_capture_token, self->language);
|
||||
lookahead = (mutable_lookahead);
|
||||
continue;
|
||||
|
|
@ -1526,7 +1524,6 @@ TSTree *ts_parser_parse(TSParser *self, TSInput input)
|
|||
|
||||
if (self->finished_tree == NULL)
|
||||
me_abort("self->finished_tree == NULL");
|
||||
ts_subtree_balance(self->finished_tree, self->language);
|
||||
result = ts_tree_new(self->finished_tree, self->language);
|
||||
self->finished_tree = NULL;
|
||||
ts_parser_reset(self);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ t_stack_version ts_stack__add_version(t_stack *self,
|
|||
}
|
||||
|
||||
void ts_stack__add_slice(t_stack *self, \
|
||||
t_stack_version original_version, t_stack_node *node, SubtreeArray *subtrees)
|
||||
t_stack_version original_version, t_stack_node *node, t_vec_subtree *subtrees)
|
||||
{
|
||||
t_u32 i;
|
||||
t_stack_version version;
|
||||
|
|
|
|||
|
|
@ -6,38 +6,38 @@
|
|||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/08/31 16:46:43 by maiboyer #+# #+# */
|
||||
/* Updated: 2024/08/31 16:47:21 by maiboyer ### ########.fr */
|
||||
/* Updated: 2024/09/02 21:22:19 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "me/vec/vec_subtree.h"
|
||||
#include "parser/inner/stack.h"
|
||||
#include "parser/stack.h"
|
||||
|
||||
t_stack_slice_array stack__iter(t_stack *self, t_stack_version version,
|
||||
t_stack_callback callback, void *payload, int goal_subtree_count)
|
||||
t_stack_slice_array stack__iter(t_stack *self, t_stack_version version, t_stack_callback callback, void *payload, int goal_subtree_count)
|
||||
{
|
||||
t_stack_head *head;
|
||||
bool include_subtrees;
|
||||
t_stack_iterator *iterator;
|
||||
t_stack_node *node;
|
||||
t_stack_action action;
|
||||
bool should_pop;
|
||||
bool should_stop;
|
||||
SubtreeArray subtrees;
|
||||
t_stack_iterator *next_iterator;
|
||||
t_stack_link link;
|
||||
t_stack_iterator current_iterator;
|
||||
t_stack_iterator new_iterator;
|
||||
t_usize i;
|
||||
t_usize j;
|
||||
t_usize size;
|
||||
t_stack_head *head;
|
||||
bool include_subtrees;
|
||||
t_stack_iterator *iterator;
|
||||
t_stack_node *node;
|
||||
t_stack_action action;
|
||||
bool should_pop;
|
||||
bool should_stop;
|
||||
t_vec_subtree subtrees;
|
||||
t_stack_iterator *next_iterator;
|
||||
t_stack_link link;
|
||||
t_stack_iterator current_iterator;
|
||||
t_stack_iterator new_iterator;
|
||||
t_usize i;
|
||||
t_usize j;
|
||||
t_usize size;
|
||||
|
||||
array_clear(&self->slices);
|
||||
array_clear(&self->iterators);
|
||||
head = array_get(&self->heads, version);
|
||||
new_iterator = (t_stack_iterator){
|
||||
.node = head->node,
|
||||
.subtrees = array_new(),
|
||||
.subtrees = vec_subtree_new(16, NULL),
|
||||
.subtree_count = 0,
|
||||
.is_pending = true,
|
||||
};
|
||||
|
|
@ -45,8 +45,7 @@ t_stack_slice_array stack__iter(t_stack *self, t_stack_version version,
|
|||
if (goal_subtree_count >= 0)
|
||||
{
|
||||
include_subtrees = true;
|
||||
array_reserve(&new_iterator.subtrees,
|
||||
(t_u32)ts_subtree_alloc_size(goal_subtree_count) / sizeof(t_subtree));
|
||||
vec_subtree_reserve(&new_iterator.subtrees, ts_subtree_alloc_size(goal_subtree_count) / sizeof(t_subtree));
|
||||
}
|
||||
array_push(&self->iterators, new_iterator);
|
||||
while (self->iterators.size > 0)
|
||||
|
|
@ -65,7 +64,7 @@ t_stack_slice_array stack__iter(t_stack *self, t_stack_version version,
|
|||
subtrees = iterator->subtrees;
|
||||
if (!should_stop)
|
||||
ts_subtree_array_copy(subtrees, &subtrees);
|
||||
ts_subtree_array_reverse(&subtrees);
|
||||
vec_subtree_reverse(&subtrees);
|
||||
ts_stack__add_slice(self, version, node, &subtrees);
|
||||
}
|
||||
if (should_stop)
|
||||
|
|
@ -76,7 +75,7 @@ t_stack_slice_array stack__iter(t_stack *self, t_stack_version version,
|
|||
i--;
|
||||
i++;
|
||||
size--;
|
||||
continue ;
|
||||
continue;
|
||||
}
|
||||
j = 1;
|
||||
while (j <= node->link_count)
|
||||
|
|
@ -91,22 +90,21 @@ t_stack_slice_array stack__iter(t_stack *self, t_stack_version version,
|
|||
if (self->iterators.size >= MAX_ITERATOR_COUNT)
|
||||
{
|
||||
j++;
|
||||
continue ;
|
||||
continue;
|
||||
}
|
||||
link = node->links[j];
|
||||
current_iterator = self->iterators.contents[i];
|
||||
array_push(&self->iterators, current_iterator);
|
||||
next_iterator = array_back(&self->iterators);
|
||||
ts_subtree_array_copy(next_iterator->subtrees,
|
||||
&next_iterator->subtrees);
|
||||
ts_subtree_array_copy(next_iterator->subtrees, &next_iterator->subtrees);
|
||||
}
|
||||
next_iterator->node = link.node;
|
||||
if (link.subtree)
|
||||
{
|
||||
if (include_subtrees)
|
||||
{
|
||||
array_push(&next_iterator->subtrees, link.subtree);
|
||||
(link.subtree->ref_count++);
|
||||
vec_subtree_push(&next_iterator->subtrees, link.subtree);
|
||||
link.subtree->ref_count++;
|
||||
}
|
||||
if (!ts_subtree_extra(link.subtree))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/08/31 17:00:07 by maiboyer #+# #+# */
|
||||
/* Updated: 2024/08/31 17:00:41 by maiboyer ### ########.fr */
|
||||
/* Updated: 2024/09/02 20:53:54 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
|
@ -18,11 +18,11 @@ t_stack_action pop_error_callback(void *payload,
|
|||
{
|
||||
bool *found_error;
|
||||
|
||||
if (iterator->subtrees.size > 0)
|
||||
if (iterator->subtrees.len > 0)
|
||||
{
|
||||
found_error = payload;
|
||||
if (!*found_error
|
||||
&& ts_subtree_is_error(iterator->subtrees.contents[0]))
|
||||
&& ts_subtree_is_error(iterator->subtrees.buffer[0]))
|
||||
{
|
||||
*found_error = true;
|
||||
return (SActionPop | SActionStop);
|
||||
|
|
@ -34,7 +34,7 @@ t_stack_action pop_error_callback(void *payload,
|
|||
return (SActionNone);
|
||||
}
|
||||
|
||||
SubtreeArray ts_stack_pop_error(t_stack *self, t_stack_version version)
|
||||
t_vec_subtree ts_stack_pop_error(t_stack *self, t_stack_version version)
|
||||
{
|
||||
t_stack_node *node;
|
||||
bool found_error;
|
||||
|
|
@ -62,7 +62,7 @@ SubtreeArray ts_stack_pop_error(t_stack *self, t_stack_version version)
|
|||
}
|
||||
i++;
|
||||
}
|
||||
return ((SubtreeArray){.size = 0});
|
||||
return ((t_vec_subtree){NULL, 0, 0, NULL});
|
||||
}
|
||||
|
||||
t_stack_action pop_all_callback(void *payload,
|
||||
|
|
|
|||
|
|
@ -3,97 +3,94 @@
|
|||
|
||||
#include "me/mem/mem.h"
|
||||
#include "me/types.h"
|
||||
#include "me/vec/vec_subtree.h"
|
||||
#include "parser/array.h"
|
||||
#include "parser/external_scanner_state.h"
|
||||
#include "parser/language.h"
|
||||
#include "parser/length.h"
|
||||
#include "parser/subtree.h"
|
||||
|
||||
void ts_subtree_array_copy(SubtreeArray self, SubtreeArray *dest)
|
||||
void ts_subtree_array_copy(t_vec_subtree self, t_vec_subtree *dest)
|
||||
{
|
||||
dest->size = self.size;
|
||||
t_usize i;
|
||||
|
||||
dest->len = self.len;
|
||||
dest->capacity = self.capacity;
|
||||
dest->contents = self.contents;
|
||||
dest->buffer = self.buffer;
|
||||
if (self.capacity > 0)
|
||||
{
|
||||
dest->contents = mem_alloc_array(self.capacity, sizeof(t_subtree));
|
||||
mem_copy(dest->contents, self.contents, self.size * sizeof(t_subtree));
|
||||
for (t_u32 i = 0; i < self.size; i++)
|
||||
(dest->contents[i]->ref_count++);
|
||||
dest->buffer = mem_alloc_array(self.capacity, sizeof(t_subtree));
|
||||
mem_copy(dest->buffer, self.buffer, self.len * sizeof(t_subtree));
|
||||
i = 0;
|
||||
while (i < self.len)
|
||||
dest->buffer[i++]->ref_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void ts_subtree_array_clear(SubtreeArray *self)
|
||||
void ts_subtree_array_clear(t_vec_subtree *self)
|
||||
{
|
||||
for (t_u32 i = 0; i < self->size; i++)
|
||||
ts_subtree_release(self->contents[i]);
|
||||
array_clear(self);
|
||||
t_usize i;
|
||||
i = 0;
|
||||
while (i < self->len)
|
||||
ts_subtree_release(self->buffer[i++]);
|
||||
}
|
||||
|
||||
void ts_subtree_array_delete(SubtreeArray *self)
|
||||
void ts_subtree_array_delete(t_vec_subtree *self)
|
||||
{
|
||||
ts_subtree_array_clear(self);
|
||||
array_delete(self);
|
||||
vec_subtree_free(*self);
|
||||
}
|
||||
|
||||
void ts_subtree_array_remove_trailing_extras(SubtreeArray *self, SubtreeArray *destination)
|
||||
void ts_subtree_array_remove_trailing_extras(t_vec_subtree *self, t_vec_subtree *destination)
|
||||
{
|
||||
array_clear(destination);
|
||||
while (self->size > 0)
|
||||
t_subtree last;
|
||||
|
||||
destination->len = 0;
|
||||
while (self->len > 0)
|
||||
{
|
||||
t_subtree last = self->contents[self->size - 1];
|
||||
last = self->buffer[self->len - 1];
|
||||
if (ts_subtree_extra(last))
|
||||
{
|
||||
self->size--;
|
||||
array_push(destination, last);
|
||||
self->len--;
|
||||
vec_subtree_push(destination, last);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
ts_subtree_array_reverse(destination);
|
||||
}
|
||||
|
||||
void ts_subtree_array_reverse(SubtreeArray *self)
|
||||
{
|
||||
for (t_u32 i = 0, limit = self->size / 2; i < limit; i++)
|
||||
{
|
||||
size_t reverse_index = self->size - 1 - i;
|
||||
t_subtree swap = self->contents[i];
|
||||
self->contents[i] = self->contents[reverse_index];
|
||||
self->contents[reverse_index] = swap;
|
||||
}
|
||||
vec_subtree_reverse(destination);
|
||||
}
|
||||
|
||||
t_subtree ts_subtree_new_leaf(TSSymbol symbol, Length padding, Length size, t_u32 lookahead_bytes, TSStateId parse_state,
|
||||
bool has_external_tokens, bool depends_on_column, bool is_keyword, const TSLanguage *language)
|
||||
{
|
||||
TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
|
||||
bool extra = symbol == ts_builtin_sym_end;
|
||||
TSSymbolMetadata metadata;
|
||||
bool extra;
|
||||
t_subtree_data *data;
|
||||
|
||||
{
|
||||
t_subtree_data *data = mem_alloc(sizeof(*data));
|
||||
*data = (t_subtree_data){.ref_count = 1,
|
||||
.padding = padding,
|
||||
.size = size,
|
||||
.lookahead_bytes = lookahead_bytes,
|
||||
.error_cost = 0,
|
||||
.child_count = 0,
|
||||
.symbol = symbol,
|
||||
.parse_state = parse_state,
|
||||
.visible = metadata.visible,
|
||||
.named = metadata.named,
|
||||
.extra = extra,
|
||||
.fragile_left = false,
|
||||
.fragile_right = false,
|
||||
.has_changes = false,
|
||||
.has_external_tokens = has_external_tokens,
|
||||
.has_external_scanner_state_change = false,
|
||||
.depends_on_column = depends_on_column,
|
||||
.is_missing = false,
|
||||
.is_keyword = is_keyword,
|
||||
{{.first_leaf = {.symbol = 0, .parse_state = 0}}}};
|
||||
return (t_subtree)data;
|
||||
}
|
||||
extra = symbol == ts_builtin_sym_end;
|
||||
metadata = ts_language_symbol_metadata(language, symbol);
|
||||
data = mem_alloc(sizeof(*data));
|
||||
*data = (t_subtree_data){.ref_count = 1,
|
||||
.padding = padding,
|
||||
.size = size,
|
||||
.lookahead_bytes = lookahead_bytes,
|
||||
.error_cost = 0,
|
||||
.child_count = 0,
|
||||
.symbol = symbol,
|
||||
.parse_state = parse_state,
|
||||
.visible = metadata.visible,
|
||||
.named = metadata.named,
|
||||
.extra = extra,
|
||||
.fragile_left = false,
|
||||
.fragile_right = false,
|
||||
.has_changes = false,
|
||||
.has_external_tokens = has_external_tokens,
|
||||
.has_external_scanner_state_change = false,
|
||||
.depends_on_column = depends_on_column,
|
||||
.is_missing = false,
|
||||
.is_keyword = is_keyword,
|
||||
{{.first_leaf = {.symbol = 0, .parse_state = 0}}}};
|
||||
return ((t_subtree)data);
|
||||
}
|
||||
|
||||
void ts_subtree_set_symbol(t_subtree *self, TSSymbol symbol, const TSLanguage *language)
|
||||
|
|
@ -115,7 +112,7 @@ t_subtree ts_subtree_new_error(t_i32 lookahead_char, Length padding, Length size
|
|||
result->fragile_left = true;
|
||||
result->fragile_right = true;
|
||||
result->lookahead_char = lookahead_char;
|
||||
return result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
// Clone a subtree.
|
||||
|
|
@ -147,7 +144,7 @@ t_subtree ts_subtree_clone(t_subtree self)
|
|||
// This takes ownership of the subtree. If the subtree has only one owner,
|
||||
// this will directly convert it into a mutable version. Otherwise, it will
|
||||
// perform a copy.
|
||||
t_subtree ts_subtree_make_mut(t_subtree self)
|
||||
t_subtree ts_subtree_ensure_owner(t_subtree self)
|
||||
{
|
||||
t_subtree result;
|
||||
|
||||
|
|
@ -156,88 +153,6 @@ t_subtree ts_subtree_make_mut(t_subtree self)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void ts_subtree__compress(t_subtree self, t_u32 count, const TSLanguage *language, SubtreeArray *stack)
|
||||
{
|
||||
t_u32 initial_stack_size;
|
||||
t_subtree tree;
|
||||
TSSymbol symbol;
|
||||
t_usize i;
|
||||
t_subtree child_grandchild[2];
|
||||
|
||||
initial_stack_size = stack->size;
|
||||
tree = self;
|
||||
symbol = tree->symbol;
|
||||
i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
if (tree->ref_count > 1 || tree->child_count < 2)
|
||||
break;
|
||||
child_grandchild[0] = (ts_subtree_children(tree)[0]);
|
||||
if (child_grandchild[0]->child_count < 2 || child_grandchild[0]->ref_count > 1 || child_grandchild[0]->symbol != symbol)
|
||||
break;
|
||||
child_grandchild[1] = (ts_subtree_children(child_grandchild[0])[0]);
|
||||
if (child_grandchild[1]->child_count < 2 || child_grandchild[1]->ref_count > 1 || child_grandchild[1]->symbol != symbol)
|
||||
break;
|
||||
ts_subtree_children(tree)[0] = (child_grandchild[1]);
|
||||
ts_subtree_children(child_grandchild[0])[0] = ts_subtree_children(child_grandchild[1])[child_grandchild[1]->child_count - 1];
|
||||
ts_subtree_children(child_grandchild[1])[child_grandchild[1]->child_count - 1] = (child_grandchild[0]);
|
||||
array_push(stack, tree);
|
||||
tree = child_grandchild[1];
|
||||
i++;
|
||||
}
|
||||
|
||||
while (stack->size > initial_stack_size)
|
||||
{
|
||||
tree = array_pop(stack);
|
||||
child_grandchild[0] = (ts_subtree_children(tree)[0]);
|
||||
child_grandchild[1] = (ts_subtree_children(child_grandchild[0])[child_grandchild[0]->child_count - 1]);
|
||||
ts_subtree_summarize_children(child_grandchild[1], language);
|
||||
ts_subtree_summarize_children(child_grandchild[0], language);
|
||||
ts_subtree_summarize_children(tree, language);
|
||||
}
|
||||
}
|
||||
|
||||
void ts_subtree_balance(t_subtree self, const TSLanguage *language)
|
||||
{
|
||||
|
||||
SubtreeArray balance_stack;
|
||||
|
||||
balance_stack = (SubtreeArray)array_new();
|
||||
array_clear(&balance_stack);
|
||||
|
||||
if (ts_subtree_child_count(self) > 0 && self->ref_count == 1)
|
||||
array_push(&balance_stack, self);
|
||||
|
||||
while (balance_stack.size > 0)
|
||||
{
|
||||
t_subtree tree = array_pop(&balance_stack);
|
||||
|
||||
if (tree->repeat_depth > 0)
|
||||
{
|
||||
t_subtree child1 = ts_subtree_children(tree)[0];
|
||||
t_subtree child2 = ts_subtree_children(tree)[tree->child_count - 1];
|
||||
long repeat_delta = (long)ts_subtree_repeat_depth(child1) - (long)ts_subtree_repeat_depth(child2);
|
||||
if (repeat_delta > 0)
|
||||
{
|
||||
t_u32 n = (t_u32)repeat_delta;
|
||||
for (t_u32 i = n / 2; i > 0; i /= 2)
|
||||
{
|
||||
ts_subtree__compress(tree, i, language, &balance_stack);
|
||||
n -= i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (t_u32 i = 0; i < tree->child_count; i++)
|
||||
{
|
||||
t_subtree child = ts_subtree_children(tree)[i];
|
||||
if (ts_subtree_child_count(child) > 0 && child->ref_count == 1)
|
||||
array_push(&balance_stack, child);
|
||||
}
|
||||
}
|
||||
array_delete(&balance_stack);
|
||||
}
|
||||
|
||||
// Assign all of the node's properties that depend on its children.
|
||||
void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
||||
{
|
||||
|
|
@ -255,20 +170,16 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
const TSSymbol *alias_sequence = ts_language_alias_sequence(language, self->production_id);
|
||||
t_u32 lookahead_end_byte = 0;
|
||||
|
||||
const t_subtree *children = ts_subtree_children(self);
|
||||
t_subtree *children = ts_subtree_children(self);
|
||||
for (t_u32 i = 0; i < self->child_count; i++)
|
||||
{
|
||||
t_subtree child = children[i];
|
||||
|
||||
if (self->size.extent.row == 0 && ts_subtree_depends_on_column(child))
|
||||
{
|
||||
self->depends_on_column = true;
|
||||
}
|
||||
|
||||
if (ts_subtree_has_external_scanner_state_change(child))
|
||||
{
|
||||
self->has_external_scanner_state_change = true;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
|
|
@ -276,20 +187,14 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
self->size = ts_subtree_size(child);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->size = length_add(self->size, ts_subtree_total_size(child));
|
||||
}
|
||||
|
||||
t_u32 child_lookahead_end_byte = self->padding.bytes + self->size.bytes + ts_subtree_lookahead_bytes(child);
|
||||
if (child_lookahead_end_byte > lookahead_end_byte)
|
||||
{
|
||||
lookahead_end_byte = child_lookahead_end_byte;
|
||||
}
|
||||
|
||||
if (ts_subtree_symbol(child) != ts_builtin_sym_error_repeat)
|
||||
{
|
||||
self->error_cost += ts_subtree_error_cost(child);
|
||||
}
|
||||
|
||||
t_u32 grandchild_count = ts_subtree_child_count(child);
|
||||
if (self->symbol == ts_builtin_sym_error || self->symbol == ts_builtin_sym_error_repeat)
|
||||
|
|
@ -297,13 +202,9 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
if (!ts_subtree_extra(child) && !(ts_subtree_is_error(child) && grandchild_count == 0))
|
||||
{
|
||||
if (ts_subtree_visible(child))
|
||||
{
|
||||
self->error_cost += ERROR_COST_PER_SKIPPED_TREE;
|
||||
}
|
||||
else if (grandchild_count > 0)
|
||||
{
|
||||
self->error_cost += ERROR_COST_PER_SKIPPED_TREE * child->visible_child_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -315,9 +216,7 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
self->visible_descendant_count++;
|
||||
self->visible_child_count++;
|
||||
if (ts_language_symbol_metadata(language, alias_sequence[structural_index]).named)
|
||||
{
|
||||
self->named_child_count++;
|
||||
}
|
||||
}
|
||||
else if (ts_subtree_visible(child))
|
||||
{
|
||||
|
|
@ -348,10 +247,8 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
self->lookahead_bytes = lookahead_end_byte - self->size.bytes - self->padding.bytes;
|
||||
|
||||
if (self->symbol == ts_builtin_sym_error || self->symbol == ts_builtin_sym_error_repeat)
|
||||
{
|
||||
self->error_cost +=
|
||||
ERROR_COST_PER_RECOVERY + ERROR_COST_PER_SKIPPED_CHAR * self->size.bytes + ERROR_COST_PER_SKIPPED_LINE * self->size.extent.row;
|
||||
}
|
||||
|
||||
if (self->child_count > 0)
|
||||
{
|
||||
|
|
@ -369,13 +266,9 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
if (self->child_count >= 2 && !self->visible && !self->named && ts_subtree_symbol(first_child) == self->symbol)
|
||||
{
|
||||
if (ts_subtree_repeat_depth(first_child) > ts_subtree_repeat_depth(last_child))
|
||||
{
|
||||
self->repeat_depth = ts_subtree_repeat_depth(first_child) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->repeat_depth = ts_subtree_repeat_depth(last_child) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -383,23 +276,25 @@ void ts_subtree_summarize_children(t_subtree self, const TSLanguage *language)
|
|||
// Create a new parent node with the given children.
|
||||
//
|
||||
// This takes ownership of the children array.
|
||||
t_subtree ts_subtree_new_node(TSSymbol symbol, SubtreeArray *children, t_u32 production_id, const TSLanguage *language)
|
||||
t_subtree ts_subtree_new_node(TSSymbol symbol, t_vec_subtree *children, t_u32 production_id, const TSLanguage *language)
|
||||
{
|
||||
TSSymbolMetadata metadata = ts_language_symbol_metadata(language, symbol);
|
||||
bool fragile = symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat;
|
||||
TSSymbolMetadata metadata;
|
||||
bool fragile;
|
||||
t_usize new_byte_size;
|
||||
t_subtree data;
|
||||
|
||||
// Allocate the node's data at the end of the array of children.
|
||||
size_t new_byte_size = ts_subtree_alloc_size(children->size);
|
||||
metadata = ts_language_symbol_metadata(language, symbol);
|
||||
fragile = symbol == ts_builtin_sym_error || symbol == ts_builtin_sym_error_repeat;
|
||||
new_byte_size = ts_subtree_alloc_size(children->len);
|
||||
if (children->capacity * sizeof(t_subtree) < new_byte_size)
|
||||
{
|
||||
children->contents = mem_realloc(children->contents, new_byte_size);
|
||||
children->buffer = mem_realloc(children->buffer, new_byte_size);
|
||||
children->capacity = (t_u32)(new_byte_size / sizeof(t_subtree));
|
||||
}
|
||||
t_subtree_data *data = (t_subtree_data *)&children->contents[children->size];
|
||||
|
||||
data = (t_subtree)&children->buffer[children->len];
|
||||
*data = (t_subtree_data){.ref_count = 1,
|
||||
.symbol = symbol,
|
||||
.child_count = children->size,
|
||||
.child_count = children->len,
|
||||
.visible = metadata.visible,
|
||||
.named = metadata.named,
|
||||
.has_changes = false,
|
||||
|
|
@ -412,20 +307,21 @@ t_subtree ts_subtree_new_node(TSSymbol symbol, SubtreeArray *children, t_u32 pro
|
|||
.production_id = production_id,
|
||||
.first_leaf = {.symbol = 0, .parse_state = 0},
|
||||
}}};
|
||||
t_subtree result = data;
|
||||
ts_subtree_summarize_children(result, language);
|
||||
return result;
|
||||
ts_subtree_summarize_children(data, language);
|
||||
return (data);
|
||||
}
|
||||
|
||||
// Create a new error node containing the given children.
|
||||
//
|
||||
// This node is treated as 'extra'. Its children are prevented from having
|
||||
// having any effect on the parse state.
|
||||
t_subtree ts_subtree_new_error_node(SubtreeArray *children, bool extra, const TSLanguage *language)
|
||||
t_subtree ts_subtree_new_error_node(t_vec_subtree *children, bool extra, const TSLanguage *language)
|
||||
{
|
||||
t_subtree result = ts_subtree_new_node(ts_builtin_sym_error, children, 0, language);
|
||||
t_subtree result;
|
||||
|
||||
result = ts_subtree_new_node(ts_builtin_sym_error, children, 0, language);
|
||||
result->extra = extra;
|
||||
return ((result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
// Create a new 'missing leaf' node.
|
||||
|
|
@ -434,104 +330,9 @@ t_subtree ts_subtree_new_error_node(SubtreeArray *children, bool extra, const TS
|
|||
// having any effect on the parse state.
|
||||
t_subtree ts_subtree_new_missing_leaf(TSSymbol symbol, Length padding, t_u32 lookahead_bytes, const TSLanguage *language)
|
||||
{
|
||||
t_subtree result = ts_subtree_new_leaf(symbol, padding, length_zero(), lookahead_bytes, 0, false, false, false, language);
|
||||
((t_subtree_data *)result)->is_missing = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ts_subtree_release(t_subtree self)
|
||||
{
|
||||
SubtreeArray to_free;
|
||||
|
||||
to_free = (SubtreeArray)array_new();
|
||||
|
||||
array_clear(&to_free);
|
||||
|
||||
assert(self->ref_count > 0);
|
||||
if (--(*(t_u32 *)(&self->ref_count)) == 0)
|
||||
array_push(&to_free, (self));
|
||||
|
||||
while (to_free.size > 0)
|
||||
{
|
||||
t_subtree tree = array_pop(&to_free);
|
||||
if (tree->child_count > 0)
|
||||
{
|
||||
t_subtree *children = ts_subtree_children(tree);
|
||||
for (t_u32 i = 0; i < tree->child_count; i++)
|
||||
{
|
||||
t_subtree child = children[i];
|
||||
assert(child->ref_count > 0);
|
||||
if (--(*(t_u32 *)(&child->ref_count)) == 0)
|
||||
array_push(&to_free, (child));
|
||||
}
|
||||
mem_free(children);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tree->has_external_tokens)
|
||||
ts_external_scanner_state_delete(&tree->external_scanner_state);
|
||||
mem_free(tree);
|
||||
}
|
||||
}
|
||||
array_delete(&to_free);
|
||||
}
|
||||
|
||||
int ts_subtree_compare(t_subtree left, t_subtree right)
|
||||
{
|
||||
SubtreeArray compare_stack = array_new();
|
||||
|
||||
array_push(&compare_stack, (left));
|
||||
array_push(&compare_stack, (right));
|
||||
|
||||
while (compare_stack.size > 0)
|
||||
{
|
||||
right = (array_pop(&compare_stack));
|
||||
left = (array_pop(&compare_stack));
|
||||
|
||||
int result = 0;
|
||||
if (ts_subtree_symbol(left) < ts_subtree_symbol(right))
|
||||
result = -1;
|
||||
else if (ts_subtree_symbol(right) < ts_subtree_symbol(left))
|
||||
result = 1;
|
||||
else if (ts_subtree_child_count(left) < ts_subtree_child_count(right))
|
||||
result = -1;
|
||||
else if (ts_subtree_child_count(right) < ts_subtree_child_count(left))
|
||||
result = 1;
|
||||
if (result != 0)
|
||||
{
|
||||
array_clear(&compare_stack);
|
||||
array_delete(&compare_stack);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (t_u32 i = ts_subtree_child_count(left); i > 0; i--)
|
||||
{
|
||||
t_subtree left_child = ts_subtree_children(left)[i - 1];
|
||||
t_subtree right_child = ts_subtree_children(right)[i - 1];
|
||||
array_push(&compare_stack, (left_child));
|
||||
array_push(&compare_stack, (right_child));
|
||||
}
|
||||
}
|
||||
|
||||
array_delete(&compare_stack);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t_subtree ts_subtree_last_external_token(t_subtree tree)
|
||||
{
|
||||
if (!ts_subtree_has_external_tokens(tree))
|
||||
return NULL;
|
||||
while (tree->child_count > 0)
|
||||
{
|
||||
for (t_u32 i = tree->child_count - 1; i + 1 > 0; i--)
|
||||
{
|
||||
t_subtree child = ts_subtree_children(tree)[i];
|
||||
if (ts_subtree_has_external_tokens(child))
|
||||
{
|
||||
tree = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
t_subtree result;
|
||||
|
||||
result = ts_subtree_new_leaf(symbol, padding, length_zero(), lookahead_bytes, 0, false, false, false, language);
|
||||
result->is_missing = true;
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
117
parser/src/subtree/subtree_funcs1.c
Normal file
117
parser/src/subtree/subtree_funcs1.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* subtree_funcs1.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/09/02 20:36:10 by maiboyer #+# #+# */
|
||||
/* Updated: 2024/09/02 20:39:57 by maiboyer ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "me/vec/vec_subtree.h"
|
||||
#include "parser/subtree.h"
|
||||
|
||||
void ts_subtree_release(t_subtree self)
|
||||
{
|
||||
t_vec_subtree to_free;
|
||||
t_subtree tree;
|
||||
t_subtree *children;
|
||||
t_usize i;
|
||||
|
||||
to_free = vec_subtree_new(16, NULL);
|
||||
if (--self->ref_count == 0)
|
||||
vec_subtree_push(&to_free, self);
|
||||
while (to_free.len > 0)
|
||||
{
|
||||
vec_subtree_pop(&to_free, &tree);
|
||||
if (tree->child_count > 0)
|
||||
{
|
||||
i = 0;
|
||||
children = ts_subtree_children(tree);
|
||||
while (i < tree->child_count)
|
||||
{
|
||||
if (--(children[i])->ref_count == 0)
|
||||
vec_subtree_push(&to_free, children[i]);
|
||||
i++;
|
||||
}
|
||||
mem_free(children);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tree->has_external_tokens)
|
||||
ts_external_scanner_state_delete(&tree->external_scanner_state);
|
||||
mem_free(tree);
|
||||
}
|
||||
}
|
||||
vec_subtree_free(to_free);
|
||||
}
|
||||
|
||||
int subtree_compare_func(t_subtree left, t_subtree right)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = 0;
|
||||
if (ts_subtree_symbol(left) < ts_subtree_symbol(right))
|
||||
result = -1;
|
||||
else if (ts_subtree_symbol(right) < ts_subtree_symbol(left))
|
||||
result = 1;
|
||||
else if (ts_subtree_child_count(left) < ts_subtree_child_count(right))
|
||||
result = -1;
|
||||
else if (ts_subtree_child_count(right) < ts_subtree_child_count(left))
|
||||
result = 1;
|
||||
return (result);
|
||||
}
|
||||
|
||||
int ts_subtree_compare(t_subtree left, t_subtree right)
|
||||
{
|
||||
t_vec_subtree cmp_stack;
|
||||
t_i8 result = 0;
|
||||
t_usize i;
|
||||
|
||||
cmp_stack = vec_subtree_new(16, NULL);
|
||||
vec_subtree_push(&cmp_stack, (left));
|
||||
vec_subtree_push(&cmp_stack, (right));
|
||||
while (cmp_stack.len >= 2)
|
||||
{
|
||||
vec_subtree_pop(&cmp_stack, &left);
|
||||
vec_subtree_pop(&cmp_stack, &right);
|
||||
|
||||
result = subtree_compare_func(left, right);
|
||||
if (result != 0)
|
||||
return (vec_subtree_free(cmp_stack), result);
|
||||
i = ts_subtree_child_count(left);
|
||||
while (i > 0)
|
||||
{
|
||||
vec_subtree_push(&cmp_stack, ts_subtree_children(left)[i - 1]);
|
||||
vec_subtree_push(&cmp_stack, ts_subtree_children(right)[i - 1]);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return (vec_subtree_free(cmp_stack), 0);
|
||||
}
|
||||
|
||||
t_subtree ts_subtree_last_external_token(t_subtree tree)
|
||||
{
|
||||
t_usize i;
|
||||
t_subtree child;
|
||||
|
||||
if (!ts_subtree_has_external_tokens(tree))
|
||||
return (NULL);
|
||||
while (tree->child_count > 0)
|
||||
{
|
||||
i = tree->child_count - 1;
|
||||
while (i + 1 > 0)
|
||||
{
|
||||
child = ts_subtree_children(tree)[i];
|
||||
if (ts_subtree_has_external_tokens(child))
|
||||
{
|
||||
tree = child;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return (tree);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue