changed ast implementation to use glib
This commit is contained in:
parent
aa5d0b0710
commit
f069d04ad1
109
src/ast/ast.c
109
src/ast/ast.c
|
@ -5,11 +5,25 @@
|
||||||
#include <sys/log.h>
|
#include <sys/log.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value) {
|
struct AST_Node_t {
|
||||||
|
// parent node that owns this node
|
||||||
|
struct AST_Node_t *parent;
|
||||||
|
|
||||||
|
// type of AST node: if, declaration, ...
|
||||||
|
enum AST_SyntaxElement_t kind;
|
||||||
|
// optional value: integer literal, string literal, ...
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
TokenLocation location;
|
||||||
|
|
||||||
|
GArray *children;
|
||||||
|
};
|
||||||
|
|
||||||
|
AST_NODE_PTR AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char *value) {
|
||||||
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
DEBUG("creating new AST node: %d \"%s\"", kind, value);
|
||||||
assert(kind < AST_ELEMENT_COUNT);
|
assert(kind < AST_ELEMENT_COUNT);
|
||||||
|
|
||||||
struct AST_Node_t *node = malloc(sizeof(struct AST_Node_t));
|
AST_NODE_PTR node = malloc(sizeof(struct AST_Node_t));
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
PANIC("failed to allocate AST node");
|
PANIC("failed to allocate AST node");
|
||||||
|
@ -20,7 +34,6 @@ struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t
|
||||||
// init to discrete state
|
// init to discrete state
|
||||||
node->parent = NULL;
|
node->parent = NULL;
|
||||||
node->children = NULL;
|
node->children = NULL;
|
||||||
node->child_count = 0;
|
|
||||||
node->kind = kind;
|
node->kind = kind;
|
||||||
node->value = value;
|
node->value = value;
|
||||||
node->location = location;
|
node->location = location;
|
||||||
|
@ -28,7 +41,7 @@ struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* lookup_table[AST_ELEMENT_COUNT] = { "__UNINIT__" };
|
static const char *lookup_table[AST_ELEMENT_COUNT] = {"__UNINIT__"};
|
||||||
|
|
||||||
void AST_init() {
|
void AST_init() {
|
||||||
DEBUG("initializing global syntax tree...");
|
DEBUG("initializing global syntax tree...");
|
||||||
|
@ -89,13 +102,13 @@ void AST_init() {
|
||||||
lookup_table[AST_Reference] = "ref";
|
lookup_table[AST_Reference] = "ref";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* AST_node_to_string(const struct AST_Node_t* node) {
|
const char *AST_node_to_string(AST_NODE_PTR node) {
|
||||||
DEBUG("converting AST node to string: %p", node);
|
DEBUG("converting AST node to string: %p", node);
|
||||||
assert(node != NULL);
|
assert(node != NULL);
|
||||||
|
|
||||||
const char* string;
|
const char *string;
|
||||||
|
|
||||||
switch(node->kind) {
|
switch (node->kind) {
|
||||||
case AST_Int:
|
case AST_Int:
|
||||||
case AST_Float:
|
case AST_Float:
|
||||||
case AST_String:
|
case AST_String:
|
||||||
|
@ -126,20 +139,15 @@ static inline unsigned long int max(unsigned long int a, unsigned long int b) {
|
||||||
return a > b ? a : b;
|
return a > b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
void AST_push_node(AST_NODE_PTR owner, AST_NODE_PTR child) {
|
||||||
DEBUG("Adding new node %p to %p", child, owner);
|
DEBUG("Adding new node %p to %p", child, owner);
|
||||||
assert(owner != NULL);
|
assert(owner != NULL);
|
||||||
assert(child != NULL);
|
assert(child != NULL);
|
||||||
|
|
||||||
// if there are no children for now
|
// if there are no children for now
|
||||||
if (owner->child_count == 0) {
|
if (owner->children == NULL) {
|
||||||
DEBUG("Allocating new children array");
|
DEBUG("Allocating new children array");
|
||||||
owner->children = malloc(sizeof(struct AST_Node_t *));
|
owner->children = g_array_new(FALSE, FALSE, sizeof(AST_NODE_PTR));
|
||||||
|
|
||||||
} else {
|
|
||||||
DEBUG("Rellocating old children array");
|
|
||||||
const size_t size = sizeof(struct AST_Node_t *) * (owner->child_count + 1);
|
|
||||||
owner->children = realloc(owner->children, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner->children == NULL) {
|
if (owner->children == NULL) {
|
||||||
|
@ -154,20 +162,20 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child) {
|
||||||
|
|
||||||
assert(owner->children != NULL);
|
assert(owner->children != NULL);
|
||||||
|
|
||||||
owner->children[owner->child_count++] = child;
|
g_array_append_val(owner->children, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, const size_t idx) {
|
AST_NODE_PTR AST_get_node(AST_NODE_PTR owner, const size_t idx) {
|
||||||
DEBUG("retrvieng node %d from %p", idx, owner);
|
DEBUG("retrvieng node %d from %p", idx, owner);
|
||||||
assert(owner != NULL);
|
assert(owner != NULL);
|
||||||
assert(owner->children != NULL);
|
assert(owner->children != NULL);
|
||||||
assert(idx < owner->child_count);
|
assert(idx < owner->children->len);
|
||||||
|
|
||||||
if (owner->children == NULL) {
|
if (owner->children == NULL) {
|
||||||
PANIC("AST owner node has no children");
|
PANIC("AST owner node has no children");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AST_Node_t *child = owner->children[idx];
|
AST_NODE_PTR child = ((AST_NODE_PTR*) owner->children->data)[idx];
|
||||||
|
|
||||||
if (child == NULL) {
|
if (child == NULL) {
|
||||||
PANIC("child node is NULL");
|
PANIC("child node is NULL");
|
||||||
|
@ -176,32 +184,27 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, const size_t idx) {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, const size_t idx) {
|
AST_NODE_PTR AST_remove_child(AST_NODE_PTR owner, const size_t idx) {
|
||||||
assert(owner != NULL);
|
assert(owner != NULL);
|
||||||
assert(owner->children != NULL);
|
assert(owner->children != NULL);
|
||||||
assert(idx < owner->child_count);
|
assert(idx < owner->children->len);
|
||||||
|
|
||||||
struct AST_Node_t* child = owner->children[idx];
|
AST_NODE_PTR child = AST_get_node(owner, idx);
|
||||||
|
|
||||||
child->parent = NULL;
|
child->parent = NULL;
|
||||||
|
|
||||||
owner->child_count--;
|
g_array_remove_index(owner->children, idx);
|
||||||
|
|
||||||
// shift back every following element by one
|
|
||||||
for (size_t i = idx; i < owner->child_count; i++) {
|
|
||||||
owner->children[i] = owner->children[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child) {
|
AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child) {
|
||||||
assert(owner != NULL);
|
assert(owner != NULL);
|
||||||
assert(child != NULL);
|
assert(child != NULL);
|
||||||
assert(owner->children != NULL);
|
assert(owner->children != NULL);
|
||||||
|
|
||||||
for (size_t i = 0; i < owner->child_count; i++) {
|
for (size_t i = 0; i < owner->children->len; i++) {
|
||||||
if (owner->children[i] == child) {
|
if (AST_get_node(owner, i) == child) {
|
||||||
return AST_remove_child(owner, i);
|
return AST_remove_child(owner, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +212,7 @@ struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_N
|
||||||
PANIC("Child to detach not a child of parent");
|
PANIC("Child to detach not a child of parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_delete_node(struct AST_Node_t *node) {
|
void AST_delete_node(AST_NODE_PTR node) {
|
||||||
assert(node != NULL);
|
assert(node != NULL);
|
||||||
|
|
||||||
DEBUG("Deleting AST node: %p", node);
|
DEBUG("Deleting AST node: %p", node);
|
||||||
|
@ -219,22 +222,23 @@ void AST_delete_node(struct AST_Node_t *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->parent != NULL) {
|
if (node->parent != NULL) {
|
||||||
const struct AST_Node_t* child = AST_detach_child(node->parent, node);
|
AST_NODE_PTR child = AST_detach_child(node->parent, node);
|
||||||
assert(child == node);
|
assert(child == node);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
for (size_t i = 0; i < node->children->len; i++) {
|
||||||
// prevent detach of children node
|
// prevent detach of children node
|
||||||
node->children[i]->parent = NULL;
|
AST_NODE_PTR child = AST_get_node(node, i);
|
||||||
AST_delete_node(node->children[i]);
|
child->parent = NULL;
|
||||||
|
AST_delete_node(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(node->children);
|
g_array_free(node->children, TRUE);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AST_visit_nodes_recurse2(struct AST_Node_t *root,
|
static void AST_visit_nodes_recurse2(AST_NODE_PTR root,
|
||||||
void (*for_each)(struct AST_Node_t *node,
|
void (*for_each)(AST_NODE_PTR node,
|
||||||
size_t depth),
|
size_t depth),
|
||||||
const size_t depth) {
|
const size_t depth) {
|
||||||
DEBUG("Recursive visit of %p at %d with %p", root, depth, for_each);
|
DEBUG("Recursive visit of %p at %d with %p", root, depth, for_each);
|
||||||
|
@ -243,13 +247,13 @@ static void AST_visit_nodes_recurse2(struct AST_Node_t *root,
|
||||||
|
|
||||||
(for_each)(root, depth);
|
(for_each)(root, depth);
|
||||||
|
|
||||||
for (size_t i = 0; i < root->child_count; i++) {
|
for (size_t i = 0; i < root->children->len; i++) {
|
||||||
AST_visit_nodes_recurse2(root->children[i], for_each, depth + 1);
|
AST_visit_nodes_recurse2(AST_get_node(root, i), for_each, depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_visit_nodes_recurse(struct AST_Node_t *root,
|
void AST_visit_nodes_recurse(AST_NODE_PTR root,
|
||||||
void (*for_each)(struct AST_Node_t *node,
|
void (*for_each)(AST_NODE_PTR node,
|
||||||
size_t depth)) {
|
size_t depth)) {
|
||||||
DEBUG("Starting recursive visit of %p with %p", root, for_each);
|
DEBUG("Starting recursive visit of %p with %p", root, for_each);
|
||||||
|
|
||||||
|
@ -259,24 +263,24 @@ void AST_visit_nodes_recurse(struct AST_Node_t *root,
|
||||||
AST_visit_nodes_recurse2(root, for_each, 0);
|
AST_visit_nodes_recurse2(root, for_each, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AST_fprint_graphviz_node_definition(FILE* stream, const struct AST_Node_t* node) {
|
static void AST_fprint_graphviz_node_definition(FILE *stream, AST_NODE_PTR node) {
|
||||||
DEBUG("Printing graphviz definition of %p", node);
|
DEBUG("Printing graphviz definition of %p", node);
|
||||||
|
|
||||||
assert(stream != NULL);
|
assert(stream != NULL);
|
||||||
assert(node != NULL);
|
assert(node != NULL);
|
||||||
|
|
||||||
fprintf(stream, "\tnode%p [label=\"%s\"]\n", (void*) node, AST_node_to_string(node));
|
fprintf(stream, "\tnode%p [label=\"%s\"]\n", (void *) node, AST_node_to_string(node));
|
||||||
|
|
||||||
if (node->children == NULL) {
|
if (node->children == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
for (size_t i = 0; i < node->children->len; i++) {
|
||||||
AST_fprint_graphviz_node_definition(stream, node->children[i]);
|
AST_fprint_graphviz_node_definition(stream, AST_get_node(node, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AST_fprint_graphviz_node_connection(FILE* stream, const struct AST_Node_t* node) {
|
static void AST_fprint_graphviz_node_connection(FILE *stream, AST_NODE_PTR node) {
|
||||||
DEBUG("Printing graphviz connection of %p", node);
|
DEBUG("Printing graphviz connection of %p", node);
|
||||||
|
|
||||||
assert(stream != NULL);
|
assert(stream != NULL);
|
||||||
|
@ -286,13 +290,14 @@ static void AST_fprint_graphviz_node_connection(FILE* stream, const struct AST_N
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < node->child_count; i++) {
|
for (size_t i = 0; i < node->children->len; i++) {
|
||||||
fprintf(stream, "\tnode%p -- node%p\n", (void*) node, (void*) node->children[i]);
|
AST_NODE_PTR child = AST_get_node(node, i);
|
||||||
AST_fprint_graphviz_node_connection(stream, node->children[i]);
|
fprintf(stream, "\tnode%p -- node%p\n", (void *) node, (void *) child);
|
||||||
|
AST_fprint_graphviz_node_connection(stream, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* root) {
|
void AST_fprint_graphviz(FILE *stream, AST_NODE_PTR root) {
|
||||||
DEBUG("Starting print of graphviz graph of %p", root);
|
DEBUG("Starting print of graphviz graph of %p", root);
|
||||||
|
|
||||||
assert(stream != NULL);
|
assert(stream != NULL);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
#ifndef _AST_H_
|
#ifndef AST_H_
|
||||||
#define _AST_H_
|
#define AST_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <io/files.h>
|
#include <io/files.h>
|
||||||
|
@ -89,23 +89,7 @@ enum AST_SyntaxElement_t {
|
||||||
* - kind: The type of the node. Such as AST_Expr, AST_Add, ...
|
* - kind: The type of the node. Such as AST_Expr, AST_Add, ...
|
||||||
* - value: A string representing an optional value. Can be a integer literal for kind AST_int
|
* - value: A string representing an optional value. Can be a integer literal for kind AST_int
|
||||||
*/
|
*/
|
||||||
struct AST_Node_t {
|
struct AST_Node_t;
|
||||||
// parent node that owns this node
|
|
||||||
struct AST_Node_t *parent;
|
|
||||||
|
|
||||||
// type of AST node: if, declaration, ...
|
|
||||||
enum AST_SyntaxElement_t kind;
|
|
||||||
// optional value: integer literal, string literal, ...
|
|
||||||
const char* value;
|
|
||||||
|
|
||||||
TokenLocation location;
|
|
||||||
|
|
||||||
// number of child nodes ownd by this node
|
|
||||||
// length of children array
|
|
||||||
size_t child_count;
|
|
||||||
// variable amount of child nodes
|
|
||||||
struct AST_Node_t **children;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shorthand type for a single AST node
|
* Shorthand type for a single AST node
|
||||||
|
@ -126,7 +110,7 @@ void AST_init(void);
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[gnu::nonnull(1)]]
|
[[gnu::nonnull(1)]]
|
||||||
const char* AST_node_to_string(const struct AST_Node_t* node);
|
const char* AST_node_to_string(AST_NODE_PTR node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new node struct on the system heap. Initializes the struct with the given values.
|
* @brief Create a new node struct on the system heap. Initializes the struct with the given values.
|
||||||
|
@ -139,7 +123,7 @@ const char* AST_node_to_string(const struct AST_Node_t* node);
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[nodiscard("pointer must be freed")]]
|
[[nodiscard("pointer must be freed")]]
|
||||||
[[gnu::returns_nonnull]]
|
[[gnu::returns_nonnull]]
|
||||||
struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value);
|
AST_NODE_PTR AST_new_node(TokenLocation location, enum AST_SyntaxElement_t kind, const char* value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deallocate this node and all of its children.
|
* @brief Deallocate this node and all of its children.
|
||||||
|
@ -149,7 +133,7 @@ struct AST_Node_t *AST_new_node(TokenLocation location, enum AST_SyntaxElement_t
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[gnu::nonnull(1)]]
|
[[gnu::nonnull(1)]]
|
||||||
void AST_delete_node(struct AST_Node_t * node);
|
void AST_delete_node(AST_NODE_PTR node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a new child node to a parent node
|
* @brief Add a new child node to a parent node
|
||||||
|
@ -159,7 +143,7 @@ void AST_delete_node(struct AST_Node_t * node);
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
||||||
void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child);
|
void AST_push_node(AST_NODE_PTR owner, AST_NODE_PTR child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove the specified child from the owner.
|
* @brief Remove the specified child from the owner.
|
||||||
|
@ -172,7 +156,7 @@ void AST_push_node(struct AST_Node_t *owner, struct AST_Node_t *child);
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[nodiscard("pointer must be freed")]]
|
[[nodiscard("pointer must be freed")]]
|
||||||
[[gnu::nonnull(1)]]
|
[[gnu::nonnull(1)]]
|
||||||
struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx);
|
AST_NODE_PTR AST_remove_child(AST_NODE_PTR owner, size_t idx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Detach a child from its parent. This involves removing the child from its parent
|
* @brief Detach a child from its parent. This involves removing the child from its parent
|
||||||
|
@ -184,7 +168,7 @@ struct AST_Node_t* AST_remove_child(struct AST_Node_t* owner, size_t idx);
|
||||||
*/
|
*/
|
||||||
[[nodiscard("pointer must be freed")]]
|
[[nodiscard("pointer must be freed")]]
|
||||||
[[gnu::nonnull(1), gnu::nonnull(1)]]
|
[[gnu::nonnull(1), gnu::nonnull(1)]]
|
||||||
struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_Node_t* child);
|
AST_NODE_PTR AST_detach_child(AST_NODE_PTR owner, AST_NODE_PTR child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a pointer to the n-th child of a node
|
* @brief Return a pointer to the n-th child of a node
|
||||||
|
@ -197,7 +181,7 @@ struct AST_Node_t* AST_detach_child(struct AST_Node_t* owner, const struct AST_N
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[gnu::nonnull(1)]]
|
[[gnu::nonnull(1)]]
|
||||||
struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx);
|
AST_NODE_PTR AST_get_node(AST_NODE_PTR owner, size_t idx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Execute a function for every child, grandchild, ... and the supplied node as topmost ancestor
|
* @brief Execute a function for every child, grandchild, ... and the supplied node as topmost ancestor
|
||||||
|
@ -206,8 +190,8 @@ struct AST_Node_t *AST_get_node(struct AST_Node_t *owner, size_t idx);
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
||||||
void AST_visit_nodes_recurse(struct AST_Node_t *root,
|
void AST_visit_nodes_recurse(AST_NODE_PTR root,
|
||||||
void (*for_each)(struct AST_Node_t *node,
|
void (*for_each)(AST_NODE_PTR node,
|
||||||
size_t depth));
|
size_t depth));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,6 +201,6 @@ void AST_visit_nodes_recurse(struct AST_Node_t *root,
|
||||||
*/
|
*/
|
||||||
[[maybe_unused]]
|
[[maybe_unused]]
|
||||||
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
[[gnu::nonnull(1), gnu::nonnull(2)]]
|
||||||
void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* node);
|
void AST_fprint_graphviz(FILE* stream, AST_NODE_PTR node);
|
||||||
|
|
||||||
#endif
|
#endif // AST_H_
|
||||||
|
|
Loading…
Reference in New Issue