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])
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)
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)
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)
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()
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
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()
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]
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)
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)
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[:]]
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]
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)]
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()
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()
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]
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)
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())
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])
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])