Problems with reentrant Flex and Bison

I am learning how to use reusable Bison and Flex together. I already have a simple calculator that works without the possibility of re-entry. However, when I activated the re-function and made the necessary changes, I could not get this to work.

Here is the code:

scanner.l

%{ #include <stdio.h> #include "parser.tab.h" %} %option 8bit reentrant bison-bridge %option warn noyywrap nodefault %option header-file="lex.yy.h" DIGIT [0-9] %% "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } "/" { return DIV; } {DIGIT}+ { *yylval = atof(yytext); return NUM; } \n { return EOL; } [ \t] { } . { printf("What is this: %s.\n", yytext); } %% 

parser.y

 %{ #include <stdio.h> #include "lex.yy.h" void yyerror(yyscan_t scanner, char const *msg); %} %define api.value.type {double} %define parse.error verbose %define api.pure %lex-param {yyscan_t scanner} %parse-param {yyscan_t scanner} %token NUM EOL %left ADD SUB %left MUL DIV %% input: %empty | input line ; line: EOL { printf("|> ");} | exp EOL { printf("|R> %.4lf\n", $exp); } ; exp: NUM { $$ = $1; } | exp ADD exp { $$ = $1 + $3; } | exp SUB exp { $$ = $1 - $3; } | exp MUL exp { $$ = $1 * $3; } | exp DIV exp { $$ = $1 / $3; } ; %% void yyerror(yyscan_t scanner, char const *msg) { fprintf(stderr, "Error: %s\n", msg); } 

main.c

 #include <stdio.h> #include "parser.tab.h" #include "lex.yy.h" int main(void) { yyscan_t scanner; yylex_init(&scanner); yyset_in(stdin, scanner); yyparse(scanner); yylex_destroy(scanner); return 0; } 

and this is the Makefile I use:

 all: calc.x parser.tab.c parser.tab.h: parser.y bison -d parser.y lex.yy.c lex.yy.h: scanner.l parser.tab.h flex scanner.l calc.x: lex.yy.c lex.yy.h parser.tab.c parser.tab.h gcc main.c parser.tab.c lex.yy.c -o calc.x clean: rm calc.x lex.yy.c lex.yy.h parser.tab.c parser.tab.h *.o 

Running make , I got the following error:

 In file included from main.c:2:0: parser.tab.h:66:14: error: unknown type name 'yyscan_t' int yyparse (yyscan_t scanner); ^ main.c: In function 'main': main.c:12:3: warning: implicit declaration of function 'yyparse' [-Wimplicit-function-declaration] yyparse(scanner); ^ In file included from parser.y:5:0: lex.yy.h:282:1: error: unknown type name 'YYSTYPE' YYSTYPE * yyget_lval (yyscan_t yyscanner ); ^ lex.yy.h:284:18: error: unknown type name 'YYSTYPE' void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); ^ lex.yy.h:332:17: error: unknown type name 'YYSTYPE' (YYSTYPE * yylval_param ,yyscan_t yyscanner); ^ parser.tab.c: In function 'yyparse': parser.tab.c:1130:16: warning: implicit declaration of function 'yylex' [-Wimplicit-function-declaration] yychar = yylex (&yylval, scanner); ^ Makefile:10: recipe for target 'calc.x' failed make: *** [calc.x] Error 1 

But I do not understand the origin of this error and warning messages, for example:

 main.c:12:3: warning: implicit declaration of function 'yyparse' 

But yyparse already defined in parser.tab.h and it is included in main.c Another example:

 parser.tab.h:66:14: error: unknown type name 'yyscan_t' 

And inside parser.y , I include the lex.yy.h scanner lex.yy.h .

I found these solutions online:

But none of them work, which leads to similar errors. If someone can guide me on this quest, I will be grateful.

Software version

OS: Debian (testing), Bison: 3.0.4, Flex: 2.5.39, GCC: 5.2.1, Make: 4.0.

+5
source share
2 answers

I immediately found a solution. Thus, problems arise due to the circular relationship between the flexible and the bison.

The parser generated the flex call procedure this way:

 yychar = yylex (&yylval, scanner); 

So, in the input of the bison, we must include the header file of the scanner lex.yy.h and it is defined as:

 int yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner); 

But YYSTYPE defined inside the parser.tab.h parser parser.tab.h , in my case I told the bison that my type would be double :

 typedef double YYSTYPE; 

Now the decision. Inside scanner.l you must include parser headers so that flex can return the correct tokens (nothing has changed).

But inside parser.y you have to include both header files, if you only include lex.yy.h , it will complain:

 lex.yy.h:282:1: error: unknown type name 'YYSTYPE' 

because YYSTYPE is defined inside parser.tab.h . And finally, for some reason, the bison parser does not know that yyscan_t even including the lexer header:

 error: unknown type name 'yyscan_t' 

One solution goes around it with void:

 %lex-param {void *scanner} %parse-param {void *scanner} 

see yyscan_t definition: flex yyscan_t

So here is the final result:

scanner.l

 %{ #include <stdio.h> #include "parser.tab.h" %} %option 8bit reentrant bison-bridge %option warn noyywrap nodefault %option header-file="lex.yy.h" //rest of the scanner 

parser.y

 %{ #include <stdio.h> #include "parser.tab.h" #include "lex.yy.h" void yyerror(yyscan_t scanner, char const *msg); %} %define api.value.type {double} %define parse.error verbose %define api.pure %lex-param {void *scanner} %parse-param {void *scanner} //rest of the input 

main.c

 #include <stdio.h> #include "parser.tab.h" #include "lex.yy.h" int main(void) { yyscan_t scanner; yylex_init(&scanner); yyset_in(stdin, scanner); yyparse(scanner); yylex_destroy(scanner); return 0; } 
+4
source

The accepted answer of Fabricio Sanches helped me solve two problems:

  • error: unknown type name 'yyscan_t' really resolved by changing to void * .

  • Conflicts associated with circular dependencies determine a very strict import order :

Your code calling Flex / Bison yyparse is:

 #import "parser.h" #import "lexer.h" 

Flex (Lexer.lm):

 %{ #import "parser.h" %} 

Bison (Parser.ym):

 %{ #import "parser.h" #import "lexer.h" %} 

I wrote a blog post about the process of creating a reentrant parser using Flex and Bison on Mac OS with an example of its integration into the Xcode project: Reenter parser using Flex and Bison .

0
source

All Articles