Разделение памяти между файлами YACC, Lex и C

У меня есть грамматика YACC (Bison), токенизатор Lex (Flex) и программа на C, среди которых мне нужно разделить struct (или любую переменную). В настоящее время я объявляю фактический объект в файле грамматики и extern его везде, где он мне нужен (то есть в исходном файле C), обычно используя указатель для управления им. У меня есть общий файл заголовка (и реализации) между файлом C и файлом грамматики с функциями, полезными для управления моей структурой данных. Это работает, но немного неудобно. Есть ли лучший способ разделить память между грамматикой и программой?


person sczizzo    schedule 14.03.2010    source источник


Ответы (2)


Файл заголовка для совместного использования объявления extern между исходными файлами, которым это необходимо, обычно является лучшим способом. Основной альтернативой является предоставление к нему «функционального доступа», т. е. своего рода функции «получения значения» и «установки значения» (или набора функций). Обычно это перебор. Убедитесь, что вы включили заголовок в грамматику (где вы определяете переменную), а также в лексер и другой код, чтобы несоответствия были обнаружены как можно скорее.

person Jonathan Leffler    schedule 14.03.2010

Если вы хотите придерживаться стандартного (POSIX) lex/yacc, то единственный вариант — использовать глобальные переменные/функции. Если вас устраивает использование расширений Bison и Flex, есть несколько способов передачи переменных, которые в основном включают добавление дополнительных параметров в yyparse() и yylex().

В Bison это достигается с помощью %lex-param и %parse-param.

%parse-param { struct somestruct *mystruct }
%lex-param { struct somestruct *mystruct }

Во Flex есть два разных механизма, в зависимости от того, нужен ли вам реентерабельный лексер или нет. Предполагая, что вы используете вариант по умолчанию (без повторного входа), вы захотите переопределить YY_DECL:

%{
#define YY_DECL int yylex(struct somestruct *mystruct)
%}

В реентерабельном лексере Flex дополнительные аргументы могут быть добавлены через структуру сканера, которую Flex переносит для сохранения своего состояния. Вы захотите определить YY_EXTRA_TYPE; доступ к дополнительным данным можно получить через yyget/set_extra().

person rz0    schedule 14.03.2010