Bison:将Union语义类型与C ++解析器结合使用 [英] Bison: using the Union semantic type with a C++ parser

查看:152
本文介绍了Bison:将Union语义类型与C ++解析器结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试在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.yy
    • location_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆