折返Flex和Bison问题 [英] Problems with reentrant Flex and Bison

查看:201
本文介绍了折返Flex和Bison问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm learning how to use reentrant Bison and Flex together. I already got a simple calculator working without the reentrant capability. However when I activated the reentrant feature and made the necessary modifications, I couldn't get this to work.

这是代码:

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

这是我正在使用的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,出现以下错误:

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 don't understand the origin of this error and warning messages, for instance:

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

但是yyparse已在parser.tab.h中定义,并且已包含在main.c中.另一个例子:

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

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

parser.y中,我包括了扫描仪头lex.yy.h.

And inside parser.y, I'm including the scanner header lex.yy.h.

我已经在Internet上找到了这些解决方案:

I have found these solutions on the Internet:

  • Configuring Bison and Flex without global or static variable
  • Reentrant parsers with Flex and Bison
  • Make a reentrant parser with Flex and Bison
  • Writing re-entrant lexer with Flex
  • Implementing re-entrant parsers in Bison and Flex

但是它们都不起作用,从而导致类似的错误.如果有人可以指导我完成这项任务,我将不胜感激.

But none of them work, resulting in similar errors. If someone could guide me in this quest I'll be grateful.

软件版本

OS:Debian(测试中),Bison:3.0.4,Flex:2.5.39,GCC:5.2.1,Make:4.0.

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

推荐答案

我稍加修改便找到了解决方案.因此,问题来自flex和bison之间的循环依赖.

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

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

The parser generated call flex routine in this way:

yychar = yylex (&yylval, scanner);

因此在野牛输入中,我们必须包括扫描仪头文件lex.yy.h 它的定义为:

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

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

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;

现在解决.在scanner.l内部,必须包含解析器标头,以便flex可以返回正确的令牌(未做任何更改).

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

但是在parser.y内部,您必须同时包含两个头文件,如果仅包含lex.yy.h,则会报错:

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‘

因为YYSTYPE是在parser.tab.h内部定义的.最后,由于某种原因,野牛解析器甚至不知道yyscan_t是什么,甚至包括词法分析器标头:

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}

请参见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;
}

这篇关于折返Flex和Bison问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆