diff --git a/tasks.md b/tasks.md index b1a811d45..02add70c0 100644 --- a/tasks.md +++ b/tasks.md @@ -501,20 +501,44 @@ def tree_to_program(tree: ParserRuleContext) -> str: ## Задача 12. Интерпретатор языка запросов к графам -Полный балл: 22 +Полный балл: 35 -В данной задаче необходимо разработать интерпретатор языка запросов, разработанного в предыдущей работе. Для исполнения запросов использовать алгоритмы, реализованные в предыдущих работах. Кроме реализации необходимо предоставить минимальную документацию, поясняющую принятые в процессе реализации решения (например, в readme). +Балл складывается из следующих подзадач. -Обратите внимание, что кроме непосредственно интерпретатора необходимо реализовать вывод типов. Тестирование данной функциональности должно быть возможно в изоляции. Фактически, должна быть реализована отдельная функция, которая по дереву разбора выводит типы и кидает исключение, если программа не можете быть типизирована корректно. +* Простой однопроходный интерпретатор: 10 +* Вывод типов: 10 +* Проверять необъявленные нетерминалы: 5 +* Проверять недостижимые нетерминалы: 5 +* Проверять непорождающие нетерминалы: 5 + +В данной задаче необходимо реализовать интерпретатор языка запросов, разработанного в предыдущей работе. Для исполнения запросов использовать алгоритмы, реализованные в предыдущих работах. Кроме реализации необходимо предоставить минимальную документацию, поясняющую принятые в процессе реализации решения (например, в readme). + +Обратите внимание, что кроме непосредственно интерпретатора необходимо реализовать вывод типов и проверку корректности запросов. +Тестирование данной функциональности должно быть возможно в изоляции. +Фактически, должна быть реализована отдельная функция, которая по дереву разбора выводит типы и кидает исключение, если программа не может быть типизирована корректно. +Аналогично с обнаружением необъявленных, недостижимых, непорождающих нетерминалов. +Важно, что все проверки производятся "статически" до непосредственно выполнения программы. + + - [ ] Используя парсер из предыдущей работы и выбранные алгоритмы, реализовать простой однопроходный интерпретатор языка, описанного в предыдущей задаче. + - На данном этапе реализовать проверки не требуется. Можно реализовать самое "наивное" поведение с пошаговым исполнением программы, которое прерывается при первой же проблеме. + - Требуется реализовать функцию, которая по дереву разбора, предоставленному ANTLR, вернёт пару из словаря, содержащего для всех связываний, где в правой части `select`, имя (левую часть связывания) в качестве ключа, а в качестве значения --- результат выполнения соответствующего запроса, и статуса выполнения (удалось ли выполнить всё до конца или же произошла ошибка). Обратите внимание, что такой словарь должен быть построен для всего корректного префикса программы. Условно, если третий `select` не удалось выполнить, то вернётся словарь с результатами для первых двух и флагом `false`, говорящем о том, что в процессе исполнения возникла ошибка. + - Проследите за адекватностью сообщений об ошибках. Вам же проще отлаживаться будет. + - Постарайтесь максимально использовать возможности ANTLR по работе с деревом разбора. - [ ] Реализовать механизм вывода типов, гарантирующий корректность построения запросов (в частности, что не строится пересечение двух контекстно-свободных языков, или что множества вершин задаются значениями допустимых типов). + - На данном этапе считаем, что все объявления сделаны корректно (все нетерминалы объявлены, все достижимы, все порождающие). - Работа системы типов должна соответствовать правилам, указанным предыдущей задаче. - Постарайтесь сделать сообщения об ошибках максимально дружественными к пользователю. + - Вывод типов запускается до интерпретации и помогает интерпретатору использовать правильные алгоритмы (если типизировалось как регулярное, то и алгоритм для регулярных). Если типизация не прошла, то интерпретатор не запускается. + + - [ ] Реализовать функцию обнаружения необъявленных нетерминалов. Функция принимает дерево разбора и возвращает **все** необъявленные нетерминалы. Проверка выполняется до интерпретации вывода типов. Если проверка не пройдена, следующие шаги не запускаются. Помните, что у нас декларативное описание грамматики (запроса), потому объявление может идти после использования. + + - [ ] Реализовать функцию обнаружения недостижимых нетерминалов. Функция принимает дерево разбора и возвращает **все** недостижимые нетерминалы. Проверка выполняется до интерпретации вывода типов. Если проверка не пройдена, следующие шаги не запускаются. + + - [ ] Реализовать функцию обнаружения непорождающих нетерминалов. Функция принимает дерево разбора и возвращает **все** непорождающие нетерминалы. Проверка выполняется до интерпретации вывода типов. Если проверка не пройдена, следующие шаги не запускаются. + - [ ] Из множества реализованных в предыдущих работах алгоритмов выполнения запросов к графам выбрать те, которые будут использоваться в интерпретаторе. Обосновать свой выбор (зафиксировать в документации). - - [ ] Используя парсер из предыдущей работы, разработанную систему вывода типов, выбранные алгоритмы, реализовать интерпретатор языка, описанного в предыдущей задаче. - - Требуется реализовать функцию, которая по дереву разбора, предоставленному ANTLR, вернёт словарь, содержащий для всех связываний, где в правой части `select`, имя (левую часть связывания) в качестве ключа, а в качестве значения --- результат выполнения соответствующего запроса. - - Проследите за адекватностью сообщений об ошибках. Вам же проще отлаживаться будет. - - Постарайтесь максимально использовать возможности ANTLR по работе с деревом разбора. + - [ ] Добавить необходимые тесты. Требуемые функции: @@ -525,4 +549,13 @@ def typing_program(program: str) -> bool: def exec_program(program: str) -> dict[str, set[tuple]]: pass + +def find_undefined_nonterminals(program: str) -> set[str]: + pass + +def find_unreachable_nonterminals(program: str) -> set[str]: + pass + +def find_non_generative_nonterminals(program: str) -> set[str]: + pass ```