110 lines
3.5 KiB
C
110 lines
3.5 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* stack_add_link.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* 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);
|
|
}
|