def c_desc(self): name = self.pop_from_semantic_stack() var_type = self.get_top_semantic_stack() if not self.symbol_table.is_var_declared(name): self.symbol_table.new_variable(name, var_type) else: error_handler( "Syntax Error", "variable with name " + name + " has already declared ")
def c_desc_normal_array(self): name = self.pop_from_semantic_stack() var_type = self.get_top_semantic_stack() if not self.symbol_table.is_var_declared(name): self.symbol_table.new_array(name, var_type, self.get_next_token_value()) else: error_handler( "Syntax Error", "variable with name " + name + " has already declared ")
def for_simple_declaration(self): value = self.get_address_or_immediate_value( self.get_next_token_value()) var_name = self.pop_from_semantic_stack() var_type = self.pop_from_semantic_stack() if not self.symbol_table.is_var_declared(var_name): self.symbol_table.new_variable(var_name, var_type, 1) code = ["mov", self.symbol_table.get_var_address(var_name), value] self.add_code(code) else: error_handler( "Syntax Error", "variable with name " + var_name + " has already declared ")
def c_desc_with_assign(self): name = self.pop_from_semantic_stack() var_type = self.get_top_semantic_stack() if not self.symbol_table.is_var_declared(name): self.symbol_table.new_variable(name, var_type) operand2 = self.get_address_or_immediate_value( self.get_next_token_value()) code = ["mov", self.symbol_table.get_var_address(name), operand2] self.add_code(code) else: error_handler( "Syntax Error", "variable with name " + name + " has already declared ")
def _fill_parse_table(self): for variable in self._variables: self._parse_table[variable] = {} for terminal in self._terminals: self._parse_table[variable][terminal] = Parser._INVALID for rule_id in range(len(self._rules)): variable = self._rules[rule_id][0] for terminal in self._terminals: if terminal in self._predicts[rule_id]: if self._parse_table[variable][terminal] != Parser._INVALID: error_handler("Grammer Error", "The grammar is not LL1. Variable: " + str(variable) + " Terminal: " + str( terminal)) else: self._parse_table[variable][terminal] = rule_id
def get_var(self, var_name): best_var_scope = -1 best_symbol_address = -1 var = {} for symbol in self.symbols: if symbol.var_name == var_name and symbol.function == self.function and symbol.scope > best_var_scope: best_symbol_address = symbol.address best_var_scope = symbol.scope var = symbol if best_symbol_address == -1: for symbol in self.symbols: if symbol.var_name == var_name and symbol.function == "Global": var = symbol best_symbol_address = symbol.address if best_symbol_address == -1: error_handler("Syntax Error", str(var_name) + " is not declared") return var
def check_all_function_have_signature(self): for item in self.function_signatures: for signature in item['signatures']: if signature['start_point'] == self._WILL_BE_SET_LATER: error_handler( "Syntax Error", " function " + item['function_name'] + " has not declared") if not self.finalCode.have_main(): error_handler("Syntax Error", "There is not int main that have no input variable") for item in self.function_call_jmp_that_do_not_have_pc: item = list(item) self.finalCode.update_code( item[0], 1, str(self.function_signatures[item[1]]["signatures"][item[2]] ['start_point']))
def function_called(self, signature): idx = len(signature["var_names"]) - 1 while idx >= 0: var_name = signature["var_names"][idx] var_type = signature["var_types"][idx] if not self.symbol_table.is_var_declared(var_name): self.symbol_table.new_variable(var_name, var_type) else: error_handler( "Syntax Error", "variable with name " + var_name + " has already declared ") code = ["pop", self.get_address_or_immediate_value(var_name)] self.add_code(code) idx -= 1 dest_temp = self.symbol_table.new_temp("int") code = ["pop", self.get_address_or_immediate_value(dest_temp)] self.add_code(code) self.function_return_address = dest_temp
def array(self): index = self.get_address_or_immediate_value( self.pop_from_semantic_stack()) array_name = self.pop_from_semantic_stack() array = self.symbol_table.get_var(array_name) if array.type_of_data != "array": error_handler("Syntax Error", array_name + " is not array") array_start = array.address array_type_size = array.type_size temp1_address = self.get_address_or_immediate_value( self.get_temp("int")) temp2 = self.get_temp("int") temp2_address = self.get_address_or_immediate_value(temp2) code1 = ["mult", temp1_address, array_type_size, index] code2 = ["add", temp2_address, array_start, temp1_address] self.add_code(code1) self.add_code(code2) self.push_to_semantic_stack("@" + str(temp2))
def _update_grammar(self, rule_text): idx = len(self._rules) rule_text_tokens = rule_text.split() self._update_variables(rule_text_tokens) self._update_terminals(rule_text_tokens) if len(rule_text_tokens) < 3: error_handler("Grammer Error", "Error in rule number " + str(idx)) if not self.is_variable(rule_text_tokens[0]) or rule_text_tokens[1] != Parser._ARROW_STRING: error_handler("Grammer Error", "Error in rule number " + str(idx)) if len(rule_text_tokens) == 3 and rule_text_tokens[2] == Parser._NIL_STRING and rule_text_tokens[ 0] not in self._nullable_variables: self._nullable_variables.append(rule_text_tokens[0]) key = rule_text_tokens[0] del rule_text_tokens[1] self._rules.append(copy.deepcopy(rule_text_tokens)) del rule_text_tokens[0] temp_list = [] if key in self._variable_rules: temp_list = self._variable_rules[key] temp_list.append(rule_text_tokens) self._variable_rules[key] = temp_list
def check_type(self, operand0, operand2, operand3): if self.symbol_table.get_var_type( operand2) == "double" and self.symbol_table.get_var_type( operand3) == "double": return "double" if self.symbol_table.get_var_type( operand2) == "int" and self.symbol_table.get_var_type( operand3) == "int": return "int" if self.symbol_table.get_var_type( operand2) == "bool" and self.symbol_table.get_var_type( operand3) == "bool": return "bool" if self.symbol_table.get_var_type( operand2) == "bool" and self.symbol_table.get_var_type( operand3) == "char": error_handler("Syntax Error", "Types does not match") if self.symbol_table.get_var_type( operand2) == self.symbol_table.get_var_type(operand3): return self.symbol_table.get_var_type(operand2) error_handler("Syntax Error", "Types does not match")
def c_desc_weird_array(self): datas = [] while self.get_top_semantic_stack() != ']': datas.append(self.pop_from_semantic_stack()) self.pop_from_semantic_stack() name = self.pop_from_semantic_stack() var_type = self.pop_from_semantic_stack() if not self.symbol_table.is_var_declared(name): self.symbol_table.new_array(name, var_type, len(datas)) else: error_handler( "Syntax Error", "variable with name " + name + " has already declared ") var = self.symbol_table.get_var(name) type_size = var.type_size address = var.address for data in reversed(datas): self.add_code([ "mov", str(address), self.get_address_or_immediate_value(data) ]) address += int(type_size)
def signature_function_declaration(self): pushed = [] while self.get_top_semantic_stack() != self._START_OF_FUNCTION: pushed.append(self.pop_from_semantic_stack()) self.pop_from_semantic_stack() if len(pushed) == 2 and pushed[1] == "void" and pushed[0] == "main": self.update_code(0, 1, self.get_pc()) function_return_type = pushed.pop() function_name = pushed.pop() self.symbol_table.set_function_name(function_name) function_variables_names = [] function_variables_types = [] while len(pushed) != 0: function_variables_types.append(pushed.pop()) function_variables_names.append(pushed.pop()) state = 0 function_declaration = {} for item in self.function_signatures: if item['function_name'] != function_name: continue if item['function_name'] == "main": error_handler("Syntax Error", "There is at least 2 main in your code") if item['function_return_type'] != function_return_type: error_handler( "Syntax Error", " function " + function_name + "has declared with different return type ") state = 1 function_declaration = item for signature in item['signatures']: is_same = True if len(signature['var_types']) != len( function_variables_types): continue for i in range(0, len(function_variables_types)): if signature['var_types'][i] != function_variables_types[i]: is_same = False break if is_same: error_handler( "Syntax Error", " function " + function_name + " has declared with same signature") break obj = { "var_types": function_variables_types, "var_names": function_variables_names, "start_point": self._WILL_BE_SET_LATER } if state == 0: function_declaration['function_return_type'] = function_return_type function_declaration['function_name'] = function_name function_declaration['signatures'] = [obj] self.function_signatures.append(function_declaration) elif state == 1: function_declaration['signatures'].append(obj)
def parse(self, tokens): tokens.append(Token('eof', 'keyword')) tokens.append(self._END_OF_FILE_CHARACTER) last_idx = -1 idx = 0 self._parse_stack.append(self._END_OF_FILE_CHARACTER) self._parse_stack.append(self._start_variable) top = self._start_variable loop_counter = 0 open_parentheses_count = 0 while top != self._END_OF_FILE_CHARACTER: loop_counter += 1 last_token = tokens[-2] if top == self._BOOLEAN_EXPRESSION_STRING and open_parentheses_count == 1 and tokens[idx - 1].value == '(': self._parse_stack.pop() top = self._get_parse_stack_top() boolean_expression_tokens = [] while open_parentheses_count != 0: boolean_expression_tokens.append(tokens[idx]) if tokens[idx].value == "(": open_parentheses_count += 1 if tokens[idx].value == ")": open_parentheses_count -= 1 idx += 1 idx -= 1 open_parentheses_count += 1 boolean_expression_tokens.pop() try: self._boolean_expression_parser.parse(boolean_expression_tokens) except: error_handler("Syntax Error:", " error in boolean expression") continue elif top == self._BOOLEAN_EXPRESSION_STRING and tokens[idx - 1].value == ';': self._parse_stack.pop() top = self._get_parse_stack_top() boolean_expression_tokens = [] while tokens[idx].value != ";": boolean_expression_tokens.append(tokens[idx]) if tokens[idx].value == "(": open_parentheses_count += 1 if tokens[idx].value == ")": open_parentheses_count -= 1 idx += 1 try: self._boolean_expression_parser.parse(boolean_expression_tokens) except: error_handler("Syntax Error:", " error in boolean expression") continue top = self._get_parse_stack_top() if top == self._NIL_STRING: top = self._get_parse_stack_top() continue if self.is_semantic_rule(top): semantic = top self._parse_stack.pop() top = self._get_parse_stack_top() self._code_generator.generate_code(semantic, tokens[idx]) continue if loop_counter > len(tokens) * 20: error_handler("Syntax Error:", " (1) next token should not be " + str(tokens[idx])) if top == self._IDENTIFIER_STRING: if tokens[idx].type == TokenType.identifier: idx = idx + 1 self._parse_stack.pop() top = self._get_parse_stack_top() continue else: error_handler("Syntax Error:", " (2) next token should not be " + str(tokens[idx])) elif top == self._NUMBER_STRING: if tokens[idx].type == TokenType.number: idx = idx + 1 self._parse_stack.pop() top = self._get_parse_stack_top() continue else: error_handler("Syntax Error:", " (3) next token should not be " + str(tokens[idx])) elif self.is_terminal(top): if tokens[idx].value == "(": open_parentheses_count += 1 if tokens[idx].value == ")": open_parentheses_count -= 1 if top == "{": self._symbol_table.one_scope_in() if top == "}": self._symbol_table.one_scope_out() if tokens[idx].value == top: idx = idx + 1 self._parse_stack.pop() top = self._get_parse_stack_top() continue else: error_handler("Syntax Error:", " (4) next token should not be " + str(tokens[idx])) try: try: nxt = tokens[idx].value if tokens[idx].type == TokenType.identifier: nxt = self._IDENTIFIER_STRING if tokens[idx].type == TokenType.number: nxt = self._NUMBER_STRING rule_idx = self._parse_table[top][nxt] product = self._rules[rule_idx][1:] self._parse_stack.pop() if product != [self._NIL_STRING]: self._parse_stack.extend(reversed(product)) except: error_handler("Syntax Error:", " (5)") except KeyError: error_handler("Syntax Error:", "6: Unable to find derivation of '{0}' on '{1}'".format(top, nxt)) top = self._get_parse_stack_top() return True
def finish_function_call(self): pushed = [] while self.get_top_semantic_stack() != self._START_OF_FUNCTION_CALL: pushed.append(self.pop_from_semantic_stack()) self.pop_from_semantic_stack() function_name = pushed.pop() pushed = list(reversed(pushed)) func_id = 0 sign_id = 0 start_point_of_jump = -1 found = False for function_dec in self.function_signatures: if function_dec["function_name"] != function_name: func_id += 1 continue sign_id = 0 for signature in function_dec["signatures"]: is_same = True if len(signature['var_types']) != len(pushed): sign_id += 1 continue for i in range(0, len(pushed)): if signature['var_types'][i] != self.get_type(pushed[i]): is_same = False break i += 1 if is_same: found = True start_point_of_jump = signature["start_point"] break sign_id += 1 if found: break else: error_handler("Syntax error", "no function with this name and signature") if not found: error_handler("Syntax error", "function is not declared") return_value_size = self.symbol_table.get_size( self.function_signatures[func_id]['function_return_type']) var_size = self.symbol_table.get_all_var_size() variables = var_size[1] pop_code = [] for var in variables: address = var[0] now_address = address while now_address < (address + var[1]): code = ["push", now_address] # , "-", str(now_address + var[2]) pop_code.append(["pop", now_address ]) # , "-", str(now_address + var[2]) self.add_code(code) now_address += var[2] code = ["push", "#" + str(self.get_pc() + 2 + len(pushed))] self.add_code(code) for push in pushed: code = ["push", self.get_address_or_immediate_value(push)] self.add_code(code) code = ["jmp", start_point_of_jump] if start_point_of_jump == self._WILL_BE_SET_LATER: self.function_call_jmp_that_do_not_have_pc.append( [int(self.get_pc()), func_id, sign_id]) self.add_code(code) if return_value_size > 0: temp = self.symbol_table.new_temp( self.function_signatures[func_id]['function_return_type']) code = ["pop", self.get_address_or_immediate_value(temp)] self.add_code(code) self.push_to_semantic_stack(temp) pop_code = reversed(pop_code) for pop in pop_code: self.add_code(pop)
def _error_handler(e): return error_handler(e)