c++ - 将 boost::qi::rule 与 BOOST_FUSION_ADAPT_STRUCT 一起使用的正确方法是什么?

标签 c++ boost-spirit boost-spirit-qi boost-fusion

我正在尝试获取 qi::rule<> 以基于 boost 员工示例发出带有 BOOST_FUSION_ADAPT_STRUCT 的结构。

我有以下结构及其关联的融合宏:

struct LineOnCommand
{
   int lineNum;
   std::vector<char> humpType;
};

BOOST_FUSION_ADAPT_STRUCT(
   LineOnCommand,
   (int, lineNum)
   (std::vector<char>, humpType)
)

相关的解析规则是:

qi::rule<Iterator, std::vector<char> ascii::space_type> humpIdentifer = qi::lit("BH") | qi::lit("DH");

qi::rule<Iterator, LineOnCommand(), ascii::space_type> Cmd_LNON = qi::int_ >> -humpIdentifier >> qi::lit("LNON");

然后我有一个复合规则,其中所有其他规则(包括这个简单的测试用例)都是传递给解析器的一部分:

qi::rule<Iterator, qi::unused_type, ascii::space_type> commands =
   +( /* other rules | */ Cmd_LNON /*| other rules */);

bool success = qi::phrase_parse(StartIterator, EndIterator, commands, ascii::space);

当我尝试编译时出现问题,并收到错误:

<boostsource>/spirit/home/qi/detail/assign_to.hpp(152): error: no suitable constructor exists to convert form "const int" to "LineOnCommand"
    attr = static_cast<Attribute>(val);

显然我做错了什么,但我不确定是什么。如果我理解 Spirit 的工作方式,规则模板的第二个参数表示属性(即规则发出的数据类型),并且 BOOST_FUSION_ADAPT_STRUCT 宏将调整我的结构,以便 boost 知道如何转换流“int,std::vector”。

我在这里所做的和 boost 员工示例之间的唯一区别是我没有使用显式语法来进行解析。我的理解是这没有必要,规则本身就足够了。

我做错了什么?

最佳答案

我不确定。我想我错过了这个问题。也许,我“自然地”回避了这个问题,因为你的样本不是独立的。

所以,这是我的看法:查看 Live On Coliru ,希望只是比较可以帮助您:

  • 我修正了您的规则声明中的明显拼写错误
  • 我建议了 qi::unused_type 之外的其他内容;如果没有属性,则无需声明;除了迭代器类型之外,qi::ruleqi::grammar 的模板参数不是位置的。所以

    qi::rule<It, qi::unused_type(), ascii::space_type> r;
    qi::rule<It, ascii::space_type, qi::unused_type()> r;
    qi::rule<It, ascii::space_type> r;
    

    在逻辑上都是等价的。

完整列表:

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct LineOnCommand
{
   int lineNum;
   std::vector<char> humpType;
};

BOOST_FUSION_ADAPT_STRUCT(
   LineOnCommand,
   (int, lineNum)
   (std::vector<char>, humpType)
)

template <typename It, typename Skipper = ascii::space_type>
struct parser : qi::grammar<It, std::vector<LineOnCommand>(), Skipper>
{
    parser() : parser::base_type(commands)
    {
        using namespace qi;
        humpIdentifier = string("BH") | string("DH");
        Cmd_LNON       = int_ >> -humpIdentifier >> "LNON";

        commands       = +( /* other rules | */ Cmd_LNON /*| other rules */ );
    }
  private:
    qi::rule<It, std::vector<char>(),          Skipper> humpIdentifier;
    qi::rule<It, LineOnCommand(),              Skipper> Cmd_LNON;
    qi::rule<It, std::vector<LineOnCommand>(), Skipper> commands;
};

int main()
{
    typedef std::string::const_iterator Iterator;
    parser<Iterator> p;

    std::string const input = 
        "123 BH LNON\n"
        "124 LNON\t\t\t"
        "125 DH LNON\n"
        "126 INVALID LNON";

    auto f(input.begin()), l(input.end());

    std::vector<LineOnCommand> data;
    bool success = qi::phrase_parse(f, l, p, ascii::space, data);

    std::cout << "success:" << std::boolalpha << success << ", " 
              << "elements: " << data.size() << "\n";

    if (success)
    {
        for (auto& el : data)
        {
            std::cout << "Item: " << el.lineNum << ", humpType '" << std::string(el.humpType.begin(), el.humpType.end()) << "'\n";
        }
    }

    if (f!=l)
        std::cout << "Trailing unparsed: '" << std::string(f,l) << "'\n";

    return success? 0 : 1;
}

输出:

success:true, elements: 3
Item: 123, humpType 'BH'
Item: 124, humpType ''
Item: 125, humpType 'DH'
Trailing unparsed: '126 INVALID LNON'

关于c++ - 将 boost::qi::rule 与 BOOST_FUSION_ADAPT_STRUCT 一起使用的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23276879/

相关文章:

c++ - 如何将字节保存到pdf文件(如何将每个pdf页面更改为字节)

c++ - Boost Spirit x3条件(三元)运算符解析器

c++ - 语法问题

c++ - 灵气 : Completely ignoring output of some rules

c++ - 在语义 Action 中添加到灵气符号表

c++ - 使用 QStringList::entryList() 时对 QStringList 进行反向排序

c++ - 修改文件路径以在 Printf 中使用

c++ - 按字符数拆分字符串的 spirit 语法

c++ - 如何在 Boost.Spirit 中跳过行/ block /嵌套 block 注释?

c++ - 为什么我不能将绑定(bind)成员函数作为可调用对象传递?