我正在学习如何使用Flex和Bison。我用C ++编写了一个解析器。我得到它来编译,但是当我添加选项来跟踪令牌位置时,我得到一个错误。
这是一个产生相同错误的小例子:
%{
#include <stdio.h>
#include "parser.tab.h"
#define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno; \
yylloc->first_column = yycolumn; \
yycolumn += yyleng;
int yycolumn = 1;
extern "C" int yyparse();
%}
%option bison-locations
%option yylineno
%option noyywrap
NAT [0-9]+
%%
{NAT} { printf("NUM: %d\n", atoi(yytext)); return NUM; }
"\n" yycolumn = 1;
.
%%
int main (int argc, char **argv) {
argc--, argv++;
if (argc > 0)
yyin = fopen(argv[0], "r");
else
yyin = stdin;
yyparse();
}
%{
#include <iostream>
#include <stdio.h>
#define YYSTYPE int
using namespace std;
void yyerror (char const*);
int yylex ();
extern "C" int yyparse ();
%}
%locations
%pure-parser
%token NUM
%%
s : NUM ;
%%
void yyerror(char const* s) {
fprintf(stderr, "%s\n", s);
}
par: parser.tab.c lex.yy.c
g++ lex.yy.c parser.tab.c -o par
parser.tab.c: parser.y
bison -d parser.y
lex.yy.c: lexer.l
flex lexer.l
当我尝试编译它时出现以下错误:
parser.tab.c: In function ‘int yyparse()’:
parser.tab.c:1314:16: error: too many arguments to function ‘int yylex()’
parser.y:9:6: note: declared here
我尝试将parser.y中yylex
的声明更改为int yylex (YYSTYPE*, YYLTYPE*)
,但名称YYLTYPE
超出了范围并尝试了一些更多但未成功的事情...... < / p>
它会在删除lexer.l中的#define YY_USER_ACTION ...
,%option bison-locations
以及解析器中的%locations
和%pure-parser
时进行编译。
我怎样才能让它发挥作用?
答案 0 :(得分:0)
您正在使用C ++编译生成的文件,尽管它们是C文件。这通常有效,但yylex
的声明存在问题。在C中,
int yylex();
将yylex
声明为函数,而不指定有关其参数列表的任何内容。 (int yylex(void)
会声明它没有参数。)这在C ++中是不可能的,因此您需要提供精确的参数列表。不幸的是,在yylex
被定义之前,包含YYLTYPE
定义的代码块被插入到生成的代码中。
一个简单的解决方案是将YYLTYPE预先声明为不完整类型:
struct YYLTYPE;
允许您在YYLTYPE*
的声明中使用yylex
。 YYLTYPE
最终将被声明为struct
,除非您提供了自己的声明。
使用最新版本的野牛,您应该可以使用以下内容:
%code requires {
#include <iostream>
#include <stdio.h>
/* If you insist :) */
using namespace std;
}
%code provides {
void yyerror (char const*);
int yylex (YYSTYPE*, YYLTYPE*);
extern "C" int yyparse ();
%}
(这很可能不是你想要的纯粹解析器。但它可能足以让你开始。)
答案 1 :(得分:0)
您正在使用bison选项%pure-parser
,该选项会更改其调用yylex
的方式。您需要将flex %option bison-bridge
添加到.l文件中以获得flex以使用yylex
的相同调用约定