我正在为一项大学作业编写一个带有 flex 和 bison 的编译器。我在向我的符号表中添加函数标识符时遇到了问题 - 在评估函数声明时,我在 yytext
中得到了我期望标识符的左括号。在我的 flex 文件中,yylval
是一个 union ,vlex
是一个 struct
:
abc [A-Za-z_]
alphanum [A-Za-z_0-9]
id {abc}+{alphanum}*
...
#define STORE_YYLVAL_NONE\
do{\
... // location control irrelevant to the problem
yylval.vlex.type = none_t;\
yylval.vlex.value.sValue = yytext;\
}while(0)
...
{id} {
LOG_DEBUG("id: %s\n", yytext);
STORE_YYLVAL_NONE;
return TK_IDENTIFIER;
}
[,;:()\[\]\{\}\+\-\*/<>!&=%#\^\.\|\?\$] {
LOG_DEBUG("special\n");
STORE_YYLVAL_NONE;
return *yytext;
}
...
在我的 bison 文件中我有:
new_identifier_with_node: TK_IDENTIFIER {
hshsym_add_or_exit(&hshsym, yylval.vlex.value.sValue, &(yylval.vlex));
$$ = ast_node_create(&(yylval.vlex));
};
func: type new_identifier_with_node '(' param_list ')' func_block { ... };
我在 hshsym_add_or_exit
中也有一个日志,它向我的符号表添加了一个标识符。解析以下程序时:
int k(int x,int y, int z){}
int f(){
k(10,20,30);
}
我得到以下调试输出:
yylex: DEBUG! id: k
yylex: DEBUG! special
hshsym_add_or_exit: DEBUG! Declaring: (
即new_identifier_with_node
产生式求值时,yytext
的内容是(
而不是k
,正如我所料。代码是上面的原因吗?我有一些尚未解决的转移/减少冲突,我猜这可能是错误的,但我不知道在这种特定情况下如何。我相信我真的错过了一些东西基本但我看不出是什么。此时该项目相当大(而且可耻地杂乱无章),但如果需要,我可以提供一个完整且可重现的示例。
最佳答案
基本问题是您在 new_identifier_with_node
生产中使用 yylval
,而不是 $1
。 $1
是产生式中第一个符号的语义值,在本例中为 TK_IDENTIFIER
。
在 bison Action 中,yylval
通常是前瞻标记的值,它是输入流中的下一个标记。这就是为什么它在这种情况下显示为括号的原因。但是您通常不能指望这一点,因为 Bison 会在读取前瞻标记之前执行默认缩减。一般来说,除了错误恢复中的某些应用程序外,在 bison 操作中使用 yylval
很少有用。
即使在您修复该问题之后,您仍会发现语义值不正确,因为您的 flex 操作正在转发指向内部数据缓冲区的指针,而不是复制 token 字符串。参见,例如,this question .
关于c - 函数声明的生产规则中 yytext 的意外值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576238/