From 009be4a4b481cb559bdb85a653ed189d29b7d49e Mon Sep 17 00:00:00 2001 From: Maieul BOYER Date: Sat, 31 Aug 2024 17:18:02 +0000 Subject: [PATCH] splitted more stuff --- Makefile | 4 +- exec/Filelist.exec.mk | 3 + parser/Filelist.parser.mk | 22 +- parser/include/parser/_inner/node.h | 43 ++ parser/include/parser/_inner/stack.h | 111 ++++ parser/src/lexer.c | 13 - parser/src/node.c | 343 ---------- parser/src/node/node_child.c | 80 +++ parser/src/node/node_child_inner.c | 55 ++ parser/src/node/node_constructor.c | 27 + parser/src/node/node_fields.c | 40 ++ parser/src/node/node_getter_funcs1.c | 93 +++ parser/src/node/node_iterator.c | 62 ++ parser/src/node/node_relevent.c | 42 ++ parser/src/stack.c | 926 --------------------------- parser/src/stack/stack_add_link.c | 85 +++ parser/src/stack/stack_funcs1.c | 56 ++ parser/src/stack/stack_funcs2.c | 80 +++ parser/src/stack/stack_funcs3.c | 110 ++++ parser/src/stack/stack_funcs4.c | 35 + parser/src/stack/stack_iter.c | 129 ++++ parser/src/stack/stack_lifetime.c | 47 ++ parser/src/stack/stack_manipulate.c | 77 +++ parser/src/stack/stack_manipulate2.c | 67 ++ parser/src/stack/stack_manipulate3.c | 81 +++ parser/src/stack/stack_node.c | 119 ++++ parser/src/stack/stack_summary.c | 66 ++ parser/src/stack/stack_version.c | 66 ++ 28 files changed, 1595 insertions(+), 1287 deletions(-) create mode 100644 parser/include/parser/_inner/node.h create mode 100644 parser/include/parser/_inner/stack.h delete mode 100644 parser/src/node.c create mode 100644 parser/src/node/node_child.c create mode 100644 parser/src/node/node_child_inner.c create mode 100644 parser/src/node/node_constructor.c create mode 100644 parser/src/node/node_fields.c create mode 100644 parser/src/node/node_getter_funcs1.c create mode 100644 parser/src/node/node_iterator.c create mode 100644 parser/src/node/node_relevent.c delete mode 100644 parser/src/stack.c create mode 100644 parser/src/stack/stack_add_link.c create mode 100644 parser/src/stack/stack_funcs1.c create mode 100644 parser/src/stack/stack_funcs2.c create mode 100644 parser/src/stack/stack_funcs3.c create mode 100644 parser/src/stack/stack_funcs4.c create mode 100644 parser/src/stack/stack_iter.c create mode 100644 parser/src/stack/stack_lifetime.c create mode 100644 parser/src/stack/stack_manipulate.c create mode 100644 parser/src/stack/stack_manipulate2.c create mode 100644 parser/src/stack/stack_manipulate3.c create mode 100644 parser/src/stack/stack_node.c create mode 100644 parser/src/stack/stack_summary.c create mode 100644 parser/src/stack/stack_version.c diff --git a/Makefile b/Makefile index 8fa67b87..9888e2ca 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: rparodi +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2023/11/12 11:05:05 by rparodi #+# #+# # -# Updated: 2024/08/22 16:39:40 by maiboyer ### ########.fr # +# Updated: 2024/08/31 17:01:44 by maiboyer ### ########.fr # # # # **************************************************************************** # @@ -51,8 +51,6 @@ CFLAGS_ADDITIONAL += -O0 CFLAGS_ADDITIONAL += -Wno-cpp -Wno-type-limits -Wno-unused-command-line-argument CFLAGS_ADDITIONAL += -gcolumn-info -g3 CFLAGS_ADDITIONAL += '-DERROR=((void)printf("ERROR HERE: " __FILE__ ":%d in %s\n", __LINE__, __func__), 1)' -CFLAGS_ADDITIONAL += '-Dinline=' -Wno-unused-function -CFLAGS_ADDITIONAL += '-Dstatic=' -Wno-unused-function #CFLAGS_ADDITIONAL += -O2 # CFLAGS_ADDITIONAL += -fuse-ld=gold -Wl,--print-symbol-counts -Wl,/tmp/symbols_count.log CFLAGS_ADDITIONAL += -fuse-ld=lld -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,-O3 -Wl,--allow-multiple-definition diff --git a/exec/Filelist.exec.mk b/exec/Filelist.exec.mk index 7793dda1..95f5853d 100644 --- a/exec/Filelist.exec.mk +++ b/exec/Filelist.exec.mk @@ -7,6 +7,9 @@ builtins/exit \ builtins/export \ builtins/pwd \ builtins/unset \ +run_arithmetic/_get_op \ +run_arithmetic/_run_arith \ +run_arithmetic/_to_ast_node \ run_arithmetic/arithmetic \ run_arithmetic/arithmetic_operation \ run_ast \ diff --git a/parser/Filelist.parser.mk b/parser/Filelist.parser.mk index 310dd6da..339046b9 100644 --- a/parser/Filelist.parser.mk +++ b/parser/Filelist.parser.mk @@ -6,12 +6,30 @@ language \ length \ lex \ lexer \ -node \ +node/node_child \ +node/node_child_inner \ +node/node_constructor \ +node/node_fields \ +node/node_getter_funcs1 \ +node/node_iterator \ +node/node_relevent \ parser \ point \ reduce_action \ scanner \ -stack \ +stack/stack_add_link \ +stack/stack_funcs1 \ +stack/stack_funcs2 \ +stack/stack_funcs3 \ +stack/stack_funcs4 \ +stack/stack_iter \ +stack/stack_lifetime \ +stack/stack_manipulate \ +stack/stack_manipulate2 \ +stack/stack_manipulate3 \ +stack/stack_node \ +stack/stack_summary \ +stack/stack_version \ subtree \ tree \ diff --git a/parser/include/parser/_inner/node.h b/parser/include/parser/_inner/node.h new file mode 100644 index 00000000..6a0e5b70 --- /dev/null +++ b/parser/include/parser/_inner/node.h @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:04:59 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:12:08 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef NODE_H +#define NODE_H + +#include "me/types.h" +#include "parser/length.h" +#include "parser/subtree.h" + +typedef struct s_node_child_iterator NodeChildIterator; +struct s_node_child_iterator +{ + Subtree parent; + const TSTree *tree; + Length position; + t_u32 child_index; + t_u32 structural_child_index; + const TSSymbol *alias_sequence; +}; + +NodeChildIterator ts_node_iterate_children(const TSNode *node); +TSFieldId ts_node__field_id_from_language(TSNode self, t_u32 structural_child_index); +TSNode ts_node__child(TSNode self, t_u32 child_index, bool include_anonymous); +TSNode ts_node__null(void); +bool ts_node__is_relevant(TSNode self, bool include_anonymous); +bool ts_node_child_iterator_done(NodeChildIterator *self); +bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result); +t_const_str ts_node__field_name_from_language(TSNode self, t_u32 structural_child_index); +t_u32 ts_node__relevant_child_count(TSNode self, bool include_anonymous); +Subtree ts_node__subtree(TSNode self); +t_u32 ts_node__alias(const TSNode *self); + +#endif /* NODE_H */ diff --git a/parser/include/parser/_inner/stack.h b/parser/include/parser/_inner/stack.h new file mode 100644 index 00000000..2a7e71a2 --- /dev/null +++ b/parser/include/parser/_inner/stack.h @@ -0,0 +1,111 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:37:50 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:53:40 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef STACK_H +#define STACK_H + +#include "me/types.h" +#include "parser/subtree.h" +#include "parser/stack.h" + +#define MAX_LINK_COUNT 1 +#define MAX_NODE_POOL_SIZE 0 +#define MAX_ITERATOR_COUNT 0 + +typedef enum e_stack_status t_stack_status; +typedef struct s_stack_head t_stack_head; +typedef struct s_stack_iterator t_stack_iterator; +typedef struct s_stack_link t_stack_link; +typedef struct s_stack_node t_stack_node; +typedef struct s_summarize_stack_session t_summarize_stack_session; +typedef t_u32 t_stack_action; + +typedef t_stack_action (*t_stack_callback)(void *, + const t_stack_iterator *); + +struct s_stack_link +{ + t_stack_node *node; + Subtree subtree; + bool is_pending; +}; + +struct s_stack_node +{ + TSStateId state; + Length position; + t_stack_link links[MAX_LINK_COUNT]; + t_u16 link_count; + t_u32 ref_count; + t_u32 error_cost; + t_u32 node_count; + int dynamic_precedence; +}; + +struct s_stack_iterator +{ + t_stack_node *node; + SubtreeArray subtrees; + t_u32 subtree_count; + bool is_pending; +}; + +enum e_stack_status +{ + SStatusActive, + SStatusPaused, + SStatusHalted, +}; + +struct s_stack_head +{ + t_stack_node *node; + t_stack_summary *summary; + t_u32 node_count_at_last_error; + Subtree last_external_token; + Subtree lookahead_when_paused; + t_stack_status status; +}; + +struct s_stack +{ + Array(t_stack_head) heads; + t_stack_slice_array slices; + Array(t_stack_iterator) iterators; + t_stack_node *base_node; +}; + +enum e_stack_action +{ + SActionNone, + SActionStop = 1, + SActionPop = 2, +}; + +struct s_summarize_stack_session +{ + t_stack_summary *summary; + t_u32 max_depth; +}; + +bool stack__subtree_is_equivalent(Subtree left, Subtree right); +t_stack_node *stack_node_new(t_stack_node *previous_node, Subtree subtree, bool is_pending, TSStateId state); +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_version ts_stack__add_version(t_stack *self, t_stack_version original_version, t_stack_node *node); +t_u32 stack__subtree_node_count(Subtree subtree); +void stack_head_delete(t_stack_head *self); +void stack_node_add_link(t_stack_node *self, t_stack_link link); +void stack_node_release(t_stack_node *self); +void stack_node_retain(t_stack_node *self); +void ts_stack__add_slice(t_stack *self, t_stack_version original_version, t_stack_node *node, SubtreeArray *subtrees); + +#endif /* STACK_H */ diff --git a/parser/src/lexer.c b/parser/src/lexer.c index df7b0564..bad21ac8 100644 --- a/parser/src/lexer.c +++ b/parser/src/lexer.c @@ -245,19 +245,6 @@ static t_u32 ts_lexer__get_column(TSLexer *_self) // Is the lexer at a boundary between two disjoint included ranges of // source code? This is exposed as an API because some languages' external // scanners need to perform custom actions at these boundaries. -static bool ts_lexer__is_at_included_range_start(const TSLexer *_self) -{ - const Lexer *self = (const Lexer *)_self; - if (self->current_included_range_index < self->included_range_count) - { - TSRange *current_range = &self->included_ranges[self->current_included_range_index]; - return self->current_position.bytes == current_range->start_byte; - } - else - { - return false; - } -} static const TSRange DEFAULT_RANGE = {.start_point = { .row = 0, diff --git a/parser/src/node.c b/parser/src/node.c deleted file mode 100644 index 45b7e91a..00000000 --- a/parser/src/node.c +++ /dev/null @@ -1,343 +0,0 @@ -#include "me/types.h" -#include "parser/api.h" -#include "parser/language.h" -#include "parser/point.h" -#include "parser/subtree.h" -#include "parser/tree.h" - -typedef struct NodeChildIterator -{ - Subtree parent; - const TSTree *tree; - Length position; - t_u32 child_index; - t_u32 structural_child_index; - const TSSymbol *alias_sequence; -} NodeChildIterator; - -// TSNode - constructors - -TSNode ts_node_new(const TSTree *tree, const Subtree *subtree, Length position, TSSymbol alias) -{ - return (TSNode){ - position.bytes, position.extent.row, position.extent.column, alias, subtree, tree, - }; -} - -static inline TSNode ts_node__null(void) -{ - return ts_node_new(NULL, NULL, length_zero(), 0); -} - -// TSNode - accessors - -t_u32 ts_node_start_byte(TSNode self) -{ - return self.start_byte; -} - -const TSLanguage *ts_node_language(TSNode self) -{ - return self.tree->language; -} - -TSPoint ts_node_start_point(TSNode self) -{ - return (TSPoint){self.start_row, self.start_col}; -} - -static inline t_u32 ts_node__alias(const TSNode *self) -{ - return self->alias; -} - -static inline Subtree ts_node__subtree(TSNode self) -{ - return *(const Subtree *)self.id; -} - -// NodeChildIterator - -static inline NodeChildIterator ts_node_iterate_children(const TSNode *node) -{ - Subtree subtree = ts_node__subtree(*node); - if (ts_subtree_child_count(subtree) == 0) - { - return (NodeChildIterator){NULL, node->tree, length_zero(), 0, 0, NULL}; - } - const TSSymbol *alias_sequence = ts_language_alias_sequence(node->tree->language, subtree->production_id); - return (NodeChildIterator){ - .tree = node->tree, - .parent = subtree, - .position = {ts_node_start_byte(*node), ts_node_start_point(*node)}, - .child_index = 0, - .structural_child_index = 0, - .alias_sequence = alias_sequence, - }; -} - -static inline bool ts_node_child_iterator_done(NodeChildIterator *self) -{ - return self->child_index == self->parent->child_count; -} - -static inline bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) -{ - if (!self->parent || ts_node_child_iterator_done(self)) - return false; - const Subtree *child = &ts_subtree_children(self->parent)[self->child_index]; - TSSymbol alias_symbol = 0; - if (!ts_subtree_extra(*child)) - { - if (self->alias_sequence) - { - alias_symbol = self->alias_sequence[self->structural_child_index]; - } - self->structural_child_index++; - } - if (self->child_index > 0) - { - self->position = length_add(self->position, ts_subtree_padding(*child)); - } - *result = ts_node_new(self->tree, child, self->position, alias_symbol); - self->position = length_add(self->position, ts_subtree_size(*child)); - self->child_index++; - return true; -} - -// TSNode - private - -static inline bool ts_node__is_relevant(TSNode self, bool include_anonymous) -{ - Subtree tree = ts_node__subtree(self); - if (include_anonymous) - { - return ts_subtree_visible(tree) || ts_node__alias(&self); - } - else - { - TSSymbol alias = ts_node__alias(&self); - if (alias) - { - return ts_language_symbol_metadata(self.tree->language, alias).named; - } - else - { - return ts_subtree_visible(tree) && ts_subtree_named(tree); - } - } -} - -static inline t_u32 ts_node__relevant_child_count(TSNode self, bool include_anonymous) -{ - Subtree tree = ts_node__subtree(self); - if (ts_subtree_child_count(tree) > 0) - { - if (include_anonymous) - { - return tree->visible_child_count; - } - else - { - return tree->named_child_count; - } - } - else - { - return 0; - } -} - -static inline TSNode ts_node__child(TSNode self, t_u32 child_index, bool include_anonymous) -{ - TSNode result = self; - bool did_descend = true; - - while (did_descend) - { - did_descend = false; - - TSNode child; - t_u32 index = 0; - NodeChildIterator iterator = ts_node_iterate_children(&result); - while (ts_node_child_iterator_next(&iterator, &child)) - { - if (ts_node__is_relevant(child, include_anonymous)) - { - if (index == child_index) - { - return child; - } - index++; - } - else - { - t_u32 grandchild_index = child_index - index; - t_u32 grandchild_count = ts_node__relevant_child_count(child, include_anonymous); - if (grandchild_index < grandchild_count) - { - printf("did_descend\n"); - did_descend = true; - result = child; - child_index = grandchild_index; - break; - } - index += grandchild_count; - } - } - } - - return ts_node__null(); -} - -// TSNode - public - -t_u32 ts_node_end_byte(TSNode self) -{ - return ts_node_start_byte(self) + ts_subtree_size(ts_node__subtree(self)).bytes; -} - -TSSymbol ts_node_symbol(TSNode self) -{ - TSSymbol symbol = ts_node__alias(&self); - if (!symbol) - symbol = ts_subtree_symbol(ts_node__subtree(self)); - return ts_language_public_symbol(self.tree->language, symbol); -} - -t_const_str ts_node_type(TSNode self) -{ - TSSymbol symbol = ts_node__alias(&self); - if (!symbol) - symbol = ts_subtree_symbol(ts_node__subtree(self)); - return ts_language_symbol_name(self.tree->language, symbol); -} - -TSSymbol ts_node_grammar_symbol(TSNode self) -{ - return ts_subtree_symbol(ts_node__subtree(self)); -} - -t_const_str ts_node_grammar_type(TSNode self) -{ - TSSymbol symbol = ts_subtree_symbol(ts_node__subtree(self)); - return ts_language_symbol_name(self.tree->language, symbol); -} - -bool ts_node_is_extra(TSNode self) -{ - return ts_subtree_extra(ts_node__subtree(self)); -} - -bool ts_node_is_named(TSNode self) -{ - TSSymbol alias = ts_node__alias(&self); - return alias ? ts_language_symbol_metadata(self.tree->language, alias).named : ts_subtree_named(ts_node__subtree(self)); -} - -TSNode ts_node_child(TSNode self, t_u32 child_index) -{ - return ts_node__child(self, child_index, true); -} - -TSNode ts_node_named_child(TSNode self, t_u32 child_index) -{ - return ts_node__child(self, child_index, false); -} - -static inline t_const_str ts_node__field_name_from_language(TSNode self, t_u32 structural_child_index) -{ - const TSFieldMapEntry *field_map, *field_map_end; - ts_language_field_map(self.tree->language, ts_node__subtree(self)->production_id, &field_map, &field_map_end); - for (; field_map != field_map_end; field_map++) - { - if (!field_map->inherited && field_map->child_index == structural_child_index) - { - return self.tree->language->field_names[field_map->field_id]; - } - } - return NULL; -} - -static inline TSFieldId ts_node__field_id_from_language(TSNode self, t_u32 structural_child_index) -{ - const TSFieldMapEntry *field_map, *field_map_end; - ts_language_field_map(self.tree->language, ts_node__subtree(self)->production_id, &field_map, &field_map_end); - for (; field_map != field_map_end; field_map++) - { - if (!field_map->inherited && field_map->child_index == structural_child_index) - return field_map->field_id; - } - return 0; -} - -t_u32 ts_node_child_count(TSNode self) -{ - Subtree tree = ts_node__subtree(self); - if (ts_subtree_child_count(tree) > 0) - { - return tree->visible_child_count; - } - else - { - return 0; - } -} - -t_u32 ts_node_named_child_count(TSNode self) -{ - Subtree tree = ts_node__subtree(self); - if (ts_subtree_child_count(tree) > 0) - return tree->named_child_count; - else - return 0; -} - -TSFieldId ts_node_field_id_for_child(TSNode self, t_u32 child_index) -{ - TSNode result = self; - bool did_descend = true; - TSFieldId inherited_field_id = 0; - - while (did_descend) - { - did_descend = false; - - TSNode child; - t_u32 index = 0; - NodeChildIterator iterator = ts_node_iterate_children(&result); - while (ts_node_child_iterator_next(&iterator, &child)) - { - if (ts_node__is_relevant(child, true)) - { - if (index == child_index) - { - if (ts_node_is_extra(child)) - return 0; - TSFieldId field_id = ts_node__field_id_from_language(result, iterator.structural_child_index - 1); - if (field_id) - return field_id; - return inherited_field_id; - } - index++; - } - else - { - t_u32 grandchild_index = child_index - index; - t_u32 grandchild_count = ts_node__relevant_child_count(child, true); - if (grandchild_index < grandchild_count) - { - TSFieldId field_id = ts_node__field_id_from_language(result, iterator.structural_child_index - 1); - if (field_id) - inherited_field_id = field_id; - did_descend = true; - result = child; - child_index = grandchild_index; - break; - } - index += grandchild_count; - } - } - } - return 0; -} diff --git a/parser/src/node/node_child.c b/parser/src/node/node_child.c new file mode 100644 index 00000000..2ceca61c --- /dev/null +++ b/parser/src/node/node_child.c @@ -0,0 +1,80 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_child.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:14:40 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:15:06 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/node.h" + +t_u32 ts_node_child_count(TSNode self) +{ + Subtree tree = ts_node__subtree(self); + if (ts_subtree_child_count(tree) > 0) + return tree->visible_child_count; + else + return 0; +} + +t_u32 ts_node_named_child_count(TSNode self) +{ + Subtree tree = ts_node__subtree(self); + if (ts_subtree_child_count(tree) > 0) + return tree->named_child_count; + else + return 0; +} + +TSFieldId ts_node_field_id_for_child(TSNode self, t_u32 child_index) +{ + TSNode result = self; + bool did_descend = true; + TSFieldId inherited_field_id = 0; + + while (did_descend) + { + did_descend = false; + + TSNode child; + t_u32 index = 0; + NodeChildIterator iterator = ts_node_iterate_children(&result); + while (ts_node_child_iterator_next(&iterator, &child)) + { + if (ts_node__is_relevant(child, true)) + { + if (index == child_index) + { + if (ts_node_is_extra(child)) + return 0; + TSFieldId field_id = ts_node__field_id_from_language(result, iterator.structural_child_index - 1); + if (field_id) + return field_id; + return inherited_field_id; + } + index++; + } + else + { + t_u32 grandchild_index = child_index - index; + t_u32 grandchild_count = ts_node__relevant_child_count(child, true); + if (grandchild_index < grandchild_count) + { + TSFieldId field_id = ts_node__field_id_from_language(result, iterator.structural_child_index - 1); + if (field_id) + inherited_field_id = field_id; + did_descend = true; + result = child; + child_index = grandchild_index; + break; + } + index += grandchild_count; + } + } + } + return 0; +} diff --git a/parser/src/node/node_child_inner.c b/parser/src/node/node_child_inner.c new file mode 100644 index 00000000..c36a11bd --- /dev/null +++ b/parser/src/node/node_child_inner.c @@ -0,0 +1,55 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_child_inner.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:16:18 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:16:34 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/node.h" + +TSNode ts_node__child(TSNode self, t_u32 child_index, bool include_anonymous) +{ + TSNode result = self; + bool did_descend = true; + + while (did_descend) + { + did_descend = false; + + TSNode child; + t_u32 index = 0; + NodeChildIterator iterator = ts_node_iterate_children(&result); + while (ts_node_child_iterator_next(&iterator, &child)) + { + if (ts_node__is_relevant(child, include_anonymous)) + { + if (index == child_index) + { + return child; + } + index++; + } + else + { + t_u32 grandchild_index = child_index - index; + t_u32 grandchild_count = ts_node__relevant_child_count(child, include_anonymous); + if (grandchild_index < grandchild_count) + { + printf("did_descend\n"); + did_descend = true; + result = child; + child_index = grandchild_index; + break; + } + index += grandchild_count; + } + } + } + + return ts_node__null(); +} diff --git a/parser/src/node/node_constructor.c b/parser/src/node/node_constructor.c new file mode 100644 index 00000000..5c4f6c83 --- /dev/null +++ b/parser/src/node/node_constructor.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_constructor.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:10:57 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:11:24 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/api.h" +#include "parser/length.h" +#include "parser/subtree.h" + +TSNode ts_node_new(const TSTree *tree, const Subtree *subtree, Length position, TSSymbol alias) +{ + return (TSNode){ + position.bytes, position.extent.row, position.extent.column, alias, subtree, tree, + }; +} + +TSNode ts_node__null(void) +{ + return ts_node_new(NULL, NULL, length_zero(), 0); +} diff --git a/parser/src/node/node_fields.c b/parser/src/node/node_fields.c new file mode 100644 index 00000000..da3f0fe5 --- /dev/null +++ b/parser/src/node/node_fields.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_fields.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:15:23 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:15:55 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/node.h" +#include "parser/api.h" +#include "parser/language.h" +#include "parser/tree.h" + +t_const_str ts_node__field_name_from_language(TSNode self, t_u32 structural_child_index) +{ + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map(self.tree->language, ts_node__subtree(self)->production_id, &field_map, &field_map_end); + for (; field_map != field_map_end; field_map++) + { + if (!field_map->inherited && field_map->child_index == structural_child_index) + return self.tree->language->field_names[field_map->field_id]; + } + return NULL; +} + +TSFieldId ts_node__field_id_from_language(TSNode self, t_u32 structural_child_index) +{ + const TSFieldMapEntry *field_map, *field_map_end; + ts_language_field_map(self.tree->language, ts_node__subtree(self)->production_id, &field_map, &field_map_end); + for (; field_map != field_map_end; field_map++) + { + if (!field_map->inherited && field_map->child_index == structural_child_index) + return field_map->field_id; + } + return 0; +} diff --git a/parser/src/node/node_getter_funcs1.c b/parser/src/node/node_getter_funcs1.c new file mode 100644 index 00000000..bd8c5e79 --- /dev/null +++ b/parser/src/node/node_getter_funcs1.c @@ -0,0 +1,93 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_getter_funcs1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:04:21 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:07:17 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/node.h" +#include "parser/tree.h" +#include "parser/language.h" + +t_u32 ts_node_start_byte(TSNode self) +{ + return self.start_byte; +} + +const TSLanguage *ts_node_language(TSNode self) +{ + return self.tree->language; +} + +TSPoint ts_node_start_point(TSNode self) +{ + return (TSPoint){self.start_row, self.start_col}; +} + +t_u32 ts_node__alias(const TSNode *self) +{ + return self->alias; +} + +Subtree ts_node__subtree(TSNode self) +{ + return *(const Subtree *)self.id; +} + +t_u32 ts_node_end_byte(TSNode self) +{ + return ts_node_start_byte(self) + ts_subtree_size(ts_node__subtree(self)).bytes; +} + +TSSymbol ts_node_symbol(TSNode self) +{ + TSSymbol symbol = ts_node__alias(&self); + if (!symbol) + symbol = ts_subtree_symbol(ts_node__subtree(self)); + return ts_language_public_symbol(self.tree->language, symbol); +} + +t_const_str ts_node_type(TSNode self) +{ + TSSymbol symbol = ts_node__alias(&self); + if (!symbol) + symbol = ts_subtree_symbol(ts_node__subtree(self)); + return ts_language_symbol_name(self.tree->language, symbol); +} + +TSSymbol ts_node_grammar_symbol(TSNode self) +{ + return ts_subtree_symbol(ts_node__subtree(self)); +} + +t_const_str ts_node_grammar_type(TSNode self) +{ + TSSymbol symbol = ts_subtree_symbol(ts_node__subtree(self)); + return ts_language_symbol_name(self.tree->language, symbol); +} + +bool ts_node_is_extra(TSNode self) +{ + return ts_subtree_extra(ts_node__subtree(self)); +} + +bool ts_node_is_named(TSNode self) +{ + TSSymbol alias = ts_node__alias(&self); + return alias ? ts_language_symbol_metadata(self.tree->language, alias).named : ts_subtree_named(ts_node__subtree(self)); +} + +TSNode ts_node_child(TSNode self, t_u32 child_index) +{ + return ts_node__child(self, child_index, true); +} + +TSNode ts_node_named_child(TSNode self, t_u32 child_index) +{ + return ts_node__child(self, child_index, false); +} diff --git a/parser/src/node/node_iterator.c b/parser/src/node/node_iterator.c new file mode 100644 index 00000000..022d1152 --- /dev/null +++ b/parser/src/node/node_iterator.c @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_iterator.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:14:00 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:14:14 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/node.h" +#include "parser/language.h" +#include "parser/tree.h" + +NodeChildIterator ts_node_iterate_children(const TSNode *node) +{ + Subtree subtree = ts_node__subtree(*node); + if (ts_subtree_child_count(subtree) == 0) + { + return (NodeChildIterator){NULL, node->tree, length_zero(), 0, 0, NULL}; + } + const TSSymbol *alias_sequence = ts_language_alias_sequence(node->tree->language, subtree->production_id); + return (NodeChildIterator){ + .tree = node->tree, + .parent = subtree, + .position = {ts_node_start_byte(*node), ts_node_start_point(*node)}, + .child_index = 0, + .structural_child_index = 0, + .alias_sequence = alias_sequence, + }; +} + +bool ts_node_child_iterator_done(NodeChildIterator *self) +{ + return self->child_index == self->parent->child_count; +} + +bool ts_node_child_iterator_next(NodeChildIterator *self, TSNode *result) +{ + if (!self->parent || ts_node_child_iterator_done(self)) + return false; + const Subtree *child = &ts_subtree_children(self->parent)[self->child_index]; + TSSymbol alias_symbol = 0; + if (!ts_subtree_extra(*child)) + { + if (self->alias_sequence) + { + alias_symbol = self->alias_sequence[self->structural_child_index]; + } + self->structural_child_index++; + } + if (self->child_index > 0) + { + self->position = length_add(self->position, ts_subtree_padding(*child)); + } + *result = ts_node_new(self->tree, child, self->position, alias_symbol); + self->position = length_add(self->position, ts_subtree_size(*child)); + self->child_index++; + return true; +} diff --git a/parser/src/node/node_relevent.c b/parser/src/node/node_relevent.c new file mode 100644 index 00000000..326e4e9a --- /dev/null +++ b/parser/src/node/node_relevent.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* node_relevent.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:16:53 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:17:09 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/node.h" +#include "parser/language.h" +#include "parser/tree.h" + +bool ts_node__is_relevant(TSNode self, bool include_anonymous) +{ + TSSymbol alias; + Subtree tree; + tree = ts_node__subtree(self); + if (include_anonymous) + return ts_subtree_visible(tree) || ts_node__alias(&self); + alias = ts_node__alias(&self); + if (alias) + return ts_language_symbol_metadata(self.tree->language, alias).named; + else + return ts_subtree_visible(tree) && ts_subtree_named(tree); +} + +t_u32 ts_node__relevant_child_count(TSNode self, bool include_anonymous) +{ + Subtree tree = ts_node__subtree(self); + if (ts_subtree_child_count(tree) > 0) + { + if (include_anonymous) + return tree->visible_child_count; + else + return tree->named_child_count; + } + return 0; +} diff --git a/parser/src/stack.c b/parser/src/stack.c deleted file mode 100644 index 20d674cb..00000000 --- a/parser/src/stack.c +++ /dev/null @@ -1,926 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* stack.c :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: maiboyer +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/08/31 15:22:58 by maiboyer #+# #+# */ -/* Updated: 2024/08/31 15:51:15 by maiboyer ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "me/mem/mem.h" -#include "me/types.h" -#include "parser/array.h" -#include "parser/language.h" -#include "parser/length.h" -#include "parser/stack.h" -#include "parser/subtree.h" -#include -#include - -#define MAX_LINK_COUNT 1 -#define MAX_NODE_POOL_SIZE 0 -#define MAX_ITERATOR_COUNT 0 - -typedef enum e_stack_status t_stack_status; -typedef struct s_stack_head t_stack_head; -typedef struct s_stack_iterator t_stack_iterator; -typedef struct s_stack_link t_stack_link; -typedef struct s_stack_node t_stack_node; -typedef struct s_summarize_stack_session t_summarize_stack_session; -typedef t_u32 t_stack_action; - -typedef t_stack_action (*t_stack_callback)(void *, - const t_stack_iterator *); - -struct s_stack_link -{ - t_stack_node *node; - Subtree subtree; - bool is_pending; -}; - -struct s_stack_node -{ - TSStateId state; - Length position; - t_stack_link links[MAX_LINK_COUNT]; - t_u16 link_count; - t_u32 ref_count; - t_u32 error_cost; - t_u32 node_count; - int dynamic_precedence; -}; - -struct s_stack_iterator -{ - t_stack_node *node; - SubtreeArray subtrees; - t_u32 subtree_count; - bool is_pending; -}; - -enum e_stack_status -{ - SStatusActive, - SStatusPaused, - SStatusHalted, -}; - -struct s_stack_head -{ - t_stack_node *node; - t_stack_summary *summary; - t_u32 node_count_at_last_error; - Subtree last_external_token; - Subtree lookahead_when_paused; - t_stack_status status; -}; - -struct s_stack -{ - Array(t_stack_head) heads; - t_stack_slice_array slices; - Array(t_stack_iterator) iterators; - t_stack_node *base_node; -}; - -enum e_stack_action -{ - SActionNone, - SActionStop = 1, - SActionPop = 2, -}; - -struct s_summarize_stack_session -{ - t_stack_summary *summary; - t_u32 max_depth; -}; - -static void stack_node_retain(t_stack_node *self) -{ - if (!self) - return ; - assert(self->ref_count > 0); - self->ref_count++; - assert(self->ref_count != 0); -} - -static void stack_node_release(t_stack_node *self) -{ - t_stack_node *first_predecessor; - t_stack_link link; - -recur: - assert(self->ref_count != 0); - self->ref_count--; - if (self->ref_count > 0) - return ; - first_predecessor = NULL; - if (self->link_count > 0) - { - for (t_u32 i = self->link_count - 1; i > 0; i--) - { - link = self->links[i]; - if (link.subtree) - ts_subtree_release(link.subtree); - stack_node_release(link.node); - } - link = self->links[0]; - if (link.subtree) - ts_subtree_release(link.subtree); - first_predecessor = self->links[0].node; - } - mem_free(self); - if (first_predecessor) - { - self = first_predecessor; - goto recur; - } -} - -/// Get the number of nodes in the subtree, for the purpose of measuring -/// how much progress has been made by a given version of the stack. -static t_u32 stack__subtree_node_count(Subtree subtree) -{ - t_u32 count; - - count = ts_subtree_visible_descendant_count(subtree); - if (ts_subtree_visible(subtree)) - count++; - // Count intermediate error nodes even though they are not visible, - // because a stack version's node count is used to check whether it - // has made any progress since the last time it encountered an error. - if (ts_subtree_symbol(subtree) == ts_builtin_sym_error_repeat) - count++; - return (count); -} - -static t_stack_node *stack_node_new(t_stack_node *previous_node, - Subtree subtree, bool is_pending, TSStateId state) -{ - t_stack_node *node; - - node = mem_alloc(sizeof(t_stack_node)); - *node = (t_stack_node){.ref_count = 1, .link_count = 0, .state = state}; - if (previous_node != NULL) - { - node->link_count = 1; - node->links[0] = (t_stack_link){ - .node = previous_node, - .subtree = subtree, - .is_pending = is_pending, - }; - node->position = previous_node->position; - node->error_cost = previous_node->error_cost; - node->dynamic_precedence = previous_node->dynamic_precedence; - node->node_count = previous_node->node_count; - if (subtree) - { - node->error_cost += ts_subtree_error_cost(subtree); - node->position = length_add(node->position, - ts_subtree_total_size(subtree)); - node->node_count += stack__subtree_node_count(subtree); - node->dynamic_precedence += ts_subtree_dynamic_precedence(subtree); - } - } - else - { - node->position = length_zero(); - node->error_cost = 0; - } - return (node); -} - -static bool stack__subtree_is_equivalent(Subtree left, Subtree right) -{ - if (left == right) - return (true); - if (!left || !right) - return (false); - // Symbols must match - if (ts_subtree_symbol(left) != ts_subtree_symbol(right)) - return (false); - // If both have errors, don't bother keeping both. - if (ts_subtree_error_cost(left) > 0 && ts_subtree_error_cost(right) > 0) - return (true); - return (ts_subtree_padding(left).bytes == ts_subtree_padding(right).bytes - && ts_subtree_size(left).bytes == ts_subtree_size(right).bytes - && ts_subtree_child_count(left) == ts_subtree_child_count(right) - && ts_subtree_extra(left) == ts_subtree_extra(right) - && ts_subtree_external_scanner_state_eq(left, right)); -} - -static void stack_node_add_link(t_stack_node *self, t_stack_link link) -{ - t_stack_link *existing_link; - t_i32 dynamic_precedence; - t_u32 node_count; - - if (link.node == self) - return ; - for (int i = 0; i < self->link_count; i++) - { - existing_link = &self->links[i]; - if (stack__subtree_is_equivalent(existing_link->subtree, link.subtree)) - { - // In general, - // we preserve ambiguities until they are removed from the stack - // during a pop operation where multiple paths lead to the same node. But in - // the special case where two links directly connect the same pair of nodes, - // we can safely remove the ambiguity ahead of time without changing behavior. - if (existing_link->node == link.node) - { - if (ts_subtree_dynamic_precedence(link.subtree) > ts_subtree_dynamic_precedence(existing_link->subtree)) - { - ts_subtree_retain(link.subtree); - ts_subtree_release(/*subtree_pool, - */ existing_link->subtree); - existing_link->subtree = link.subtree; - self->dynamic_precedence = link.node->dynamic_precedence - + ts_subtree_dynamic_precedence(link.subtree); - } - return ; - } - // If the previous nodes are mergeable, merge them recursively. - if (existing_link->node->state == link.node->state - && existing_link->node->position.bytes == link.node->position.bytes - && existing_link->node->error_cost == link.node->error_cost) - { - for (int j = 0; j < link.node->link_count; j++) - { - stack_node_add_link(existing_link->node, - link.node->links[j]); - } - dynamic_precedence = link.node->dynamic_precedence; - if (link.subtree) - { - dynamic_precedence - += ts_subtree_dynamic_precedence(link.subtree); - } - if (dynamic_precedence > self->dynamic_precedence) - { - self->dynamic_precedence = dynamic_precedence; - } - return ; - } - } - } - if (self->link_count == MAX_LINK_COUNT) - return ; - stack_node_retain(link.node); - node_count = link.node->node_count; - dynamic_precedence = link.node->dynamic_precedence; - self->links[self->link_count++] = link; - if (link.subtree) - { - ts_subtree_retain(link.subtree); - node_count += stack__subtree_node_count(link.subtree); - dynamic_precedence += ts_subtree_dynamic_precedence(link.subtree); - } - if (node_count > self->node_count) - self->node_count = node_count; - if (dynamic_precedence > self->dynamic_precedence) - self->dynamic_precedence = dynamic_precedence; -} - -static void stack_head_delete(t_stack_head *self) -{ - if (self->node) - { - if (self->last_external_token) - { - ts_subtree_release(self->last_external_token); - } - if (self->lookahead_when_paused) - { - ts_subtree_release(self->lookahead_when_paused); - } - if (self->summary) - { - array_delete(self->summary); - mem_free(self->summary); - } - stack_node_release(self->node); - } -} - -static t_stack_version ts_stack__add_version(t_stack *self, - t_stack_version original_version, t_stack_node *node) -{ - t_stack_head head; - - head = (t_stack_head){ - .node = node, - .node_count_at_last_error = self->heads.contents[original_version].node_count_at_last_error, - .last_external_token = self->heads.contents[original_version].last_external_token, - .status = SStatusActive, - .lookahead_when_paused = NULL, - }; - array_push(&self->heads, head); - stack_node_retain(node); - if (head.last_external_token) - ts_subtree_retain(head.last_external_token); - return ((t_stack_version)(self->heads.size - 1)); -} - -static void ts_stack__add_slice(t_stack *self, t_stack_version original_version, - t_stack_node *node, SubtreeArray *subtrees) -{ - t_stack_version version; - t_stack_slice slice; - - for (t_u32 i = self->slices.size - 1; i + 1 > 0; i--) - { - version = self->slices.contents[i].version; - if (self->heads.contents[version].node == node) - { - slice = (t_stack_slice){*subtrees, version}; - array_insert(&self->slices, i + 1, slice); - return ; - } - } - version = ts_stack__add_version(self, original_version, node); - slice = (t_stack_slice){*subtrees, version}; - array_push(&self->slices, slice); -} - -static 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; - - 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(), - .subtree_count = 0, - .is_pending = true, - }; - include_subtrees = false; - if (goal_subtree_count >= 0) - { - include_subtrees = true; - array_reserve(&new_iterator.subtrees, - (t_u32)ts_subtree_alloc_size(goal_subtree_count) / sizeof(Subtree)); - } - array_push(&self->iterators, new_iterator); - while (self->iterators.size > 0) - { - for (t_u32 i = 0, size = self->iterators.size; i < size; i++) - { - iterator = &self->iterators.contents[i]; - node = iterator->node; - action = callback(payload, iterator); - should_pop = action & SActionPop; - should_stop = action & SActionStop || node->link_count == 0; - if (should_pop) - { - subtrees = iterator->subtrees; - if (!should_stop) - { - ts_subtree_array_copy(subtrees, &subtrees); - } - ts_subtree_array_reverse(&subtrees); - ts_stack__add_slice(self, version, node, &subtrees); - } - if (should_stop) - { - if (!should_pop) - { - ts_subtree_array_delete(&iterator->subtrees); - } - array_erase(&self->iterators, i); - i--, size--; - continue ; - } - for (t_u32 j = 1; j <= node->link_count; j++) - { - if (j == node->link_count) - { - link = node->links[0]; - next_iterator = &self->iterators.contents[i]; - } - else - { - if (self->iterators.size >= MAX_ITERATOR_COUNT) - 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); - } - next_iterator->node = link.node; - if (link.subtree) - { - if (include_subtrees) - { - array_push(&next_iterator->subtrees, link.subtree); - ts_subtree_retain(link.subtree); - } - if (!ts_subtree_extra(link.subtree)) - { - next_iterator->subtree_count++; - if (!link.is_pending) - { - next_iterator->is_pending = false; - } - } - } - else - { - next_iterator->subtree_count++; - next_iterator->is_pending = false; - } - } - } - } - return (self->slices); -} - -t_stack *ts_stack_new(void) -{ - t_stack *self; - - self = mem_alloc(sizeof(*self)); - array_init(&self->heads); - array_init(&self->slices); - array_init(&self->iterators); - array_reserve(&self->heads, 4); - array_reserve(&self->slices, 4); - array_reserve(&self->iterators, 4); - self->base_node = stack_node_new(NULL, NULL, false, 1); - ts_stack_clear(self); - return (self); -} - -void ts_stack_delete(t_stack *self) -{ - if (self->slices.contents) - array_delete(&self->slices); - if (self->iterators.contents) - array_delete(&self->iterators); - stack_node_release(self->base_node); - for (t_u32 i = 0; i < self->heads.size; i++) - { - stack_head_delete(&self->heads.contents[i]); - } - array_clear(&self->heads); - array_delete(&self->heads); - mem_free(self); -} - -t_u32 ts_stack_version_count(const t_stack *self) -{ - return (self->heads.size); -} - -TSStateId ts_stack_state(const t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->node->state); -} - -Length ts_stack_position(const t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->node->position); -} - -Subtree ts_stack_last_external_token(const t_stack *self, - t_stack_version version) -{ - return (array_get(&self->heads, version)->last_external_token); -} - -void ts_stack_set_last_external_token(t_stack *self, t_stack_version version, - Subtree token) -{ - t_stack_head *head; - - head = array_get(&self->heads, version); - if (token) - ts_subtree_retain(token); - if (head->last_external_token) - ts_subtree_release(head->last_external_token); - head->last_external_token = token; -} - -t_u32 ts_stack_error_cost(const t_stack *self, t_stack_version version) -{ - t_stack_head *head; - t_u32 result; - - head = array_get(&self->heads, version); - result = head->node->error_cost; - if (head->status == SStatusPaused || (head->node->state == ERROR_STATE - && !head->node->links[0].subtree)) - { - result += ERROR_COST_PER_RECOVERY; - } - return (result); -} - -t_u32 ts_stack_node_count_since_error(const t_stack *self, - t_stack_version version) -{ - t_stack_head *head; - - head = array_get(&self->heads, version); - if (head->node->node_count < head->node_count_at_last_error) - { - head->node_count_at_last_error = head->node->node_count; - } - return (head->node->node_count - head->node_count_at_last_error); -} - -void ts_stack_push(t_stack *self, t_stack_version version, Subtree subtree, - bool pending, TSStateId state) -{ - t_stack_head *head; - t_stack_node *new_node; - - head = array_get(&self->heads, version); - new_node = stack_node_new(head->node, subtree, pending, state); - if (!subtree) - head->node_count_at_last_error = new_node->node_count; - head->node = new_node; -} - -t_stack_action pop_count_callback(void *payload, - const t_stack_iterator *iterator) -{ - t_u32 *goal_subtree_count; - - goal_subtree_count = payload; - if (iterator->subtree_count == *goal_subtree_count) - { - return (SActionPop | SActionStop); - } - else - { - return (SActionNone); - } -} - -t_stack_slice_array ts_stack_pop_count(t_stack *self, t_stack_version version, - t_u32 count) -{ - return (stack__iter(self, version, pop_count_callback, &count, (int)count)); -} - -t_stack_action pop_pending_callback(void *payload, - const t_stack_iterator *iterator) -{ - (void)payload; - if (iterator->subtree_count >= 1) - { - if (iterator->is_pending) - return (SActionPop | SActionStop); - else - return (SActionStop); - } - else - return (SActionNone); -} - -t_stack_slice_array ts_stack_pop_pending(t_stack *self, t_stack_version version) -{ - t_stack_slice_array pop; - - pop = stack__iter(self, version, pop_pending_callback, NULL, 0); - if (pop.size > 0) - { - ts_stack_renumber_version(self, pop.contents[0].version, version); - pop.contents[0].version = version; - } - return (pop); -} - -t_stack_action pop_error_callback(void *payload, - const t_stack_iterator *iterator) -{ - bool *found_error; - - if (iterator->subtrees.size > 0) - { - found_error = payload; - if (!*found_error - && ts_subtree_is_error(iterator->subtrees.contents[0])) - { - *found_error = true; - return (SActionPop | SActionStop); - } - else - return (SActionStop); - } - else - return (SActionNone); -} - -SubtreeArray ts_stack_pop_error(t_stack *self, t_stack_version version) -{ - t_stack_node *node; - bool found_error; - t_stack_slice_array pop; - t_usize i; - - node = array_get(&self->heads, version)->node; - i = 0; - while (i < node->link_count) - { - if (node->links[i].subtree - && ts_subtree_is_error(node->links[i].subtree)) - { - found_error = false; - 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].subtrees); - } - break ; - } - i++; - } - return ((SubtreeArray){.size = 0}); -} - -t_stack_action pop_all_callback(void *payload, - const t_stack_iterator *iterator) -{ - (void)payload; - if (iterator->node->link_count == 0) - return (SActionPop); - else - return (SActionNone); -} - -t_stack_slice_array ts_stack_pop_all(t_stack *self, t_stack_version version) -{ - return (stack__iter(self, version, pop_all_callback, NULL, 0)); -} - -t_stack_action summarize_stack_callback(void *payload, - const t_stack_iterator *iterator) -{ - t_summarize_stack_session *session; - TSStateId state; - t_u32 depth; - t_stack_summary_entry entry; - t_usize i; - - session = payload; - state = iterator->node->state; - depth = iterator->subtree_count; - if (depth > session->max_depth) - return (SActionStop); - i = session->summary->size - 1; - while (i + 1 > 0) - { - entry = session->summary->contents[i--]; - if (entry.depth < depth) - break ; - if (entry.depth == depth && entry.state == state) - return (SActionNone); - } - array_push(session->summary, - ((t_stack_summary_entry){ - .position = iterator->node->position, - .depth = depth, - .state = state, - })); - return (SActionNone); -} - -void ts_stack_record_summary(t_stack *self, t_stack_version version, - t_u32 max_depth) -{ - t_summarize_stack_session session; - t_stack_head *head; - - session = (t_summarize_stack_session){.summary = mem_alloc(sizeof(t_stack_summary)), .max_depth = max_depth}; - array_init(session.summary); - stack__iter(self, version, summarize_stack_callback, &session, -1); - head = &self->heads.contents[version]; - if (head->summary) - { - array_delete(head->summary); - mem_free(head->summary); - } - head->summary = session.summary; -} - -t_stack_summary *ts_stack_get_summary(t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->summary); -} - -int ts_stack_dynamic_precedence(t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->node->dynamic_precedence); -} - -bool ts_stack_has_advanced_since_error(const t_stack *self, - t_stack_version version) -{ - const t_stack_head *head = array_get(&self->heads, version); - const t_stack_node *node = head->node; - Subtree subtree; - - if (node->error_cost == 0) - return (true); - while (node) - { - if (node->link_count > 0) - { - subtree = node->links[0].subtree; - if (subtree) - { - if (ts_subtree_total_bytes(subtree) > 0) - { - return (true); - } - else if (node->node_count > head->node_count_at_last_error - && ts_subtree_error_cost(subtree) == 0) - { - node = node->links[0].node; - continue ; - } - } - } - break ; - } - return (false); -} - -void ts_stack_remove_version(t_stack *self, t_stack_version version) -{ - stack_head_delete(array_get(&self->heads, version)); - array_erase(&self->heads, version); -} - -void ts_stack_renumber_version(t_stack *self, t_stack_version v1, - t_stack_version v2) -{ - t_stack_head *source_head; - t_stack_head *target_head; - - if (v1 == v2) - return ; - assert(v2 < v1); - assert((t_u32)v1 < self->heads.size); - source_head = &self->heads.contents[v1]; - target_head = &self->heads.contents[v2]; - if (target_head->summary && !source_head->summary) - { - source_head->summary = target_head->summary; - target_head->summary = NULL; - } - stack_head_delete(target_head); - *target_head = *source_head; - array_erase(&self->heads, v1); -} - -void ts_stack_swap_versions(t_stack *self, t_stack_version v1, - t_stack_version v2) -{ - t_stack_head temporary_head; - - temporary_head = self->heads.contents[v1]; - self->heads.contents[v1] = self->heads.contents[v2]; - self->heads.contents[v2] = temporary_head; -} - -t_stack_version ts_stack_copy_version(t_stack *self, t_stack_version version) -{ - t_stack_head *head; - - assert(version < self->heads.size); - array_push(&self->heads, self->heads.contents[version]); - head = array_back(&self->heads); - stack_node_retain(head->node); - if (head->last_external_token) - ts_subtree_retain(head->last_external_token); - head->summary = NULL; - return (self->heads.size - 1); -} - -bool ts_stack_merge(t_stack *self, t_stack_version version1, - t_stack_version version2) -{ - t_stack_head *head1; - t_stack_head *head2; - t_usize i; - - if (!ts_stack_can_merge(self, version1, version2)) - return (false); - head1 = &self->heads.contents[version1]; - head2 = &self->heads.contents[version2]; - i = 0; - while (i < head2->node->link_count) - stack_node_add_link(head1->node, head2->node->links[i++]); - if (head1->node->state == ERROR_STATE) - head1->node_count_at_last_error = head1->node->node_count; - ts_stack_remove_version(self, version2); - return (true); -} - -bool ts_stack_can_merge(t_stack *self, t_stack_version version1, - t_stack_version version2) -{ - t_stack_head *head1; - t_stack_head *head2; - - head1 = &self->heads.contents[version1]; - head2 = &self->heads.contents[version2]; - return (head1->status == SStatusActive && head2->status == SStatusActive - && head1->node->state == head2->node->state - && head1->node->position.bytes == head2->node->position.bytes - && head1->node->error_cost == head2->node->error_cost - && ts_subtree_external_scanner_state_eq(head1->last_external_token, - head2->last_external_token)); -} - -void ts_stack_halt(t_stack *self, t_stack_version version) -{ - array_get(&self->heads, version)->status = SStatusHalted; -} - -void ts_stack_pause(t_stack *self, t_stack_version version, - Subtree lookahead) -{ - t_stack_head *head; - - head = array_get(&self->heads, version); - head->status = SStatusPaused; - head->lookahead_when_paused = lookahead; - head->node_count_at_last_error = head->node->node_count; -} - -bool ts_stack_is_active(const t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->status == SStatusActive); -} - -bool ts_stack_is_halted(const t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->status == SStatusHalted); -} - -bool ts_stack_is_paused(const t_stack *self, t_stack_version version) -{ - return (array_get(&self->heads, version)->status == SStatusPaused); -} - -Subtree ts_stack_resume(t_stack *self, t_stack_version version) -{ - t_stack_head *head; - Subtree result; - - head = array_get(&self->heads, version); - assert(head->status == SStatusPaused); - result = head->lookahead_when_paused; - head->status = SStatusActive; - head->lookahead_when_paused = NULL; - return (result); -} - -void ts_stack_clear(t_stack *self) -{ - t_usize i; - - stack_node_retain(self->base_node); - i = 0; - while (i < self->heads.size) - stack_head_delete(&self->heads.contents[i++]); - array_clear(&self->heads); - array_push(&self->heads, - ((t_stack_head){ - .node = self->base_node, - .status = SStatusActive, - .last_external_token = NULL, - .lookahead_when_paused = NULL, - })); -} - -#undef forceinline diff --git a/parser/src/stack/stack_add_link.c b/parser/src/stack/stack_add_link.c new file mode 100644 index 00000000..08bdd1ef --- /dev/null +++ b/parser/src/stack/stack_add_link.c @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_add_link.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:52:46 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:59:20 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +// In general, +// we preserve ambiguities until they are removed from the stack +// during a pop operation where multiple paths lead to the same node. But in +// the special case where two links directly connect the same pair of nodes, +// we can safely remove the ambiguity ahead of time without changing behavior. +void stack_node_add_link(t_stack_node *self, t_stack_link link) +{ + t_stack_link *existing_link; + t_i32 dynamic_precedence; + t_u32 node_count; + t_usize i; + t_usize j; + + if (link.node == self) + return ; + i = 0; + while (i < self->link_count) + { + existing_link = &self->links[i]; + if (stack__subtree_is_equivalent(existing_link->subtree, link.subtree)) + { + if (existing_link->node == link.node) + { + if (ts_subtree_dynamic_precedence(\ + link.subtree) > ts_subtree_dynamic_precedence(existing_link->subtree)) + { + ts_subtree_retain(link.subtree); + ts_subtree_release(existing_link->subtree); + existing_link->subtree = link.subtree; + self->dynamic_precedence = link.node->dynamic_precedence + + ts_subtree_dynamic_precedence(link.subtree); + } + return ; + } + if (existing_link->node->state == link.node->state \ + && existing_link->node->position.bytes == link.node->position.bytes + && existing_link->node->error_cost == link.node->error_cost) + { + j = 0; + while (j < link.node->link_count) + stack_node_add_link(existing_link->node, + link.node->links[j++]); + dynamic_precedence = link.node->dynamic_precedence; + if (link.subtree) + dynamic_precedence + += ts_subtree_dynamic_precedence(link.subtree); + if (dynamic_precedence > self->dynamic_precedence) + self->dynamic_precedence = dynamic_precedence; + return ; + } + } + i++; + } + if (self->link_count == MAX_LINK_COUNT) + return ; + stack_node_retain(link.node); + node_count = link.node->node_count; + dynamic_precedence = link.node->dynamic_precedence; + self->links[self->link_count++] = link; + if (link.subtree) + { + ts_subtree_retain(link.subtree); + node_count += stack__subtree_node_count(link.subtree); + dynamic_precedence += ts_subtree_dynamic_precedence(link.subtree); + } + if (node_count > self->node_count) + self->node_count = node_count; + if (dynamic_precedence > self->dynamic_precedence) + self->dynamic_precedence = dynamic_precedence; +} diff --git a/parser/src/stack/stack_funcs1.c b/parser/src/stack/stack_funcs1.c new file mode 100644 index 00000000..f87d2a5a --- /dev/null +++ b/parser/src/stack/stack_funcs1.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_funcs1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:52:03 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:58:37 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +bool ts_stack_is_active(const t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->status == SStatusActive); +} + +bool ts_stack_is_halted(const t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->status == SStatusHalted); +} + +bool ts_stack_is_paused(const t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->status == SStatusPaused); +} + +Subtree ts_stack_resume(t_stack *self, t_stack_version version) +{ + t_stack_head *head; + Subtree result; + + head = array_get(&self->heads, version); + assert(head->status == SStatusPaused); + result = head->lookahead_when_paused; + head->status = SStatusActive; + head->lookahead_when_paused = NULL; + return (result); +} + +void ts_stack_clear(t_stack *self) +{ + t_usize i; + + stack_node_retain(self->base_node); + i = 0; + while (i < self->heads.size) + stack_head_delete(&self->heads.contents[i++]); + array_clear(&self->heads); + array_push(&self->heads, ((t_stack_head){.node = self->base_node, \ + .status = SStatusActive, .last_external_token = NULL, \ + .lookahead_when_paused = NULL, })); +} diff --git a/parser/src/stack/stack_funcs2.c b/parser/src/stack/stack_funcs2.c new file mode 100644 index 00000000..81e4cadd --- /dev/null +++ b/parser/src/stack/stack_funcs2.c @@ -0,0 +1,80 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_funcs2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:55:52 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:56:19 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +t_u32 ts_stack_error_cost(const t_stack *self, t_stack_version version) +{ + t_stack_head *head; + t_u32 result; + + head = array_get(&self->heads, version); + result = head->node->error_cost; + if (head->status == SStatusPaused || (head->node->state == ERROR_STATE + && !head->node->links[0].subtree)) + { + result += ERROR_COST_PER_RECOVERY; + } + return (result); +} + +t_u32 ts_stack_node_count_since_error(const t_stack *self, + t_stack_version version) +{ + t_stack_head *head; + + head = array_get(&self->heads, version); + if (head->node->node_count < head->node_count_at_last_error) + { + head->node_count_at_last_error = head->node->node_count; + } + return (head->node->node_count - head->node_count_at_last_error); +} + +int ts_stack_dynamic_precedence(t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->node->dynamic_precedence); +} + +bool ts_stack_has_advanced_since_error(const t_stack *self, + t_stack_version version) +{ + const t_stack_head *head = array_get(&self->heads, version); + const t_stack_node *node = head->node; + Subtree subtree; + + if (node->error_cost == 0) + return (true); + while (node) + { + if (node->link_count > 0) + { + subtree = node->links[0].subtree; + if (subtree) + { + if (ts_subtree_total_bytes(subtree) > 0) + { + return (true); + } + else if (node->node_count > head->node_count_at_last_error + && ts_subtree_error_cost(subtree) == 0) + { + node = node->links[0].node; + continue ; + } + } + } + break ; + } + return (false); +} diff --git a/parser/src/stack/stack_funcs3.c b/parser/src/stack/stack_funcs3.c new file mode 100644 index 00000000..69ffefe0 --- /dev/null +++ b/parser/src/stack/stack_funcs3.c @@ -0,0 +1,110 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_funcs3.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:56:40 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:56:49 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +bool stack__subtree_is_equivalent(Subtree left, Subtree right) +{ + if (left == right) + return (true); + if (!left || !right) + return (false); + if (ts_subtree_symbol(left) != ts_subtree_symbol(right)) + return (false); + if (ts_subtree_error_cost(left) > 0 && ts_subtree_error_cost(right) > 0) + return (true); + return (ts_subtree_padding(left).bytes == ts_subtree_padding(right).bytes + && ts_subtree_size(left).bytes == ts_subtree_size(right).bytes + && ts_subtree_child_count(left) == ts_subtree_child_count(right) + && ts_subtree_extra(left) == ts_subtree_extra(right) + && ts_subtree_external_scanner_state_eq(left, right)); +} + +void stack_head_delete(t_stack_head *self) +{ + if (self->node) + { + if (self->last_external_token) + { + ts_subtree_release(self->last_external_token); + } + if (self->lookahead_when_paused) + { + ts_subtree_release(self->lookahead_when_paused); + } + if (self->summary) + { + array_delete(self->summary); + mem_free(self->summary); + } + stack_node_release(self->node); + } +} + +t_stack_version ts_stack__add_version(t_stack *self, + t_stack_version original_version, t_stack_node *node) +{ + t_stack_head head; + + head = (t_stack_head){ + .node = node, + .node_count_at_last_error = \ + self->heads.contents[original_version].node_count_at_last_error, + .last_external_token = \ + self->heads.contents[original_version].last_external_token, + .status = SStatusActive, + .lookahead_when_paused = NULL, + }; + array_push(&self->heads, head); + stack_node_retain(node); + if (head.last_external_token) + ts_subtree_retain(head.last_external_token); + return ((t_stack_version)(self->heads.size - 1)); +} + +void ts_stack__add_slice(t_stack *self, \ +t_stack_version original_version, t_stack_node *node, SubtreeArray *subtrees) +{ + t_u32 i; + t_stack_version version; + t_stack_slice slice; + + i = self->slices.size - 1; + while (i + 1 > 0) + { + version = self->slices.contents[i].version; + if (self->heads.contents[version].node == node) + { + slice = (t_stack_slice){.subtrees = *subtrees, .version = version}; + array_insert(&self->slices, i + 1, slice); + return ; + } + i--; + } + version = ts_stack__add_version(self, original_version, node); + slice = (t_stack_slice){.subtrees = *subtrees, .version = version}; + array_push(&self->slices, slice); +} + +void ts_stack_set_last_external_token(t_stack *self, t_stack_version version, + Subtree token) +{ + t_stack_head *head; + + head = array_get(&self->heads, version); + if (token) + ts_subtree_retain(token); + if (head->last_external_token) + ts_subtree_release(head->last_external_token); + head->last_external_token = token; +} diff --git a/parser/src/stack/stack_funcs4.c b/parser/src/stack/stack_funcs4.c new file mode 100644 index 00000000..204b22ca --- /dev/null +++ b/parser/src/stack/stack_funcs4.c @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_funcs4.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:58:39 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:58:51 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +t_u32 ts_stack_version_count(const t_stack *self) +{ + return (self->heads.size); +} + +TSStateId ts_stack_state(const t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->node->state); +} + +Length ts_stack_position(const t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->node->position); +} + +Subtree ts_stack_last_external_token(const t_stack *self, + t_stack_version version) +{ + return (array_get(&self->heads, version)->last_external_token); +} diff --git a/parser/src/stack/stack_iter.c b/parser/src/stack/stack_iter.c new file mode 100644 index 00000000..36d59fc0 --- /dev/null +++ b/parser/src/stack/stack_iter.c @@ -0,0 +1,129 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_iter.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:46:43 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:47:21 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#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_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; + + 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(), + .subtree_count = 0, + .is_pending = true, + }; + include_subtrees = false; + if (goal_subtree_count >= 0) + { + include_subtrees = true; + array_reserve(&new_iterator.subtrees, + (t_u32)ts_subtree_alloc_size(goal_subtree_count) / sizeof(Subtree)); + } + array_push(&self->iterators, new_iterator); + while (self->iterators.size > 0) + { + i = 0; + size = self->iterators.size; + while (i < size) + { + iterator = &self->iterators.contents[i]; + node = iterator->node; + action = callback(payload, iterator); + should_pop = action & SActionPop; + should_stop = action & SActionStop || node->link_count == 0; + if (should_pop) + { + subtrees = iterator->subtrees; + if (!should_stop) + ts_subtree_array_copy(subtrees, &subtrees); + ts_subtree_array_reverse(&subtrees); + ts_stack__add_slice(self, version, node, &subtrees); + } + if (should_stop) + { + if (!should_pop) + ts_subtree_array_delete(&iterator->subtrees); + array_erase(&self->iterators, i); + i--; + i++; + size--; + continue ; + } + j = 1; + while (j <= node->link_count) + { + if (j == node->link_count) + { + link = node->links[0]; + next_iterator = &self->iterators.contents[i]; + } + else + { + if (self->iterators.size >= MAX_ITERATOR_COUNT) + { + j++; + 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); + } + next_iterator->node = link.node; + if (link.subtree) + { + if (include_subtrees) + { + array_push(&next_iterator->subtrees, link.subtree); + ts_subtree_retain(link.subtree); + } + if (!ts_subtree_extra(link.subtree)) + { + next_iterator->subtree_count++; + if (!link.is_pending) + next_iterator->is_pending = false; + } + } + else + { + next_iterator->subtree_count++; + next_iterator->is_pending = false; + } + j++; + } + i++; + } + } + return (self->slices); +} diff --git a/parser/src/stack/stack_lifetime.c b/parser/src/stack/stack_lifetime.c new file mode 100644 index 00000000..d65726d0 --- /dev/null +++ b/parser/src/stack/stack_lifetime.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_lifetime.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:47:47 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:48:13 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/stack.h" +#include "parser/stack.h" + +t_stack *ts_stack_new(void) +{ + t_stack *self; + + self = mem_alloc(sizeof(*self)); + array_init(&self->heads); + array_init(&self->slices); + array_init(&self->iterators); + array_reserve(&self->heads, 4); + array_reserve(&self->slices, 4); + array_reserve(&self->iterators, 4); + self->base_node = stack_node_new(NULL, NULL, false, 1); + ts_stack_clear(self); + return (self); +} + +void ts_stack_delete(t_stack *self) +{ + t_usize i; + + i = 0; + if (self->slices.contents) + array_delete(&self->slices); + if (self->iterators.contents) + array_delete(&self->iterators); + stack_node_release(self->base_node); + while (i < self->heads.size) + stack_head_delete(&self->heads.contents[i++]); + array_clear(&self->heads); + array_delete(&self->heads); + mem_free(self); +} diff --git a/parser/src/stack/stack_manipulate.c b/parser/src/stack/stack_manipulate.c new file mode 100644 index 00000000..3920d4c2 --- /dev/null +++ b/parser/src/stack/stack_manipulate.c @@ -0,0 +1,77 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_manipulate.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:50:04 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:00:34 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/stack.h" +#include "parser/language.h" + +void ts_stack_push(t_stack *self, t_stack_version version, Subtree subtree, + bool pending, TSStateId state) +{ + t_stack_head *head; + t_stack_node *new_node; + + head = array_get(&self->heads, version); + new_node = stack_node_new(head->node, subtree, pending, state); + if (!subtree) + head->node_count_at_last_error = new_node->node_count; + head->node = new_node; +} + +t_stack_action pop_count_callback(void *payload, + const t_stack_iterator *iterator) +{ + t_u32 *goal_subtree_count; + + goal_subtree_count = payload; + if (iterator->subtree_count == *goal_subtree_count) + { + return (SActionPop | SActionStop); + } + else + { + return (SActionNone); + } +} + +t_stack_slice_array ts_stack_pop_count(t_stack *self, t_stack_version version, + t_u32 count) +{ + return (stack__iter(self, version, pop_count_callback, &count, (int)count)); +} + +t_stack_action pop_pending_callback(void *payload, + const t_stack_iterator *iterator) +{ + (void)payload; + if (iterator->subtree_count >= 1) + { + if (iterator->is_pending) + return (SActionPop | SActionStop); + else + return (SActionStop); + } + else + return (SActionNone); +} + +t_stack_slice_array ts_stack_pop_pending(t_stack *self, t_stack_version version) +{ + t_stack_slice_array pop; + + pop = stack__iter(self, version, pop_pending_callback, NULL, 0); + if (pop.size > 0) + { + ts_stack_renumber_version(self, pop.contents[0].version, version); + pop.contents[0].version = version; + } + return (pop); +} diff --git a/parser/src/stack/stack_manipulate2.c b/parser/src/stack/stack_manipulate2.c new file mode 100644 index 00000000..21291a88 --- /dev/null +++ b/parser/src/stack/stack_manipulate2.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_manipulate2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:54:26 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:59:43 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/types.h" +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +bool ts_stack_merge(t_stack *self, t_stack_version version1, + t_stack_version version2) +{ + t_stack_head *head1; + t_stack_head *head2; + t_usize i; + + if (!ts_stack_can_merge(self, version1, version2)) + return (false); + head1 = &self->heads.contents[version1]; + head2 = &self->heads.contents[version2]; + i = 0; + while (i < head2->node->link_count) + stack_node_add_link(head1->node, head2->node->links[i++]); + if (head1->node->state == ERROR_STATE) + head1->node_count_at_last_error = head1->node->node_count; + ts_stack_remove_version(self, version2); + return (true); +} + +bool ts_stack_can_merge(t_stack *self, t_stack_version version1, + t_stack_version version2) +{ + t_stack_head *head1; + t_stack_head *head2; + + head1 = &self->heads.contents[version1]; + head2 = &self->heads.contents[version2]; + return (head1->status == SStatusActive && head2->status == SStatusActive + && head1->node->state == head2->node->state + && head1->node->position.bytes == head2->node->position.bytes + && head1->node->error_cost == head2->node->error_cost + && ts_subtree_external_scanner_state_eq(head1->last_external_token, + head2->last_external_token)); +} + +void ts_stack_halt(t_stack *self, t_stack_version version) +{ + array_get(&self->heads, version)->status = SStatusHalted; +} + +void ts_stack_pause(t_stack *self, t_stack_version version, + Subtree lookahead) +{ + t_stack_head *head; + + head = array_get(&self->heads, version); + head->status = SStatusPaused; + head->lookahead_when_paused = lookahead; + head->node_count_at_last_error = head->node->node_count; +} diff --git a/parser/src/stack/stack_manipulate3.c b/parser/src/stack/stack_manipulate3.c new file mode 100644 index 00000000..901103db --- /dev/null +++ b/parser/src/stack/stack_manipulate3.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_manipulate3.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 17:00:07 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 17:00:41 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +t_stack_action pop_error_callback(void *payload, + const t_stack_iterator *iterator) +{ + bool *found_error; + + if (iterator->subtrees.size > 0) + { + found_error = payload; + if (!*found_error + && ts_subtree_is_error(iterator->subtrees.contents[0])) + { + *found_error = true; + return (SActionPop | SActionStop); + } + else + return (SActionStop); + } + else + return (SActionNone); +} + +SubtreeArray ts_stack_pop_error(t_stack *self, t_stack_version version) +{ + t_stack_node *node; + bool found_error; + t_stack_slice_array pop; + t_usize i; + + node = array_get(&self->heads, version)->node; + i = 0; + while (i < node->link_count) + { + if (node->links[i].subtree + && ts_subtree_is_error(node->links[i].subtree)) + { + found_error = false; + 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].subtrees); + } + break ; + } + i++; + } + return ((SubtreeArray){.size = 0}); +} + +t_stack_action pop_all_callback(void *payload, + const t_stack_iterator *iterator) +{ + (void)payload; + if (iterator->node->link_count == 0) + return (SActionPop); + else + return (SActionNone); +} + +t_stack_slice_array ts_stack_pop_all(t_stack *self, t_stack_version version) +{ + return (stack__iter(self, version, pop_all_callback, NULL, 0)); +} diff --git a/parser/src/stack/stack_node.c b/parser/src/stack/stack_node.c new file mode 100644 index 00000000..a07e8f35 --- /dev/null +++ b/parser/src/stack/stack_node.c @@ -0,0 +1,119 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_node.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:48:48 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:49:38 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/_inner/stack.h" +#include "parser/language.h" +#include "parser/stack.h" + +void stack_node_retain(t_stack_node *self) +{ + if (!self) + return ; + assert(self->ref_count > 0); + self->ref_count++; + assert(self->ref_count != 0); +} + +void stack_node_release(t_stack_node *self) +{ + t_stack_node *first_predecessor; + t_stack_link link; + bool continue_; + t_usize i; + + continue_ = true; + while (continue_) + { + continue_ = false; + assert(self->ref_count != 0); + self->ref_count--; + if (self->ref_count > 0) + return ; + first_predecessor = NULL; + if (self->link_count > 0) + { + i = self->link_count - 1; + while (i > 0) + { + link = self->links[i]; + if (link.subtree) + ts_subtree_release(link.subtree); + stack_node_release(link.node); + i--; + } + link = self->links[0]; + if (link.subtree) + ts_subtree_release(link.subtree); + first_predecessor = self->links[0].node; + } + mem_free(self); + if (first_predecessor) + { + self = first_predecessor; + continue_ = true; + } + } +} + +/// Get the number of nodes in the subtree, for the purpose of measuring +/// how much progress has been made by a given version of the stack. +// +// Count intermediate error nodes even though they are not visible, +// because a stack version's node count is used to check whether it +// has made any progress since the last time it encountered an error. +t_u32 stack__subtree_node_count(Subtree subtree) +{ + t_u32 count; + + count = ts_subtree_visible_descendant_count(subtree); + if (ts_subtree_visible(subtree)) + count++; + if (ts_subtree_symbol(subtree) == ts_builtin_sym_error_repeat) + count++; + return (count); +} + +t_stack_node *stack_node_new(t_stack_node *previous_node, + Subtree subtree, bool is_pending, TSStateId state) +{ + t_stack_node *node; + + node = mem_alloc(sizeof(t_stack_node)); + *node = (t_stack_node){.ref_count = 1, .link_count = 0, .state = state}; + if (previous_node != NULL) + { + node->link_count = 1; + node->links[0] = (t_stack_link){ + .node = previous_node, + .subtree = subtree, + .is_pending = is_pending, + }; + node->position = previous_node->position; + node->error_cost = previous_node->error_cost; + node->dynamic_precedence = previous_node->dynamic_precedence; + node->node_count = previous_node->node_count; + if (subtree) + { + node->error_cost += ts_subtree_error_cost(subtree); + node->position = length_add(node->position, + ts_subtree_total_size(subtree)); + node->node_count += stack__subtree_node_count(subtree); + node->dynamic_precedence += ts_subtree_dynamic_precedence(subtree); + } + } + else + { + node->position = length_zero(); + node->error_cost = 0; + } + return (node); +} diff --git a/parser/src/stack/stack_summary.c b/parser/src/stack/stack_summary.c new file mode 100644 index 00000000..52aef009 --- /dev/null +++ b/parser/src/stack/stack_summary.c @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_summary.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:50:56 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:51:36 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +t_stack_action summarize_stack_callback(void *payload, + const t_stack_iterator *iterator) +{ + t_summarize_stack_session *session; + TSStateId state; + t_u32 depth; + t_stack_summary_entry entry; + t_usize i; + + session = payload; + state = iterator->node->state; + depth = iterator->subtree_count; + if (depth > session->max_depth) + return (SActionStop); + i = session->summary->size - 1; + while (i + 1 > 0) + { + entry = session->summary->contents[i--]; + if (entry.depth < depth) + break ; + if (entry.depth == depth && entry.state == state) + return (SActionNone); + } + array_push(session->summary, ((t_stack_summary_entry){\ + .position = iterator->node->position, .depth = depth, .state = state, })); + return (SActionNone); +} + +void ts_stack_record_summary(t_stack *self, t_stack_version version, + t_u32 max_depth) +{ + t_summarize_stack_session session; + t_stack_head *head; + + session = (t_summarize_stack_session){.summary = \ + mem_alloc(sizeof(t_stack_summary)), .max_depth = max_depth}; + array_init(session.summary); + stack__iter(self, version, summarize_stack_callback, &session, -1); + head = &self->heads.contents[version]; + if (head->summary) + { + array_delete(head->summary); + mem_free(head->summary); + } + head->summary = session.summary; +} + +t_stack_summary *ts_stack_get_summary(t_stack *self, t_stack_version version) +{ + return (array_get(&self->heads, version)->summary); +} diff --git a/parser/src/stack/stack_version.c b/parser/src/stack/stack_version.c new file mode 100644 index 00000000..b359ee10 --- /dev/null +++ b/parser/src/stack/stack_version.c @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stack_version.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/08/31 16:55:04 by maiboyer #+# #+# */ +/* Updated: 2024/08/31 16:55:34 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "parser/stack.h" +#include "parser/_inner/stack.h" + +void ts_stack_remove_version(t_stack *self, t_stack_version version) +{ + stack_head_delete(array_get(&self->heads, version)); + array_erase(&self->heads, version); +} + +void ts_stack_renumber_version(t_stack *self, t_stack_version v1, + t_stack_version v2) +{ + t_stack_head *source_head; + t_stack_head *target_head; + + if (v1 == v2) + return ; + assert(v2 < v1); + assert((t_u32)v1 < self->heads.size); + source_head = &self->heads.contents[v1]; + target_head = &self->heads.contents[v2]; + if (target_head->summary && !source_head->summary) + { + source_head->summary = target_head->summary; + target_head->summary = NULL; + } + stack_head_delete(target_head); + *target_head = *source_head; + array_erase(&self->heads, v1); +} + +void ts_stack_swap_versions(t_stack *self, t_stack_version v1, + t_stack_version v2) +{ + t_stack_head temporary_head; + + temporary_head = self->heads.contents[v1]; + self->heads.contents[v1] = self->heads.contents[v2]; + self->heads.contents[v2] = temporary_head; +} + +t_stack_version ts_stack_copy_version(t_stack *self, t_stack_version version) +{ + t_stack_head *head; + + assert(version < self->heads.size); + array_push(&self->heads, self->heads.contents[version]); + head = array_back(&self->heads); + stack_node_retain(head->node); + if (head->last_external_token) + ts_subtree_retain(head->last_external_token); + head->summary = NULL; + return (self->heads.size - 1); +}