import math import os from typing import Callable from lexer import LexemeType, Lexer from prettytable import PrettyTable class IdentifierMapper: def __init__(self): self.id_table = {} self.counter = 0 def __call__(self, lex_text: str) -> str: if lex_text not in self.id_table: self.id_table[lex_text] = f"{lex_text} : {self.counter}" self.counter += 1 return self.id_table[lex_text] def exp_form_to_complex(exp_str: str) -> str: # Разделяем строку по 'E' base, exponent = exp_str.split("E") r = float(base) phi = float(exponent) # Преобразуем в алгебраическую форму a = r * math.cos(phi) b = r * math.sin(phi) return f"{a:.2f} + i * {b:.2f}" LEXEME_TYPES: dict[str, LexemeType] = { # 1. Идентификаторы "IDENTIFIER": LexemeType( "IDENTIFIER", r"[A-Za-z][A-Za-z_0-9]{0,15}(?![A-Za-z_0-9])", IdentifierMapper() ), # 2. Комплексные числа в показательной форме (на самом деле — числа в экспоненциальной форме) "COMPLEX": LexemeType( # "COMPLEX", r"[+-]?\d+(?:\.\d+)?E[+-]?\d+(?!E)", exp_form_to_complex "COMPLEX", r"[+-]?\d+(?:\.\d+)?E[+-]?\d+(?:\.\d+)?", exp_form_to_complex, ), # 3. Оператор присваивания := "ASSIGN": LexemeType("ASSIGN", r"\:="), # 4. Арифметические операторы "ARITHMETIC_OP": LexemeType("ARITHMETIC_OP", r"[+\-*/^]"), # 5. Левая скобка "LPAREN": LexemeType("LPAREN", r"\("), # 6. Правая скобка "RPAREN": LexemeType("RPAREN", r"\)"), # 7. Разделитель выражений | "SEPARATOR": LexemeType("SEPARATOR", r"\|"), # 8. Комментарии от # до конца строки "COMMENT": LexemeType("COMMENT", r"\#.*"), } ERROR_REGEX = r".[^|()+\-*/^:=\s]*" def analyze_and_print_table(code: str): lexer = Lexer(LEXEME_TYPES.values(), ERROR_REGEX, skip_types=["COMMENT"]) lexemes = lexer.analyze(code) table = PrettyTable(["Лексема", "Тип лексемы", "Значение"]) for l in lexemes: table.add_row([l.text, l.type_name, l.value]) print(table) print() LEXEME_TYPES["IDENTIFIER"].value_func = IdentifierMapper() def main(): while True: # Запрашиваем название файла file_name = input( "Введите название файла для анализа (или 'exit' для выхода): " ) if file_name.lower() == "exit": print("Завершаю программу.") break if not os.path.isfile(file_name): print(f"Файл '{file_name}' не найден. Попробуйте снова.") continue # Читаем содержимое файла with open(file_name, "r", encoding="utf-8") as file: code = file.read() # Анализируем и выводим таблицу analyze_and_print_table(code) if __name__ == "__main__": main()