【问题标题】:Unable to define a rule in Spirit:: Qi无法在 Spirit:: Qi 中定义规则
【发布时间】:2011-07-27 21:08:40
【问题描述】:

我正在尝试将 Unix 文件路径解析为文件夹对(键/值对 - 根据我的应用程序的需要)。问题是我无法正确定义使用 qi::rule 的解析器。我得到了我无法完全理解的编译器错误页面(对不起,如果问题听起来很简单,但我真的卡住了,无法继续)

下面是程序sn-p。

更新:我已经按照 Nicol 和 ildjarn 的建议修改了程序,但问题仍然存在。

namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    namespace phoenix = boost::phoenix;

    template <typename Iterator>
    bool parse_data(Iterator first, Iterator last, std::vector< std::pair<std::string, std::string> >& v)
    {
        using qi::double_;
        using qi::char_;
        using qi::phrase_parse;
        using qi::_1;
        using ascii::space_type;
        using phoenix::ref;
        using phoenix::push_back;

        std::pair<std::string, std::string> p;

        qi::rule<Iterator, std::string()> key = '/' >> *char_("a-zA-Z0-9");
        qi::rule<Iterator, std::string()> val = '/' >> *char_("a-zA-Z0-9");
        qi::rule<Iterator, std::pair<std::string, std::string>()> ppair = key >> val ;

        //bool r = phrase_parse(
        bool r = parse(
            first,
            last,
            (
                +ppair[push_back(ref(v), _1)]
            )
            );

        if (first != last)
            return false;
        return r;
    }
}

int  
main()
{
    std::string str;

    while (getline(std::cin, str))
    {
        if (str.empty())
            break;

        std::vector< std::pair<std::string, std::string> > vec_pair;
        if(client::parse_data(str.begin(), str.end(), vec_pair))
        {
            std::cout << std::endl << "Parsing done" << std::endl;
            std::cout << "Strings are " ;

            std::pair<std::string, std::string> temp;
            for(std::vector< std::pair<std::string, std::string> >::iterator i = vec_pair.begin(); i < vec_pair.end(); i++)
            {
                temp = *i;
                std::cout << temp.first <<"|" << temp.second;
            }
            std::cout << std::endl;
        }
        else
        {
            std::cout << "Parsing Failed" << std::endl;
        }
    }

    return 0;
}

错误:

/usr/local/include/boost_1_46_1/boost/spirit/home/qi/detail/assign_to.hpp:109: error: no matching function for call to
‘std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::pair(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)’
/usr/lib/gcc/x86_64-redhat-linux/4.3.2/../../../../include/c++/4.3.2/bits/stl_pair.h:88: note: candidates are:
std::pair<_T1, _T2>::pair(const _T1&, const _T2&) [with _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
/usr/lib/gcc/x86_64-redhat-linux/4.3.2/../../../../include/c++/4.3.2/bits/stl_pair.h:84: note:                 std::pair<_T1, _T2>::pair() [with _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]
/usr/lib/gcc/x86_64-redhat-linux/4.3.2/../../../../include/c++/4.3.2/bits/stl_pair.h:73: note:                 std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::pair(const std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)

你能帮我解决这个问题吗?

谢谢

【问题讨论】:

  • 跳出来的第一件事是你正在使用phrase_parse,但你还没有在rules 上指定船长类型。
  • @ildjarn 我不想跳过任何内容。我想捕获斜线之间的所有内容。
  • 那么你应该使用parse,而不是phrase_parse。 :-]
  • @ildjarn 我尝试使用parse,但没有任何改变。我仍然遇到同样的错误。
  • 哦,我知道这与您报告的问题无关,我只是想指出一个明显的错误。如果有时间,我将在今天晚些时候发布完整的答案。

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


【解决方案1】:

为了让 Spirit 将数据解析为用户定义的数据结构,您必须提供一个适配器。这是通过 Boost.Fusion 完成的,如 shown in the documentation。你需要这样做:

BOOST_FUSION_ADAPT_STRUCT(
    client::pair,
    (std::string, key)
    (std::string, val)

注意这个必须定义一个全局范围(你必须退出你的client命名空间,定义这个,然后重新进入client命名空间)。

但是对于这种狭隘的情况,您最好解析为std::pair&lt;std::string, std::string&gt;。 Spirit 知道如何处理这类事情。

另外,请注意,这是 ildjarn 指出的 parseparse_phrase 问题的补充。两者都必须修复。

还有一件事。您应该重新定义您正在解析的规则。这个:

ppair >> *(ppair)

具有boost.tuple&lt;client::pair, std::vector&lt;client::pair&gt; &gt; 的原始属性类型。如果你这样做:

+ppair

然后你得到一个干净的std::vector&lt;client::pair&gt;

【讨论】:

  • 谢谢!我已按照您的建议修改了程序,但仍然无法编译。 (见上面有问题的更新)
【解决方案2】:

添加这些#include 后,您的上面的程序对我来说编译得很好(Boost V1.47):

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/std_pair.hpp>

请注意,在此(最新)版本中,Spirit 的实现发生了相当多的更改,这可能解释了为什么它在这里编译,但不适用于您(如果您使用的是旧版本)。

【讨论】:

  • 是的,我使用的是 Boost 1.46。我将尝试使用 1.47 并查看它是否可以编译。谢谢
  • 使用Boost 1.47后问题已解决!再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多