Какова сфера действия yacc / bison? - PullRequest
0 голосов
/ 24 февраля 2011

Я пытаюсь написать (относительно) простой анализатор конфигурационных файлов в flex / bison. Основная идея заключается в том, что моя грамматика bison использует некоторые функции языка Си для организации разобранных данных в ряд структур языка Си. Я был бы рад опубликовать свой код, если кто-то посчитает необходимым ответить на вопрос, просто прокомментируйте.

Проблема, с которой я сталкиваюсь, связана с объемом процедур в действиях bison. Например, если у меня есть что-то вроде:

set
          : NTOK name    {
                          section *sec
                          init_s(sec, $2);
                          add_s(cf, sec);
                         }

Разве sec не должен быть доступен в более позднем правиле грамматики для использования? Я получаю error: 'sec' undeclared, когда пытаюсь снова вызвать это как аргумент позже. Может ли кто-нибудь просветить меня?

Ответы [ 2 ]

4 голосов
/ 24 февраля 2011

Весь код, сгенерированный для действий в bison, находится в собственной области видимости (IIRC, сгенерированный код заключает его в фигурные скобки, чтобы обеспечить это).Если вы хотите сделать данные глобально доступными для других действий, вам нужно явно объявить глобальную переменную где-нибудь (возможно, в верхней части скрипта flex или bison?), А затем записать в эту переменную.Это объясняется тем, что если бы каждая переменная в действии была неявно глобальной или, по крайней мере, читаемой другими действиями, тогда было бы очень легко случайно перерабатывать данные мусора, когда вы собирались создавать новые данные.

0 голосов
/ 24 февраля 2011

Эта проблема обычно решается путем назначения типов токенам и правилам. Вы также можете добавить свои параметры к функции парсера.

%union {
  char* name;
  section* sec;
}

%parse-param {whatever_type cf}

%token <name> name
%type <sec> set

%%

set      : NTOK name    {
                          init_s(&$$, $2);
                          add_s(cf, $$);
                         }
         ;

other_rule: set name {do_something_other($1 $2);}
          ;
...