Как сгенерировать различные функции yyparse из lex/yacc для использования в одной и той же программе?

Я хочу сгенерировать две отдельные функции синтаксического анализа из lex/yacc. Обычно yacc дает вам функцию yyparse(), которую вы можете вызвать, когда вам нужно выполнить какой-то анализ, но мне нужно иметь несколько разных yyparse, каждый из которых связан с разными лексерами и грамматиками. Страница руководства, кажется, предлагает флаг -p (префикс), но это не сработало для меня. Я получил ошибки от gcc, которые указывали на то, что yylval не был должным образом перемаркирован (т.е. он утверждает, что несколько разных токенов не определены). Кто-нибудь знает общую процедуру создания этих отдельных функций?

Благодарность


person th.    schedule 19.03.2010    source источник
comment
(a) Какие версии инструментов вы используете? (b) Искали ли вы неожиданные вхождения «yy» в грамматиках/лексерах, которые должны были использовать какой-то другой префикс? Мы использовали сценарии «sed» в течение эонов (то есть более 20 лет) для этого — потому что параметры префикса не всегда были доступны так давно — с большим успехом. ... Я должен квалифицировать материал 'grep yy'; flex -P zz lex.l оставляет много вхождений 'yy' в исходном коде C, lex.zz.c, но ни один из них не виден за пределами объектного файла (nm -g lex.zz.o).   -  person Jonathan Leffler    schedule 20.03.2010


Ответы (3)


У меня была такая же проблема некоторое время назад, и я написал следующий заголовочный файл:

#ifndef RENAME_FLEX_H
#define RENAME_FLEX_H

#define yy_create_buffer scan__create_buffer
#define yy_delete_buffer scan__delete_buffer
#define yy_init_buffer scan_init_buffer
#define yy_load_buffer_state scan_load_buffer_state
#define yy_switch_to_buffer scan_switch_to_buffer
#define yyin scan_in
#define yyleng scan_leng
#define yylex scan_lex
#define yyout scan_out
#define yyrestart scan_restart
#define yytext scan_text
#define yy_flex_debug scab_flex_debug
#define yywrap scan_wrap
#define yyrealloc scan_realloc
#define yyfree scan_free
#define yy_flush_buffer scan_flush_buffer
#define yypush_buffer_state scan_push_buffer_state
#define yypop_buffer_state scan_pop_buffer_state
#define yy_scan_buffer scan_scan_buffer
#define yy_scan_string scan_scan_string
#define yy_scan_bytes scan_scan_bytes
#define yyget_in scan_get_in
#define yyget_out scan_get_out
#define yyget_leng scan_get_leng
#define yyset_text scan_set_text
#define yyset_in scan_set_in
#define yyset_out scan_set_out
#define yyget_debug scan_get_debug
#define yyset_debug scan_set_debug
#define yylex_destroy scan_lex_destroy
#define yyalloc scan_alloc
#define yyget_text scan_get_text

#endif

и включить его в .l, поэтому из моего файла .c я могу использовать символы с префиксом scan_ для второго сканера, а не с префиксом yy

person qrdl    schedule 20.03.2010

Как насчет указателя функции в окружающем коде, который меняет синтаксические анализаторы, предполагая, что вы не хотите менять контекст синтаксического анализа в середине yylex() в том же буфере.

Указатель функции можно установить, включив парсеры с опцией префикса или загруженные из DSO во время выполнения, как установка плагина.

Преимущество этого, которое может быть полезно или не полезно для вас, заключается в том, что ваш код, обрабатывающий AST, может быть слеп к тому, какая комбинация парсера/лексера использовалась для его создания.

person Aiden Bell    schedule 19.03.2010

Если вы используете flex/bison, вы можете использовать «реентерабельные» опции, которые позволяют иметь несколько экземпляров одного и того же (или разных) сканера. Эта опция присутствует в последней гибкой версии. ИМХО, это более чистый способ иметь несколько сканеров/парсеров в одной программе. Эта статья подробно объясняет проблему.

Альтернативный способ — использовать способность flex генерировать класс C++ вместо статического сканера, но это вынуждает программиста C писать некоторые функции-оболочки.

С Уважением

person Giuseppe Guerrini    schedule 19.03.2010