我正在尝试为简单的编程语言构建 AST(家庭作业)。 但是我无法使其工作:似乎中间值($1,$2,...)无效,并且与我在“子表达式”中返回的内容不对应。
这是我项目的 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 = $1; return 0; /************ $1 seems to be garbage ************/ }
;
E: E ADD T { $$ = newAddNode($1,$3); }
| E SUB T { $$ = newSubNode($1,$3); }
| T { $$ = $1; }
;
T: T MUL F { $$ = newMulNode($1,$3); }
| F { $$ = $1; }
;
F: '(' E ')' { $$ = $2; }
| NUMBER { $$ = newNumberNode($1); }
| VAR { $$ = newVarNode($1); }
;
C: SKIP { $$ = newSkipNode(); }
| VAR AF E { $$ = newAfNode($1,$3); }
| '(' C ')' { $$ = $2; }
| IF E THEN C ELSE C { $$ = newIfNode($2,$4,$6); }
| WHILE E DO C { $$ = newWhileNode($2,$4); }
| C SEQ C { $$ = newSeqNode($1,$3); /************ $1 and $3 seems to be garbage ************/ }
;
%%
int main()
{
yyparse();
}
int yyerror(char * s)
{
fprintf(stderr, "yyerror: %s\n", s);
}
最佳答案
最常见的是,您描述的症状发生是因为您的词法分析器(弹性代码,您不显示)直接返回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; }
可以解决这个问题,尽管它会让你面临内存泄漏。
关于c - 使用 Bison 构建 AST 时指针无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42726054/