Added simplifying methods
- Prune children to remove unneeded nodes - resolve constant expressions - Flatten listsmain
parent
8c85391fb9
commit
10515c009a
|
@ -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];
|
||||
|
||||
//node_finalize(parent);
|
||||
parent = child;
|
||||
default:
|
||||
// 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;
|
||||
}
|
||||
|
||||
/*
|
||||
if (parent->n_children != 1 || parent->data)
|
||||
*simplified = result;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resolve_constant_expressions(node_t **simplified, node_t *root)
|
||||
{
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
printf("delete parent\n");
|
||||
node_t *child = parent->children[0];
|
||||
//parent->children = NULL;
|
||||
node_finalize(parent);
|
||||
parent = child;*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue