#include 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; in_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); }