使用boost :: qi :: rule和BOOST_FUSION_ADAPT_STRUCT的正确方法是什么? [英] What is the correct way to use boost::qi::rule with BOOST_FUSION_ADAPT_STRUCT?

查看:1090
本文介绍了使用boost :: qi :: rule和BOOST_FUSION_ADAPT_STRUCT的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图获取一个qi :: rule<>来发布一个结构BOOST_FUSION_ADAPT_STRUCT基于boost employee示例。

I am attempting to get a qi::rule<> to emit a struct with BOOST_FUSION_ADAPT_STRUCT based on the boost employee example.

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

I have the following struct and its associated fusion macro:

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");

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

I then have a compound rule, of which all others (including this simple test case) are a part which is passed to the parser:

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);

问题出现在我尝试编译时,我得到错误:

The problem comes when I attempt to compile, and I get the error:

<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);

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

Clearly I'm doing something wrong, but I'm not sure what. If I understand the way spirit works, the 2nd argument to the template of the rule represents the attribute (i.e. the data type emitted by the rule), and the BOOST_FUSION_ADAPT_STRUCT macro will adapt my struct so that boost knows how to convert a stream that is "int, std::vector" to it.

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

The only difference between what I'm doing here and the boost employee example is that I'm not using an explicit grammar to do the parsing. My understanding is this is not necessary, and that a rule by itself is sufficient.

我做错了什么?

推荐答案

我不确定。我想我错过了这个问题。也许,我自然回避这个问题,因为你的样品不是自给自足。

I'm not sure. I think I'm missing the problem. Perhaps, I "naturally" sidestep the problem because your sample is not self-contained.

因此,这里是我的承诺:查看 Live on Coliru ,希望只是比较内容可以帮助您:

So, here's my take on it: See it Live On Coliru, in the hope that just comparing things helps you:


  • 修正规则声明中的明显错误。

  • 我建议使用 qi :: unused_type 如果没有属性,没有必要说明它;除了迭代器类型, qi :: rule qi :: grammar 的模板参数不是位置

  • I fixed the obvious typos in your rule declaration
  • I suggested something other than qi::unused_type; if there's no attribute, there's no need to state it; beyond the iterator type, the template arguments to qi::rule and qi::grammar are not positional. So

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;

均为/逻辑/等效。



    完整列表:

Full listing:

#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'

这篇关于使用boost :: qi :: rule和BOOST_FUSION_ADAPT_STRUCT的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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