2009-08-10 3 views
1

В Bison У меня есть союзКак инициализировать значение объединения Union Bison?

%union 
{ 
    std::string* sval; 
} 

И я хочу, чтобы использовать его как этот

В Lex:

*(yylval->sval) = "ABCD"; 

Вместо

yylval->sval = new std::string("ABCD"); 

Для предотвращения утечки памяти легко

Однако мне нужно каким-то образом выделить std :: string для sval.

Как я могу это сделать?

ответ

0

Я не полностью ясно, почему вы хотите это сделать, но я могу понять, почему то, что у вас есть, не работает. Это потому, что "ABCD" является const char *, а не std::string.

Я знаю, что с Yacc, что первый "%{ ... %}" секция позволяет определить C материал вне контроля Yacc (и, кажется, Bison имеет аналогичную функцию, основанную на его вверх требование совместимости и документации here, 2.1.1). Почему бы вам не ставить:

std::string *strABCD = new std::string("ABCD"); 

в этом разделе, а затем использовать:

yylval->sval = strABCD; 

позже, когда вам нужен указатель на эту строку?

Мне кажется, что это самый простой способ добиться того, что (я думаю) вам нужно.

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

Update:

Вот как я бы это сделать, чтобы избежать выделения/освобождения, что фиксированное значение в пределах синтаксического анализатора Bison. Установите его как глобальный, который живет на протяжении всей программы.

Главный код:

std::string *strABCD = new std::string ("ABCD"); 

int main(...) { 
    // Do some stuff. 
    : : : 
    yyparse(); 
    : : : 
    // Do some other stuff. 
} 

Bison источник парсер:

%{ 
    extern std::string *strABCD; 
%} 
: : : 
yylval->sval = strABCD; 

Это возвращает фиксированный указатель на вашей ABCD строку с не выделения или высвобождая в коде Bison на всех (и драгоценные немного даже в основном коде).

+0

Потому что теперь у вас есть утечка памяти, если вы не освободите свои входы для Yacc для каждого совпадения правил. – DevDevDev

+0

Хорошо, но если вы собираетесь выделить память, вам нужно ее освободить. Если вы этого не хотите, не выделяйте - замените ваш союз на char *. Большинство парсеров, которые я написал, были однократными, поэтому код прелюдии «утечка» одной строки std :: был бы неактуальным. Ваша архитектура может отличаться. В качестве альтернативы настройте его перед вызовом анализатора и затем порвите его. См. Обновление. – paxdiablo

+0

Ваш код будет просачивать одну строку для каждого правила, соответствующего типу возврата. – DevDevDev

2

Вы не можете безопасно помещать типы с конструкторами или деструкторами (например, std :: string) в объединение, так что это не сработает.

Что вы можете сделать, вместо того, чтобы не использовать% союз вообще - вместо того, чтобы использовать макрос для отображения YYSTYPE непосредственно в какой-то другой тип:

%{ 
#define YYSTYPE std::string 
%} 

тогда yylval будет этот тип (как будет все $ п опции в коде грамматики)

+0

Где я могу это сделать? Также как определить типы моих правил? как % Тип правило – DevDevDev

+0

Я попробовал и теперь я получаю «не может конвертировать из полукокса * до * semantic_type» – DevDevDev

+0

Я не думаю, что ваш код работает. – DevDevDev

Смежные вопросы