нормальный интерфейс в lab3

This commit is contained in:
2025-05-14 11:15:28 +03:00
parent 3c09cc0e9b
commit d7a0e400cd
4 changed files with 167 additions and 60 deletions

View File

@@ -1,2 +1,3 @@
grammar_*
analysis_*
generation_*

View File

@@ -255,6 +255,37 @@ class Grammar:
table.add_row(row)
return str(table)
def format_first_sets(self) -> str:
"""Форматирует множества FIRST в читаемый вид."""
result = []
result.append("Множества FIRST:")
result.append("=" * 40)
# Сортируем для гарантии порядка вывода
for symbol in sorted(self.first_sets.keys()):
# Заменяем пустую строку на эпсилон для лучшей читаемости
first_set = {
self.EPSILON if item == "" else item for item in self.first_sets[symbol]
}
result.append(f"FIRST({symbol}) = {{{', '.join(sorted(first_set))}}}")
return "\n".join(result)
def format_follow_sets(self) -> str:
"""Форматирует множества FOLLOW в читаемый вид."""
result = []
result.append("Множества FOLLOW:")
result.append("=" * 40)
# Обрабатываем только нетерминалы
for non_terminal in sorted(self.productions.keys()):
follow_set = self.follow_sets.get(non_terminal, set())
result.append(
f"FOLLOW({non_terminal}) = {{{', '.join(sorted(follow_set))}}}"
)
return "\n".join(result)
def analyze(self, string: str) -> list[int]:
input_tokens = string.split() + ["$"]
input_pos = 0

View File

@@ -2,7 +2,7 @@
ПрямойПорядок -> Подлежащее ДополнениеКПодлежащему Глагол ВторостепенныеЧлены Отрицание
Инверсия -> Обстоятельство Глагол Подлежащее ВторостепенныеЧлены Отрицание
Подлежащее -> ИменнаяГруппа ПридаточноеПредложение | Местоимение
ПридаточноеПредложение -> ", " Союз Подлежащее Глагол ВторостепенныеЧлены Отрицание ", " | epsilon
ПридаточноеПредложение -> "," Союз Подлежащее Глагол Отрицание "," | epsilon
ВторостепенныеЧлены -> ВторостепенныйЧлен ВторостепенныеЧлены | epsilon
ВторостепенныйЧлен -> Обстоятельство | Дополнение
Обстоятельство -> ОбстоятельствоВремени | ОбстоятельствоМеста | ОбстоятельствоОбразаДействия

View File

@@ -1,40 +1,57 @@
import json
from grammar import Grammar
with open("grammar.txt", "r", encoding="utf-8") as file:
def load_grammar(filename: str = "grammar.txt") -> Grammar | None:
try:
with open(filename, "r", encoding="utf-8") as file:
text = file.read()
# text = """
# S -> A b B | d
# A -> C A b | B
# B -> c S d | epsilon
# C -> a | e d
# """
# text = """
# S -> F | ( S + F )
# F -> 1
# """
grammar = Grammar(text)
grammar = Grammar(text)
print("FIRST sets:", grammar.first_sets)
print("FOLLOW sets:", grammar.follow_sets)
with open("grammar_rules.txt", "w", encoding="utf-8") as output_file:
# Сохраняем информацию о грамматике в файлы
with open("grammar_rules.txt", "w", encoding="utf-8") as output_file:
output_file.write(grammar.format_rules())
print("Правила грамматики с номерами сохранены в grammar_rules.txt")
with open("grammar_lookup_table.txt", "w", encoding="utf-8") as output_file:
with open("grammar_lookup_table.txt", "w", encoding="utf-8") as output_file:
output_file.write(grammar.format_lookup_table())
print("Таблица синтаксического анализа сохранена в grammar_lookup_table.txt")
print(
"Таблица синтаксического анализа сохранена в grammar_lookup_table.txt"
)
input_string = "ich las gestern ein alt Buch"
input_string = "der alt Mann las ein Buch"
input_string = "gestern las der alt Mann ein Buch"
print(f"Analyzing input '{input_string}':")
parse_result = grammar.analyze(input_string)
print(f"Applied rules: {parse_result}")
with open("grammar_first.txt", "w", encoding="utf-8") as output_file:
output_file.write(grammar.format_first_sets())
print("Множества FIRST сохранены в grammar_first.txt")
with open("analysis_result.txt", "w", encoding="utf-8") as f:
with open("grammar_follow.txt", "w", encoding="utf-8") as output_file:
output_file.write(grammar.format_follow_sets())
print("Множества FOLLOW сохранены в grammar_follow.txt")
print(f"Грамматика успешно загружена из файла {filename}")
return grammar
except FileNotFoundError:
print(f"Ошибка: Файл {filename} не найден")
return None
except ValueError as e:
print(f"Ошибка при загрузке грамматики: {e}")
return None
except Exception as e:
print(f"Неизвестная ошибка: {e}")
return None
def check_string(grammar: Grammar | None, input_string: str) -> None:
if not grammar:
print("Ошибка: Грамматика не загружена")
return
print(f"Проверка строки: '{input_string}'")
try:
parse_result = grammar.analyze(input_string)
print(f"Результат: Строка соответствует грамматике")
print(f"Применённые правила: {parse_result}")
# Сохраняем результат анализа в файл
with open("analysis_result.txt", "w", encoding="utf-8") as f:
f.write(f"Input: {input_string}\n")
f.write("Applied rules: ")
f.write(str(parse_result))
@@ -45,21 +62,27 @@ with open("analysis_result.txt", "w", encoding="utf-8") as f:
for step in derivation_steps:
f.write(f"{step}\n")
print("Результат анализа сохранен в analysis_result.txt")
print("Подробный результат анализа сохранен в analysis_result.txt")
except ValueError as e:
print(f"Результат: Строка не соответствует грамматике")
print(f"Ошибка: {e}")
except Exception as e:
print(f"Произошла ошибка при анализе: {e}")
# Тестирование функции генерации строк
print("\nГенерация строк по грамматике:")
for i in range(5):
def generate_string(grammar: Grammar | None) -> None:
if not grammar:
print("Ошибка: Грамматика не загружена")
return
try:
terminals, rules = grammar.generate()
generated_string = " ".join(terminals)
print(f"Сгенерированная строка {i+1}: {generated_string}")
print(f"Сгенерированная строка: {generated_string}")
print(f"Применённые правила: {rules}")
# Запись одной сгенерированной строки в файл
with open("generation_result.txt", "w", encoding="utf-8") as f:
terminals, rules = grammar.generate()
generated_string = " ".join(terminals)
# Сохраняем результат генерации в файл
with open("generation_result.txt", "w", encoding="utf-8") as f:
f.write(f"Generated string: {generated_string}\n")
f.write("Applied rules: ")
f.write(str(rules))
@@ -70,4 +93,56 @@ with open("generation_result.txt", "w", encoding="utf-8") as f:
for step in derivation_steps:
f.write(f"{step}\n")
print("Результат генерации сохранен в generation_result.txt")
print("Подробный результат генерации сохранен в generation_result.txt")
except Exception as e:
print(f"Произошла ошибка при генерации: {e}")
def main():
print("Программа для работы с LL(1)-грамматиками")
print("=" * 60)
print("Варианты команд:")
print(" - load <файл> - загрузить грамматику из файла (по умолчанию grammar.txt)")
print(" - check <строка> - проверить, соответствует ли строка грамматике")
print(" - generate - сгенерировать случайную строку по грамматике")
print(" - exit - выход из программы")
print("=" * 60)
# Загружаем грамматику по умолчанию при старте
grammar = load_grammar()
while True:
command = input("\nВведите команду: ").strip()
if not command:
continue
parts = command.split(maxsplit=1)
cmd = parts[0].lower()
if cmd == "exit":
print("Выход из программы.")
break
elif cmd == "load":
filename = "grammar.txt"
if len(parts) > 1:
filename = parts[1].strip()
grammar = load_grammar(filename)
elif cmd == "check":
input_string = ""
if len(parts) > 1:
input_string = parts[1].strip()
check_string(grammar, input_string)
elif cmd == "generate":
generate_string(grammar)
else:
print(f"Неизвестная команда: {cmd}")
print("Доступные команды: load, check, generate, exit")
if __name__ == "__main__":
main()