нормальный интерфейс в lab3
This commit is contained in:
1
lab3/programm/.gitignore
vendored
1
lab3/programm/.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
grammar_*
|
grammar_*
|
||||||
analysis_*
|
analysis_*
|
||||||
|
generation_*
|
||||||
@@ -255,6 +255,37 @@ class Grammar:
|
|||||||
table.add_row(row)
|
table.add_row(row)
|
||||||
return str(table)
|
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]:
|
def analyze(self, string: str) -> list[int]:
|
||||||
input_tokens = string.split() + ["$"]
|
input_tokens = string.split() + ["$"]
|
||||||
input_pos = 0
|
input_pos = 0
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
ПрямойПорядок -> Подлежащее ДополнениеКПодлежащему Глагол ВторостепенныеЧлены Отрицание
|
ПрямойПорядок -> Подлежащее ДополнениеКПодлежащему Глагол ВторостепенныеЧлены Отрицание
|
||||||
Инверсия -> Обстоятельство Глагол Подлежащее ВторостепенныеЧлены Отрицание
|
Инверсия -> Обстоятельство Глагол Подлежащее ВторостепенныеЧлены Отрицание
|
||||||
Подлежащее -> ИменнаяГруппа ПридаточноеПредложение | Местоимение
|
Подлежащее -> ИменнаяГруппа ПридаточноеПредложение | Местоимение
|
||||||
ПридаточноеПредложение -> ", " Союз Подлежащее Глагол ВторостепенныеЧлены Отрицание ", " | epsilon
|
ПридаточноеПредложение -> "," Союз Подлежащее Глагол Отрицание "," | epsilon
|
||||||
ВторостепенныеЧлены -> ВторостепенныйЧлен ВторостепенныеЧлены | epsilon
|
ВторостепенныеЧлены -> ВторостепенныйЧлен ВторостепенныеЧлены | epsilon
|
||||||
ВторостепенныйЧлен -> Обстоятельство | Дополнение
|
ВторостепенныйЧлен -> Обстоятельство | Дополнение
|
||||||
Обстоятельство -> ОбстоятельствоВремени | ОбстоятельствоМеста | ОбстоятельствоОбразаДействия
|
Обстоятельство -> ОбстоятельствоВремени | ОбстоятельствоМеста | ОбстоятельствоОбразаДействия
|
||||||
|
|||||||
@@ -1,39 +1,56 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
from grammar import Grammar
|
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 = 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())
|
output_file.write(grammar.format_rules())
|
||||||
print("Правила грамматики с номерами сохранены в grammar_rules.txt")
|
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())
|
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"
|
with open("grammar_first.txt", "w", encoding="utf-8") as output_file:
|
||||||
input_string = "der alt Mann las ein Buch"
|
output_file.write(grammar.format_first_sets())
|
||||||
input_string = "gestern las der alt Mann ein Buch"
|
print("Множества FIRST сохранены в grammar_first.txt")
|
||||||
print(f"Analyzing input '{input_string}':")
|
|
||||||
|
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)
|
parse_result = grammar.analyze(input_string)
|
||||||
print(f"Applied rules: {parse_result}")
|
print(f"Результат: Строка соответствует грамматике")
|
||||||
|
print(f"Применённые правила: {parse_result}")
|
||||||
|
|
||||||
|
# Сохраняем результат анализа в файл
|
||||||
with open("analysis_result.txt", "w", encoding="utf-8") as f:
|
with open("analysis_result.txt", "w", encoding="utf-8") as f:
|
||||||
f.write(f"Input: {input_string}\n")
|
f.write(f"Input: {input_string}\n")
|
||||||
f.write("Applied rules: ")
|
f.write("Applied rules: ")
|
||||||
@@ -45,21 +62,27 @@ with open("analysis_result.txt", "w", encoding="utf-8") as f:
|
|||||||
for step in derivation_steps:
|
for step in derivation_steps:
|
||||||
f.write(f"{step}\n")
|
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Генерация строк по грамматике:")
|
def generate_string(grammar: Grammar | None) -> None:
|
||||||
for i in range(5):
|
if not grammar:
|
||||||
|
print("Ошибка: Грамматика не загружена")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
terminals, rules = grammar.generate()
|
terminals, rules = grammar.generate()
|
||||||
generated_string = " ".join(terminals)
|
generated_string = " ".join(terminals)
|
||||||
print(f"Сгенерированная строка {i+1}: {generated_string}")
|
print(f"Сгенерированная строка: {generated_string}")
|
||||||
print(f"Применённые правила: {rules}")
|
print(f"Применённые правила: {rules}")
|
||||||
|
|
||||||
# Запись одной сгенерированной строки в файл
|
# Сохраняем результат генерации в файл
|
||||||
with open("generation_result.txt", "w", encoding="utf-8") as f:
|
with open("generation_result.txt", "w", encoding="utf-8") as f:
|
||||||
terminals, rules = grammar.generate()
|
|
||||||
generated_string = " ".join(terminals)
|
|
||||||
|
|
||||||
f.write(f"Generated string: {generated_string}\n")
|
f.write(f"Generated string: {generated_string}\n")
|
||||||
f.write("Applied rules: ")
|
f.write("Applied rules: ")
|
||||||
f.write(str(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:
|
for step in derivation_steps:
|
||||||
f.write(f"{step}\n")
|
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()
|
||||||
|
|||||||
Reference in New Issue
Block a user