2013-11-20 100 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 */ 

你去那裏。