函数声明的生产规则中 yytext 的意外值
Unexpected value in yytext in production rule for function declaration
我正在为一项大学作业编写一个带有 flex 和 bison 的编译器。我在向我的符号 table 添加函数标识符时遇到问题 - 在评估函数声明时,我在 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;
}
...
在我的 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
,它为我的符号table添加了一个标识符。解析以下程序时:
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
。上面的代码是原因吗?我有一些尚未解决的 shift/reduce 冲突,我想这可能是错误的,但我不知道在这种特定情况下如何。我相信我错过了一些非常基本的东西,但我看不到什么。目前该项目非常大(可耻地杂乱无章),但如果需要,我可以提供一个完整且可重现的示例。
基本问题是您在 new_identifier_with_node
生产中使用 yylval
,而不是 </code>。 <code>
是产生式中第一个符号的语义值,在本例中为 TK_IDENTIFIER
。
在bison action中,yylval
通常是lookahead token的值,也就是输入流中的next token。这就是为什么它在这种情况下显示为括号的原因。但是您通常不能指望这一点,因为野牛会在读取前瞻标记之前执行默认缩减。通常,除了错误恢复中的某些应用程序外,在 bison 操作中使用 yylval
很少有用。
即使在您修复该问题之后,您仍会发现语义值不正确,因为您的 flex 操作正在转发指向内部数据缓冲区的指针,而不是复制令牌字符串。例如,参见 this question.
我正在为一项大学作业编写一个带有 flex 和 bison 的编译器。我在向我的符号 table 添加函数标识符时遇到问题 - 在评估函数声明时,我在 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;
}
...
在我的 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
,它为我的符号table添加了一个标识符。解析以下程序时:
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
。上面的代码是原因吗?我有一些尚未解决的 shift/reduce 冲突,我想这可能是错误的,但我不知道在这种特定情况下如何。我相信我错过了一些非常基本的东西,但我看不到什么。目前该项目非常大(可耻地杂乱无章),但如果需要,我可以提供一个完整且可重现的示例。
基本问题是您在 new_identifier_with_node
生产中使用 yylval
,而不是 </code>。 <code>
是产生式中第一个符号的语义值,在本例中为 TK_IDENTIFIER
。
在bison action中,yylval
通常是lookahead token的值,也就是输入流中的next token。这就是为什么它在这种情况下显示为括号的原因。但是您通常不能指望这一点,因为野牛会在读取前瞻标记之前执行默认缩减。通常,除了错误恢复中的某些应用程序外,在 bison 操作中使用 yylval
很少有用。
即使在您修复该问题之后,您仍会发现语义值不正确,因为您的 flex 操作正在转发指向内部数据缓冲区的指针,而不是复制令牌字符串。例如,参见 this question.