简单的yacc语法出现了错误。

8
我有一个关于yacc编译器的问题。我无法编译简单的yacc语法。以下是代码部分:

我有一个关于yacc编译器的问题。我无法编译简单的yacc语法。以下是代码部分:

/*anbn_0.y */
%token A B
%%
start: anbn '\n' {printf(" is in anbn_0\n");
return 0;}
anbn: empty
| A anbn B
;
empty: ;
%%
#include "lex.yy.c"
yyerror(s)
char *s;
{ printf("%s, it is not in anbn_0\n", s);

我使用的是 Mac OS X 操作系统,我尝试执行以下命令:

$ yacc anbn_0.y

然后执行

$ gcc -o anbn_0 y.tab.c -ll

但是出现了错误,下面是错误信息:

warning: implicit declaration of function 'yylex' is invalid in C99 [-Wimplicit-function-declaration]
      yychar = YYLEX;

为什么会出现错误?

2
你没有收到错误 -- 那只是一个警告。这很容易理解 -- 你正在运行的yacc版本生成的代码遵循旧的C89标准(甚至更早),而不是较新的C99标准。 - Chris Dodd
2个回答

17

这只是一个警告,不是错误,如果您忽略它,应该没事。但是如果您真的想消除警告,您可以添加

%{
int yylex();
%}

将其添加至你的.y文件的顶部


如果您正在使用可重入解析器且 yylex 具有 YYSTYPE * 参数,则无法正常工作。在文件的该点上,YYSTYPE 类型未知。您应该将其更改为 int yylex(void),避免使用 pre-ANSI 非原型语法。 - Kaz
如果您使用byacc(伯克利Yacc),则可以将声明放在最后一个%%后的最后一节语法之后,一切都很好:生成的解析器仍然在该范围内。这在Bison中不起作用。 - Kaz
@Kaz:在Bison和Berkeley Yacc中不需要任何东西,因为它们在尝试使用yylex之前会在骨架中正确声明它(如果您正在使用可重入的相关内容,则包括所有相关内容)。您只需要为古老版本的AT&T Yacc添加一个声明,以假定隐式声明。 - Chris Dodd
1
我最近使用Bison 2.5和Byacc 1.9 20110908的经验告诉我不同的事情。它们都没有在y.tab.c中添加任何yylex声明。也许新版本的工具做事情有所不同。我注意到Bison 3.x(我在Solaris机器上安装了一个版本)在y.tab.h中声明了yyparse,而2.5没有这样做。下次我在那台机器上工作时,我会寻找yylex - Kaz
同样的问题,我正在使用bison 3.3.2,.tab.c.tab.h文件都没有声明yylex函数。这个版本是2019年的,所以它不声明该函数的原因是什么? - xdavidliu

11

这里是对一个更为复杂的版本的问题的答案,该问题不容易通过添加声明语句来解决。

GNU Bison支持生成与Flex协同工作的可重入解析器(使用Flex的%option bison-bridge re-entrant)。Berkeley Yacc提供了兼容的实现。

以下是如何解决这个问题的指南,适用于两种解析器生成器。

使用可重入、Bison桥接的词法分析器时,yylex的声明变成了这样:

int yylex(YYSTYPE *yylval, void *scanner);
如果你把这个原型放在Yacc解析器的%{ ... %}初始头部分,并使用Bison或Berkeley Yacc生成解析器,编译器会报错YYSTYPE未声明。
你不能简单地为YYSTYPE创建一个前向声明,因为在Berkeley Yacc中它没有联合标签。在Bison中,它是typedef union YYSTYPE { ... } YYSTYPE,但在Berkeley Yacc中,它是typedef { ... } YYSTYPE:没有标签。
但是,在Berkeley Yacc中,如果您将声明放在解析器的第三部分中,它就在yylex调用的范围内!所以以下内容适用于Berkeley yacc:
%{
/* includes, C defs */
%}

/* Yacc defs */

%%

/* Yacc grammar */

%%

int yylex(YYSTYPE *, void *);

/* code */

如果这是由Bison生成的,则问题仍然存在:在yylex调用范围内没有原型。

这个小修复程序让GNU Bison可以工作:

%{
/* includes, C defs */

#if YYBISON
union YYSTYPE;
int yylex(union YYSTYPE *, void *);
#endif

%}

/* Yacc defs */

%%

/* Yacc grammar */

%%

int yylex(YYSTYPE *, void *);

/* code */

就是这样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接