Совместное использование памяти между файлами YACC, Lex и C - PullRequest
4 голосов
/ 14 марта 2010

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

Ответы [ 2 ]

4 голосов
/ 14 марта 2010

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

2 голосов
/ 14 марта 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 ().

...