配置没有全局或静态变量的Bison和Flex [英] Configuring Bison and Flex without global or static variable
问题描述
我使用小语言/ IDE。我需要知道如何配置flex和bison一起工作,但不使用任何全局或静态变量。我需要传递给bison我的AST指针。我也需要bison传递我的AST flex。这是一个线程环境,但我不需要任何线程同步。我需要一个separete yylineno变量为每个yyparse()调用。我阅读了关于%define api.pure,%parse-param和%选项可重入。但我不知道如何让他们一起工作... thx提前...
我试过:
scanner.l:
%{
#include< iostream>
#include< sstream>
#includeparser.tab.h
#define YY_DECL externCint 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代码
parser.y:
%{
#include< iostream&
#includeAST.h
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void * yyscan_t;
#endif
externCint yylex(YYSTYPE * lvalp,yyscan_t scanner);
externCFILE * yyin;
extern int yylineno;
void yyerror(yyscan_t scanner,NBloco * bloco,const char * s);
%}
%union {
//联盟代码
}
%define api.pure full
%lex -param {yyscan_t scanner}
%parse-param {yyscan_t scanner}
%parse-param {NBlock * block}
// tokens ...
/ / types ...
%%
//解析器代码...
我有这个:
parser.y:13:22:warning:'yylex '初始化和声明'extern'[默认启用] externCint yylex(YYSTYPE * lvalp,yyscan_t scanner);
parser.y:13:22:错误:'YYSTYPE'未在此范围内声明
parser.y:13:32 :error:'lvalp'未在此范围内声明externCint yylex(YYSTYPE * lvalp,yyscan_t scanner);
parser.y:13:48:error:预期的主表达式'scanner'
externCint yylex(YYSTYPE * lvalp,yyscan_t scanner);
^
parser.y:13:55:error:初始化器中作为复合表达式处理的表达式列表[-fpermissive]
externCint yylex(YYSTYPE * lvalp, yyscan_t scanner);
^
parser.tab.c:在函数'int yyparse(yyscan_t,NBloco *)':
parser.tab.c:932:39:error:'yylex '不能用作函数
#define YYLEX yylex(& yylval,scanner)
parser.tab.c:1618:16:注意:在宏的扩展'YYLEX'
yychar = YYLEX;
//更多错误...
我也修复yylineno是每个文件...
i am基于 http://benlynn.blogspot.com.br/2013/12/reentrant-parsers-with-flex-and-bison.html 和 http://www.lemoda.net/c/reentrant-parser/index.html
首先,这里有一个可重入的flex解析器和纯bison示例,用于解析与以下语法匹配的语法:
()
(())
()()()()()
lexer.l
%选项bison-bridge
%选项bison-locations
%选项ecs
%选项nodefault
%选项noyywrap
%选项reentrant
%选项stack
%选项warn
%选项yylineno
%{
#includeparser.h
%}
%%
({return(LPAREN); }
){return(RPAREN); }
[\f\r\t\v\\\
] + / * eat whitespace * /
%%
/ *不使用lexer.l代码,在其他地方逻辑组织* /
解析器。 y
%define parse.error verbose
%define api.pure true
%locations
%token-table
%glr-parser
%lex-param {void * scanner}
%parse-param {void * scanner}
%{
/ *你的最高代码在这里* /
%}
%union {
int value; //或其他任何内容
}
%令牌LPAREN
%令牌RPAREN
%%
文档
: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)\\\
,
msg,
locp-> first_line,locp-> first_column,
locp-> last_line,locp - > last_column
);
/ * todo:添加一些花哨的^^^^^错误处理在这里* /
} else {
fprintf(stderr,parse error:%s\\\
,msg);
}
return(0);
}
main.c
< pre class =lang-c prettyprint-override>
#includeparser.h
#includelexer.h
int
main (int argc,char ** argv){
int result;
yyscan_t scanner;
yylex_init(& scanner);
result =(yyparse(scanner));
yylex_destroy(scanner);
return(result);
}
建立
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
注意: OSX的内置野牛已过时,因此请安装3.x:
brew install bison
/ usr / local / opt / bison / bin / bison ....
现在,迁移到C ++
- 将.l复制到.lxx,将.y复制到.yxx
- 更改输出文件的名称到* .cxx和* .hxx。
lexer.lxx
- 添加
%option c ++
- 删除
可重入
,bison-bridge
和bison-locations
- 更改所有标记如下:
LPAREN
到yy :: parser :: token :: LPAREN
parser.yxx
- 添加
%skeletonlalr1 .cc
- 删除
api.pure
-
yyerror
main.cxx
- 重写它为C ++
挂接词法分析器和解析器对象是一个练习
另请参阅: https:// github .com / bingmann / flex-bison-cpp-example 但是请注意它使用的是旧的bison 2.x接口。
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...
I tried this:
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:
%{
#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
First, here's a C reentrant flex parser and pure bison example that parses a grammar that matches the following:
()
(())
(()())
()()(())()()
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:
brew install bison
And then run it like /usr/local/opt/bison/bin/bison ....
Now, to migrate to C++
- copy .l to .lxx and .y to .yxx
- change names for output files to *.cxx and *.hxx respectively.
lexer.lxx
- add
%option c++
- remove
reentrant
,bison-bridge
andbison-locations
- change all tokens like the following:
LPAREN
toyy::parser::token::LPAREN
parser.yxx
- add
%skeleton "lalr1.cc"
- remove
api.pure
- remove
yyerror
main.cxx
- rewrite it for C++
Hooking up the lexer and parser objects is an exercise for the reader.
See also: https://github.com/bingmann/flex-bison-cpp-example but beware it uses the old bison 2.x interfaces.
GNU Bison 3.x C++ Example docs
这篇关于配置没有全局或静态变量的Bison和Flex的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!