Задание 5.1D

Лабораторная №5 — задание 5.1D #

Нужно внедрить AST, а затем реализовать для своего языка поддержку ветвлений, циклов и пользовательских функций.

⚠️ Обратите внимание #

Это задание выполняется по спецификации грамматики, подготовленной аналитиком в задании 5.1A.

  • Спецификация должна появиться до начала кодирования — так же, как и в реальных проектах.
  • Вы можете составлять спецификацию совместно с аналитиком, а затем приступить к реализации.
  • Ждать проверки спецификации преподавателем не нужно.

Порядок выполнения #

  1. Получите спецификацию грамматики ветвлений, циклов и функций для своего языка программирования у аналитика
  2. Проведите предварительный рефакторинг
    • выделите модуль src/Ast и в нём опишите иерархию классов для узлов абстрактного синтаксического дерева
    • определите интерфейс IAstVisitor для обхода узлов AST
    • в модуле src/Execution реализуйте интерфейс IAstVisitor в новом классе AstEvaluator
    • класс Parser теперь должен строить AST программы, а не вычислять результат самостоятельно
  3. Допишите список тестов синтаксического анализатора
    • список тестов ранее был добавлен в tests/Parser.UnitTests/TESTLIST.md
    • вы можете добавить в список тестов новые разделы под новые возможности языка
  4. Доработайте синтаксический анализатор по TDD

Требования к AST #

Вы можете поменять именование или способ декомпозиции на классы, если это не ухудшает архитектуру проекта.

В иерархии узлов AST предусмотрите абстрактные классы:

  • AstNode — базовый для всех
  • Expression — базовый для узлов выражений
  • Declaration — базовый для узлов объявлений/определений
  • Statement — базовый для узлов инструкций, если в языке есть инструкции

Класс AstEvaluator должен:

  1. Реализовывать интерфейс IAstVisitor
  2. Вычислять выражения стековым методом
  3. Делегировать контроль за таблицей символов своим зависимостям (например, классу Context)
  4. Делегировать ввод-вывод своим зависимостям (например, через интерфейс IEnvironment)

Требования к списку тестов #

Список тестов должен соответствовать спецификации, подготовленной аналитиком:

  1. Список должен быть полным — каждый тип инструкции, каждое правило спецификации должно быть покрыто хотя бы одним тестом
    • Не нужно на каждую фразу спецификации делать отдельный тест, поскольку один тест может проверить несколько вещей
    • Пример: тест разбора выражения pi * radius ** 2 проверяет сразу два оператора и незачем разделять его на два теста
  2. Список тестов должен быть корректным — в нём нет лишних пунктов, противоречащих спецификации
    • Антипример: спецификация лексики говорит, что идентификаторы начинаются только с буквы, а тест проверяет разбор идентификатора _myField

Справочные материалы #

  1. Каноничный TDD и список тестов
  2. Пример PsKaleidoscope