Example #1
0
    def do(self, parser):
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-2]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-2]
        ).declaration_type == DeclarationType.ARRAY:
            raise SemanticError('Assignment to array is not allowed',
                                parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-2]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-2]
        ).declaration_type == DeclarationType.FUNCTION:
            raise SemanticError('Assignment to array is not allowed',
                                parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ).declaration_type == DeclarationType.ARRAY:
            raise SemanticError('Assignment from function is not allowed',
                                parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ).declaration_type == DeclarationType.FUNCTION:
            raise SemanticError('Assignment to function is not allowed',
                                parser.scanner)

        parser.program.add_inst(Mnemonic.ASSIGN, parser.semantic_stack.pop(),
                                parser.semantic_stack[-1])
Example #2
0
    def do(self, parser):
        top_of_stack = parser.semantic_stack.pop()
        if top_of_stack == 'None':
            raise SemanticError('Cannot pass a void argument to a function',
                                parser.scanner)
        if not parser.argument_stack[-1]:
            raise SemanticError('Too many arguments passed', parser.scanner)
        if isinstance(top_of_stack, str) and top_of_stack[0] == '#':
            if parser.argument_stack[-1][
                    0].declaration_type == DeclarationType.ARRAY:
                print(parser.argument_stack[-1])
                raise SemanticError(
                    'Cannot convert an integer literal to an array',
                    parser.scanner)

        if isinstance(
                top_of_stack, int) and parser.scanner.get_token_by_address(
                    top_of_stack) and parser.scanner.get_token_by_address(
                        top_of_stack
                    ).declaration_type == DeclarationType.ARRAY:
            if parser.argument_stack[-1][
                    0].declaration_type == DeclarationType.VARIABLE:
                raise SemanticError(
                    'Cannot convert an array to an integer type',
                    parser.scanner)

        if parser.scanner.get_token_by_address(
                top_of_stack) and parser.scanner.get_token_by_address(
                    top_of_stack).declaration_type == DeclarationType.FUNCTION:
            raise SemanticError('Cannot pass a function to a function',
                                parser.scanner)

        parser.argument_stack[-1] = parser.argument_stack[-1][1:]
        parser.program.add_push(top_of_stack)
Example #3
0
 def do(self, parser):
     token = parser.lookahead_token
     if token.data_type == DataType.VOID:
         raise SemanticError("Cannot declare a variable with void type",
                             parser.scanner)
     token.declaration_type = DeclarationType.VARIABLE
     if len(parser.function_stack
            ) == 1 and parser.function_stack[-1].lexeme == 'main':
         raise SemanticError('Invalid prototype for function main',
                             parser.scanner)
     parser.function_stack[-1].prototype.append(token)
Example #4
0
 def check_main(self):
     main_token = self.find_symbol_token('main', 0)
     if main_token is None:
         return
     if main_token.data_type != DataType.VOID:
         raise SemanticError('main should be of type `void`', self)
     # TODO check main have (void) as args
     if main_token.declaration_type in {
             DeclarationType.VARIABLE, DeclarationType.ARRAY
     }:
         raise SemanticError(
             'main function in the parent scope should be declared as a function',
             self)
Example #5
0
 def do(self, parser):
     function_symbol_address = parser.semantic_stack[-1]
     function_data_type = parser.scanner.get_token_by_address(
         function_symbol_address).data_type
     activity_record_address = parser.get_temp()
     return_address_address = parser.get_temp()
     parser.program.add_inst(Mnemonic.ASSIGN, function_symbol_address,
                             activity_record_address)
     parser.program.add_inst(Mnemonic.ADD, activity_record_address,
                             immval(1), return_address_address)
     parser.program.add_inst(Mnemonic.ASSIGN, immval(parser.program.pc + 3),
                             indval(return_address_address))
     start_pc = parser.get_temp()
     parser.program.add_inst(Mnemonic.ASSIGN,
                             indval(activity_record_address), start_pc)
     parser.program.add_inst(Mnemonic.JUMP, indval(start_pc))
     if function_data_type == DataType.INTEGER:
         return_value = parser.get_temp()
         parser.program.add_pop(return_value)
         parser.semantic_stack[-1] = return_value
     else:
         parser.semantic_stack[-1] = 'None'
     if parser.argument_stack[-1]:
         raise SemanticError('Too few arguments passed', parser.scanner)
     parser.argument_stack.pop()
Example #6
0
 def malloc(self, size=1):
     if size <= 0:
         raise SemanticError('Array size must be a positive integer value',
                             self)
     address = self.first_free_memory
     self.first_free_memory += size
     return address
Example #7
0
 def do(self, parser):
     parser.program.edit_inst(parser.semantic_stack.pop(), Mnemonic.JUMP,
                              parser.program.pc + 1)
     parser.program.add_inst(Mnemonic.JUMP,
                             indval(parser.return_stack.pop()))
     if parser.function_stack[
             -1].has_return == False and parser.function_stack[
                 -1].data_type != DataType.VOID:
         raise SemanticError('Missing return statement inside the function',
                             parser.scanner)
     if len(parser.function_stack) == 1 and parser.function_stack[
             -1].lexeme == 'main' and parser.function_stack[
                 -1].data_type != DataType.VOID:
         raise SemanticError('Invalid prototype for function main',
                             parser.scanner)
     parser.function_stack.pop()
Example #8
0
    def do(self, parser):
        tmp = parser.get_temp()
        if parser.semantic_stack[-1] == 'None' or parser.semantic_stack[
                -3] == 'None':
            raise SemanticError('Cannot add/sub a void value', parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ).declaration_type == DeclarationType.FUNCTION:
            raise SemanticError('Cannot add/sub a function value',
                                parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-1]
        ).declaration_type == DeclarationType.ARRAY:
            raise SemanticError('Cannot add/sub an array value',
                                parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-3]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-3]
        ).declaration_type == DeclarationType.FUNCTION:
            raise SemanticError('Cannot add/sub a function value',
                                parser.scanner)
        if parser.scanner.get_token_by_address(
                parser.semantic_stack[-3]
        ) and parser.scanner.get_token_by_address(
                parser.semantic_stack[-3]
        ).declaration_type == DeclarationType.ARRAY:
            raise SemanticError('Cannot add/sub an array value',
                                parser.scanner)

        if parser.semantic_stack[-2] == '+':
            parser.program.add_inst(Mnemonic.ADD, parser.semantic_stack[-3],
                                    parser.semantic_stack[-1], tmp)
        elif parser.semantic_stack[-2] == '-':
            parser.program.add_inst(Mnemonic.SUBTRACT,
                                    parser.semantic_stack[-3],
                                    parser.semantic_stack[-1], tmp)
        else:
            assert 0, 'Either + or - must have been provided'
        parser.semantic_stack.pop()
        parser.semantic_stack.pop()
        parser.semantic_stack.pop()
        parser.semantic_stack += [tmp]
Example #9
0
    def do(self, parser):
        test = parser.semantic_stack[-3]
        if test == 'None':
            raise SemanticError('Cannot use a void value as switch condition',
                                parser.scanner)

        parser.program.edit_inst(parser.semantic_stack.pop(),
                                 Mnemonic.JUMP_FALSE, test, parser.program.pc)
Example #10
0
 def check_declaration_and_data_type_consistency(self):
     for scope_table in self.symbol_table:
         for name, token in scope_table.items():
             if token.declaration_type is not None:
                 if token.declaration_type in {
                         DeclarationType.VARIABLE, DeclarationType.ARRAY
                 } and token.data_type != DataType.INTEGER:
                     raise SemanticError(
                         'variable {} should be of type `int`'.format(name),
                         self)
Example #11
0
    def do(self, parser):
        function_symbol_address = parser.semantic_stack[-1]
        prototype = parser.scanner.get_token_by_address(
            function_symbol_address).prototype
        if parser.scanner.get_token_by_address(
                function_symbol_address
        ).declaration_type != DeclarationType.FUNCTION:
            raise SemanticError('Dude it is not a function!', parser.scanner)

        parser.argument_stack += [prototype[:]]
Example #12
0
    def do(self, parser):
        tmp = parser.get_temp()
        if parser.semantic_stack[-1] == 'None' or parser.semantic_stack[
                -2] == 'None':
            raise SemanticError('Cannot mult a void value', parser.scanner)

        parser.program.add_inst(Mnemonic.MULTIPLY, parser.semantic_stack[-2],
                                parser.semantic_stack[-1], tmp)
        parser.semantic_stack.pop()
        parser.semantic_stack.pop()
        parser.semantic_stack += [tmp]
Example #13
0
 def do(self, parser):
     tmp = parser.get_temp()
     if parser.scanner.get_token_by_address(
             parser.semantic_stack[-2]
     ) and parser.scanner.get_token_by_address(
             parser.semantic_stack[-2]
     ).declaration_type == DeclarationType.FUNCTION:
         raise SemanticError('Subscription from function is not allowed',
                             parser.scanner)
     parser.program.add_inst(Mnemonic.ADD, parser.semantic_stack.pop(),
                             parser.semantic_stack.pop(), tmp)
     parser.semantic_stack += [indval(tmp)]
Example #14
0
    def do(self, parser):
        if parser.semantic_stack[-2] == 'None':
            raise SemanticError('Cannot use a void value as while condition',
                                parser.scanner)

        parser.program.edit_inst(parser.semantic_stack.pop(),
                                 Mnemonic.JUMP_FALSE,
                                 parser.semantic_stack.pop(),
                                 parser.program.pc + 1)
        parser.program.add_inst(Mnemonic.JUMP, parser.semantic_stack.pop())
        parser.program.edit_inst(parser.break_stack.pop(), Mnemonic.JUMP,
                                 parser.program.pc)
        parser.continue_stack.pop()
Example #15
0
    def do(self, parser):
        # Jump
        if parser.semantic_stack[-2] == 'None':
            raise SemanticError('Cannot use a void value as if condition',
                                parser.scanner)

        parser.program.edit_inst(parser.semantic_stack.pop(),
                                 Mnemonic.JUMP_FALSE,
                                 parser.semantic_stack.pop(),
                                 parser.program.pc + 1)

        # Save
        parser.semantic_stack += [parser.program.pc]
        parser.program.add_fake_inst()
Example #16
0
    def do(self, parser):
        tmp = parser.get_temp()
        if parser.semantic_stack[-1] == 'None' or parser.semantic_stack[
                -3] == 'None':
            raise SemanticError('Cannot compare a void value', parser.scanner)

        if parser.semantic_stack[-2] == 'L':
            parser.program.add_inst(Mnemonic.LESS_THAN,
                                    parser.semantic_stack[-3],
                                    parser.semantic_stack[-1], tmp)
        elif parser.semantic_stack[-2] == 'E':
            parser.program.add_inst(Mnemonic.EQUALS, parser.semantic_stack[-3],
                                    parser.semantic_stack[-1], tmp)
        else:
            assert 0, 'Either < or == must have been provided'
        parser.semantic_stack.pop()
        parser.semantic_stack.pop()
        parser.semantic_stack.pop()
        parser.semantic_stack += [tmp]
Example #17
0
 def do(self, parser):
     if parser.function_stack[-1].data_type != DataType.VOID:
         raise SemanticError('Invalid return value for a non-void function',
                             parser.scanner)
Example #18
0
 def do(self, parser):
     if parser.function_stack[-1].data_type == DataType.VOID:
         raise SemanticError('Invalid return value for a void function',
                             parser.scanner)
     parser.program.add_push(parser.semantic_stack.pop())
Example #19
0
 def do(self, parser):
     if len(parser.break_stack) == 0:
         raise SemanticError(
             '`break` statement has no parent `while` or `switch`',
             parser.scanner)
     parser.program.add_inst(Mnemonic.JUMP, parser.break_stack[-1])
Example #20
0
 def do(self, parser):
     if len(parser.continue_stack) == 0:
         raise SemanticError('`continue` statement has no parent `while`',
                             parser.scanner)
     parser.program.add_inst(Mnemonic.JUMP, parser.continue_stack[-1])