可重入Flex和Bison的问题

我正在学习如何一起使用折返Bison和Flex。 我已经有了一个简单的计算器,没有重入功能。 但是,当我激活重入特性并进行必要的修改时,我无法使其工作。

代码如下:

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> %.4lfn", $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: %sn", 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;
}

这是我正在使用的Makefile

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

运行make ,我得到了以下错误:

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

但是我不明白这个错误和警告信息的来源,例如:

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

但是yyparse已经在parser.tab.h定义了,它被包含在main.c 。 另一个例子:

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

parser.y ,我包含了扫描头lex.yy.h

我在互联网上找到了这些解决方案:

  • 配置没有全局或静态变量的Bison和Flex
  • Flex和Bison的可重入解析器
  • 用Flex和Bison制作一个可重入的解析器
  • 使用Flex编写重入词法分析器
  • 在Bison和Flex中实现重入式解析器
  • 但是他们都没有工作,导致类似的错误。 如果有人能够在这个任务中指导我,我会很感激。

    软件版本

    操作系统:Debian(测试),Bison:3.0.4,Flex:2.5.39,GCC:5.2.1,Make:4.0。


    我修改了一下后找到了一个解决方案。 所以问题来自flex和野牛之间的循环依赖。

    解析器以这种方式生成调用flex例程:

    yychar = yylex (&yylval, scanner);
    

    所以在野牛输入中,我们必须包含扫描头文件lex.yy.h ,它的定义如下:

    int yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner);
    

    YYSTYPE是在解析器头文件parser.tab.h定义的,在我的情况下,我对野牛说我的类型是double

    typedef double YYSTYPE;
    

    现在解决方案。 在scanner.l内部,您必须包含解析器头文件,以便flex可以返回正确的标记(没有任何更改)。

    但是在parser.y你必须包含两个头文件,如果你只包含lex.yy.h它会抱怨:

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

    因为YYSTYPE是在parser.tab.h定义的。 最后,出于某种原因,野牛分析器甚至不知道yyscan_t甚至包括词法分析器头文件:

    error: unknown type name ‘yyscan_t’
    

    一种解决方法是将其定义为void:

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

    请参阅yyscan_t定义:flex yyscan_t

    所以这是最后的结果:

    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;
    }
    

    链接地址: http://www.djcxy.com/p/41747.html

    上一篇: Problems with reentrant Flex and Bison

    下一篇: Flex & Bison Segmenation fault