diff --git a/exercises/03/vslc/src/tree.c b/exercises/03/vslc/src/tree.c index 5e58deb..b3367dd 100644 --- a/exercises/03/vslc/src/tree.c +++ b/exercises/03/vslc/src/tree.c @@ -33,7 +33,8 @@ tree_print(node_t* root, stem head) printf("──%s", node_string[root->type] ); if ( root->type == IDENTIFIER_DATA || root->type == STRING_DATA || - root->type == EXPRESSION ) + root->type == EXPRESSION || + root->type == RELATION) printf("(%s)", (char *) root->data); else if (root->type == NUMBER_DATA) printf ( "(%ld)", *((int64_t *)root->data) ); @@ -73,8 +74,8 @@ simplify_syntax_tree ( void ) void print_syntax_tree ( void ) { - node_print ( root, 0 ); - //tree_print(root, 0); + //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 @@ -144,45 +145,146 @@ destroy_subtree ( node_t *discard ) } static void -prune_children(node_t *parent) +prune_children(node_t **simplified, node_t *root) { - if (!parent) + if (!root) return; - for (int i = 0; i < parent->n_children; i++) - prune_children(parent->children[i]); - - printf("Trying to remove node!\n"); - if (parent->data != NULL || parent->n_children != 1) - return; - printf("Only one child found. Purging...\n"); - - node_t *child = parent->children[0]; - switch (parent->type) + node_t *result = root; + switch (root->type) { - case PROGRAM: + case GLOBAL: + case ARGUMENT_LIST: + case PARAMETER_LIST: case STATEMENT: - case EXPRESSION: case PRINT_ITEM: - printf("Removing node!\n"); - //parent->children = NULL; - free(parent->children); + 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(parent); - parent = child; - default: + node_finalize(root); break; } - /* - if (parent->n_children != 1 || parent->data) + *simplified = result; +} + + +static void +resolve_constant_expressions(node_t **simplified, node_t *root) +{ + if (!root) + return; + + if (root->type != EXPRESSION) return; - printf("delete parent\n"); - node_t *child = parent->children[0]; - //parent->children = NULL; - node_finalize(parent); - parent = child;*/ + 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; } @@ -226,6 +328,9 @@ simplify_tree ( node_t **simplified, node_t *root ) for (int i = 0; i < root->n_children; i++) simplify_tree(&root->children[i], root->children[i]); - prune_children(root); + prune_children(&root, root); + resolve_constant_expressions(&root, root); + flatten(&root, root); + *simplified = root; }