我对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,我试试yo命令;
$ 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;
为什么会出错?
答案 0 :(得分:9)
它是一个警告,而不是一个错误,所以如果你忽略它你应该没事。但如果你真的想摆脱警告,你可以添加
%{
int yylex();
%}
到.y
文件的顶部
答案 1 :(得分:8)
这是对这个问题的更复杂版本的答案,仅通过添加声明就不容易解决。
GNU Bison支持生成与Flex一起使用的重入解析器(使用Flex的%option bison-bridge re-entrant
)。 Berkeley Yacc提供兼容的实现。
以下是有关如何为两个解析器生成器解决此未声明yylex
的指南。
对于一个可重入的“Bison桥接”词法分子,yylex
的声明变成了这个:
int yylex(YYSTYPE *yylval, void *scanner);
如果将此原型放在Yacc解析器的%{ ... %}
初始标题部分中,并使用Bison或Berkeley Yacc生成解析器,编译器会抱怨未声明YYSTYPE
。
您不能简单地为YYSTYPE
创建前向声明,因为在Berkeley Yacc中,它没有union标记。在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 */
你去。