99 lines
3.0 KiB
Python
99 lines
3.0 KiB
Python
import math
|
|
import os
|
|
from typing import Callable
|
|
|
|
from prettytable import PrettyTable
|
|
|
|
from lexer import LexemeType, Lexer
|
|
|
|
|
|
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+)?(?!E)",
|
|
exp_form_to_complex,
|
|
),
|
|
# 3. Оператор присваивания :=
|
|
"ASSIGN": LexemeType("ASSIGN", r"\:=(?![\:=])"),
|
|
# 4. Арифметические операторы
|
|
"ARITHMETIC_OP": LexemeType("ARITHMETIC_OP", r"[+\-*/^]"),
|
|
# 5. Скобки
|
|
"PAREN": LexemeType("PAREN", r"[()]"),
|
|
# 6. Разделитель выражений |
|
|
"SEPARATOR": LexemeType("SEPARATOR", r"\|"),
|
|
# 7. Комментарии от # до конца строки
|
|
"COMMENT": LexemeType("COMMENT", r"\#.*"),
|
|
}
|
|
|
|
|
|
def analyze_and_print_table(code: str):
|
|
lexer = Lexer(LEXEME_TYPES.values())
|
|
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()
|