使 yylex return symbol_type 而不是 int
Make yylex return symbol_type instead of int
我正在尝试 return 来自 yylex 的符号对象,如本文档中所示 http://www.gnu.org/software/bison/manual/html_node/Complete-Symbols.html
但是,当我编译时,我发现 return yy::parser::make_PLUS();
被放入了 int yyFlexLexer::yylex()
,所以我得到了这个错误消息(以及其他规则中的许多类似消息):
lexer.ll:22:10: error: no viable conversion from 'parser::symbol_type' (aka 'basic_symbol<yy::parser::by_type>') to 'int'
{ return yy::parser::make_PLUS(); }
解决这个问题的正确方法是什么?
lexer.ll
%{
#include "ASTNode.hpp"
// why isn't this in parser.tab.hh?
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
# define YY_NULLPTR nullptr
# else
# define YY_NULLPTR 0
# endif
# endif
#include "parser.tab.hh"
#define yyterminate() return yy::parser::make_END()
%}
%option nodefault c++ noyywrap
%%
"+" { return yy::parser::make_PLUS(); }
"-" { return yy::parser::make_MINUS(); }
... more rules ...
%%
parser.yy
%{
#include "AstNode.hpp"
#include ...
static int yylex(yy::parser::semantic_type *arg);
%}
%skeleton "lalr1.cc"
%define api.token.constructor
%define api.value.type variant
%define parse.assert
%token END 0
%token PLUS
%token MINUS
%token ... many tokens ...
%type <ASTNode *> S statement_list ...
%%
S: statement_list
{ $$ = g_ast = (StatementList *); }
;
... more rules ...
%%
static int yylex(yy::parser::semantic_type *arg) {
(void)arg;
static FlexLexer *flexLexer = new yyFlexLexer();
return flexLexer->yylex();
}
void yy::parser::error(const std::string &msg) {
std::cout << msg << std::endl;
exit(1);
}
您必须在生成的扫描器和生成的解析器中使用正确的签名声明 yylex
。显然,返回int
并不是你想要的。
在 bison 分布中包含的 calc++ 示例中(并在 bison manual 中描述),您可以看到如何执行此操作:
Then comes the declaration of the scanning function. Flex expects the signature of yylex to be defined in the macro YY_DECL, and the C++ parser expects it to be declared. We can factor both as follows.
// Tell Flex the lexer's prototype ...
# define YY_DECL \
yy::calcxx_parser::symbol_type yylex (calcxx_driver& driver)
// ... and declare it for the parser's sake.
YY_DECL;
这只是更改 yylex
声明的常规方法。虽然 bison 手册没有提到这一点,并且 .ll
后缀可以说是误导,但它是 而不是 使用 C++ flex 骨架。它使用 C 框架生成一个可以用 C++ 编译的文件。据我所知,它甚至没有生成可重入词法分析器。
calc++.yy
file里面还有一个重要的选项:
The driver is passed by reference to the parser and to the scanner. This provides a simple but effective pure interface, not relying on global variables.
// The parsing context.
%param { calcxx_driver& driver }
这表明 calcxx_driver& driver
是解析器和扫描器的参数。也就是说,您将它提供给解析器,解析器会自动将它传递给扫描器。这与使用 YY_DECL
.
生成的 yylex
原型匹配
您实际上可能不需要在扫描仪操作中使用该对象。我不认为它的使用是强制性的,但我几乎没有在 bison 或 flex 中使用过 C++ API,所以我很可能是错的。
我正在尝试 return 来自 yylex 的符号对象,如本文档中所示 http://www.gnu.org/software/bison/manual/html_node/Complete-Symbols.html
但是,当我编译时,我发现 return yy::parser::make_PLUS();
被放入了 int yyFlexLexer::yylex()
,所以我得到了这个错误消息(以及其他规则中的许多类似消息):
lexer.ll:22:10: error: no viable conversion from 'parser::symbol_type' (aka 'basic_symbol<yy::parser::by_type>') to 'int'
{ return yy::parser::make_PLUS(); }
解决这个问题的正确方法是什么?
lexer.ll
%{
#include "ASTNode.hpp"
// why isn't this in parser.tab.hh?
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
# define YY_NULLPTR nullptr
# else
# define YY_NULLPTR 0
# endif
# endif
#include "parser.tab.hh"
#define yyterminate() return yy::parser::make_END()
%}
%option nodefault c++ noyywrap
%%
"+" { return yy::parser::make_PLUS(); }
"-" { return yy::parser::make_MINUS(); }
... more rules ...
%%
parser.yy
%{
#include "AstNode.hpp"
#include ...
static int yylex(yy::parser::semantic_type *arg);
%}
%skeleton "lalr1.cc"
%define api.token.constructor
%define api.value.type variant
%define parse.assert
%token END 0
%token PLUS
%token MINUS
%token ... many tokens ...
%type <ASTNode *> S statement_list ...
%%
S: statement_list
{ $$ = g_ast = (StatementList *); }
;
... more rules ...
%%
static int yylex(yy::parser::semantic_type *arg) {
(void)arg;
static FlexLexer *flexLexer = new yyFlexLexer();
return flexLexer->yylex();
}
void yy::parser::error(const std::string &msg) {
std::cout << msg << std::endl;
exit(1);
}
您必须在生成的扫描器和生成的解析器中使用正确的签名声明 yylex
。显然,返回int
并不是你想要的。
在 bison 分布中包含的 calc++ 示例中(并在 bison manual 中描述),您可以看到如何执行此操作:
Then comes the declaration of the scanning function. Flex expects the signature of yylex to be defined in the macro YY_DECL, and the C++ parser expects it to be declared. We can factor both as follows.
// Tell Flex the lexer's prototype ...
# define YY_DECL \
yy::calcxx_parser::symbol_type yylex (calcxx_driver& driver)
// ... and declare it for the parser's sake.
YY_DECL;
这只是更改 yylex
声明的常规方法。虽然 bison 手册没有提到这一点,并且 .ll
后缀可以说是误导,但它是 而不是 使用 C++ flex 骨架。它使用 C 框架生成一个可以用 C++ 编译的文件。据我所知,它甚至没有生成可重入词法分析器。
calc++.yy
file里面还有一个重要的选项:
The driver is passed by reference to the parser and to the scanner. This provides a simple but effective pure interface, not relying on global variables.
// The parsing context.
%param { calcxx_driver& driver }
这表明 calcxx_driver& driver
是解析器和扫描器的参数。也就是说,您将它提供给解析器,解析器会自动将它传递给扫描器。这与使用 YY_DECL
.
yylex
原型匹配
您实际上可能不需要在扫描仪操作中使用该对象。我不认为它的使用是强制性的,但我几乎没有在 bison 或 flex 中使用过 C++ API,所以我很可能是错的。