Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple yacc grammars give an error

Tags:

yacc

I have a question for yacc compiler. I do not compile simple yacc grammar. Here is the code section :

/*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);

I use mac os x and, i try yo command; $ yacc anbn_0.y and then $ gcc -o anbn_0 y.tab.c -ll and give me error. Here is the error ;

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

Why do I get an error ?

like image 231
tilt_y Avatar asked Nov 20 '13 20:11

tilt_y


2 Answers

Its a warning, not an error, so you should be fine if you ignore it. But if you really want to get rid of the warning, you could add

%{
int yylex();
%}

to the top of your .y file

like image 194
Chris Dodd Avatar answered Oct 23 '22 03:10

Chris Dodd


Here is an answer to a more sophisticated version of this problem which isn't easily solved just by adding a declaration.

GNU Bison supports the generation of re-entrant parsers which work together with Flex (using Flex's %option bison-bridge re-entrant). Berkeley Yacc provides a compatible implementation.

Here is a guide on how to solve this undeclared yylex for both parser generators.

With a re-entrant, "Bison bridged" lexer, the declaration of yylex turns into this:

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

If you place this prototype in the %{ ... %} initial header section of your Yacc parser, and generate the parser with either Bison or Berkeley Yacc, the compiler will complain that YYSTYPE is not declared.

You cannot simply create a forward declaration for YYSTYPE, because in Berkeley Yacc, it does not have a union tag. In Bison, it is typedef union YYSTYPE { ... } YYSTYPE, but in Berkeley Yacc it is typedef { ... } YYSTYPE: no tag.

But, in Berkeley Yacc, if you put a declaration in the third section of the parser, it is in scope of the yylex call! So the following works for Berkeley yacc:

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

/* Yacc defs */

%%

/* Yacc grammar */

%%

int yylex(YYSTYPE *, void *);

/* code */

If this is generated with Bison, the problem persists: there is no prototype in scope of the yylex call.

This little fix makes it work for GNU Bison:

%{
/* includes, C defs */

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

%}

/* Yacc defs */

%%

/* Yacc grammar */

%%

int yylex(YYSTYPE *, void *);

/* code */

There you go.

like image 30
Kaz Avatar answered Oct 23 '22 05:10

Kaz