2016-04-17 7 views
2

Hier ist der Teil ich spreche:Wie deklariert man eine persistente Variable bei der Verwendung der linken Rekursion in bison/flex?

block  : statement 
      { 
       NBlock* myBlock = new NBlock(); 
       myBlock->AddStatement($1); 
      } 
      | block statement 
      { 
       std::cout << "More than one statement" << std::endl; 
       myBlock->AddStatement($2); 
      } 
; 

Hier ist ein Auszug aus den Anweisungen für diese Aufgabe:

Die Mehrheit der Grammatik Aktionen werden nur $$ auf eine neue Einstellung erfordern Instanz des Knotens, wie mit NRotate. Aber es gibt ein paar spezielle Fälle, auf die man achten sollte.

Die Aktion main_loop muss einfach den Block, den sie hat, erfassen und den globalen Zeiger g_MainBlock darauf setzen. Für diesen globalen Block sollte dann auch SetMainBlock aufgerufen werden.

Der andere Sonderfall sind die Aktionen für Block. Wenn die erste Anweisung übereinstimmt, müssen Sie einen neuen NBlock erstellen und die Anweisung der neuen Anweisungsliste dieses NBlocks hinzufügen. Aber wenn aufeinander folgende Anweisungen übereinstimmen, anstatt einen neuen NBlock zu erstellen, sollten Sie einfach die neue Anweisung zu dem bereits vorhandenen NBlock hinzufügen.

Wie erreiche ich das?

ETA:

/* Add one union member for each Node* type */ 
%union { 
    Node* node; 
    NBlock* block; 
    NStatement* statement; 
    NNumeric* numeric; 
    NBoolean* boolean; 
    std::string* string; 
    int token; 
} 

%error-verbose 

/* Terminal symbols */ 
%token <string> TINTEGER 
%token <token> TLBRACE TRBRACE TSEMI TLPAREN TRPAREN 
%token <token> TMAIN TROTATE TFORWARD TISHUMAN TATTACK TISPASSABLE TISRANDOM TISZOMBIE TRANGED 
%token <token> TIF TELSE 

/* Statements */ 
%type <block> main_loop block 
%type <statement> statement rotate forward is_human is_passable is_random is_zombie ranged 

/* Expressions */ 
%type <numeric> numeric 

Antwort

2

sollten Sie in der Lage sein, einfach das ursprüngliche Objekt in $1 zu finden, und es in $$ zu bewegen, anstatt einen neuen zu erstellen. Die erste Anweisung setzt $$ auf myBlock. Die rekursive Anweisung ergreift sie aus $1 und setzt $$ zu ihm.

P.S. Sie sollten intelligente Zeiger verwenden, d. H. std::shared_ptr, um zu vermeiden, dass aufgrund von Analysefehlern Speicher verloren geht.

+0

Wenn Sie sagen "finde das Originalobjekt in $ 1", bin ich mir nicht sicher, was du meinst. Ich verstehe, dass 41 der erste Block sein wird, in dem myBlock deklariert wäre, aber wie kann ich darauf zugreifen? Vielen Dank! –

+0

Ich weiß nicht, was du mit "41" meinst. –

+0

@SamVarshavchik - Wahrscheinlich ein Tippfehler. Das OP bedeutete "$ 1". – owacoder

0

Normalerweise würde schreiben Sie dies als

block  : statement 
      { 
       $$ = new NBlock(); 
       $$->AddStatement($1); 
      } 
      | block statement 
      { 
       std::cout << "More than one statement" << std::endl; 
       ($$ = $1)->AddStatement($2); 
      } 
; 

Dies verwendet die sematischen Wert von block das erstellte NBlock Objekt zwischen Produktionen zu übergeben.

Verwandte Themen