2013-11-20 71 views
4

我对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标准。 –

回答

6

它的警告,而不是一个错误,所以你应该罚款,如果你忽略它。但如果你真的想摆脱的警告,您可以添加

%{ 
int yylex(); 
%} 

.y文件

+0

如果您使用的是重入式解析器,那么这将不起作用,而yylex具有'YYSTYPE *'参数。该文件中的YYSTYPE类型在这一点上是未知的。你应该做这个'int yylex(void)',避免使用ANSI之前的非原型语法。 – Kaz

+0

如果你使用byacc(Berkeley Yacc),你可以在最后一节'%%'后面的语法之后放置声明,并且一切都很酷:生成的解析器仍然在该范围内。这在Bison中不起作用。 – Kaz

+0

@Kaz:野牛和伯克利yacc不需要任何东西,因为它们在尝试使用它之前正确地声明了yylex(并且包含所有相关的可重入内容,如果使用的话)。你只需要添加一个假定隐式声明的AT&T yacc古老版本的声明。 –

6

这里的顶部是一个答案,一个更复杂的版本,这个问题是不容易只需添加一个声明即可解决。

GNU Bison支持生成与Flex一起工作的重入式分析器(使用Flex的%option bison-bridge re-entrant)。伯克利Yacc提供了兼容的实现。

这里是关于如何解决这两个解析器生成器的未声明的yylex的指南。

随着重入,“野牛桥”词法分析器的yylex声明变成这样:

int yylex(YYSTYPE *yylval, void *scanner); 

如果你把这个原型在你的Yacc解析器的%{ ... %}最初的标题部分,并生成解析器与Bison或Berkeley Yacc,编译器会抱怨YYSTYPE未被声明。

您不能简单地创建YYSTYPE的前向声明,因为在Berkeley Yacc中,它没有联合标记。在野牛,这是typedef union YYSTYPE { ... } YYSTYPE,但在伯克利Yacc它是typedef { ... } YYSTYPE:没有标签。

但是,在Berkeley Yacc中,如果您在解析器的第三部分中声明了一个声明,则它在yylex调用的范围内!因此,对于伯克利YACC了以下工作:

%{ 
/* includes, C defs */ 
%} 

/* Yacc defs */ 

%% 

/* Yacc grammar */ 

%% 

int yylex(YYSTYPE *, void *); 

/* code */ 

如果这与野牛产生,问题仍然存在:存在于yylex通话的范围没有原型。

这个小补丁,使其成为GNU野牛工作:

%{ 
/* includes, C defs */ 

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

%} 

/* Yacc defs */ 

%% 

/* Yacc grammar */ 

%% 

int yylex(YYSTYPE *, void *); 

/* code */ 

你去那里。