为什么我不能在 yyerror (Yacc) 中使用 yytext

Why can't I use yytext inside yyerror (Yacc)

我的分析仪有点问题。 I.m 试图在我的 yyerror 中使用 yytext 但它向我显示此错误,你能帮我吗?

您不能在解析器中使用 yytext,因为它是由词法分析器定义的。

事实上,您通常不应该在解析器中使用 yytext,因为它的值对解析没有意义。您尝试使用它来提供错误消息中的上下文几乎是唯一合理的用途,即使这样也存在一定的歧义,因为您无法判断错误标记是当前 yytext 中的标记还是之前的标记令牌,当解析器获得其先行令牌时被覆盖。

无论如何,如果你想在你的解析器中引用 yytext,你需要声明它,这通常需要把

extern char* yytext;

进入你的 bison 语法文件。由于唯一可以合理使用 yytext 的地方是 yyerror,您可以将该函数的定义更改为:

void yyerror(const char* msg) {
  extern char* yytext;
  fprintf(stderr, "%s at line %d near '%s'\n", msg, nLineas, yytext);
}

请注意,您可以让 flex 自动跟踪行号,因此您不需要跟踪自己的 nLineas 变量。只需添加

%option yylineno

在你的 flex 文件的顶部,全局变量 yylineno 将在词法分析期间自动维护。如果你想在你的解析器中使用 yylineno,你还需要为它添加一个 extern 声明:

extern int yylineno;

同样,在解析器中使用 yylineno 可能不精确,因为它可能引用错误后标记的行号,它可能与错误位于不同的行(甚至可能被分开来自多行评论的错误)。


作为使用 yytextyylineno 的外部声明的替代方法,您可以自由地将 yyerror 的实现放在扫描器定义中而不是语法定义中。你的语法文件应该已经有一个yyerror的前向声明,所以它放在哪个文件中并不重要。如果你把它放在扫描器文件中,全局扫描器变量已经被声明了。