使用 Bison 构建 AST 时指针无效

Invalid pointer while building an AST with Bison

我正在尝试为一种简单的编程语言构建 AST(家庭作业)。 但是我无法让它工作:似乎中间值 ($1, $2, ...) 无效并且与我 return 在 "sub-expressions".[=11= 中的值不对应]

这是我的项目的 Bison 代码(我认为问题出在这里而不是我的 AST 函数):我在遇到无效值的地方添加了注释。这是我第一个使用 Bison 的项目,所以我不确定我做的是否正确。

我也使用 Flex,但 flex 代码似乎可以正常工作。

谢谢。

%{
#include <stdio.h>

#include "node.h"
#include "print_node.h"

int yylex();
int yyerror(char * s);

CommandNode * root = NULL;
%}

%union
{
    struct ExpressionNode * expression;
    struct CommandNode    * command;
    int    number;
    char * var;
}

%type   <expression>    E T F
%type   <command>       C

%token  <number>        NUMBER
%token  <var>           VAR

%token                  AF SKIP SEQ IF THEN ELSE WHILE DO ADD SUB MUL EOL

%%

root:           C EOL      { root = ; return 0; /************  seems to be garbage ************/ }
                ;

E:              E ADD T    { $$ = newAddNode(,); }
        |       E SUB T    { $$ = newSubNode(,); }
        |       T          { $$ = ;                }
        ;

T:              T MUL F    { $$ = newMulNode(,); }
        |       F          { $$ = ;                }
        ;

F:              '(' E ')'  { $$ = ;                }
        |       NUMBER     { $$ = newNumberNode(); }
        |       VAR        { $$ = newVarNode();    }
        ;

C:              SKIP                 { $$ = newSkipNode();       }
        |       VAR AF E             { $$ = newAfNode(,);    }
        |       '(' C ')'            { $$ = ;                  }
        |       IF E THEN C ELSE C   { $$ = newIfNode(,,); }
        |       WHILE E DO C         { $$ = newWhileNode(,); }
        |       C SEQ C              { $$ = newSeqNode(,); /************  and  seems to be garbage ************/ }
        ;

%%

int main()
{
    yyparse();
}

int yyerror(char * s)
{
    fprintf(stderr, "yyerror: %s\n", s);
}

最常见的是,您描述的症状的发生是因为您的词法分析器(flex 代码,您没有显示)直接 returns yytext。由于 yytext 指向扫描器的内部缓冲区,它在那个实例中看起来很好,但在读取下一个标记后,它的值神秘地发生了变化。如果您有如下弹性规则,就会发生这种情况:

[a-zA-A][a-zA-Z0-9]*    { yylval.var = yytext; return VAR; }

要修复它,您需要在将 yytext 返回给解析器之前制作一份副本。像

[a-zA-A][a-zA-Z0-9]*    { yylval.var = strdup(yytext); return VAR; }

虽然会导致内存泄漏,但可以解决问题。