使用boost :: qi :: rule和BOOST_FUSION_ADAPT_STRUCT的正确方法是什么?

时间:2014-04-24 18:24:50

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

我试图获得一个qi :: rule<>根据boost employee示例发出带有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);

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

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

我做错了什么?

1 个答案:

答案 0 :(得分:2)

我不确定。我想我错过了这个问题。也许,我自然而然地#34;因为你的样本不是独立的,所以回避这个问题。

所以,我采取了以下措施:看到它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'