Example #1
0
void doOp( node_t* node, node_t* parent) {
    // DEBUG
    //fprintf(stdout, "doOp(%s)", node->data);

    uint32_t* result = malloc(sizeof(uint32_t));
    uint32_t* tall1 = (uint32_t*)node->children[0]->data;
    uint32_t* tall2 = (uint32_t*)node->children[1]->data;
    char* c = (char*)node->data;
    if(*c == '+') {
        *result = *tall1 + *tall2;
    }
    if(*c == '-') {
        *result = *tall1 - *tall2;
    }
    if(*c == '*') {
        *result = *tall1 * *tall2;
    }
    if(*c == '/') {
        *result = *tall1 / *tall2;
    }
    if(*c == '^') {
        *result = (int)pow((double)*tall1, *tall2);
    }
    // DEBUG
    //fprintf(stdout, "%d %c %d = %d\n", *tall1, *c, *tall2, *result);
    free(node->data);
    node_finalize(node->children[0]);
    node_finalize(node->children[1]);
    //free(node->children);
    node->n_children = 0;
    node->data = result;
    node->type = integer_n;
}
Example #2
0
void prune_node(node_t* node, node_t** simpler) {
    if(node == NULL) {
        // update simpler so that if we are pruning,
        // the pointer pointing to this node, will point to this node instead
        *simpler = node;
        return;
    }

    if(is_prunable(node)) {
        // update the pointer pointing to the node we want to point to instead
        //prune_node(node->children[0], simpler);
        for(int i = 0; i < node->n_children; i++) {
            prune_node(node->children[i], simpler);
        }
        // clean up node we are removing
        node_finalize(node);
    } else {
        // recurse down the children and update pointers
        for (int i = 0; i < node->n_children; ++i) {
            node_t* child = node->children[i];
            prune_node(child, simpler);
            // update the child pointer we are exploring, in case it was prunable
            node->children[i] = *simpler;
        }
        *simpler = node;
    }

}
Example #3
0
File: tree.c Project: sondrele/NTNU
void destroy_subtree ( node_t *discard ) {
	if ( discard != NULL ) {
		for ( uint32_t i = 0; i < discard->n_children; i++ )
			destroy_subtree ( discard->children[i] );
		node_finalize ( discard );
	}
}
Example #4
0
/* Recursively remove the entire tree rooted at a node */
void
destroy_subtree ( node_t *discard )
{
    if( discard == NULL )
        return;
    node_finalize( discard );
    free ( discard );
}
Example #5
0
void destroy_subtree(node_t *discard) {
	if (!discard)
		return;
	for (int i=0; i < discard->n_children; i++) {
		destroy_subtree((node_t*)discard->children + i);
	}
	node_finalize(discard);
}
Example #6
0
void destroy_subtree ( node_t *discard ){
    if(discard == NULL) return;

    for(int i =0; i < discard->n_children; i++){
        destroy_subtree(discard->children[i]);
    }
    node_finalize(discard);
    
}
Example #7
0
void destroy_subtree ( FILE *output, node_t *discard )
{
    if ( discard != NULL )
    {
        for ( int i=0; i<discard->n_children; i++ )
            destroy_subtree ( output, discard->children[i] );
        if( output != NULL)
        	fprintf ( output, "Freeing %s\n", discard->nodetype.text );
        node_finalize ( discard );
    }
}
Example #8
0
void
simplify_tree ( node_t **simplified, node_t *root )
{
    node_t *result = root;

    /*
     * First, we ensure that we have a node to look at. This has the
     * convenient side-effect that optional elements in the syntax
     * remain marked by a NULL placeholder in the tree, keeping it simple
     * to recognize the structures imposed by the grammar.
     */
    if ( root != NULL )
    {
        /* Recur before treating any single node: depth-first traversal */
        for ( uint32_t i=0; i<root->n_children; i++ )
            simplify_tree ( &root->children[i], root->children[i] );

        /* Here is where we do something to the lowest nodes in the tree */
        switch ( root->type.index )
        {
            /*
             * These types have only syntactic value, so we can throw
             * them out now:
             * STATEMENT always has one child, which can identify itself
             * PARAMETER_LIST only serves to make variable lists optional
             *                in function declarations
             * ARGUMENT_LIST does the same thing for function calls
             */
            case STATEMENT: case PRINT_ITEM:
            case PARAMETER_LIST: case ARGUMENT_LIST: 
                result = root->children[0];
                node_finalize ( root );
                break;

            /*
             * Print statements always have exactly one PRINT_LIST child.
             * Since we are done with the recursive list definition,
             * its descendants may instead be children of the print statement
             * itself now. (Quick hack - it's easier to rename the list node
             * and eliminate the old statement than to copy/move all children.)
             */
            case PRINT_STATEMENT:
                result = root->children[0];
                result->type = root->type;
                node_finalize ( root );
                break;

            /*
             * DECLARATION_LIST can be NULL altogether, but we preserved
             * that at the beginning of the function. This has a somewhat
             * nasty side-effect in the grammar, however, as it gets a
             * different structure from the other lists when it DOES exist
             * (such as here). Other lists have a single-element list with
             * the last list item at the bottom of the tree, whereas
             * declaration lists have a 2-element list with NULL and the
             * last item. The code that follows molds the bottom of a
             * declaration list into the same form as the other lists, so
             * the rest can be handled by the otherwise standard
             * list-flattening code.
             */
            case DECLARATION_LIST:
                if ( root->children[0] == NULL )
                {
                    root->children[0] = root->children[1];
                    root->n_children--;
                    root->children = realloc (
                        root->children, root->n_children * sizeof(node_t *)
                    );
                }
                /* NB! There is no 'break' here on purpose - since the
                 * declaration list is now in the standard form, we WANT
                 * control to fall through to the standard list-handling
                 * code below.
                 */

            /*
             * All these lists have the same structure, so general flattening
             * is quite simple: extend the left child's list with the right
             * child, and substitute the parent.
             */
            case FUNCTION_LIST: case STATEMENT_LIST: case PRINT_LIST:
            case EXPRESSION_LIST: case VARIABLE_LIST:
                if ( root->n_children >= 2 )
                {
                    result = root->children[0];
                    uint32_t n = (result->n_children += 1);
                    result->children =
                        realloc ( result->children, n * sizeof(node_t *) );
                    result->children[n-1] = root->children[1];
                    node_finalize ( root );
                }
                break;

            case EXPRESSION:
                switch ( root->n_children )
                {
                    case 1:
                        if ( root->children[0]->type.index == INTEGER )
                        {   /* Single integers */
                            result = root->children[0];
                            if ( root->data != NULL )   /* Negative constants */
                                *((int32_t *)result->data) *= -1;
                            node_finalize ( root );
                        }
                        else if ( root->data == NULL )
                        {   /* Single variables, parentheses, etc. */
                            result = root->children[0];
                            node_finalize ( root );
                        }
                        break;
                    case 2:     /* Constant binary expressions */
                        if ( root->children[0]->type.index == INTEGER &&
                             root->children[1]->type.index == INTEGER &&
                             root->data != NULL )
                        {
                            result = root->children[0];
                            int32_t
                                *a = result->data,
                                *b = root->children[1]->data;
                            switch ( *((char *)root->data) )
                            {
                                case '+': *a += *b; break;
                                case '-': *a -= *b; break;
                                case '*': *a *= *b; break;
                                case '/': *a /= *b; break;
                                case '^': 
                                          if (*b < 0 && *a != 1)
                                              *a = 0;
                                          else {
                                              *a = 1;
                                              for (int32_t x=*a, c=*b; c > 0; c--) 
                                                  *a *= x; 
                                          }
                                          break;
                            }
                            node_finalize ( root->children[1] );
                            node_finalize ( root );
                        }
                        break;
                }
                break;
        }
    }
    *simplified = result;
}
Example #9
0
node_t* simplify_tree ( node_t* node )
{

    if ( node != NULL ){

        // Recursively simplify the children of the current node
        for ( uint32_t i=0; i<node->n_children; i++ ){
            node->children[i] = simplify_tree ( node->children[i] );
        }

        // After the children have been simplified, we look at the current node
        // What we do depend upon the type of node
        switch ( node->type.index )
        {
            // These are lists which needs to be flattened. Their structure
            // is the same, so they can be treated the same way.
            case FUNCTION_LIST: case STATEMENT_LIST: case PRINT_LIST:
            case EXPRESSION_LIST: case VARIABLE_LIST:
                if(node->n_children > 1){
                    node_t *temp, *simplified;
                    temp = node->children[node->n_children - 1];
                    node->n_children += simplified->n_children;
                    node->children = realloc(node->children, (1 + simplified->n_children)*sizeof(node_t));
                    for(int i = 0; i < simplified->n_children; i++){
                        node->children[i] = simplified->children[i];
                    }
                    node->children[simplified->n_children] = temp;

                }
                else{
                    node->type = node->children[0]->type;
                    node->data = node->children[0]->data;
                    node->entry = node->children[0]->entry;
                    node->n_children = 0;
                    node_finalize(node->children[0]);
                }
                break;


            // Declaration lists should also be flattened, but their stucture is sligthly
            // different, so they need their own case
            case DECLARATION_LIST:
                if(node->n_children > 1){
                    node_t *temp, *simplified;
                    temp = node->children[node->n_children -1];
                    node->n_children += simplified->n_children;
                    node->children = realloc(node->children, (1+simplified->n_children)*sizeof(node_t));
                    for(int i = 0; i < simplified->n_children; i++){
                        node->children[i] = simplified->children[i];
                    }
                    node->children[simplified->n_children] = temp;
                }
                else if (node->n_children == 1){
                    node->type = node->children[0]->type;
                    node->data = node->children[0]->data;
                    node->entry = node->children[0]->entry;
                    node->n_children = 0;
                    node_finalize(node->children[0]);
                }
                break;

            
            // These have only one child, so they are not needed
            case STATEMENT: case PARAMETER_LIST: case ARGUMENT_LIST:
                node->type = node->children[0]->type;
                node->data = node->children[0]->data;
                node->entry = node->children[0]->entry;
                node->n_children = 0;
                node_finalize(node->children[0]);
                break;


            // Expressions where both children are integers can be evaluated (and replaced with
            // integer nodes). Expressions whith just one child can be removed (like statements etc above)
            case EXPRESSION:
                if(node->n_children = 1){
                    node->type = node->children[0]->type;
                    node->data = node->children[0]->data;
                    node->entry = node->children[0]->entry;
                    node->n_children = 0;
                    node_finalize(node->children[0]);
                }
                else if( node->n_children = 2){
                    if(node->children[0]->type.index == INTEGER && node->children[0]->type.index == INTEGER){
                        node->type = node->children[0]->type;
                        int *a = (node->children[0]->data);
                        int *b = (node->children[0]->data);
                        int *result =  malloc(sizeof(int));
                        {
                        switch(((char *)node->data)[0]){
                            case '+':
                                *result = *a + *b;
                                break;
                            case '-':
                                *result = *a - *b;
                                break;
                            case '*':
                                *result = (*a) * (*b);
                                break;
                            case '/':
                                *result = (*a) / (*b);
                                break;
                        }
                        }
                        node->data = &result;
                        node->entry = node->children[0]->entry;
                        node->n_children = 0;
                        node_finalize(node->children[0]);
                        node_finalize(node->children[1]);


                    }

                }
                break;

        }
    }
    return node;
}