无法在 Spirit:: Qi 中定义规则

发布于 2024-11-26 19:34:15 字数 3987 浏览 0 评论 0 原文

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

下面是程序片段。

更新:我已经按照 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> > >&)

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

谢谢

I am trying to parse a Unix file path into pairs of folders(key/value pairs - as needed by my application). The problem is I am unable to define parsers using qi::rule correctly. I get pages of compiler errors which I am unable to understand completely (Sorry if the question sounds simple but I am really stuck and unable to proceed)

The below is the program snippet.

UPDATE: I have modified the program as per Nicol and ildjarn's suggestions, but the problem still persists.

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

Errors:

/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> > >&)

Can you please help me fix this problem ?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

回心转意 2024-12-03 19:34:15

为了让 Spirit 将数据解析为用户定义的数据结构,您必须提供一个适配器。这是通过 Boost.Fusion 完成的,如 文档中显示。您需要执行此操作:

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

请注意,此必须定义为全局范围(您必须退出client命名空间,定义它,然后重新进入client 命名空间)。

但对于这种狭窄的情况,您最好解析为 std::pair。精神知道如何处理这类事情。

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

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

ppair >> *(ppair)

具有 boost.tuple 的原始属性类型; >。如果你这样做:

+ppair

那么你会得到一个干净的 std::vector

In order for Spirit to parse data into a user-defined data structure, you must provide an adapter. This is done with Boost.Fusion, as shown in the documentation. You would need to do this:

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

Note that this must be defined a global scope (you must exit your client namespace, define this, then re-enter the client namespace).

But for this narrow case, you'd be better off parsing into a std::pair<std::string, std::string>. Spirit knows how to work with that sort of thing.

Also, note that this is in addition to the parse vs. parse_phrase issue that ildjarn pointed out. Both must be fixed.

One more thing. You should redefine the rule you are parsing. This:

ppair >> *(ppair)

Has a raw attribute type of boost.tuple<client::pair, std::vector<client::pair> >. If you do this:

+ppair

Then you get a clean std::vector<client::pair>.

浅蓝的眸勾画不出的柔情 2024-12-03 19:34:15

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

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

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

After adding these #include's your program above compiles fine for me (Boost V1.47):

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

Please note that there have been quite some implementation changes to Spirit in this (newest) version, which might explain why it compiles here, but not for you (if you're using an older version).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文