【问题标题】:Boost Spirit parser with inherited attributes - simple example won't compile具有继承属性的 Boost Spirit 解析器 - 简单示例无法编译
【发布时间】:2013-12-07 19:50:09
【问题描述】:

我正在尝试为带有 boost::spirit 的类 C 语言编写一个解析器,它使用继承的属性来传输有关变量范围的信息。例如,“namespace a { var b }”会将“a”作为属性传递给“var b”的解析器。

我在获取使用继承属性编译此代码的基本解析器时遇到了问题:

#ifndef CPARSER_DEF_HPP
#define CPARSER_DEF_HPP

#include <string>

#include <boost/spirit/include/qi.hpp>

namespace encoding = boost::spirit::ascii;
using boost::spirit::unused_type;
using boost::spirit::qi::rule;

template <typename Iterator>
struct cparser : boost::spirit::qi::grammar<
                    Iterator,
                    std::string(std::string),
                    encoding::space_type
                    >
{
    rule<Iterator, std::string(std::string), encoding::space_type> start;
    rule<Iterator, std::string(std::string), encoding::space_type> sym_list;

    cparser() :
        cparser::base_type(start)
    {
        sym_list         = encoding::string(boost::spirit::qi::_r1);
        start            = sym_list(boost::spirit::qi::_r1);
    }

};

#endif

这个解析器在 main() 中用cparser&lt;std::string::const_iterator&gt; parser 实例化。

我相信这个解析器应该接受一个 std::string 作为它的继承属性,解析匹配这个字符串的输入,然后把这个字符串作为一个综合属性返回。此示例代码无法编译,我无法弄清楚原因。我一直在使用启用 C++11 的 GCC 和 Clang 进行编译。任何一个编译器的输出都是巨大的(大约 1000 行),我无法理解它。 boost::spirit::qi::_r1的使用有问题吗?规则声明中的std::string(std::string) 有问题?

提前感谢您的帮助。

【问题讨论】:

  • 我没有尝试过你的代码,但是当你说 GCC 时,你的意思是 gcc --std=c++11g++ --std=c++11?您应该使用第二个。
  • 对不起,问题没有更具体,我正在使用这个命令:g++ -std=c++11 src/simple_cparser.cpp -c -o objs/simple_cparser.o,并且用 clang++ 替换 g++ 的相同命令。

标签: c++ boost boost-spirit


【解决方案1】:

我尝试构建一个示例here。我不确定我是否遇到过与您相同的问题(因为您没有提供重现它们的方法),但我认为有两个不同的问题:第一个非常常见的问题是 PhoenixV2 无法使用“现代编译器”,因为 Boost 1.52 中的重大更改使 BOOST_RESULT_OF_USE_DECLTYPE 成为默认值。 有两种方法可以解决这个问题(至少使用 coliru 使用的 clang 版本)或者通过定义 BOOST_SPIRIT_USE_PHOENIX_V3 使用 V3(这是我推荐的,我认为它应该是默认值)或者将 result_of 协议返回给V2 通过定义 BOOST_RESULT_OF_USE_TR1 所期望的行为。第二个问题,我不太熟悉,所以对此持保留态度,或者只是等待“更有经验的人”的回答,似乎你不能直接将字符串文字作为继承属性传递,您需要将它们作为字符串传递(使用 phx::val("foo") 似乎也可以)。

短版:定义 BOOST_SPIRIT_USE_PHOENIX_V3 并将继承的属性作为 std::string 而非字符串文字传递。

【讨论】:

  • 谢谢,定义 BOOST_SPIRIT_USE_PHOENIX_V3 并传递 std::string 而不是 const char* 作为继承属性是唯一需要的更改。定义 BOOST_RESULT_OF_USE_TR1 也可以,但我会按照建议使用 BOOST_SPIRIT_USE_PHOENIX_V3。
  • 我想知道继承的属性是否需要是 std::string 而不是 const char* 因为它被 Spirit 隐式转换为另一种类型。编译器将执行一次隐式转换(std::string 到 Spirit 内部类型或 const char* 到 std::string),但不会执行两次。这纯粹是一种猜测,但更具体地了解属性的类型并没有什么坏处。
  • This thread in the mailing list 显示了与继承属性和字符串文字相同的问题,并且 sehe(A.K.A.“更有经验的人”)提出了另一种方法(atm 仅适用于 g++ 和 clang++),即添加+ 在你的文字前面,迫使它从 const char[N] 衰减到 const char*The same example in my answer with this approach.
猜你喜欢
  • 2011-07-23
  • 1970-01-01
  • 2015-01-25
  • 2011-01-21
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
  • 2017-03-26
  • 1970-01-01
相关资源
最近更新 更多