Лексер и парсер для Рефала+, сделанные через JavaCC
Зачем нужны лексер и парсер для Рефала+?
Для интерактивной работы с разработчиком, нужно иметь программу в проанализированном виде (в абстрактном синтаксисе). Предполагаются такие виды помощи разработчику:
- Раскраска синтаксиса с учетом контекстных зависимостей. Например, могут краситься разным цветом главные вхождения переменной (где определяется ее значение) и повторными вхождениями (где ее значение используется).
- Показ синтаксических и семантических ошибок.
- Рефакторизация (преобразования программы без изменения ее смысла).
Для реализации таких возможностей, недостаточно иметь компилятор, который устроен как "черный ящик" (на входе - программа, на выходе - результат компиляции).
Преимущества Antlr перед JavaCC
- JavaCC генерирует только Java-программы, а Antlr - программы на разных языках (в частности Java с C#). Теоретически это позволяет использовать одну и ту же грамматику для версий одного и того же компилятора на разных языках.
Однако, возможность использовать одну и ту же грамматику в разных средах - иллюзорна, ибо в грамматику обычно приходится вставлять куски на каком-то языке программирования, которые зависят от этого языка.
Кроме того, грамматика по размеру составляет незначительную часть всего компилятора. Недолго ее и переделать под другой CC.
Преимущества JavaCC перед Antlt
- Вопрос, в значительной мере, субъективный, но создается впечатление, что в Antlr есть некоторая "расхристанность", а JavaCC сдалан как-то поаккуратней, что ли. Система понятий у JavaCC выглядит стройнее.
- В JavaCC грамматика превращается в определения нескольких Java-классов, которые в программу и вставляются. Т.е., в отличие от Antlr, не требуется таскать за программой дополнительную библиотеку периода исполнения.
Запуск лексера и парсера
Лексер и парсер предполагается вставлять в плагины для Eclipse и (может быть) NetBeans. Но, для проверки грамматики, их можно запускать и отдельно.
Для компиляции проекта под Эклипсом нужно предварительно установить JavaCC-плагин:
После этого можно скомпилировать проект.
Далее есть два способа запуска лексера и парсера: в качестве консольного приложения или через JUnit.
Запуск в качестве консольного приложения
Запускаем как консольное приложение через функцию
org.refal.plus.test.Main.main
После этого вводим через System.in реализацию Рефал-модуля (т.е. то, что обычно находится в rf-файле).
Запуск через JUnit
В классе
org.refal.plus.test.RfpStringParserTest?
определены две функции
testParseModuleInterface
testParseModuleImplementation
которые запускают набор тестов для проверки лексера и парсера. Функция testParseModuleInterface применяет лексер и парсер к "интерфейсам" модулей (обычно находящимся в rfi-файлах), а testParseModuleInterface применяет лексер и парсер к "реализациям" модулей (обычно находящимся в rf-файлах).