/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* stack_add_link.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: maiboyer +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/08/31 16:52:46 by maiboyer #+# #+# */ /* Updated: 2024/09/19 18:49:32 by maiboyer ### ########.fr */ /* */ /* ************************************************************************** */ #include "parser/inner/stack_inner.h" #include "parser/inner/stack_inner.h" void _add_link_tail(t_stack_node *self, t_stack_link link) { t_i32 dynamic_precedence; t_u32 node_count; 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) { (link.subtree->ref_count++); 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; } bool _is_link_node_similar(\ t_stack_node *self, t_stack_link link, \ t_stack_link *ext_link) { t_usize j; t_i32 dynamic_precedence; if (ext_link->node->state == link.node->state \ && ext_link->node->position.bytes == link.node->position.bytes && ext_link->node->error_cost == link.node->error_cost) { j = 0; while (j < link.node->link_count) stack_node_add_link(ext_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 (true); } return (false); } bool _is_link_same_node(\ t_stack_node *self, t_stack_link link, \ t_stack_link *ext_link) { if (ext_link->node == link.node) { if (ts_subtree_dynamic_precedence(\ link.subtree) > ts_subtree_dynamic_precedence(ext_link->subtree)) { link.subtree->ref_count++; ts_subtree_release(ext_link->subtree); ext_link->subtree = link.subtree; self->dynamic_precedence = link.node->dynamic_precedence + ts_subtree_dynamic_precedence(link.subtree); } return (true); } return (false); } // 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 *ext_link; t_usize i; if (link.node == self) return ; i = 0; while (i < self->link_count) { ext_link = &self->links[i]; if (stack__subtree_is_equivalent(ext_link->subtree, link.subtree)) { if (_is_link_same_node(self, link, ext_link) \ || _is_link_node_similar(self, link, ext_link)) return ; } i++; } _add_link_tail(self, link); }