配置Bison和Flex没有全局变量或静态变量。

时间:2022-10-26 09:42:11

i am working in a small language/IDE. And I need to know how to configure flex and bison to work together but without using any global or static variable. I need to pass to bison my AST pointer. I also need that bison pass my AST to flex as well. It's a thread environment but i dont need any thread sync. And I need a separete yylineno variable for each yyparse() call. I read about %define api.pure , %parse-param and %option reentrant. But i don't know how to put them to work together... thx in advance...

我用的是一种小型语言/IDE。我需要知道如何配置flex和bison一起工作,但不需要使用任何全局或静态变量。我需要传给bison我的AST指针。我还需要那个bison把我的AST传递给flex。这是一个线程环境,但我不需要任何线程同步。每个yyparse()调用都需要一个独立的yylineno变量。我阅读了大约%define api。纯的,%parse-param和%option reentrant。但是我不知道如何让他们一起工作……提前谢谢…

I tried this:

我试着这样的:

scanner.l:

scanner.l:

%{

#include <iostream>
#include <sstream>
#include "parser.tab.h"
#define YY_DECL extern "C" int yylex(YYSTYPE * lvalp, yyscan_t scanner)
extern void yyerror(yyscan_t scanner, NBloco * bloco, const char *s);

%}

%option noyywrap
%option yylineno
%option reentrant 
%option bison-bridge

%%
//...scanner code

parser.y:

parser.y:

%{
#include <iostream>
#include "AST.h"

#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif

extern "C" int yylex(YYSTYPE * lvalp, yyscan_t scanner);
extern "C" FILE *yyin;
extern int yylineno;
void yyerror(yyscan_t scanner, NBloco * bloco, const char *s);
%}

%union{ 
//union code
}

%define api.pure full
%lex-param   { yyscan_t scanner }
%parse-param { yyscan_t scanner }
%parse-param { NBlock* block}

//tokens...
//types...

%%

//parser code...

And I got this:

我得到了这个:

parser.y:13:22: warning: 'yylex' initialized and declared 'extern' [enabled by default] extern "C" int yylex(YYSTYPE * lvalp, yyscan_t scanner);


parser.y:13:22: error: 'YYSTYPE' was not declared in this scope


parser.y:13:32: error: 'lvalp' was not declared in this scope extern "C" int yylex(YYSTYPE * lvalp, yyscan_t scanner);


parser.y:13:48: error: expected primary-expression before 'scanner'
 extern "C" int yylex(YYSTYPE * lvalp, yyscan_t scanner);

                                            ^
parser.y:13:55: error: expression list treated as compound expression in initializer [-fpermissive]
 extern "C" int yylex(YYSTYPE * lvalp, yyscan_t scanner);

                                                   ^
parser.tab.c: In function 'int yyparse(yyscan_t, NBloco*)':
parser.tab.c:932:39: error: 'yylex' cannot be used as a function
 # define YYLEX yylex (&yylval, scanner)


parser.tab.c:1618:16: note: in expansion of macro 'YYLEX'
       yychar = YYLEX;

// more errors...

/ /更多的错误……

I also to fix the yylineno to be per file... i am basing on http://benlynn.blogspot.com.br/2013/12/reentrant-parsers-with-flex-and-bison.html and http://www.lemoda.net/c/reentrant-parser/index.html

我也要把yylineno的文件固定在每个文件上…我的基础是http://benlynn.blogspot.com.br/2013/12/reentrant-parsers-with-flex- bison.html和http://www.lemoda.net/c/reentrant-parser/index.html。

1 个解决方案

#1


15  

First, here's a C reentrant flex parser and pure bison example that parses a grammar that matches the following:

首先,这里有一个C reentrant flex解析器和纯bison示例,它解析了与以下内容匹配的语法:

()
(())
(()())

()()(())()()

lexer.l

%option bison-bridge
%option bison-locations
%option ecs
%option nodefault
%option noyywrap
%option reentrant
%option stack
%option warn
%option yylineno

%{
  #include "parser.h"
%}

%%

"(" { return (LPAREN); }
")" { return (RPAREN); }

[ \f\r\t\v\n]+ /* eat whitespace */

%%

/* don't use lexer.l for code, organize it logically elsewhere */

parser.y

%define parse.error verbose
%define api.pure true
%locations
%token-table
%glr-parser
%lex-param {void *scanner}
%parse-param {void *scanner}

%{
/* your top code here */
%}

%union {
  int value; // or whatever else here
}

%token LPAREN
%token RPAREN

%%

document
    : exprs

exprs
    : %empty
    | expr exprs

expr
    : parens

parens
    : LPAREN exprs RPAREN


%%

int
yyerror(YYLTYPE *locp, char *msg) {
  if (locp) {
    fprintf(stderr, "parse error: %s (:%d.%d -> :%d.%d)\n",
                    msg,
                    locp->first_line, locp->first_column,
                    locp->last_line,  locp->last_column
    );
    /* todo: add some fancy ^^^^^ error handling here */
  } else {
    fprintf(stderr, "parse error: %s\n", msg);
  }
  return (0);
}

main.c

#include "parser.h"
#include "lexer.h"

int
main(int argc, char **argv) {
  int result;
  yyscan_t scanner;

  yylex_init(&scanner);
  result = (yyparse(scanner));
  yylex_destroy(scanner);
  return (result);
}

Building

flex --header-file=lexer.h --outfile=lexer.c lexer.l
bison --output-file=parser.c --defines=parser.h --warnings=all --feature=all parser.y
cc lexer.c parser.c main.c -o parser
./parser

Note: OSX's built-in bison is outdated, so install 3.x:

注:OSX内置的bison已经过时,安装3.x:

brew install bison

And then run it like /usr/local/opt/bison/bin/bison ....

然后运行它像/usr/local/opt/bison/bin/bison ....

Now, to migrate to C++

  • copy .l to .lxx and .y to .yxx
  • 复制。l到。lxx和。y到。yxx。
  • change names for output files to *.cxx and *.hxx respectively.
  • 将输出文件的名称更改为*。cxx和*。hxx分别。

lexer.lxx

  • add %option c++
  • 添加%选项c + +
  • remove reentrant, bison-bridge and bison-locations
  • 删除重入者、bison-bridge和bison-location。
  • change all tokens like the following: LPAREN to yy::parser::token::LPAREN
  • 将所有令牌更改如下:LPAREN到yy::解析器::令牌::LPAREN。

parser.yxx

  • add %skeleton "lalr1.cc"
  • 添加%骨架“lalr1.cc”
  • remove api.pure
  • 删除api.pure
  • remove yyerror
  • 删除yyerror

main.cxx

  • rewrite it for C++
  • 为c++重写它

Hooking up the lexer and parser objects is an exercise for the reader.

连接lexer和解析器对象是读者的练习。

See also: https://github.com/bingmann/flex-bison-cpp-example but beware it uses the old bison 2.x interfaces.

参见:https://github.com/bingmann/flex-bison-cpp-example,但要注意它使用了老的bison 2。x接口。

GNU Bison 3.x C++ Example docs

GNU野牛3。x c++文档示例

#1


15  

First, here's a C reentrant flex parser and pure bison example that parses a grammar that matches the following:

首先,这里有一个C reentrant flex解析器和纯bison示例,它解析了与以下内容匹配的语法:

()
(())
(()())

()()(())()()

lexer.l

%option bison-bridge
%option bison-locations
%option ecs
%option nodefault
%option noyywrap
%option reentrant
%option stack
%option warn
%option yylineno

%{
  #include "parser.h"
%}

%%

"(" { return (LPAREN); }
")" { return (RPAREN); }

[ \f\r\t\v\n]+ /* eat whitespace */

%%

/* don't use lexer.l for code, organize it logically elsewhere */

parser.y

%define parse.error verbose
%define api.pure true
%locations
%token-table
%glr-parser
%lex-param {void *scanner}
%parse-param {void *scanner}

%{
/* your top code here */
%}

%union {
  int value; // or whatever else here
}

%token LPAREN
%token RPAREN

%%

document
    : exprs

exprs
    : %empty
    | expr exprs

expr
    : parens

parens
    : LPAREN exprs RPAREN


%%

int
yyerror(YYLTYPE *locp, char *msg) {
  if (locp) {
    fprintf(stderr, "parse error: %s (:%d.%d -> :%d.%d)\n",
                    msg,
                    locp->first_line, locp->first_column,
                    locp->last_line,  locp->last_column
    );
    /* todo: add some fancy ^^^^^ error handling here */
  } else {
    fprintf(stderr, "parse error: %s\n", msg);
  }
  return (0);
}

main.c

#include "parser.h"
#include "lexer.h"

int
main(int argc, char **argv) {
  int result;
  yyscan_t scanner;

  yylex_init(&scanner);
  result = (yyparse(scanner));
  yylex_destroy(scanner);
  return (result);
}

Building

flex --header-file=lexer.h --outfile=lexer.c lexer.l
bison --output-file=parser.c --defines=parser.h --warnings=all --feature=all parser.y
cc lexer.c parser.c main.c -o parser
./parser

Note: OSX's built-in bison is outdated, so install 3.x:

注:OSX内置的bison已经过时,安装3.x:

brew install bison

And then run it like /usr/local/opt/bison/bin/bison ....

然后运行它像/usr/local/opt/bison/bin/bison ....

Now, to migrate to C++

  • copy .l to .lxx and .y to .yxx
  • 复制。l到。lxx和。y到。yxx。
  • change names for output files to *.cxx and *.hxx respectively.
  • 将输出文件的名称更改为*。cxx和*。hxx分别。

lexer.lxx

  • add %option c++
  • 添加%选项c + +
  • remove reentrant, bison-bridge and bison-locations
  • 删除重入者、bison-bridge和bison-location。
  • change all tokens like the following: LPAREN to yy::parser::token::LPAREN
  • 将所有令牌更改如下:LPAREN到yy::解析器::令牌::LPAREN。

parser.yxx

  • add %skeleton "lalr1.cc"
  • 添加%骨架“lalr1.cc”
  • remove api.pure
  • 删除api.pure
  • remove yyerror
  • 删除yyerror

main.cxx

  • rewrite it for C++
  • 为c++重写它

Hooking up the lexer and parser objects is an exercise for the reader.

连接lexer和解析器对象是读者的练习。

See also: https://github.com/bingmann/flex-bison-cpp-example but beware it uses the old bison 2.x interfaces.

参见:https://github.com/bingmann/flex-bison-cpp-example,但要注意它使用了老的bison 2。x接口。

GNU Bison 3.x C++ Example docs

GNU野牛3。x c++文档示例