gux/lang/src/node.c

159 lines
2.8 KiB
C
Raw Normal View History

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;
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);
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;
}
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);
}