2024-02-10 15:16:00 +00:00
|
|
|
#include "node.h"
|
|
|
|
#include "vec.h"
|
|
|
|
|
|
|
|
GUX_ENUM_C(NodeType, NODE_TYPE);
|
|
|
|
|
|
|
|
void node_init(struct node* self, enum NodeType type,
|
|
|
|
char const* value, int line)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
self->type = type;
|
|
|
|
self->value = strdup(value);
|
|
|
|
vec_init(&self->children, 1);
|
|
|
|
self->line = line;
|
2024-02-12 19:21:05 +00:00
|
|
|
self->parent = NULL;
|
2024-02-10 15:16:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void node_free(struct node* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
free(self->value);
|
|
|
|
|
|
|
|
for (size_t i=0; i<self->children.size; i++)
|
|
|
|
{
|
|
|
|
node_free(self->children.data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
vec_free_elements(&self->children);
|
|
|
|
vec_free(&self->children);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node* node_add_new_child(struct node* self,
|
|
|
|
enum NodeType type, char const* value)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
struct node* child = malloc(sizeof(struct node));
|
|
|
|
node_init(child, type, value, self->line);
|
|
|
|
|
|
|
|
vec_push(&self->children, child);
|
|
|
|
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node* node_add_child(struct node* self, struct node* child)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
vec_push(&self->children, child);
|
2024-02-12 19:21:05 +00:00
|
|
|
child->parent = self;
|
2024-02-10 15:16:00 +00:00
|
|
|
return child;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t node_str(struct node* self, char* buffer, size_t size)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
assert(buffer);
|
|
|
|
|
|
|
|
size_t sz = 0;
|
|
|
|
|
|
|
|
sz += snprintf(buffer + sz, size - sz, "%s",
|
|
|
|
NodeTypeStr[self->type] + strlen("NODE_"));
|
|
|
|
|
|
|
|
if (strcmp(self->value, "") != 0)
|
|
|
|
{
|
|
|
|
sz += snprintf(buffer + sz, size - sz, "[%s]", self->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self->children.size > 0)
|
|
|
|
{
|
|
|
|
sz += snprintf(buffer + sz, size - sz, "(");
|
|
|
|
|
|
|
|
for (size_t i=0; i<self->children.size; i++)
|
|
|
|
{
|
|
|
|
if (i > 0)
|
|
|
|
{
|
|
|
|
sz += snprintf(buffer + sz, size - sz, ",");
|
|
|
|
}
|
|
|
|
|
|
|
|
sz += node_str(self->children.data[i], buffer + sz, size - sz);
|
|
|
|
}
|
|
|
|
|
|
|
|
sz += snprintf(buffer + sz, size - sz, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
return sz;
|
|
|
|
}
|
2024-02-12 19:21:05 +00:00
|
|
|
|
|
|
|
int node_depth(struct node* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
struct node* itr = self;
|
|
|
|
int depth = 0;
|
|
|
|
|
|
|
|
while (itr != NULL)
|
|
|
|
{
|
|
|
|
if (itr->type == NODE_BLOCK)
|
|
|
|
{
|
|
|
|
depth++;
|
|
|
|
}
|
|
|
|
|
|
|
|
itr = itr->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return depth;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct node* node_try_find_parent(struct node* self, enum NodeType type)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
|
|
|
|
struct node* p = self;
|
|
|
|
|
|
|
|
while (p != NULL && p->type != type)
|
|
|
|
{
|
|
|
|
p = p->parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t node_parent_index(struct node* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
|
|
|
|
struct node* parent = self->parent;
|
|
|
|
|
|
|
|
if (parent == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i=0; i<parent->children.size; i++)
|
|
|
|
{
|
|
|
|
if (parent->children.data[i] == self)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t node_block_index(struct node* self)
|
|
|
|
{
|
|
|
|
assert(self);
|
|
|
|
struct node* block = node_try_find_parent(self, NODE_BLOCK);
|
|
|
|
|
|
|
|
if (block == NULL)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (self->parent == block)
|
|
|
|
{
|
|
|
|
return node_parent_index(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
return node_block_index(self->parent);
|
|
|
|
}
|