如何在bison / flex中使用左递归时声明持久变量?

时间:2016-04-17 01:09:08

标签: c++ recursion bison

这是我正在谈论的部分:

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

以下是此作业说明的摘录:

  

大多数语法操作只需要将$$设置为节点的新实例,如   与NRotate。但有几个特殊情况需要注意。

     

main_loop操作只需要获取它拥有的块并设置全局g_MainBlock   指向它的指针。这个全局块也应该在其上调用SetMainBlock。

     

另一个特例是阻止的动作。当第一个语句匹配时,你想要   构造一个新的NBlock,并将该语句添加到这个新的NBlock的语句列表中。但当   后续语句是匹配的,而不是创建一个新的NBlock,你应该简单地添加   已经存在的NBlock的新陈述。

我如何实现这一目标?

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

2 个答案:

答案 0 :(得分:2)

您应该能够在$1中找到原始对象,并将其移至$$,而不是创建新对象。

第一个语句将$$设置为myBlock。递归语句从$1抓取它,并将$$设置为它。

P.S。您应该使用智能指针,即std::shared_ptr,以避免因解析失败而导致内存泄漏。

答案 1 :(得分:0)

通常你会把它写成

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

这使用block的sematic值在制作之间传递创建的NBlock对象。