Esempio n. 1
0
int
main ( int argc, char **argv )
{
    read_args ( argc, argv );
    yyparse ();

#ifdef DUMPTREES
    FILE *pre = fopen ( "pre.tree", "w" ),
        *post = fopen ( "post.tree", "w" );
    print_node ( pre, root, 0 );
#endif

    root = simplify_tree ( root );

#ifdef DUMPTREES
    print_node ( post, root, 0 );
    fclose ( pre );
    fclose ( post );
#endif

    init_scopes ( 256 );

    find_symbols ( root );

    destroy_scopes ();
    destroy_subtree ( root );
    exit ( EXIT_SUCCESS );
}
Esempio n. 2
0
int
main(int argc, char **argv) {
	options(argc, argv);

	yyparse();

#ifdef DUMP_TREES
	if ((DUMP_TREES & 1) != 0)
		node_print(stderr, root, 0);
#endif

	simplify_tree(&root, root);

#ifdef DUMP_TREES
	if ((DUMP_TREES & 2) != 0)
		node_print(stderr, root, 0);
#endif

	/* Parsing and semantics are ok, redirect stdout to file (if requested) */
	if (outfile != NULL) {
		if (freopen(outfile, "w", stdout) == NULL) {
			fprintf(stderr, "Could not open output file '%s'\n", outfile);
			exit(EXIT_FAILURE);
		}
		free(outfile);
	}

	destroy_subtree(root);

	exit(EXIT_SUCCESS);
}
Esempio n. 3
0
int
main ( int argc, char **argv )
{
    yyparse();
    simplify_tree ( &root, root );
    // node_print(root, 0);
    find_globals();
    size_t n_globals = tlhash_size(global_names);
    symbol_t *global_list[n_globals];
    tlhash_values ( global_names, (void **)&global_list );
    for ( size_t i=0; i<n_globals; i++ )
        if ( global_list[i]->type == SYM_FUNCTION )
            bind_names ( global_list[i], global_list[i]->node );

//    print_globals();

    generate_program ();    

    destroy_subtree ( root );
    destroy_symtab();
}
Esempio n. 4
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 == 2){
					node_t *current; 
					current = node;
					node = current->children[0];
					node->n_children++;
					node->children = (node_t**) realloc(node->children, node->n_children*sizeof(node_t*));
					node->children[node->n_children-1] = current->children[1];
					finalize_node(current);
				}
                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 == 2){
					if(node->children[0] == NULL){
						node_t *child;
						child = node->children[1];
						free(node->children);
						node->children = (node_t**) malloc(sizeof(node_t*));
						node->n_children--;
						node->children[0] = child;
					} else {
						//Else do the same as the case above...
						node_t *current; 
						current = node;
						node = current->children[0];
						node->n_children++;
						node->children = (node_t**) realloc(node->children, node->n_children*sizeof(node_t*));
						node->children[node->n_children-1] = current->children[1];
						finalize_node(current);
					}
				}
                break;

            // These have only one child, so they are not needed
            case STATEMENT: case PARAMETER_LIST: case ARGUMENT_LIST:
				if(node->n_children == 1){
					node_t *current;
					current = node;
					node = current->children[0];
					finalize_node(current);
				}
                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:
				//Mistenker at feilen avhenger av min forståelse av hvilke cases som skal dekkes/hvordan case'ene fungerer.
				//liker ikke at vi selv må finne ut av hvilke cases vi skal dekke når dette ikke er skrevet eksplisitt i oppgaveteksten (PDF'en).
				//Sliter med å finne ut hvilken av if-testene nedenfor som forårsaker feilen. Mistenker det har noe å gjøre med den
				//nederste, men klarer ikke å tenke ut hva som er feil med den, eller hva som faktisk går galt...
				if(node->n_children == 2 &&
					node->children[0]->type.index == INTEGER &&
					node->children[1]->type.index == INTEGER){
					node_t *current = node;
					node = node->children[0];
					if(strcmp(current->data, "+") == 0){
						*((int*)node->data) = *((int*)node->data) + 
							(*(int*)current->children[1]->data);
					} else if(strcmp(current->data, "-") == 0){
						*((int*)node->data) = *((int*)node->data) -
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, "*") == 0){
						*((int*)node->data) = *((int*)node->data) *
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, "/") == 0){
						*((int*)node->data) = *((int*)node->data) /
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, "==") == 0){
						*((int*)node->data) = *((int*)node->data) ==
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, "!=") == 0){
						*((int*)node->data) = *((int*)node->data) !=
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, "<=") == 0){
						*((int*)node->data) = *((int*)node->data) <=
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, ">=") == 0){
						*((int*)node->data) = *((int*)node->data) >=
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, "<") == 0){
						*((int*)node->data) = *((int*)node->data) <
							(*(int*)current->children[1]->data);
					} else if (strcmp(current->data, ">") == 0){
						*((int*)node->data) = *((int*)node->data) >
							(*(int*)current->children[1]->data);
					}
					finalize_node(current->children[1]);
					finalize_node(current);
				} else if (node->n_children == 1){
					node_t *other = node;
					node = node->children[0];
					if(other->data == NULL){
						free(other);
					} else if(strcmp(other->data, "-") &&
						node->children[0]->type.index == INTEGER){
						*((int*)node->data) = *((int*)node->data) -
							2*(*((int*)node->data));
						node->type = other->type;
						finalize_node(other);
					}
				}
				break;
		}
	}
	return node;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}