From 94d83fc59b181cb5bbb1d2a8bd17340e8eaa0837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind?= Date: Sat, 12 Mar 2022 19:21:53 +0100 Subject: [PATCH] fixed bug where the simplify is to aggressive --- exercises/04/vslc/src/tree.c | 227 ++++++++++++++++++++++++----------- 1 file changed, 154 insertions(+), 73 deletions(-) diff --git a/exercises/04/vslc/src/tree.c b/exercises/04/vslc/src/tree.c index ef7658c..4ef10bf 100644 --- a/exercises/04/vslc/src/tree.c +++ b/exercises/04/vslc/src/tree.c @@ -40,7 +40,8 @@ print_syntax_tree ( void ) } -void +// 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, ...) { va_list child_list; @@ -55,6 +56,8 @@ node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...) for ( uint64_t i=0; ichildren[i] = va_arg ( child_list, node_t * ); va_end ( child_list ); + + return nd; } @@ -150,83 +153,161 @@ destroy_subtree ( node_t *discard ) } } +static void +prune_children(node_t **simplified, node_t *root) +{ + if (!root) + return; + + node_t *result = root; + switch (root->type) + { + case GLOBAL: + //case ARGUMENT_LIST: + //case PARAMETER_LIST: + case STATEMENT: + case PRINT_ITEM: + case PRINT_STATEMENT: + result = root->children[0]; + + // The print_statement only contains a print_list, still need a print_statement. + if (root->type == PRINT_STATEMENT) + result->type = PRINT_STATEMENT; + + node_finalize(root); + break; + } + + *simplified = result; +} + + +static void +resolve_constant_expressions(node_t **simplified, node_t *root) +{ + if (!root) + return; + + if (root->type != EXPRESSION) + return; + + node_t *result = root; + + switch (root->n_children) + { + case 1: + result = root->children[0]; + + if (root->data && + result->type == NUMBER_DATA && + result->data) + { + switch (*((char*)root->data)) + { + case '-': + *((int64_t*)result->data) *= -1; + break; + case '~': + *((int64_t*)result->data) = ~*((int64_t*)result->data); + break; + } + } + + node_finalize(root); + break; + + case 2: + // Both children needs to be numbers to resolve constants + if (root->children[0]->type == NUMBER_DATA && + root->children[1]->type == NUMBER_DATA) + { + // Check if children does not contain null pointers + if (!root->children[0]->data) + break; + if (!root->children[1]->data) + break; + + // Check if data field is not null pointer + if (!root->data) + break; + + result = root->children[0]; + int64_t + *lhs = result->data, + *rhs = root->children[1]->data; + + switch (*(char*)root->data) + { + case '|': *lhs |= *rhs; break; + case '^': *lhs ^= *rhs; break; + case '&': *lhs &= *rhs; break; + case '+': *lhs += *rhs; break; + case '-': *lhs -= *rhs; break; + case '*': *lhs *= *rhs; break; + case '/': *lhs /= *rhs; break; + } + + node_finalize(root->children[1]); + node_finalize(root); + } + + + break; + } + *simplified = result; +} + +static void +flatten(node_t **simplified, node_t *root) +{ + /* This will flatten left-expanded lists */ + if (!root) + return; + + node_t **new_children, *result = root; + switch (root->type) + { + case GLOBAL_LIST: + case STATEMENT_LIST: + case PRINT_LIST: + case EXPRESSION_LIST: + case VARIABLE_LIST: + case DECLARATION_LIST: + // Check if node have more than two children + if (root->n_children < 2) + break; + + result = root->children[0]; + result->n_children++; + + // Realloc the array of children to the new size + if (!(new_children = realloc(result->children, result->n_children * sizeof(node_t*)))) + break; + // if successs, insert the new array + result->children = new_children; + + // Insert child at the end + result->children[result->n_children - 1] = root->children[1]; + + node_finalize(root); + break; + } + + *simplified = result; +} static void simplify_tree ( node_t **simplified, node_t *root ) { - if ( root == NULL ) + if (!root) return; - /* Simplify subtrees before examining this node */ - for ( uint64_t i=0; in_children; i++ ) - simplify_tree ( &root->children[i], root->children[i] ); + for (int i = 0; i < root->n_children; i++) + simplify_tree(&root->children[i], root->children[i]); - node_t *discard, *result = root; - switch ( root->type ) - { - /* Structures of purely syntactic function */ - case PARAMETER_LIST: case ARGUMENT_LIST: - case STATEMENT: case PRINT_ITEM: case GLOBAL: - result = root->children[0]; - node_finalize ( root ); - break; - case PRINT_STATEMENT: - result = root->children[0]; - result->type = PRINT_STATEMENT; - node_finalize(root); - /* Flatten lists: - * Take left child, append right child, substitute left for root. - */ - case STATEMENT_LIST: case DECLARATION_LIST: case GLOBAL_LIST: - case PRINT_LIST: case EXPRESSION_LIST: case VARIABLE_LIST: - if ( root->n_children >= 2 ) - { - result = root->children[0]; - result->n_children += 1; - result->children = realloc ( - result->children, result->n_children * sizeof(node_t *) - ); - result->children[result->n_children-1] = root->children[1]; - node_finalize ( root ); - } - break; - case EXPRESSION: - switch ( root->n_children ) - { - case 1: - if ( root->children[0]->type == NUMBER_DATA ) - { - result = root->children[0]; - if ( root->data != NULL ) - *((int64_t *)result->data) *= -1; - node_finalize (root); - } - else if ( root->data == NULL ) - { - result = root->children[0]; - node_finalize (root); - } - break; - case 2: - if ( root->children[0]->type == NUMBER_DATA && - root->children[1]->type == NUMBER_DATA - ) { - result = root->children[0]; - int64_t - *x = result->data, - *y = root->children[1]->data; - switch ( *((char *)root->data) ) - { - case '+': *x += *y; break; - case '-': *x -= *y; break; - case '*': *x *= *y; break; - case '/': *x /= *y; break; - } - node_finalize ( root->children[1] ); - node_finalize ( root ); - } - break; - } - } - *simplified = result; + prune_children(&root, root); + resolve_constant_expressions(&root, root); + flatten(&root, root); + + *simplified = root; }