Yacc - 使用%union和linked-list构建数据结构

时间:2016-01-17 08:35:24

标签: c linked-list bison yacc

我正在尝试使用yacc在我的程序中构建特殊的数据结构。这是我的语法的一部分:

commands      : commands command    {if($$ == 0){$$ = &$2;}
                                     struct Command* ptr = $$;
                                     while(ptr->next != 0){ ptr=ptr->next;} ptr->next = &$2;
                                     }
                  |                  {$$= 0;}
                  ;

command       : identifier ASSGNOP expression';'  {$$.id = $1; $$.exp=$3; $$.next = 0; }
              | IF condition THEN commands ENDIF  {$$.next = $4;  = $2; $4 = &$$; }
              ;

我希望我的程序在执行时创建链表。

%type <Command> command
%type <Commands> commands

     //..part in union%{
    struct Command {
        struct Command * next;
        struct Expression exp;
        char*  id;

        struct Condition cond;  
        int licznik;

        }Command;

       struct Command* Commands;         
    }

通过将命令连接在一起,列表应该增长。最后,应该返回一个指向整个结构列表的指针。不幸的是,我正在进行细分&#39;错误错误。此外,它永远迭代,永远不会遇到NULL。如果有人指着我做错了,我将不胜感激。当我删除ptr = ptr-&gt; next时;它工作,但我不明白为什么会这样。它应该在最后指向NULL。

1 个答案:

答案 0 :(得分:0)

语义值$n保留在解析器堆栈上。它们不会占用持久性内存,因此获取其地址通常是错误的。执行语义操作后,它们将立即从堆栈中弹出,任何指向它们的指针都将无效。

如果要创建语义对象的链接列表,则需要手动分配内存,并将语义值设置为已分配对象的地址。

顺便说一下,通过在列表的头部按下每个新节点,然后在完成时反转列表,向后构建列表更有效。这避免了每次推送时列表的二次扫描。