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 |
|
|
Текстовая версия | Сейчас: 25.11.2024, 17:35 |