Programming Assignment 4

 

Due Date:  11:59PM on April 14, 2009

 

 

For PA3 you have developed the compiler for a Bronco# programming language. In this programming assignment, there is no error in any input file and your program is to translate the input file into some intermediate representation which is output to an external file.

 

Your intermediate representation as the output should consider the following issues:

  1. replace each variable with its offset, and
  2. translate an expression into a prefix representation.
  3. implement some other restrictions.

 

 

 

 


INPUT GRAMMAR FOR PA2

 

Module

           

                        module            → unit  { unit }                       //{…} represents 0 or many

                                                                                                   repetitions

 

                        unit                  → declaration ‘;’                     //global variables

                                                → function                              //functions

                                                type_decl   ‘;’                     //types

                                                λ                                         // NULL

Type Declarations

 

                        type_decl        type ident ‘=’ type_def

                        type_def          array ‘[ int_const “..” int_const ‘]’ of type_id

                                                record field_list end

                                                enum ‘{‘ ident_list ‘}’

                                                pointer of type_id

                        field_list          field  {‘;’ field}

                        field                 type_id ident_list

                        type_id                        ident | base_type                 //’ident’ is a defined type

                        base_type        int | float | short               // short takes 2 bytes and 

                                                                                                   others take 4 bytes

 

Variable Declarations

 

                        declaration_list→declaration { ‘;’ declaration }

                        declaration      type_id ident_list

                        ident_list         ident  { ‘,’ ident }

 

Function Declarations

 

                        function           function return_type ident ‘(‘ parameter_list ‘)’

                                                      compound_stmt

                        return_type      type_id | void                     //Function returns nothing

                        parameter_list  → parameter {‘,’ parameter }   |  λ

                        parameter        → mode type_id ident

                        mode               ref | λ

 

Statements

 

                        stmt_list          → statement { ‘;’ statement}             

                        statement         assign_stmt

                                                while_stmt

                                                if_stmt

                                                function_call                      //Must return VOID

                                                compound_stmt

                                                return_stmt

                                                print_stmt

                                                new_stmt

                                                λ                                         //NULL statement

 

                        assign_stmt     → variable “=” expr

                        while_stmt      while ‘(expr ‘)’ statement

                        if_stmt             if ‘(expr ‘)’  statement

                                                if ‘(‘ expr ‘)’  statement else statement

                        function_call   ident ‘(expr_list ‘)’

                        compound_stmt’{declaration_list ‘;’ stmt_list ‘}’

                                                  {‘ stmt_list ‘}’

                        return_stmt      return ‘(expr ‘)’ | return

                        print_stmt        print ‘(output_list ‘)’

                                                println ‘(‘ output_list ‘)’ | println

                        new_stmt         new variable

 

Output List

 

                        output_list       output_element { ‘,’ output_element }

output_element           expr | string

                     

 

Expression List

 

                        expr_list          expr { ‘,’ expr } | λ

 

Variables

 

                        variable            ident variable_tail

                        variable_tail     → ‘[expr ‘]’ variable_tail

                                                → ‘.’ ident variable_tail          //Ident is defined field

                                                → ‘->’ ident variable_tail

                                                λ

 

Expressions

 

                        expr                 expr bin_op expr

                                                unary_op expr

                                                → ‘(expr ‘)’

                                                variable

                                                function_call

                                                int_const

                                                real_const

                        bin_op             → ‘+’ | ‘-‘ | ‘*’ | ‘/’ | ‘%’

                                                → ‘<’ | ‘>’ | ‘<=’ | ‘>=’ | ‘!=’ | ‘==’

                                                → ‘&&’ | ‘||’

                        unary_op         → ‘-‘ | ‘!’

 

Standard mathematical rules of precedence and associativity apply (‘%’ has the same associativity as ‘+’). Binary operators are LEFT associative.

 

 

 

 

Output Grammar for P4

 

Module

 

                        Module            function_list

                        function_list    function_list function | function

                        function           ident compound_stmt

 

Statements

 

                        stmt_list          stmt_list stmt | stmt

                        statement         assign_stmt

                                                while_stmt

                                                if_stmt

                                                function_call

                                                compound_stmt

                                                print_stmt

                                                return_stmt

                                                new_stmt

                        assign_stmt     assign expr variable

                                                assign variable variable                  //Big assignment

                        while_stmt      while expr statement

                        if_stmt             if expr statement

                                                if expr statement else statement

 

                                                                                    //Parameters are on the stack

                                                                                    //Constant is new Top-of-stack offset

                                                                                    //(aka “high_water_mark”)

                        function_call   ({first_letter_result_type}_call | expr)__ident              {({first_letter_type_name}_param| ref ) expr } end   // _param normal parameters; ref  is a pointer

                        compound_stmt’{‘ –integer_const stmt_list ‘}’

                        return_stmt      return_{ first_letter_result_type} expr

                        print_stmt        print print_list | println print_list

                        print_list         expr | string |  print_list { expr} | print_list {string}

                        new_stmt        → new variable integer_const

 

Expressions

 

                        expr                 bin_op_{first_letter_type_name} expr expr

                                                unary_op_{first_letter_type_name} expr

                                                variable

                                                function_call 

                        bin_op             → ‘+’ | ‘-‘ | ‘*’ | ‘/’ | ‘%’

                                                → ‘<’ | ‘>’ | ‘<=’ | ‘>=’ | ‘!=’ | ‘==’

                                                → ‘&&’ | ‘||’

                        unary_op         → ‘uminus’ | ‘!’

                        variable            datatype object_area offset

                        datatype          integer | float | composite length_of_size  // size of the data

                        object_area      local | global | ref_parameter | parameter

                        offset               expr

                       

 

An important note about Storage Allocation:

The stack in the output file grows in a negative location (do minus operation for each allocation). The parameter list to a function is located at a positive offset above the frame pointer; the local area is allocated from a negative offset from the frame pointer. The return value should be located at a positive offset above 0 and below the parameter list.

Locations 0 and -4 of the activation record (i.e. in the local object area) are used by the code generator to save the dynamic link and return address of the program. Therefore, you must begin storage allocation at location -8 of your activation record. So the configuration of a stack is shown as follows:


Example Transformations

 

Consider the recursive implementation of the factorial function:

 

function int factorial( int n )

{

    if (n <= 1)

        return( 1 )

    else

                        if (1)

                           return( n * factorial( n - 1 ))

                        else

                        {

                                    int temp;

 

                                    temp = factorial( n - 1 );

                                    println(" Return value from factorial is ", temp );

                                    return( n * temp );

                        }

}

           

 

We can see by inspection that there are no undefined variables or parse errors. The following is a transformation into prefix form:

 

__factorial

{ -8

    if <=_i  integer  parameter 8 1 return_i 1

    else if 1 return_i *_i  integer  parameter 8 i_call __factorial i_param -_i  integer  parameter 8 1 end

    else { -12

        assign i_call __factorial i_param -_i  integer  parameter 8 1 end  integer  local -8

        println " Return value from factorial is "  integer  local -8

        return_i *_i  integer  parameter 8  integer  local -8

    }

}


Consider the DOT-product:

 

type vector = array[ 1 .. 10 ] of float;

function float dot_product( vector x, vector y )

{

    int i;

    float result;

 

    i = 1;

    result = 0.0;

    while (i <= 10)

    {

        result = result + x[ i ] * y[ i ];

        i = i + 1;

    }

 

    return( result );

}

 

This would translate into:

 

__dot_product

{ -16

    assign 1  integer  local -8

    assign 0.0  float  local -12

    while <=_i  integer  local -8 10 { -16

        assign +_f  float  local -12 *_f  float  parameter -_i 44 *_i  4 -_i  integer  local -8  1  float  parameter -_i 84 *_i  4 -_i  integer  local -8  1  float  local -12

        assign +_i  integer  local -8 1  integer  local -8

    }

    return_f  float  local -12

}