Bison:将Union语义类型与C ++解析器结合使用 [英] Bison: using the Union semantic type with a C++ parser
问题描述
我一直在尝试在Bison中设置一个小解析器,但是当我尝试构建它时,我得到了:
I've been trying to set up a little parser in Bison, but when I try to build it I get:
stone.tab.cc:在成员函数"virtual int yy :: StoneParser :: parse()"中: stone.tab.cc:507:81:错误:从类型为"yy :: StoneParser :: semantic_type *"的右值对类型为"StoneDriver&"的非常量引用进行了无效的初始化 yyla.type = yytranslate_(yylex(& yyla.value,& yyla.location,驱动程序));
stone.tab.cc: In member function ‘virtual int yy::StoneParser::parse()’: stone.tab.cc:507:81: error: invalid initialization of non-const reference of type ‘StoneDriver&’ from an rvalue of type ‘yy::StoneParser::semantic_type*’ yyla.type = yytranslate_ (yylex (&yyla.value, &yyla.location, driver));
我怀疑原因是在bison生成的C ++编译器中使用联合定义的语义类型存在问题,但是我似乎无法解决它...
I suspect the reason is there's a problem using union-defined semantic types with a bison-generated C++ compiler, but I can't seem to resolve it...
如何生成具有联合"语义定义的有效C ++野牛解析器?
How can I generate a valid C++ bison parser with 'union' semantic definitions?
stone.yy:
%skeleton "lalr1.cc"
%require "3.0.4"
%defines
%define parser_class_name {StoneParser}
%code requires
{
# include <string>
class StoneDriver;
}
%param { StoneDriver& driver }
%locations
%code
{
# include "StoneDriver.hpp"
}
%union
{
int intVal;
char* stringVal;
}
%token <stringVal> KEY_ENUM
%token <stringVal> KEY_CLASS
%token K_TEST
%token T_ID
%type <stringVal> class
%type <stringVal> enum
%%
input: toplevel_declarations
toplevel_declarations: toplevel_declarations toplevel_declaration
| %empty
toplevel_declaration: class
| enum
class: KEY_CLASS { $$ = "test"; }
enum: KEY_ENUM { $$ = "test"; }
StoneDriver.hpp
StoneDriver.hpp
#ifndef STONEDRIVER_INCLUDED_HPP
#define STONEDRIVER_INCLUDED_HPP
#include <string>
#include <map>
#include "stone.tab.hh"
class StoneDriver;
//Tell Flex the lexer's prototype ...
#define YY_DECL \
yy::StoneParser::symbol_type yylex (StoneDriver& driver)
// ... and declare it for the parser's sake.
YY_DECL;
//Scans and parses Stone
class StoneDriver
{
public:
//Constructor
StoneDriver();
//Destructor
virtual ~StoneDriver();
std::map<std::string, int> variables;
int result;
// Handling the scanner.
void scan_begin ();
void scan_end ();
bool trace_scanning;
// Run the parser on file F.
// Return 0 on success.
int parse (const std::string& f);
// The name of the file being parsed.
// Used later to pass the file name to the location tracker.
std::string file;
// Whether parser traces should be generated.
bool trace_parsing;
// Error handling.
void error (const yy::location& l, const std::string& m);
void error (const std::string& m);
};//StoneDriver
#endif
StoneDriver.cpp:
StoneDriver.cpp:
#include "StoneDriver.hpp"
#include "stone.tab.hh"
StoneDriver::StoneDriver()
: trace_scanning (false), trace_parsing (false)
{
variables["one"] = 1;
variables["two"] = 2;
}//constructor
StoneDriver::~StoneDriver()
{
}//destructor
int StoneDriver::parse(const std::string &f)
{
file = f;
scan_begin();
yy::StoneParser parser(*this);
#if YYDEBUG
parser.set_debug_level(trace_parsing);
#endif
int res = parser.parse();
scan_end();
return res;
}//parse
void StoneDriver::error(const yy::location& l, const std::string& m)
{
std::cerr << l << ": " << m << std::endl;
}//error
void StoneDriver::error(const std::string& m)
{
std::cerr << m << std::endl;
}//error
解决方案: Rici显示YY_DECL的方法签名应定义如下:
SOLUTION: Rici showed that the method signature for YY_DECL should be defined like so:
int yylex (semantic_type* YYLVAL, location_type* YYLLOC, TYPE1 ARG1, ...)
在我的情况下,魔术线是:
In my case, the magic line was:
#define YY_DECL int yylex( yy::StoneParser::semantic_type* const lval, yy::StoneParser::location_type* location, StoneDriver& driver )
-
yy::
是我的Bison文件中的命名空间(在我的情况下为stone.yy) -
StoneParser
是stone.yy中定义的parser_class_name -
location_type
是必需的,因为stone.yy具有%locations 定义. -
StoneDriver&
是来自stone.yy的解析上下文, 定义为%param { StoneDriver& driver }
yy::
is the namespace from my Bison file (stone.yy in my case)StoneParser
is the defined parser_class_name from stone.yylocation_type
is required because stone.yy has %locations defined.StoneDriver&
is the parsing context from stone.yy, defined as%param { StoneDriver& driver }
感谢您的帮助!
推荐答案
尽管奇怪地将焦点放在yylex
的第一个参数中而不是类型上,但错误消息提供了关于问题所在的清晰指示.您为yylex
提供的原型只有一个参数,而调用只有三个参数. lang声更清晰:
The error message provides a somewhat clear indication of what the problem is, although it is oddly focused on the type mismatch in the first argument to yylex
rather than the fact that the prototype you provide for yylex
has only one parameter whereas the call has three arguments. Clang is clearer:
stone.tab.cc:474:39: error: no matching function for call to 'yylex'
yyla.type = yytranslate_ (yylex (&yyla.value, &yyla.location, driver));
^~~~~
./stone_driver.hpp:14:1: note: candidate function not viable: requires single argument 'driver', but 3 arguments were provided
YY_DECL;
^
野牛信息文件10.1.5.1节介绍了语义类型为union
的C ++扫描程序中yylex
的调用约定:
The bison info file, section 10.1.5.1, describes the calling convention of yylex
from C++ scanners with a union
semantic type:
The interface is as follows.
-- Method on parser: int yylex (semantic_type* YYLVAL, location_type*
YYLLOC, TYPE1 ARG1, ...)
-- Method on parser: int yylex (semantic_type* YYLVAL, TYPE1 ARG1, ...)
Return the next token. Its type is the return value, its semantic
value and location (if enabled) being YYLVAL and YYLLOC.
Invocations of ‘%lex-param {TYPE1 ARG1}’ yield additional
arguments.
这实际上与C API中的纯解析器使用的调用约定相同:yylex
的前两个参数(如果已启用位置,如程序中的情况)是语义值的地址对象和位置对象的地址;第三个及后续参数是%param
(如果存在)指定的参数.
This is effectively the same calling convention as is used with pure parsers in the C API: the first two arguments to yylex
(if locations are enabled, as is the case in your program) are the address of the semantic value object and the address of the location object; the third and subsequent arguments are the parameters specified by %param
(if present).
因此,您应该根据上述原型修复YY_DECL
的定义.
So you should fix the definition of YY_DECL
according to the above prototype.
您还必须更改flex动作,以将yylval
(或称为第一个参数的任何内容)视为指针而不是并集,这通常意味着将.
更改为->
.
You will also have to change your flex actions to treat yylval
(or whatever you call the first parameter) as a pointer rather than a union, which mostly means changing .
to ->
.
这篇关于Bison:将Union语义类型与C ++解析器结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!