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

标签 c compiler-construction bison flex-lexer

我正在为一项大学作业编写一个带有 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/

相关文章:

c - 读取和写入管道 c 问题

java - 如何从命令提示符编译 servlet?

c - 关于 Flex、Bison 和 Segmentation Fault

linux - 编译错误 : No suitable bison/yacc found

c++ - CvCapture结构和VideoCapture结构有什么区别?

c - 释放分配给 char* (由 `malloc` 分配)的 int* 是否会调用未定义的行为?

c - 常量 C 表达式是在编译时还是在运行时求值?

parsing - 为什么我的三元运算符会导致移位减少冲突?

parsing - 分号作为由 flex/bison 解析的自定义语法中的分隔符

c - 如何从 PCM 获取缓冲区?