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

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

这是我要说的部分:

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

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

The majority of grammar actions will only require setting $$ to a new instance of the node, as with NRotate. But there are a couple of special cases to watch out for.

The main_loop action simply needs to grab the block it has and set the global g_MainBlock pointer to it. This global block should then also have SetMainBlock called on it.

The other special case is the actions for block. When the first statement is matched, you want to construct a new NBlock, and add the statement to this new NBlock’s list of statements. But when subsequent statements are matched, rather than creating a new NBlock, you should simply add the new statement to the already existing NBlock.

如何实现?

预计到达时间:

/* 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

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

第一条语句将 $$ 设置为 myBlock。递归语句从 </code> 中获取它,并将其设置为 <code>$$

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

通常你会这样写

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

这使用 block 的语义值在产品之间传递创建的 NBlock 对象。