174 lines
6.9 KiB
Python
174 lines
6.9 KiB
Python
from grammar import ActionsListWithAppliedCount, Grammar
|
||
|
||
|
||
def load_grammar(filename: str = "grammar.txt") -> Grammar | None:
|
||
try:
|
||
# #b - 2 * #a + 3 * #c
|
||
actions = [
|
||
lambda rule_number, applied_count, _: print(
|
||
f"Rule #{rule_number} (applied x{applied_count} times): iconst_1"
|
||
),
|
||
lambda rule_number, applied_count, _: print(
|
||
f"Rule #{rule_number} (applied x{applied_count} times): iconst_2 isub"
|
||
),
|
||
lambda rule_number, applied_count, _: print(
|
||
f"Rule #{rule_number} (applied x{applied_count} times): iconst_1 iadd"
|
||
),
|
||
lambda rule_number, applied_count, _: print(
|
||
f"Rule #{rule_number} (applied x{applied_count} times): iconst_1 iadd"
|
||
),
|
||
lambda rule_number, applied_count, _: print(
|
||
f"Rule #{rule_number} (applied x{applied_count} times): iconst_3 iadd"
|
||
),
|
||
]
|
||
|
||
with open(filename, "r", encoding="utf-8") as file:
|
||
text = file.read()
|
||
grammar = Grammar(text, ActionsListWithAppliedCount(actions))
|
||
|
||
# Сохраняем информацию о грамматике в файлы
|
||
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:
|
||
output_file.write(grammar.format_lookup_table())
|
||
print(
|
||
"Таблица синтаксического анализа сохранена в grammar_lookup_table.txt"
|
||
)
|
||
|
||
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("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 tokenize_string(input_string: str) -> list[str]:
|
||
return input_string.split()
|
||
|
||
|
||
def check_string(grammar: Grammar | None, input_string: str) -> None:
|
||
if not grammar:
|
||
print("Ошибка: Грамматика не загружена")
|
||
return
|
||
|
||
print(f"Проверка строки: '{input_string}'")
|
||
try:
|
||
input_tokens = tokenize_string(input_string)
|
||
parse_result = grammar.analyze(input_tokens)
|
||
|
||
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))
|
||
f.write("\n\n")
|
||
f.write("Derivation steps:\n")
|
||
|
||
derivation_steps = grammar.generate_derivation_steps(parse_result)
|
||
for step in derivation_steps:
|
||
f.write(f"{step}\n")
|
||
|
||
print("Подробный результат анализа сохранен в analysis_result.txt")
|
||
except ValueError as e:
|
||
print(f"Результат: Строка не соответствует грамматике")
|
||
print(f"Ошибка: {e}")
|
||
except Exception as e:
|
||
print(f"Произошла ошибка при анализе: {e}")
|
||
|
||
|
||
def generate_string(grammar: Grammar | None) -> None:
|
||
if not grammar:
|
||
print("Ошибка: Грамматика не загружена")
|
||
return
|
||
|
||
try:
|
||
terminals, rules = grammar.generate()
|
||
generated_string = " ".join(terminals)
|
||
print(f"Сгенерированная строка: {generated_string}")
|
||
print(f"Применённые правила: {rules}")
|
||
|
||
# Сохраняем результат генерации в файл
|
||
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))
|
||
f.write("\n\n")
|
||
f.write("Derivation steps:\n")
|
||
|
||
derivation_steps = grammar.generate_derivation_steps(rules)
|
||
for step in derivation_steps:
|
||
f.write(f"{step}\n")
|
||
|
||
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()
|