import lexer loop_program = '''x1 := 2; x2 := 3; x3 := x2 + 0; LOOP x1 DO x2 := x3 + 1; x3 := x2 + 0 END; x0 := x2 + 0''' def process_assignment(token_queue, position, value_list, forbidden_identifiers): identifier_1 = token_queue[position].v if identifier_1 in forbidden_identifiers: raise Exception("Identifier " + identifier_1 + "ist bereits in Loop vorhanden und darf nicht verwendet werden.") if not token_queue[position + 1].k == 'EQUALS': raise SyntaxError(":= in Zuweisung erwartet.") if identifier_1 in value_list: value_1 = value_list.get(identifier_1) else: value_1 = 0 if token_queue[position + 2].k == 'NUMBER': value_1 += int(token_queue[position + 2].v) value_list.update({identifier_1: value_1}) return position+3, value_list if not token_queue[position + 2].k == 'IDENTIFIER': raise SyntaxError("IDENTIFIER in Zuweisung erwartet.") identifier_2 = token_queue[position + 2].v if identifier_2 in forbidden_identifiers: raise Exception("Identifier " + identifier_2 + " ist bereits in Loop vorhanden und darf nicht verwendet werden.") if identifier_2 in value_list: value_2 = value_list.get(identifier_2) else: value_2 = 0 if not token_queue[position + 4].k == 'NUMBER': raise SyntaxError("NUMBER in Zuweisung erwartet.") if token_queue[position + 3].k == 'PLUS': value_1 = value_2 + int(token_queue[position + 4].v) elif token_queue[position + 3].k == 'MINUS': value_1 = max(0, value_2 + token_queue[position + 4].v) else: raise SyntaxError("PLUS oder MINUS in Zuweisung erwartet.") value_list.update({identifier_1: value_1}) return position + 5, value_list def process_loop(token_queue, position, value_list, forbidden_identifiers): identifier_token = token_queue[position+1] if not identifier_token.k == 'IDENTIFIER': raise SyntaxError('IDENTIFIER in LOOP erwartet.') if not token_queue[position+2].k == 'DO': raise SyntaxError('DO in LOOP erwartet.') number_of_loops = int(value_list.get(identifier_token.v)) saved_position = position + 3 forbidden_identifiers.append(identifier_token.v) for index in range(number_of_loops): position = saved_position end_found = False while(not end_found): position, value_list = process_program(token_queue, position, value_list, forbidden_identifiers) if token_queue[position].k == 'SEMICOLON': position = position + 1 continue elif token_queue[position].k == 'END': end_found = True else: raise SyntaxError("SEMICOLON oder END erwartet.") return position+1, value_list def process_program(token_queue, position, value_list, forbidden_identifiers): current_key = token_queue[position].k if current_key == 'IDENTIFIER': try: current_position, values = process_assignment(token_queue, position, value_list, forbidden_identifiers) except IndexError: raise Exception("Frühzeitiges Ende einer Zuweisung.") elif current_key == 'LOOP': try: current_position, values = process_loop(token_queue, position, value_list, forbidden_identifiers) except IndexError: raise Exception("Frühzeitiges Ende eines LOOPs") else: raise SyntaxError("Keine passende Anweisung gefunden") return current_position, values def interpret(program): tokens = lexer.tokenize(program) current_position = 0 values = {} forbidden_identifiers = [] while current_position < len(tokens): current_position, values = process_program(tokens, current_position, values, forbidden_identifiers) if current_position < len(tokens) and not tokens[current_position].k == 'SEMICOLON': raise SyntaxError("Semicolon erwartet") else: current_position = current_position + 1 if "x0" in values: return values.get("x0") return 0 print(interpret(loop_program))