Problems with reentrant Flex and Bison

丶灬走出姿态 提交于 2019-12-04 06:09:19
Fabricio

I found a solution after tinkering a bit. So the problems arise from a circular dependency between flex and bison.

The parser generated call flex routine in this way:

yychar = yylex (&yylval, scanner);

So in the bison input we must include the scanner header file lex.yy.h and it's define as:

int yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner);

But YYSTYPE is defined inside the parser header parser.tab.h, in my case i said to bison that my type will be double:

typedef double YYSTYPE;

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

But inside the parser.y you must include both headers file, if you include only the 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 doesn't know what yyscan_t even including the lexer header:

error: unknown type name ‘yyscan_t’

One workaround is defining it to 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;
}

Accepted answer by Fabricio Sanches helped me to resolve two issues:

  1. error: unknown type name ‘yyscan_t’ has indeed been solved by changing to void *.

  2. Conflicts related to circular dependencies dictate very strict order of imports:

Your code where Flex/Bison's yyparse is called:

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

Flex (Lexer.lm):

%{
#import "parser.h"
%}

Bison (Parser.ym):

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

I have written blog post about the process of creation of reentrant parser using Flex and Bison on Mac OS with example of its integration to Xcode project: Reentrant parser using Flex and Bison.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!