TDT4205/exercises/02/vslc/src/tree.c

145 lines
3.6 KiB
C

#include <vslc.h>
static void node_print ( node_t *root, int nesting );
static void node_finalize ( node_t *discard );
static void destroy_subtree ( node_t *discard );
typedef struct stem_t *stem;
struct stem_t { const char *str; stem next; };
static void
tree_print(node_t* root, stem head)
{
static const char *sdown = "", *slast = "", *snone = " ";
struct stem_t col = {0, 0}, *tail;
for (tail = head; tail; tail = tail->next) {
if (!tail->next) {
if (!strcmp(sdown, tail->str))
printf("");
else
printf("%s", tail->str);
break;
}
printf("%s", tail->str);
}
printf("──%s", node_string[root->type] );
if ( root->type == IDENTIFIER_DATA ||
root->type == STRING_DATA ||
root->type == EXPRESSION )
printf("(%s)", (char *) root->data);
else if (root->type == NUMBER_DATA)
printf ( "(%ld)", *((int64_t *)root->data) );
putchar ( '\n' );
if (!root->n_children) return;
if (tail && tail->str == slast)
tail->str = snone;
if (!tail) tail = head = &col;
else tail->next = &col;
for ( int64_t i=0; i < root->n_children; i++ ) {
col.str = root->n_children - i - 1 ? sdown : slast;
tree_print(root->children[i], head);
}
tail->next = 0;
}
/* External interface */
void
destroy_syntax_tree ( void )
{
destroy_subtree ( root );
}
void
print_syntax_tree ( void )
{
//node_print ( root, 0 );
tree_print(root, 0);
}
// Changed so it returns the pointer to the new node, can be used as before, but makes the parser file cleaner
node_t*
node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...)
{
// Copy the type
nd->type = type;
// Copy n_children
nd->n_children = n_children;
/*
The memory for this data needs to be
allocated somewhere not here, since this
function does not know the type.
*/
nd->data = data;
// Prepeare the VA list
va_list list_children;
va_start(list_children, n_children);
// Create memory region for the children pointers
nd->children = malloc(n_children * sizeof(node_t*));
// Populate the memory with pointers to children
for (int i = 0; i < n_children; i++)
nd->children[i] = va_arg(list_children, node_t*);
return nd;
}
static void
node_print ( node_t *root, int nesting )
{
if ( root != NULL )
{
printf ( "%*c%s", nesting, ' ', node_string[root->type] );
if ( root->type == IDENTIFIER_DATA ||
root->type == STRING_DATA ||
root->type == EXPRESSION )
printf ( "(%s)", (char *) root->data );
else if ( root->type == NUMBER_DATA )
printf ( "(%ld)", *((int64_t *)root->data) );
putchar ( '\n' );
for ( int64_t i=0; i<root->n_children; i++ )
node_print ( root->children[i], nesting+1 );
}
else
printf ( "%*c%p\n", nesting, ' ', root );
}
static void
node_finalize ( node_t *discard )
{ // The discard should have zero children here. If not -> MEMORY LEAK
// Free the data and the children list.
free(discard->data);
free(discard->children);
free(discard);
}
static void
destroy_subtree ( node_t *discard )
{
// Don't do anything if discard is nullptr
if (discard == NULL)
return;
// This will not run if n_children is zero
// If non-zero, destroy all children recursivly
while (discard->n_children--)
destroy_subtree(discard->children[discard->n_children]);
// Finally, destroy yourself
node_finalize(discard);
}