使用 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; }
虽然会导致内存泄漏,但可以解决问题。
我正在尝试为一种简单的编程语言构建 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; }
虽然会导致内存泄漏,但可以解决问题。