2009-08-10 11 views
1

In Bison habe ich eine VereinigungWie initialisiert Bisons% Union Wert?

%union 
{ 
    std::string* sval; 
} 

Und ich will es wie diese

In Lex verwenden:

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

Statt

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

Um zu verhindern Speicherlecks leicht

Allerdings brauche ich irgendwie eine std :: string zu sval zu beginnen.

Wie kann ich das tun?

Antwort

0

Ich bin nicht ganz klar, warum Sie das tun wollen, aber ich kann sehen, warum, was Sie haben, funktioniert nicht. Es ist, weil "ABCD" ein const char * ist, kein std::string.

Ich weiß, mit Yacc, dass der erste "%{ ... %}" Abschnitt ermöglicht es Ihnen, C Sachen außerhalb der Kontrolle von Yacc (und es scheint, Bison hat eine ähnliche Funktion bietet, basierend auf es ist Aufwärtskompatibilität Anspruch und die Dokumentation here, 2.1.1) zu definieren. Warum würden Sie nicht sagen:

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

in diesem Abschnitt und dann verwenden:

yylval->sval = strABCD; 

später, wenn Sie einen Zeiger benötigt, um diese Zeichenfolge?

Das scheint mir der einfachste Weg zu sein, was (ich denke) du willst.

Wenn Sie besorgt sind, dass Zuweisungen innerhalb des Bison-Parsers nicht freigegeben werden (und das sollten sie sein), ist mein Ratschlag, sie nicht dort zu tun. Sie können Ihre Zeichenfolge vor dem Aufruf von yyparse() einrichten und dann nach der Rückkehr freigeben.

Update:

Hier ist, wie ich tun würde es die Zuweisung zu vermeiden/diesen festen Wert innerhalb der Bison-Parser zu befreien. Richten Sie es als ein globales ein, das für die Dauer des Programms lebt.

Hauptcode:

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

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

Bison-Parser Quelle:

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

dass die festen Zeiger auf Ihre ABCD String zurückgibt mit keine Zuordnung oder gar im Bison-Code befreien (und Edel wenig sogar im Hauptcode).

+0

Weil Sie jetzt ein Speicherleck haben, es sei denn, Sie geben Ihre Eingaben an Yacc für jede Übereinstimmung der Regeln frei. – DevDevDev

+0

Okay, aber wenn Sie Speicher reservieren wollen, müssen Sie ihn freigeben. Wenn Sie das nicht möchten, nicht zuweisen - ändern Sie stattdessen Ihre Vereinigung, um ein char * zu sein. Die meisten Parser, die ich geschrieben habe, waren One-Shots, also wäre der Prelude-Code, der eine std :: string "leckt", irrelevant. Deine Architektur kann anders sein. Alternativ können Sie es vor dem Aufruf des Parsers einrichten und anschließend abreißen. Siehe das Update. – paxdiablo

+0

Ihr Code wird für jede Regel, die mit einem Rückgabetyp übereinstimmt, eine Zeichenfolge verlieren. – DevDevDev

2

Sie können nicht sicher Typen mit Konstruktoren oder Destruktoren (wie zB std :: string) in eine Union einfügen, so dass dies nicht funktioniert.

Was können Sie stattdessen tun ist, nicht verwendet% union - statt mit einem Makro YYSTYPE direkt zu einem anderen Typ zuzuordnen:

%{ 
#define YYSTYPE std::string 
%} 

dann yylval dass Typ sein (wie alle n $ Optionen im Grammatik-Code)

+0

Wo mache ich das? Wie definiere ich auch die Arten meiner Regeln? wie % Typ Regel – DevDevDev

+0

ich es versucht, und jetzt bin ich immer „kann von char * nicht konvertieren semantic_type *“ – DevDevDev

+0

Ich glaube nicht, Ihr Code funktioniert. – DevDevDev