示例#1
0
 def setUp(self):
     self.compiler_state = CompilerState()
     self.enable_debug(False)
     UUID_TICKETS.next_value = 0
     LABEL_TICKETS.next_value = 0
     INT_REGISTER_TICKETS.next_value = 0
     FLOAT_REGISTER_TICKETS.next_value = 0
示例#2
0
 def setUp(self):
     self.compiler_state = CompilerState()
     self.enable_debug(False)
     UUID_TICKETS.next_value = 0
     LABEL_TICKETS.next_value = 0
     INT_REGISTER_TICKETS.next_value = 0
     FLOAT_REGISTER_TICKETS.next_value = 0
示例#3
0
def main():
    ##
    #  WRITE YOUR C PROGRAM IN THIS STRING!
    ##
    your_c_program = """
      // your program here!
      int main() {
        int my_3d_array[1][2][3][4];
        return 0;
      }
    """

    compiler_state = CompilerState()
    ast = compiler_state.parse(your_c_program)

    ast.to_3ac(include_source=True)
示例#4
0
def main():
    ##
    #  WRITE YOUR C PROGRAM IN THIS STRING!
    ##
    your_c_program = """
      // your program here!
      int main() {
        int my_3d_array[1][2][3][4];
        return 0;
      }
    """

    compiler_state = CompilerState()
    ast = compiler_state.parse(your_c_program)

    ast.to_3ac(include_source=True)
示例#5
0
 def setUp(self):
     self.debug = True
     self.compiler_state = CompilerState()
示例#6
0
class TestParser(unittest.TestCase):
    def setUp(self):
        self.debug = True
        self.compiler_state = CompilerState()

    def tearDown(self):
        self.compiler_state.teardown()
        self.compiler_state = None

    def test_plain_main(self):
        data = """
            int main()
            {
                return 0;
            }
            int i; // Needed to clone the symbol table at the correct time
            !!C
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'main', 0, 'int main()')

    def test_declare_primitive_variable(self):
        self.enable_parser_debugging()

        data = """
            int main() {
                int i;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')
        symbol, _ = symbol_table_clone.find('i')
        self.assertEqual(0, symbol.activation_frame_offset)

    def test_declare_and_assign_primitive_variable(self):
        data = """
            int main() {
                int i = 5;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_declare_multiple_primitive_variable(self):
        # self.enable_parser_debugging()
        data = """
            int main() {
                int i, j, k;

                i = 0;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')
        self.check_correct_element(symbol_table_clone, 'j', 2, 'int j')
        self.check_correct_element(symbol_table_clone, 'k', 2, 'int k')

        i_symbol, _ = symbol_table_clone.find('i')
        j_symbol, _ = symbol_table_clone.find('j')
        k_symbol, _ = symbol_table_clone.find('k')

        self.assertEqual(0, i_symbol.activation_frame_offset)
        self.assertEqual(4, j_symbol.activation_frame_offset)
        self.assertEqual(8, k_symbol.activation_frame_offset)

    def test_modify_primitive_variable(self):
        self.enable_parser_debugging()

        data = """
            int main() {
                int i = 0;
                i += 5;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_declare_pointer_variable(self):
        self.enable_parser_debugging()
        data = """
            int main() {
                int* i;
                i = 0;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int * i')

    def test_declare_deep_pointer_variable(self):
        data = """
            int main() {
                int*** i;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        print(symbol_table_clone)

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int *** i')

    def test_declare_global_constant(self):
        self.enable_parser_debugging()
        data = """
            const int GLOBAL_CONSTANT = 5;

            int main() {
              int i = GLOBAL_CONSTANT;
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'GLOBAL_CONSTANT', 0, 'const int GLOBAL_CONSTANT')
        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_assign_to_immutable_variable_fails(self):
        with self.assertRaises(CompileError):
            data = """
                const int GLOBAL_CONSTANT = 5;

                int main() {
                  GLOBAL_CONSTANT = 0;
                  return 0;
                }
            """
            self.compiler_state.parse(data)

    def test_plain_if(self):
        data = """
            int main(int argc, char** argv)
            {
              if (1 != 1)
              {
                int wtf_result = -1;
                return wtf_result;
                !!C
              }

              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]
        self.check_correct_element(symbol_table_clone, 'wtf_result', 3, 'int wtf_result')

    def test_ternary_operator(self):
        data = """
            int main(int argc, char** argv)
            {
               return 0 == 0 ? 1 : 0;
            }
           """
        self.compiler_state.parse(data)
        self.assertTrue(True, "No exceptions means a successful parse.")

    def test_plain_if_else(self):
        data = """
            int main(int argc, char** argv)
            {
                if (1 != 1)
                {
                    !!C
                    int wtf_result = -1;
                    return wtf_result;
                }
                else
                {
                    !!C
                    int i_guess_its_fine = 0;
                    return i_guess_its_fine;
                }
                return 0;
            }
        """
        print(data)
        self.compiler_state.parse(data)
        if_symbol_table_clone = self.compiler_state.cloned_tables[0]
        else_symbol_table_clone = self.compiler_state.cloned_tables[1]

        self.check_correct_element(if_symbol_table_clone, 'wtf_result', 3, 'int wtf_result')
        self.check_correct_element(else_symbol_table_clone, 'i_guess_its_fine', 3, 'int i_guess_its_fine')

    def test_lone_else_fails(self):

        with self.assertRaises(Exception):
            data = 'int main(int argc, char** argv) {\n' \
                   '  else {\n' \
                   '    int wtf = 0;\n' \
                   '    return wtf;\n' \
                   '  }\n' \
                   '\n' \
                   '  return 0;\n' \
                   '}\n' \
                   ''
            self.compiler_state.parse(data)

    def test_while_loop(self):
        data = """
            int main()
            {
              while (1) {}
              return 0;
            }
            int i; // Needed to clone the symbol table at the correct time
            !!C
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'main', 0, 'int main()')

    def test_for_loop(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              int i;
              for (i = 0; i < 3; i++) {}
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_do_while_loop(self):
        data = """
            int main()
            {
              int i = 1;
              do {i++;} while(i);
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_cast_in_binary_expression(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
                int i = 5;
                float f = -4.5;

                i = (int) ((float) i + f);

                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_declare_array(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              int my_array[10];
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'my_array', 2, 'int my_array[10]')

    def test_declare_array_with_constant_expression_in_subscript(self):
        data = """
            int main()
            {
              int my_array[5 + 5];
              int i;
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'my_array', 2, 'int my_array[10]')

    def test_access_array(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              int i = 0;
              int my_array[10];

              int first_element = my_array[0];
              int some_other_element = my_array[i];

              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        print(symbol_table_clone)

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')
        self.check_correct_element(symbol_table_clone, 'my_array', 2, 'int my_array[10]')
        self.check_correct_element(symbol_table_clone, 'first_element', 2, 'int first_element')
        self.check_correct_element(symbol_table_clone, 'some_other_element', 2, 'int some_other_element')

    def test_declare_function(self):
        self.enable_parser_debugging()
        data = """
            int do_stuff(char c);
            !!C

            int main()
            {
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        result, _ = symbol_table_clone.find('do_stuff')
        print(result, type(result))
        assert(isinstance(result, FunctionSymbol))
        p = result.named_parameters[0]
        print(p, type(p))
        print(p.type_specifiers)

        self.check_correct_element(symbol_table_clone, 'do_stuff', 0, 'int do_stuff(char c)')

    def test_declare_function_implementation(self):
        data = """
            int do_stuff(char c)
            {
                return c + c;
            }

            int main()
            {
              return 0;
            }
            !!C
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'do_stuff', 0, 'int do_stuff(char c)')

    def test_call_function(self):
        self.enable_parser_debugging()
        data = """
            int do_stuff(int c);
            !!C

            int main()
            {
              do_stuff(4);

              return 0;
            }

            int do_stuff(int c)
            {
                return c + c;
                !!C
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone_inner = self.compiler_state.cloned_tables[0]
        symbol_table_clone_outer = self.compiler_state.cloned_tables[1]

        self.check_correct_element(symbol_table_clone_inner, 'do_stuff', 0, 'int do_stuff(int c)')
        self.check_correct_element(symbol_table_clone_outer, 'c', 1, 'int c')

        symbol, _ = symbol_table_clone_outer.find('c')
        self.assertEqual(0, symbol.activation_frame_offset)

    def test_declare_string_literal_char_star(self):
        self.enable_parser_debugging()
        data = """
            char* literal_string = "hello there";
            !!C

            int main()
            {
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'literal_string', 0, 'char * literal_string')

    def test_declare_string_as_array(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              char array_string[] = "hey";
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'array_string', 2, 'char array_string[4]')

    def test_declare_segmented_string_literal(self):
        data = """
            char literal_string[] = "hello "
                                   "world";
            !!C
            int main() {
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'literal_string', 0, 'char literal_string[12]')

    def test_bubble_sort(self):
        # TODO: this test is failing because we are not handling pointers as though they were arrays and vice versa
        # TODO: perhaps we should change our test case? Maybe this is why Fred said pointers were hard...

        data = """
            void print(int list[], int size);
            void bubbleSort(int list[], int size);

            int main()
            {
               int list[10];
               int i;
               //srand(time(NULL));

               // create list
               for(i =0; i<10;i++)
               {
                   //list[i] = rand() % 10 + 1;
               }
               print(list, 10);

               // bubble sort
               bubbleSort(list, 10 );

               //printf( "Sorted " );
               print(list, 10);

               !!C

               // return
               return 0;

            }

            void bubbleSort(int list[], int size)
            {
               int i, j;
               int temp;
               int swapped;

               for( i = 0; i < size; i++)
               {

                  // swapped is false
                  swapped = 0;

                  for( j = 0; j < size - 1; j++)
                  {
                     if(list[j+1] < list[j])
                     {
                        temp = list[j];
                        list[j] = list[j+1];
                        list[j+1] = temp;
                        swapped = 1;
                     }
                  }

                  if (swapped == 0)
                  {
                     break;
                  }
               }
            }

            void print(int list[], int size)
            {
               int i;
               //printf("List is: ");

               for(i =0; i < size; i++)
               {
                  //printf( "%d ", list[i] );
               }
               //printf("");
            }
        """
        self.compiler_state.parse(data)
        #symbol_table_clone = self.compiler_state.cloned_tables[0]

        # TODO: Determine what scopes we want to test here
        #self.check_correct_element(symbol_table_clone, '', 1, '')
        self.assertTrue(True, 'No exceptions = Parser successfully parsed.')

    def test_recursive_factorial(self):
        data = """
            long int recur_Fact(int number);

            int main() {
              int number;
              long int fact;

              //printf( "Enter number to get factorial of: ");
              //scanf( "%d", &number );

              fact = recur_Fact(number);

              //printf("Factorial of %d is:  %ld", number, fact);

              return 0;
            }

            long int recur_Fact( int number) {
              // base case
              if(number <= 0)
                return 1;

              // recursive case
              else if( number > 1 ) {
                return number*recur_Fact(number-1);
              }
            }
        """
        self.compiler_state.parse(data)
        #symbol_table_clone = self.compiler_state.cloned_tables[0]

        # TODO: Determine what scopes we want to test here
        #self.check_correct_element(symbol_table_clone, '', 1, '')

        self.assertTrue(True, 'No exceptions = Parser successfully parsed.')

    def test_iterative_factorial(self):
        data = """
            long int iter_Fact(int number);

            int main()
            {
                int number;
                long int fact;

                // printf("Enter number to get factorial of: ");
                // scanf( "%d", &number );

                fact = iter_Fact(number);

                // printf("Factorial of %d is:  %ld ", number, fact);

                return 0;
            }

            long int iter_Fact(int number)
            {
                int i;
                long int fact = 1;

                if( i < 0)
                {
                    return 1;
                }

                for( i = number; i > 0; i --)
                {
                    fact = fact*i;
                }
                return fact;
            }
        """
        self.compiler_state.parse(data)
        #symbol_table_clone = self.compiler_state.cloned_tables[0]

        # TODO: Determine what scopes we want to test here
        #self.check_correct_element(symbol_table_clone, '', 1, '')

        self.assertTrue(True, 'No exceptions = Parser successfully parsed.')

    # TODO: don't put a lot of emphasis on bad cases until things are strong with the good cases
    def test_malformed_main_fails(self):
        with self.assertRaises(Exception):
            data = 'badmain(] {return 0;}'
            self.compiler_state.parse(data)


    # def test_declare_typedef(self):
    #     self.enable_parser_debugging()
    #     data = """
    #     typedef int GlorifiedInt;
    #     !!C
    #
    #     int main() {
    #       return 0;
    #     }
    #     """
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: How are we handling typedefs?
    #     self.check_correct_element(symbol_table_clone, 'GlorifiedInt', 0, 'typedef int GlorifiedInt')

    # def test_declare_typedef_and_use_typedef_in_variable_declaration(self):
    #     self.enable_parser_debugging()
    #
    #     data = """
    #     typedef int GlorifiedInt;
    #
    #     int main() {
    #       GlorifiedInt i = 3;
    #       return 0;
    #       !!C
    #     }
    #     """
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: How are we handling typedefs?
    #     self.check_correct_element(symbol_table_clone, 'GlorifiedInt', 0, 'typedef int GlorifiedInt')
    #     self.check_correct_element(symbol_table_clone, 'i', 1, 'GlorifiedInt')

    # def test_declare_struct(self):
    #     data = """
    #         !!C
    #         struct Pixel {
    #             char r;
    #             char g;
    #             char b;
    #             !!C
    #         };
    #
    #         int main() {
    #           struct Pixel pixel;
    #           pixel.r = 255;
    #           pixel.g = 255;
    #           pixel.b = 255;
    #           !!C
    #           return 0;
    #         }
    #     """
    #
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: How are we handling structs?
    #     self.check_correct_element(symbol_table_clone, 'Pixel', 0, 'struct Pixel')
    #     self.check_correct_element(symbol_table_clone, 'r', 1, 'char r')
    #     self.check_correct_element(symbol_table_clone, 'g', 1, 'char g')
    #     self.check_correct_element(symbol_table_clone, 'b', 1, 'char b')
    #     self.check_correct_element(symbol_table_clone, 'pixel', 1, 'struct Pixel pixel')
    #
    #
    # def test_declare_function_pointer_typedef(self):
    #     data = """
    #     typedef int (*add_callback)(int a, int b);
    #
    #     int add_two(int a, int b, add_callback callback);
    #
    #     int normal_add(int a, int b);
    #     int weird_add(int a, int b);
    #
    #     int main() {
    #       int x;
    #       int y;
    #
    #       x = add_two(1, 2, normal_add);
    #       y = add_two(1, 2, weird_add);
    #
    #       !!C
    #       return 0;
    #     }
    #
    #     int add_two(int a, int b, add_callback callback) {
    #         return callback(a, b);
    #     }
    #
    #     int normal_add(int a, int b) {
    #         return a + b;
    #     }
    #
    #     int weird_add(int a, int b) {
    #         return (a + b) % 4;
    #     }
    #     """
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: Function Pointers??
    #     self.check_correct_element(symbol_table_clone, 'x', 1, 'int x')

    def test_super_function_testing(self):
        data = """
            !!C void do_stuff(int* array);

            int main()
            {
                return 0;
            }

            void do_stuff(int* array)
            {
                int* i;
                do_stuff(i);
            }
        """

        self.compiler_state.parse(data)

        symbol_table = self.compiler_state.cloned_tables[0]
        print(symbol_table)
        x, y = symbol_table.find('do_stuff')
        self.check_correct_element(symbol_table, 'do_stuff', 0, 'void do_stuff(int * array)')

    def test_super_memory_allocation(self):
        data = """
            char g_char;
            int g_int;
            float g_float;

            void do_stuff(char a, int b) {
                int c;
                float d;

                !!C
                return a + b;
            }

            int main()
            {
                int i = do_stuff('a', 2);
                return 0;
            }
            !!C
        """

        self.compiler_state.parse(data)

        function_symbol_table, global_symbol_table = self.compiler_state.cloned_tables[0:2]

        # g_char, _ = global_symbol_table.find('g_char')
        # self.assertEqual(0x10010000, g_char.global_memory_location)
        # g_int, _ = global_symbol_table.find('g_int')
        # self.assertEqual(0x10010004, g_int.global_memory_location)
        # g_float, _ = global_symbol_table.find('g_float')
        # self.assertEqual(0x10010008, g_float.global_memory_location)

        f_a, _ = function_symbol_table.find('a')
        self.assertEqual(0, f_a.activation_frame_offset)
        f_b, _ = function_symbol_table.find('b')
        self.assertEqual(4, f_b.activation_frame_offset)
        f_c, _ = function_symbol_table.find('c')
        self.assertEqual(8, f_c.activation_frame_offset)
        f_d, _ = function_symbol_table.find('d')
        self.assertEqual(12, f_d.activation_frame_offset)

    def enable_parser_debugging(self):
        if self.debug:
            self.compiler_state.get_parser_logger().add_switch(Logger.PRODUCTION)
            self.compiler_state.get_parser_logger().add_switch(Logger.INFO)
            self.compiler_state.get_parser_logger().add_switch(Logger.SOURCE)

    def check_correct_element(self, symbol_table_clone, check_value, check_scope, check_string):
        found_symbol, in_scope = symbol_table_clone.find(check_value)
        self.assertEqual(check_scope, in_scope, "The symbol was not found in the expected scope")
        self.assertEqual(check_string, str(found_symbol), "The symbols don't match")
示例#7
0
 def setUp(self):
     self.compiler_state = CompilerState()
     lexer = JSTLexer(self.compiler_state)
     self.scanner = lex.lex(module=lexer)
示例#8
0
    def setUp(self):
        self.compiler_state = CompilerState(print_productions=False)
        self.enable_debug(False)

        self.generator = generation.MipsGenerator(self.compiler_state, inject_source=True, inject_3ac=True)
示例#9
0
class TestMipsGenerator(unittest.TestCase):
    def setUp(self):
        self.compiler_state = CompilerState(print_productions=False)
        self.enable_debug(False)

        self.generator = generation.MipsGenerator(self.compiler_state, inject_source=True, inject_3ac=True)

    def tearDown(self):
        self.compiler_state.teardown()
        self.compiler_state = None

    def enable_debug(self, enable, productions=True, source=False):
        if enable:
            prod_logger = self.compiler_state.get_parser_logger()

            prod_logger.add_switch(Logger.INFO)
            if productions:
                prod_logger.add_switch(Logger.PRODUCTION)

            if source:
                prod_logger.add_switch(Logger.SOURCE)

    def test_plain_main(self):
        data = """
            int main()
            {
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()

        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_global_variable_declaration(self):
        data = """
            int g = 5;

            int main() {
              return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_print_int(self):
        data = """
            int main() {
              print_int(777);
              return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_declarations(self):
        data = """
            int main()
            {
                char c;
                short s;
                int i;
                long long l;

                char arr[13];

                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_simple_assignment(self):
        data = """
            int main()
            {
                int i;
                i = 0;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_constant_expression(self):
        data = """
            int main()
            {
                int i, a, b;
                i = a + b;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_explicit_cast(self):
        # self.enable_debug(True)
        data = """
            int main()
            {
                int i;
                i = (int) 4.2;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_if_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
                else
                {
                    i = 5;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_if_elif_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 1)
                {
                    i = 7;
                }
                else if(i == 2)
                {
                    i = 8;
                }
                else
                {
                    i = 9;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_while_loop(self):
        data = """
            int main()
            {
                int i;
                while(i < 5){}
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_array_access(self):
        data = """
            int main()
            {
                int a[2][2];
                a[0][0] = a[1][1];
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_constant_folding(self):
        data = """
            const int a = 1 + 1;
            const int b = a + 2;
            int main()
            {
                int c = a + b;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_array_initializers(self):
        data = """
            int main()
            {
                int a[5] = {1,2,3,4,5};
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_function_with_param(self):
        data = """
            int foo( int a, int b, int c);

            int main()
            {
                int i = foo(1,2,3);
                return 0;
            }

            int foo( int a, int b, int c)
            {
                return 1;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_for_loop(self):
        data = """
            int main()
            {
                int i = 0;
                int j;
                for(i=0;i<3;i++)
                {
                    j = 5;
                }
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_do_while_loop(self):
        data = """
            int main()
            {
                int i;
                do
                {
                    i = 5;
                }
                while (i > 10);
            }
            """
        ast = self.compiler_state.parse(data)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_matrix_multiplication(self):
        test_program = """
            const int ARRAY_DIM = 2;

            // hard code dimensions for simplicity
            int matrix_multiply(int C[ARRAY_DIM][ARRAY_DIM], int A[ARRAY_DIM][ARRAY_DIM], int B[ARRAY_DIM][ARRAY_DIM]);

            int main() {
              int i, j;
              int A[ARRAY_DIM][ARRAY_DIM], B[ARRAY_DIM][ARRAY_DIM], C[ARRAY_DIM][ARRAY_DIM];

              for (i = 0; i < ARRAY_DIM; i++) {
                for (j = 0; j < ARRAY_DIM; j++) {
                  A[i][j] = B[i][j] = 1;
                }
              }

              matrix_multiply(C, A, B);

              return 0;
            }

            int matrix_multiply(int C[ARRAY_DIM][ARRAY_DIM], int A[ARRAY_DIM][ARRAY_DIM], int B[ARRAY_DIM][ARRAY_DIM]) {
              int i, j, k;

              for (i = 0; i < ARRAY_DIM; i++) {
                for (j = 0; j < ARRAY_DIM; j++) {
                  C[i][j] = 0;
                  for (k = 0; k < ARRAY_DIM; k++) {
                    C[i][j] += A[i][j + k] * B[i + k][j];
                  }
                }
              }
            }
            """
        ast = self.compiler_state.parse(test_program)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())

    def test_bubble_sort(self):
        test_program = """
            const int N_ITEMS = 5;
            int bubble_sort(int items[N_ITEMS], int n_items);

            int main() {
              int items[N_ITEMS] = {5, 1, 4, 3, 2};

              bubble_sort(items, 5);

              return 0;
            }

            int bubble_sort(int items[N_ITEMS], int n_items) {
              int i, j;
              int temp;

              for (i = 0; i < n_items; i++) {
                for (j = i; j < n_items; j++) {
                  if (items[i] < items[j]) {
                    temp = items[i];
                    items[i] = items[j];
                    items[j] = temp;
                  }
                }
              }
            }
            """
        ast = self.compiler_state.parse(test_program)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())


    def test_recursive_factorial(self):
        test_program = """
            int factorial(int x);

            int main() {
              int x = 5;
              int result = factorial(x);

              return 0;
            }

            int factorial(int x) {
              if (x > 1) {
                return factorial(x - 1);
              } else {
                return 1;
              }
            }
            """
        ast = self.compiler_state.parse(test_program)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())


    def test_land_and_lor(self):
        test_program = """
            int main() {
              int x = 5;
              x = x && 5;

              return 0;
            }
            """
        ast = self.compiler_state.parse(test_program)
        source_tac, tac_str = ast.to_3ac()
        # print(source_tac)
        print('---------------------------')

        self.generator.load(source_tac)
        self.generator.translate_tac_to_mips()
        print(self.generator.dumps())
示例#10
0
def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("source",
                            type=str,
                            help="The C program file to compile.")
    arg_parser.add_argument(
        "-o",
        "--outfile",
        type=str,
        default='STDOUT',
        help=
        "The name of the output file. MUST be a .asm file! (Default: STDOUT)")
    arg_parser.add_argument(
        "-sym",
        "--symtable",
        action='store_true',
        help="Enables the printing of symbol table in other options.")
    arg_parser.add_argument(
        "-s",
        "--scandebug",
        type=int,
        choices=[0, 1, 2, 3],
        default=0,
        help=
        "The debug level for the scanner. \n 0: No debug \n 1: Tokens \n 2: Source Code \n "
        "3: Tokens and Source Code")
    arg_parser.add_argument(
        "-p",
        "--parsedebug",
        type=int,
        choices=[0, 1, 2, 3],
        default=0,
        help=
        "The debug level for the parser. \n 0: No debug \n 1: Productions \n "
        " 2: Productions and Source Code \n 3: Productions, Source, Misc info")
    arg_parser.add_argument(
        "-ast",
        "--astree",
        action='store_true',
        help="Enables the printing of the GraphViz string after parsing.")
    arg_parser.add_argument(
        "-tac",
        "--threeac",
        type=int,
        choices=[0, 1, 2],
        default=0,
        help="The debug level for the 3AC. \n 0: No debug \n 1: 3AC \n "
        " 2: 3AC + Source")
    arg_parser.add_argument(
        "-mips",
        "--mips",
        type=int,
        choices=[0, 1, 2, 3],
        default=0,
        help="The debug level for the MIPS. \n 0: No debug \n 1: 3AC \n "
        " 2: Source \n 3: 3AC + Source")
    arg_parser.add_argument("-w",
                            "--warnings",
                            action='store_true',
                            help="Enables warnings being printed.")

    args = vars(arg_parser.parse_args())

    # Set Symbol Table flags
    print_table = args['symtable']

    # Set Scanner flags
    print_tokens, print_source_scanner = False, False
    if args['scandebug'] is 1:
        print_tokens = True
    elif args['scandebug'] is 2:
        print_source_scanner = True
    elif args['scandebug'] is 3:
        print_tokens = True
        print_source_scanner = True

    # Set Parser flags
    print_productions, print_source_parser, print_info = False, False, False
    if args['parsedebug'] is 1:
        print_productions = True
    elif args['parsedebug'] is 2:
        print_productions = True
        print_source_parser = True
    elif args['parsedebug'] is 3:
        print_productions = True
        print_source_parser = True
        print_info = True

    source_file = open(args['source'], 'r')
    data = source_file.read()
    compiler_state = CompilerState(print_table=print_table,
                                   print_tokens=print_tokens,
                                   print_source_scanner=print_source_scanner,
                                   print_productions=print_productions,
                                   print_source_parser=print_source_parser,
                                   print_info=print_info,
                                   print_warnings=args['warnings'])

    try:
        ast = compiler_state.parse(data)
        if args['astree']:
            print(ast.to_graph_viz_str())

        if args['threeac'] is 2:
            source_tac, tac_as_str = ast.to_3ac(include_source=True)
        else:
            source_tac, tac_as_str = ast.to_3ac()

        if args['mips'] == 1:
            generator = generation.MipsGenerator(compiler_state,
                                                 inject_source=False,
                                                 inject_3ac=True)
        elif args['mips'] == 2:
            generator = generation.MipsGenerator(compiler_state,
                                                 inject_source=True,
                                                 inject_3ac=False)
        elif args['mips'] == 3:
            generator = generation.MipsGenerator(compiler_state,
                                                 inject_source=True,
                                                 inject_3ac=True)
        else:
            generator = generation.MipsGenerator(compiler_state,
                                                 inject_source=False,
                                                 inject_3ac=False)

        generator.load(source_tac)
        generator.translate_tac_to_mips()

        if args['outfile'] != 'STDOUT':
            fout = open(args['outfile'], 'w')
            fout.write(generator.dumps())
            fout.close()
        else:
            print(generator.dumps())

    except CompileError as error:
        print(error)
    finally:
        compiler_state.teardown()
示例#11
0
class TestParser(unittest.TestCase):
    def setUp(self):
        self.debug = True
        self.compiler_state = CompilerState()

    def tearDown(self):
        self.compiler_state.teardown()
        self.compiler_state = None

    def test_plain_main(self):
        data = """
            int main()
            {
                return 0;
            }
            int i; // Needed to clone the symbol table at the correct time
            !!C
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'main', 0, 'int main()')

    def test_declare_primitive_variable(self):
        self.enable_parser_debugging()

        data = """
            int main() {
                int i;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')
        symbol, _ = symbol_table_clone.find('i')
        self.assertEqual(0, symbol.activation_frame_offset)

    def test_declare_and_assign_primitive_variable(self):
        data = """
            int main() {
                int i = 5;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_declare_multiple_primitive_variable(self):
        # self.enable_parser_debugging()
        data = """
            int main() {
                int i, j, k;

                i = 0;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')
        self.check_correct_element(symbol_table_clone, 'j', 2, 'int j')
        self.check_correct_element(symbol_table_clone, 'k', 2, 'int k')

        i_symbol, _ = symbol_table_clone.find('i')
        j_symbol, _ = symbol_table_clone.find('j')
        k_symbol, _ = symbol_table_clone.find('k')

        self.assertEqual(0, i_symbol.activation_frame_offset)
        self.assertEqual(4, j_symbol.activation_frame_offset)
        self.assertEqual(8, k_symbol.activation_frame_offset)

    def test_modify_primitive_variable(self):
        self.enable_parser_debugging()

        data = """
            int main() {
                int i = 0;
                i += 5;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_declare_pointer_variable(self):
        self.enable_parser_debugging()
        data = """
            int main() {
                int* i;
                i = 0;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int * i')

    def test_declare_deep_pointer_variable(self):
        data = """
            int main() {
                int*** i;
                !!C
                return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        print(symbol_table_clone)

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int *** i')

    def test_declare_global_constant(self):
        self.enable_parser_debugging()
        data = """
            const int GLOBAL_CONSTANT = 5;

            int main() {
              int i = GLOBAL_CONSTANT;
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'GLOBAL_CONSTANT', 0,
                                   'const int GLOBAL_CONSTANT')
        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_assign_to_immutable_variable_fails(self):
        with self.assertRaises(CompileError):
            data = """
                const int GLOBAL_CONSTANT = 5;

                int main() {
                  GLOBAL_CONSTANT = 0;
                  return 0;
                }
            """
            self.compiler_state.parse(data)

    def test_plain_if(self):
        data = """
            int main(int argc, char** argv)
            {
              if (1 != 1)
              {
                int wtf_result = -1;
                return wtf_result;
                !!C
              }

              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]
        self.check_correct_element(symbol_table_clone, 'wtf_result', 3,
                                   'int wtf_result')

    def test_ternary_operator(self):
        data = """
            int main(int argc, char** argv)
            {
               return 0 == 0 ? 1 : 0;
            }
           """
        self.compiler_state.parse(data)
        self.assertTrue(True, "No exceptions means a successful parse.")

    def test_plain_if_else(self):
        data = """
            int main(int argc, char** argv)
            {
                if (1 != 1)
                {
                    !!C
                    int wtf_result = -1;
                    return wtf_result;
                }
                else
                {
                    !!C
                    int i_guess_its_fine = 0;
                    return i_guess_its_fine;
                }
                return 0;
            }
        """
        print(data)
        self.compiler_state.parse(data)
        if_symbol_table_clone = self.compiler_state.cloned_tables[0]
        else_symbol_table_clone = self.compiler_state.cloned_tables[1]

        self.check_correct_element(if_symbol_table_clone, 'wtf_result', 3,
                                   'int wtf_result')
        self.check_correct_element(else_symbol_table_clone, 'i_guess_its_fine',
                                   3, 'int i_guess_its_fine')

    def test_lone_else_fails(self):

        with self.assertRaises(Exception):
            data = 'int main(int argc, char** argv) {\n' \
                   '  else {\n' \
                   '    int wtf = 0;\n' \
                   '    return wtf;\n' \
                   '  }\n' \
                   '\n' \
                   '  return 0;\n' \
                   '}\n' \
                   ''
            self.compiler_state.parse(data)

    def test_while_loop(self):
        data = """
            int main()
            {
              while (1) {}
              return 0;
            }
            int i; // Needed to clone the symbol table at the correct time
            !!C
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'main', 0, 'int main()')

    def test_for_loop(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              int i;
              for (i = 0; i < 3; i++) {}
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_do_while_loop(self):
        data = """
            int main()
            {
              int i = 1;
              do {i++;} while(i);
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')

    def test_cast_in_binary_expression(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
                int i = 5;
                float f = -4.5;

                i = (int) ((float) i + f);

                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_declare_array(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              int my_array[10];
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'my_array', 2,
                                   'int my_array[10]')

    def test_declare_array_with_constant_expression_in_subscript(self):
        data = """
            int main()
            {
              int my_array[5 + 5];
              int i;
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'my_array', 2,
                                   'int my_array[10]')

    def test_access_array(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              int i = 0;
              int my_array[10];

              int first_element = my_array[0];
              int some_other_element = my_array[i];

              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        print(symbol_table_clone)

        self.check_correct_element(symbol_table_clone, 'i', 2, 'int i')
        self.check_correct_element(symbol_table_clone, 'my_array', 2,
                                   'int my_array[10]')
        self.check_correct_element(symbol_table_clone, 'first_element', 2,
                                   'int first_element')
        self.check_correct_element(symbol_table_clone, 'some_other_element', 2,
                                   'int some_other_element')

    def test_declare_function(self):
        self.enable_parser_debugging()
        data = """
            int do_stuff(char c);
            !!C

            int main()
            {
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        result, _ = symbol_table_clone.find('do_stuff')
        print(result, type(result))
        assert (isinstance(result, FunctionSymbol))
        p = result.named_parameters[0]
        print(p, type(p))
        print(p.type_specifiers)

        self.check_correct_element(symbol_table_clone, 'do_stuff', 0,
                                   'int do_stuff(char c)')

    def test_declare_function_implementation(self):
        data = """
            int do_stuff(char c)
            {
                return c + c;
            }

            int main()
            {
              return 0;
            }
            !!C
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'do_stuff', 0,
                                   'int do_stuff(char c)')

    def test_call_function(self):
        self.enable_parser_debugging()
        data = """
            int do_stuff(int c);
            !!C

            int main()
            {
              do_stuff(4);

              return 0;
            }

            int do_stuff(int c)
            {
                return c + c;
                !!C
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone_inner = self.compiler_state.cloned_tables[0]
        symbol_table_clone_outer = self.compiler_state.cloned_tables[1]

        self.check_correct_element(symbol_table_clone_inner, 'do_stuff', 0,
                                   'int do_stuff(int c)')
        self.check_correct_element(symbol_table_clone_outer, 'c', 1, 'int c')

        symbol, _ = symbol_table_clone_outer.find('c')
        self.assertEqual(0, symbol.activation_frame_offset)

    def test_declare_string_literal_char_star(self):
        self.enable_parser_debugging()
        data = """
            char* literal_string = "hello there";
            !!C

            int main()
            {
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'literal_string', 0,
                                   'char * literal_string')

    def test_declare_string_as_array(self):
        self.enable_parser_debugging()
        data = """
            int main()
            {
              char array_string[] = "hey";
              !!C
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'array_string', 2,
                                   'char array_string[4]')

    def test_declare_segmented_string_literal(self):
        data = """
            char literal_string[] = "hello "
                                   "world";
            !!C
            int main() {
              return 0;
            }
        """
        self.compiler_state.parse(data)
        symbol_table_clone = self.compiler_state.cloned_tables[0]

        self.check_correct_element(symbol_table_clone, 'literal_string', 0,
                                   'char literal_string[12]')

    def test_bubble_sort(self):
        # TODO: this test is failing because we are not handling pointers as though they were arrays and vice versa
        # TODO: perhaps we should change our test case? Maybe this is why Fred said pointers were hard...

        data = """
            void print(int list[], int size);
            void bubbleSort(int list[], int size);

            int main()
            {
               int list[10];
               int i;
               //srand(time(NULL));

               // create list
               for(i =0; i<10;i++)
               {
                   //list[i] = rand() % 10 + 1;
               }
               print(list, 10);

               // bubble sort
               bubbleSort(list, 10 );

               //printf( "Sorted " );
               print(list, 10);

               !!C

               // return
               return 0;

            }

            void bubbleSort(int list[], int size)
            {
               int i, j;
               int temp;
               int swapped;

               for( i = 0; i < size; i++)
               {

                  // swapped is false
                  swapped = 0;

                  for( j = 0; j < size - 1; j++)
                  {
                     if(list[j+1] < list[j])
                     {
                        temp = list[j];
                        list[j] = list[j+1];
                        list[j+1] = temp;
                        swapped = 1;
                     }
                  }

                  if (swapped == 0)
                  {
                     break;
                  }
               }
            }

            void print(int list[], int size)
            {
               int i;
               //printf("List is: ");

               for(i =0; i < size; i++)
               {
                  //printf( "%d ", list[i] );
               }
               //printf("");
            }
        """
        self.compiler_state.parse(data)
        #symbol_table_clone = self.compiler_state.cloned_tables[0]

        # TODO: Determine what scopes we want to test here
        #self.check_correct_element(symbol_table_clone, '', 1, '')
        self.assertTrue(True, 'No exceptions = Parser successfully parsed.')

    def test_recursive_factorial(self):
        data = """
            long int recur_Fact(int number);

            int main() {
              int number;
              long int fact;

              //printf( "Enter number to get factorial of: ");
              //scanf( "%d", &number );

              fact = recur_Fact(number);

              //printf("Factorial of %d is:  %ld", number, fact);

              return 0;
            }

            long int recur_Fact( int number) {
              // base case
              if(number <= 0)
                return 1;

              // recursive case
              else if( number > 1 ) {
                return number*recur_Fact(number-1);
              }
            }
        """
        self.compiler_state.parse(data)
        #symbol_table_clone = self.compiler_state.cloned_tables[0]

        # TODO: Determine what scopes we want to test here
        #self.check_correct_element(symbol_table_clone, '', 1, '')

        self.assertTrue(True, 'No exceptions = Parser successfully parsed.')

    def test_iterative_factorial(self):
        data = """
            long int iter_Fact(int number);

            int main()
            {
                int number;
                long int fact;

                // printf("Enter number to get factorial of: ");
                // scanf( "%d", &number );

                fact = iter_Fact(number);

                // printf("Factorial of %d is:  %ld ", number, fact);

                return 0;
            }

            long int iter_Fact(int number)
            {
                int i;
                long int fact = 1;

                if( i < 0)
                {
                    return 1;
                }

                for( i = number; i > 0; i --)
                {
                    fact = fact*i;
                }
                return fact;
            }
        """
        self.compiler_state.parse(data)
        #symbol_table_clone = self.compiler_state.cloned_tables[0]

        # TODO: Determine what scopes we want to test here
        #self.check_correct_element(symbol_table_clone, '', 1, '')

        self.assertTrue(True, 'No exceptions = Parser successfully parsed.')

    # TODO: don't put a lot of emphasis on bad cases until things are strong with the good cases
    def test_malformed_main_fails(self):
        with self.assertRaises(Exception):
            data = 'badmain(] {return 0;}'
            self.compiler_state.parse(data)

    # def test_declare_typedef(self):
    #     self.enable_parser_debugging()
    #     data = """
    #     typedef int GlorifiedInt;
    #     !!C
    #
    #     int main() {
    #       return 0;
    #     }
    #     """
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: How are we handling typedefs?
    #     self.check_correct_element(symbol_table_clone, 'GlorifiedInt', 0, 'typedef int GlorifiedInt')

    # def test_declare_typedef_and_use_typedef_in_variable_declaration(self):
    #     self.enable_parser_debugging()
    #
    #     data = """
    #     typedef int GlorifiedInt;
    #
    #     int main() {
    #       GlorifiedInt i = 3;
    #       return 0;
    #       !!C
    #     }
    #     """
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: How are we handling typedefs?
    #     self.check_correct_element(symbol_table_clone, 'GlorifiedInt', 0, 'typedef int GlorifiedInt')
    #     self.check_correct_element(symbol_table_clone, 'i', 1, 'GlorifiedInt')

    # def test_declare_struct(self):
    #     data = """
    #         !!C
    #         struct Pixel {
    #             char r;
    #             char g;
    #             char b;
    #             !!C
    #         };
    #
    #         int main() {
    #           struct Pixel pixel;
    #           pixel.r = 255;
    #           pixel.g = 255;
    #           pixel.b = 255;
    #           !!C
    #           return 0;
    #         }
    #     """
    #
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: How are we handling structs?
    #     self.check_correct_element(symbol_table_clone, 'Pixel', 0, 'struct Pixel')
    #     self.check_correct_element(symbol_table_clone, 'r', 1, 'char r')
    #     self.check_correct_element(symbol_table_clone, 'g', 1, 'char g')
    #     self.check_correct_element(symbol_table_clone, 'b', 1, 'char b')
    #     self.check_correct_element(symbol_table_clone, 'pixel', 1, 'struct Pixel pixel')
    #
    #
    # def test_declare_function_pointer_typedef(self):
    #     data = """
    #     typedef int (*add_callback)(int a, int b);
    #
    #     int add_two(int a, int b, add_callback callback);
    #
    #     int normal_add(int a, int b);
    #     int weird_add(int a, int b);
    #
    #     int main() {
    #       int x;
    #       int y;
    #
    #       x = add_two(1, 2, normal_add);
    #       y = add_two(1, 2, weird_add);
    #
    #       !!C
    #       return 0;
    #     }
    #
    #     int add_two(int a, int b, add_callback callback) {
    #         return callback(a, b);
    #     }
    #
    #     int normal_add(int a, int b) {
    #         return a + b;
    #     }
    #
    #     int weird_add(int a, int b) {
    #         return (a + b) % 4;
    #     }
    #     """
    #     self.compiler_state.parse(data)
    #     symbol_table_clone = self.compiler_state.cloned_tables[0]
    #
    #     # TODO: Function Pointers??
    #     self.check_correct_element(symbol_table_clone, 'x', 1, 'int x')

    def test_super_function_testing(self):
        data = """
            !!C void do_stuff(int* array);

            int main()
            {
                return 0;
            }

            void do_stuff(int* array)
            {
                int* i;
                do_stuff(i);
            }
        """

        self.compiler_state.parse(data)

        symbol_table = self.compiler_state.cloned_tables[0]
        print(symbol_table)
        x, y = symbol_table.find('do_stuff')
        self.check_correct_element(symbol_table, 'do_stuff', 0,
                                   'void do_stuff(int * array)')

    def test_super_memory_allocation(self):
        data = """
            char g_char;
            int g_int;
            float g_float;

            void do_stuff(char a, int b) {
                int c;
                float d;

                !!C
                return a + b;
            }

            int main()
            {
                int i = do_stuff('a', 2);
                return 0;
            }
            !!C
        """

        self.compiler_state.parse(data)

        function_symbol_table, global_symbol_table = self.compiler_state.cloned_tables[
            0:2]

        # g_char, _ = global_symbol_table.find('g_char')
        # self.assertEqual(0x10010000, g_char.global_memory_location)
        # g_int, _ = global_symbol_table.find('g_int')
        # self.assertEqual(0x10010004, g_int.global_memory_location)
        # g_float, _ = global_symbol_table.find('g_float')
        # self.assertEqual(0x10010008, g_float.global_memory_location)

        f_a, _ = function_symbol_table.find('a')
        self.assertEqual(0, f_a.activation_frame_offset)
        f_b, _ = function_symbol_table.find('b')
        self.assertEqual(4, f_b.activation_frame_offset)
        f_c, _ = function_symbol_table.find('c')
        self.assertEqual(8, f_c.activation_frame_offset)
        f_d, _ = function_symbol_table.find('d')
        self.assertEqual(12, f_d.activation_frame_offset)

    def enable_parser_debugging(self):
        if self.debug:
            self.compiler_state.get_parser_logger().add_switch(
                Logger.PRODUCTION)
            self.compiler_state.get_parser_logger().add_switch(Logger.INFO)
            self.compiler_state.get_parser_logger().add_switch(Logger.SOURCE)

    def check_correct_element(self, symbol_table_clone, check_value,
                              check_scope, check_string):
        found_symbol, in_scope = symbol_table_clone.find(check_value)
        self.assertEqual(check_scope, in_scope,
                         "The symbol was not found in the expected scope")
        self.assertEqual(check_string, str(found_symbol),
                         "The symbols don't match")
示例#12
0
 def setUp(self):
     self.compiler_state = CompilerState(print_productions=False)
     self.enable_debug(False)
示例#13
0
class TestTac(unittest.TestCase):

    def setUp(self):
        self.compiler_state = CompilerState(print_productions=False)
        self.enable_debug(False)

    def tearDown(self):
        self.compiler_state.teardown()
        self.compiler_state = None

    def enable_debug(self, enable, productions=True, source=False):
        if enable:
            prod_logger = self.compiler_state.get_parser_logger()

            prod_logger.add_switch(Logger.INFO)
            if productions:
                prod_logger.add_switch(Logger.PRODUCTION)

            if source:
                prod_logger.add_switch(Logger.SOURCE)

    def test_plain_main(self):
        data = """
            int main()
            {
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_declarations(self):
        data = """
            int main()
            {
                char c;
                short s;
                int i;
                long long l;

                char arr[13];

                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_simple_assignment(self):
        data = """
            int main()
            {
                int i;
                i = 0;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        # print(ast.to_graph_viz_str())
        ast.to_3ac()

    def test_constant_expression(self):
        data = """
            int main()
            {
                int i, a, b;
                i = a + b;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        # print(ast.to_graph_viz_str())
        ast.to_3ac()

    def test_explicit_cast(self):
        # self.enable_debug(True)
        data = """
            int main()
            {
                int i;
                i = (int) 4.2;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_if_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
                else
                {
                    i = 5;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_if_elif_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 1)
                {
                    i = 7;
                }
                else if(i == 2)
                {
                    i = 8;
                }
                else
                {
                    i = 9;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()
        # print(ast.to_graph_viz_str())

    def test_while_loop(self):
        data = """
            int main()
            {
                int i;
                while(i < 5){}
            }
            """
        ast = self.compiler_state.parse(data)
        # print(ast.to_graph_viz_str())
        ast.to_3ac()

    def test_array_access(self):
        data = """
            int main()
            {
                int a[2][2];
                a[0][0] = a[1][1];
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_constant_folding(self):
        data = """
            const int a = 1 + 1;
            const int b = a + 2;
            int main()
            {
                int c = a + b;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_array_initializers(self):
        data = """
            int main()
            {
                int a[5] = {1,2,3,4,5};
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_function_with_param(self):
        data = """
            int foo( int a, int b, int c);

            int main()
            {
                int i = foo(1,2,3);
                return 0;
            }

            int foo( int a, int b, int c)
            {
                return 1;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_for_loop(self):
        data = """
            int main()
            {
                int i = 0;
                int j;
                for(i=0;i<3;i++)
                {
                    j = 5;
                }
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        ast.to_3ac()

    def test_do_while_loop(self):
        data = """
            int main()
            {
                int i;
                do
                {
                    i = 5;
                }
                while (i > 10);
            }
            """
        ast = self.compiler_state.parse(data)
        # print(ast.to_graph_viz_str())
        ast.to_3ac()

    def test_matrix_multiplication(self):
        test_program = """
            const int ARRAY_DIM = 2;

            // hard code dimensions for simplicity
            int matrix_multiply(int C[ARRAY_DIM][ARRAY_DIM], int A[ARRAY_DIM][ARRAY_DIM], int B[ARRAY_DIM][ARRAY_DIM]);

            int main() {
              int i, j;
              int A[ARRAY_DIM][ARRAY_DIM], B[ARRAY_DIM][ARRAY_DIM], C[ARRAY_DIM][ARRAY_DIM];

              for (i = 0; i < ARRAY_DIM; i++) {
                for (j = 0; j < ARRAY_DIM; j++) {
                  A[i][j] = B[i][j] = 1;
                }
              }

              matrix_multiply(C, A, B);

              return 0;
            }

            int matrix_multiply(int C[ARRAY_DIM][ARRAY_DIM], int A[ARRAY_DIM][ARRAY_DIM], int B[ARRAY_DIM][ARRAY_DIM]) {
              int i, j, k;

              for (i = 0; i < ARRAY_DIM; i++) {
                for (j = 0; j < ARRAY_DIM; j++) {
                  C[i][j] = 0;
                  for (k = 0; k < ARRAY_DIM; k++) {
                    C[i][j] += A[i][j + k] * B[i + k][j];
                  }
                }
              }
            }
            """

        ast = self.compiler_state.parse(test_program)
        ast.to_3ac()

    def test_bubble_sort(self):
        test_program = """
            const int N_ITEMS = 5;
            int bubble_sort(int items[N_ITEMS], int n_items);

            int main() {
              int items[N_ITEMS] = {5, 1, 4, 3, 2};

              bubble_sort(items, 5);

              return 0;
            }

            int bubble_sort(int items[N_ITEMS], int n_items) {
              int i, j;
              int temp;

              for (i = 0; i < n_items; i++) {
                for (j = i; j < n_items; j++) {
                  if (items[i] < items[j]) {
                    temp = items[i];
                    items[i] = items[j];
                    items[j] = temp;
                  }
                }
              }
            }
            """

        ast = self.compiler_state.parse(test_program)
        ast.to_3ac()

    def test_recursive_factorial(self):
        test_program = """
            int factorial(int x);

            int main() {
              int x = 5;
              int result = factorial(x);

              return 0;
            }

            int factorial(int x) {
              if (x > 1) {
                return factorial(x - 1);
              } else {
                return 1;
              }
            }
            """

        ast = self.compiler_state.parse(test_program)
        ast.to_3ac()
示例#14
0
class TestAst(unittest.TestCase):

    def setUp(self):
        self.compiler_state = CompilerState()
        self.enable_debug(False)
        UUID_TICKETS.next_value = 0
        LABEL_TICKETS.next_value = 0
        INT_REGISTER_TICKETS.next_value = 0
        FLOAT_REGISTER_TICKETS.next_value = 0

    def tearDown(self):
        self.compiler_state.teardown()
        self.compiler_state = None

    def enable_debug(self, enable, productions=True, source=False):
        if enable:
            prod_logger = self.compiler_state.get_parser_logger()

            prod_logger.add_switch(Logger.INFO)
            if productions:
                prod_logger.add_switch(Logger.PRODUCTION)

            if source:
                prod_logger.add_switch(Logger.SOURCE)

    def test_empty_file(self):
        data = ""
        ast = self.compiler_state.parse(data)
        print(ast)

    def test_plain_main(self):
        data = """
            int main()
            {
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_variable_declaration(self):
        data = """
            int main()
            {
                int i;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_variable_initialization(self):
        data = """
            int main()
            {
                int i = 5;
                int j = i;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_const_declaration(self):
        data = """
            int main()
            {
                const int i = 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_declaration(self):
        data = """
            int main()
            {
                int i[5];
            }
            """
        ast = self.compiler_state.parse(data)
        result = ast.to_graph_viz_str()
        print(result)

        import re

        expected_solution = \
            'digraph {\n' \
                '\t"FileAST\\\\n\d\d\d\d\d" -> {"FunctionDefinition\\\\nint main\\\\n\d\d\d\d\d"};\n' \
                '\t"FunctionDefinition\\\\nint main\\\\n\d\d\d\d\d" -> {"CompoundStatement\\\\n\d\d\d\d\d"};\n' \
                '\t"CompoundStatement\\\\n\d\d\d\d\d" -> {"ArrayDeclaration\\\\nint\[5\]\[5\] i\\\\n\d\d\d\d\d"};\n' \
                '\t"ArrayDeclaration\\\\nint\[5\]\[5\] i\\\\n\d\d\d\d\d" -> {};\n' \
            '}'

        m = re.match(expected_solution, result)
        print(m)
        self.assertTrue(True if m else False)

    def test_2d_array_declaration(self):
        data = """
            int main()
            {
                int i[5][7];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_post_plus_plus(self):
        data = """
            int main()
            {
                int i = 0;
                int b = 0;
                b = i++;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_lone_if(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_if_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
                else
                {
                    i = 5;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_if_elif_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
                else if(i == 6)
                {
                    i = 7;
                }
                else
                {
                    i = 5;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_assign_const(self):
        data = """
            int main()
            {
                int g;
                char a;
                float p;

                g = 5;
                a = 2;
                p = 1.2;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_assign_var(self):
        data = """
            int main()
            {
                int g;
                int G;

                g = 5;
                G = g;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_cast_in_binary_expression(self):
        data = """
            int main()
            {
                int i = 5;
                float f = -4.5;

                i = (int) ((float) i + f);

                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())


    def test_array_simple_assign(self):
        data = """
            int main()
            {
                int a[10];
                a[1] = 4;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_simple_access(self):
        data = """
            int main()
            {
                int g;
                int a[10];
                a[1] = 4;
                g = a[1];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_access_const_expr(self):
        data = """
            int main()
            {
                int g;
                int a[10];
                a[6] = 4;
                g = a[5 + 1];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_access_var_expr(self):
        data = """
            int main()
            {
                int g;
                int a[10];
                a[1] = 4;
                g = a[1];
                g = a[g + 1];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_twodim(self):
        data = """
            int main()
            {
                int b[10][10];
                b[1][1] = 5;
            }
            """

        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_for_loop_1(self):
        data = """
            int main()
            {
                int i;
                for(i = 0; ;) {}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_for_loop_2(self):
        data = """
            int main()
            {
                int i;
                for(i = 0; ; i++) {}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_for_loop_3(self):
        data = """
            int main()
            {
                int i;
                for(i = 0; i < 1; i++) {}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_while_loop(self):
        data = """
            int main()
            {
                int i;
                while(i < 5){}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_do_while_loop(self):
        data = """
            int main()
            {
                int i;
                do {} while (i > 10);
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_decl_top_impl_bottom(self):
        data = """
            int do_stuff();

            int do_stuff()
            {
                return 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_decl_top_impl_bottom_call_middle(self):
        data = """
            int do_stuff();

            int main()
            {
                return do_stuff();
            }

            int do_stuff()
            {
                return 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_parameters(self):
        # TODO: this one fails because we don't have the concept of a "dereference expression/operation", although
        # TODO: we aren't super worried about pointers for now.
        data = """
            int do_stuff(int* ret, int x)
            {
                *ret = x + x;
                return 5;
            }

            int main()
            {
                int* ptr;
                int num;
                return do_stuff(ptr, num);
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_def_on_top(self):
        data = """
            // Definition on top
            int do_stuff()
            {
                return 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_def_on_top_call(self):
        data = """
            int do_stuff()
            {
                return 5;
            }

            int main()
            {
                return do_stuff();
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_declare_const_and_var_types(self):
        data = """
            int main(){

                int x;
                int * y = 0;
                int z[10];
                const int i;
                float j;
                char k = 'a';
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())
示例#15
0
class TestAst(unittest.TestCase):
    def setUp(self):
        self.compiler_state = CompilerState()
        self.enable_debug(False)
        UUID_TICKETS.next_value = 0
        LABEL_TICKETS.next_value = 0
        INT_REGISTER_TICKETS.next_value = 0
        FLOAT_REGISTER_TICKETS.next_value = 0

    def tearDown(self):
        self.compiler_state.teardown()
        self.compiler_state = None

    def enable_debug(self, enable, productions=True, source=False):
        if enable:
            prod_logger = self.compiler_state.get_parser_logger()

            prod_logger.add_switch(Logger.INFO)
            if productions:
                prod_logger.add_switch(Logger.PRODUCTION)

            if source:
                prod_logger.add_switch(Logger.SOURCE)

    def test_empty_file(self):
        data = ""
        ast = self.compiler_state.parse(data)
        print(ast)

    def test_plain_main(self):
        data = """
            int main()
            {
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_variable_declaration(self):
        data = """
            int main()
            {
                int i;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_variable_initialization(self):
        data = """
            int main()
            {
                int i = 5;
                int j = i;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_const_declaration(self):
        data = """
            int main()
            {
                const int i = 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_declaration(self):
        data = """
            int main()
            {
                int i[5];
            }
            """
        ast = self.compiler_state.parse(data)
        result = ast.to_graph_viz_str()
        print(result)

        import re

        expected_solution = \
            'digraph {\n' \
                '\t"FileAST\\\\n\d\d\d\d\d" -> {"FunctionDefinition\\\\nint main\\\\n\d\d\d\d\d"};\n' \
                '\t"FunctionDefinition\\\\nint main\\\\n\d\d\d\d\d" -> {"CompoundStatement\\\\n\d\d\d\d\d"};\n' \
                '\t"CompoundStatement\\\\n\d\d\d\d\d" -> {"ArrayDeclaration\\\\nint\[5\]\[5\] i\\\\n\d\d\d\d\d"};\n' \
                '\t"ArrayDeclaration\\\\nint\[5\]\[5\] i\\\\n\d\d\d\d\d" -> {};\n' \
            '}'

        m = re.match(expected_solution, result)
        print(m)
        self.assertTrue(True if m else False)

    def test_2d_array_declaration(self):
        data = """
            int main()
            {
                int i[5][7];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_post_plus_plus(self):
        data = """
            int main()
            {
                int i = 0;
                int b = 0;
                b = i++;
                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_lone_if(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_if_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
                else
                {
                    i = 5;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_if_elif_else(self):
        data = """
            int main()
            {
                int i;
                if (i == 5)
                {
                    i = 6;
                }
                else if(i == 6)
                {
                    i = 7;
                }
                else
                {
                    i = 5;
                }
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_assign_const(self):
        data = """
            int main()
            {
                int g;
                char a;
                float p;

                g = 5;
                a = 2;
                p = 1.2;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_simple_assign_var(self):
        data = """
            int main()
            {
                int g;
                int G;

                g = 5;
                G = g;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_cast_in_binary_expression(self):
        data = """
            int main()
            {
                int i = 5;
                float f = -4.5;

                i = (int) ((float) i + f);

                return 0;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_simple_assign(self):
        data = """
            int main()
            {
                int a[10];
                a[1] = 4;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_simple_access(self):
        data = """
            int main()
            {
                int g;
                int a[10];
                a[1] = 4;
                g = a[1];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_access_const_expr(self):
        data = """
            int main()
            {
                int g;
                int a[10];
                a[6] = 4;
                g = a[5 + 1];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_access_var_expr(self):
        data = """
            int main()
            {
                int g;
                int a[10];
                a[1] = 4;
                g = a[1];
                g = a[g + 1];
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_array_twodim(self):
        data = """
            int main()
            {
                int b[10][10];
                b[1][1] = 5;
            }
            """

        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_for_loop_1(self):
        data = """
            int main()
            {
                int i;
                for(i = 0; ;) {}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_for_loop_2(self):
        data = """
            int main()
            {
                int i;
                for(i = 0; ; i++) {}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_for_loop_3(self):
        data = """
            int main()
            {
                int i;
                for(i = 0; i < 1; i++) {}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_while_loop(self):
        data = """
            int main()
            {
                int i;
                while(i < 5){}
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_do_while_loop(self):
        data = """
            int main()
            {
                int i;
                do {} while (i > 10);
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_decl_top_impl_bottom(self):
        data = """
            int do_stuff();

            int do_stuff()
            {
                return 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_decl_top_impl_bottom_call_middle(self):
        data = """
            int do_stuff();

            int main()
            {
                return do_stuff();
            }

            int do_stuff()
            {
                return 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_parameters(self):
        # TODO: this one fails because we don't have the concept of a "dereference expression/operation", although
        # TODO: we aren't super worried about pointers for now.
        data = """
            int do_stuff(int* ret, int x)
            {
                *ret = x + x;
                return 5;
            }

            int main()
            {
                int* ptr;
                int num;
                return do_stuff(ptr, num);
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_def_on_top(self):
        data = """
            // Definition on top
            int do_stuff()
            {
                return 5;
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_function_def_on_top_call(self):
        data = """
            int do_stuff()
            {
                return 5;
            }

            int main()
            {
                return do_stuff();
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())

    def test_declare_const_and_var_types(self):
        data = """
            int main(){

                int x;
                int * y = 0;
                int z[10];
                const int i;
                float j;
                char k = 'a';
            }
            """
        ast = self.compiler_state.parse(data)
        print(ast.to_graph_viz_str())
示例#16
0
 def setUp(self):
     self.debug = True
     self.compiler_state = CompilerState()
示例#17
0
def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("source", type=str, help="The C program file to compile.")
    arg_parser.add_argument("-o", "--outfile", type=str, default='STDOUT',
                            help="The name of the output file. MUST be a .asm file! (Default: STDOUT)")
    arg_parser.add_argument("-sym", "--symtable", action='store_true',
                            help="Enables the printing of symbol table in other options.")
    arg_parser.add_argument("-s", "--scandebug", type=int, choices=[0, 1, 2, 3], default=0,
                            help="The debug level for the scanner. \n 0: No debug \n 1: Tokens \n 2: Source Code \n "
                                 "3: Tokens and Source Code")
    arg_parser.add_argument("-p", "--parsedebug", type=int, choices=[0, 1, 2, 3], default=0,
                            help="The debug level for the parser. \n 0: No debug \n 1: Productions \n "
                                 " 2: Productions and Source Code \n 3: Productions, Source, Misc info")
    arg_parser.add_argument("-ast", "--astree", action='store_true',
                            help="Enables the printing of the GraphViz string after parsing.")
    arg_parser.add_argument("-tac", "--threeac", type=int, choices=[0, 1, 2], default=0,
                            help="The debug level for the 3AC. \n 0: No debug \n 1: 3AC \n "
                                 " 2: 3AC + Source")
    arg_parser.add_argument("-mips", "--mips", type=int, choices=[0, 1, 2, 3], default=0,
                            help="The debug level for the MIPS. \n 0: No debug \n 1: 3AC \n "
                                 " 2: Source \n 3: 3AC + Source")
    arg_parser.add_argument("-w", "--warnings", action='store_true',
                            help="Enables warnings being printed.")

    args = vars(arg_parser.parse_args())

    # Set Symbol Table flags
    print_table = args['symtable']

    # Set Scanner flags
    print_tokens, print_source_scanner = False, False
    if args['scandebug'] is 1:
        print_tokens = True
    elif args['scandebug'] is 2:
        print_source_scanner = True
    elif args['scandebug'] is 3:
        print_tokens = True
        print_source_scanner = True

    # Set Parser flags
    print_productions, print_source_parser, print_info = False, False, False
    if args['parsedebug'] is 1:
        print_productions = True
    elif args['parsedebug'] is 2:
        print_productions = True
        print_source_parser = True
    elif args['parsedebug'] is 3:
        print_productions = True
        print_source_parser = True
        print_info = True

    source_file = open(args['source'], 'r')
    data = source_file.read()
    compiler_state = CompilerState(print_table=print_table,
                                   print_tokens=print_tokens,
                                   print_source_scanner=print_source_scanner,
                                   print_productions=print_productions,
                                   print_source_parser=print_source_parser,
                                   print_info=print_info,
                                   print_warnings=args['warnings'])

    try:
        ast = compiler_state.parse(data)
        if args['astree']:
            print(ast.to_graph_viz_str())

        if args['threeac'] is 2:
            source_tac, tac_as_str = ast.to_3ac(include_source=True)
        else:
            source_tac, tac_as_str = ast.to_3ac()

        if args['mips'] == 1:
            generator = generation.MipsGenerator(compiler_state, inject_source=False, inject_3ac=True)
        elif args['mips'] == 2:
            generator = generation.MipsGenerator(compiler_state, inject_source=True, inject_3ac=False)
        elif args['mips'] == 3:
            generator = generation.MipsGenerator(compiler_state, inject_source=True, inject_3ac=True)
        else:
            generator = generation.MipsGenerator(compiler_state, inject_source=False, inject_3ac=False)

        generator.load(source_tac)
        generator.translate_tac_to_mips()

        if args['outfile'] != 'STDOUT':
            fout = open(args['outfile'], 'w')
            fout.write(generator.dumps())
            fout.close()
        else:
            print(generator.dumps())

    except CompileError as error:
        print(error)
    finally:
        compiler_state.teardown()
示例#18
0
    def setUp(self):
        self.compiler_state = CompilerState(print_productions=False)
        self.enable_debug(False)

        self.generator = generation.MipsGenerator(self.compiler_state, inject_source = True, inject_3ac=True)