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

How to declare a persistent variable when using left recursion in bison/flex?

本文关键字:何声明 声明 变量 flex bison 递归      更新时间:2023-10-16

这是我要讨论的部分:

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

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

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

附言:您应该使用智能指针,即std::shared_ptr,以避免由于解析失败而导致内存泄漏。

通常你会把它写成

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

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