ANTLR и С++, использование классов в парсерах ANTLR |
Здравствуйте, гость ( Вход | Регистрация )
ANTLR и С++, использование классов в парсерах ANTLR |
Iron Bug |
12.3.2011, 19:24
Сообщение
#1
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
Вот, ещё одна моя заметка из раздела "химия и жизнь", я бы так сказала
В общем, наверняка кому-то пригодится. Задача: есть парсер ANTLR3 с целевым языком С (используется libantlr3c) и очень лень(или просто некогда) писать интерфейс к нему на чистом С (это медленно и для больших проектов, обычно написанных на С++, это лишний геморрой). Решение: сгенерированный сишный ANTLR парсер можно компилить как CPP! Но для этого нужны некоторые хитрости, которые я и попытаюсь изложить. Я рассмотрю пример, в котором в парсере используется глобальная область переменных (можно аналогично использовать и локальные области), которая содержит указатель на С++ класс. (Про области переменных см. книжку Теренса Парра и вики на сайте ANTLR, я это тут пояснять не буду). Пример доработанного для работы с C++ ANTLR парсера: Раскрывающийся текст
Примечания: в области видимости ANTLR (scope) могут использоваться только переменные фиксированного размера. Т.е. мы не можем использовать, например, строку (string), а можем использовать только указатель на неё. Аналогично и с классами: обязательно используются только указатели. Ну либо типы фиксированного размера (например, int, char). Для инициализации указателей и удаления объектов после работы используются блоки @init и @after. Там же можно выполнить какие-то другие действия, например, инициализацию созданного объекта. Из этого парсера мы получим файлы: MyLexer.h,MyLexer.c,MyParser.h,MyParser.c Подключаем их к проекту и указываем компилятору компилировать их как CPP. Пишем сам класс MyScopeClass: MyScopeClass.h Раскрывающийся текст
MyScopeClass.cpp Раскрывающийся текст
Собственно, всё. Всё это работает и под вендой, и под линюксом. Однако, есть ещё некоторые нюансы: Если в заголовочник MyScopeClass.h нужно включить другой заголовочный CPP файл, то в его начало нужно поместить что-то вроде: #ifndef __cplusplus #define __cplusplus #define __remove_cplusplus #endif а в конец #ifdef __remove_cplusplus #undef __cplusplus #undef __remove_cplusplus #endif Это чтобы компилятор обошёл наши объявления из парсерного кода и воспринял заголовок как код CPP. Далее, если в проект включены сразу несколько парсеров, то нужно придерживаться строгого разделения пространств имён. Проблема в том, что libantlr3c генерит все имена правил и лексем в общем пространстве имён и нельзя использовать в разных парсерах одни и те же имена для правил и лексем, иначе потом при включении заголовков они будут перекрывать друг друга. В этом случае лучше именовать все правила как-то так: My_rule1,MY_LEXEM1. Всё. Теперь класс CPP можно смело использовать из кода ANTLR. Сообщение отредактировал Iron Bug - 12.3.2011, 19:29 |
|
|
smartchecker |
5.12.2012, 16:13
Сообщение
#2
|
Студент Группа: Участник Сообщений: 83 Регистрация: 7.9.2011 Пользователь №: 2853 Спасибо сказали: 0 раз(а) Репутация: 0 |
Не совсем понятно, что нужно сделать, если нужен только lexer.
|
|
|
Iron Bug |
5.12.2012, 18:38
Сообщение
#3
|
Профессионал Группа: Модератор Сообщений: 1611 Регистрация: 6.2.2009 Из: Yekaterinburg Пользователь №: 533 Спасибо сказали: 219 раз(а) Репутация: 12 |
бери лексер и собирай проект с ним.
вызов стандартный, как описано на сайте ANTLR. я не работала отдельно только с лексерами, ибо смысла в этом особого нет. так что не могу в деталях сказать, как употреблять их результаты. наверное, какая-то последовательность лексем на выходе должна быть. вообще, создаётся лексер так (этот кусок читает данные из файла):
А вот удаление объектов:
тут script_name - имя скрипта (script_name.g) ANTLR. реализация в С создаёт фабрику script_nameLexerNew для генерации лексера. это описано в документации к libantlr3c. как работать с полученным tstream - я сказать не могу. я его скармливаю парсеру. код libantlr3c открыт - можешь там посмотреть, что парсер с ним делает. или в документации поискать. ещё есть рассылка по ANTLR - там автор libantlr3c тоже участвует и отвечает на вопросы. P.S. насчёт макросов переопределения _cplusplus - это нужно не для всех компиляторов. похоже, что для современных вообще не нужно. у меня относительно недавно собирался проект с парсером и спокойно всё собралось без лишних препроцессорных команд. только опции компиляции сишных файлов как С++ нужны были. Сообщение отредактировал Iron Bug - 5.12.2012, 18:50 |
|
|
ViGOur |
8.12.2012, 22:05
Сообщение
#4
|
Мастер Группа: Модератор Сообщений: 3296 Регистрация: 9.10.2007 Из: Москва Пользователь №: 4 Спасибо сказали: 231 раз(а) Репутация: 40 |
Разделил тему: Ошибка при использовании ANTLR, Java
|
|
|
Текстовая версия | Сейчас: 29.11.2024, 10:05 |