函数声明的生产规则中 yytext 的意外值

Unexpected value in yytext in production rule for function declaration

我正在为一项大学作业编写一个带有 flex 和 bison 的编译器。我在向我的符号 table 添加函数标识符时遇到问题 - 在评估函数声明时,我在 yytext 中得到了我期望标识符的左括号。在我的 flex 文件中,yylval 是联合,vlexstruct:

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.