我正在编写带有flex和bison的编译器以进行大学作业。我在向符号表添加函数标识符时遇到了麻烦-在评估函数声明时,我在yytext
中得到了期望的标识符的括号。在我的flex文件中,其中yylval
是一个联合,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;
}
...
而且在我的野牛文件中,我有:
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
,正如我所期望的那样。代码是否高于原因?我仍然有一些尚未解决的转移/减少冲突,我认为这可能是错误的,但是我看不出在这种特定情况下的情况。我相信我缺少真正基本的东西,但是我看不到。这时该项目很大(可耻地混乱了),但是如果需要,我可以提供一个完整且可复制的示例。
基本问题是您正在yylval
生产中使用new_identifier_with_node
,而不是$1
。 $1
是生产中第一个符号的语义值,在这种情况下为TK_IDENTIFIER
。
在野牛动作中,yylval
通常是超前标记的值,即输入流中的next标记。这就是在这种情况下它显示为括号的原因。但是您通常不能指望这一点,因为野牛会在读取先行标记之前执行默认还原。通常,除错误恢复中的某些应用程序外,在野牛操作中使用yylval
很少有用。
即使在解决此问题之后,您仍会发现语义值不正确,因为您的flex操作正在将指针转发到内部数据缓冲区,而不是复制令牌字符串。参见,例如,this question。