本文介绍了Adapt类包含一个字符串成员作为合成属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将字符串解析为自定义类型符号的属性,其中包含 std :: string 成员。我想我可以使用 BOOST_FUSION_ADAPT_STRUCT 这里但是不起作用。

I’m trying to parse a character string into an attribute of a custom type symbol, which contains a std::string member. I thought I could use BOOST_FUSION_ADAPT_STRUCT here but that doesn’t work.

如果我声明规则为 rule< It,std :: string(),space_type> 它工作。如果我把它定义为 rule< It,symbol(),space_type> 它失败,错误没有类型名称 value_type 符号中。我认为Spirit正试图将字符为字符的值附加到属性,这会按预期失败。但是没有一种方法来进行这项工作,没有添加一个额外的中间规则捕获 std :: string 属性?

If I declare the rule as rule<It, std::string(), space_type> it works. If I define it as rule<It, symbol(), space_type> it fails with the error "no type name value_type in symbol". I think Spirit is trying to append the value character-for-character to the attribute, which fails as expected. But isn’t there a way of making this work, without adding an additional intermediate rule which captures the std::string attribute?

以下是完整的MWE:

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>

struct symbol 
{ 
    std::string repr; 
};

BOOST_FUSION_ADAPT_STRUCT(symbol, (std::string, repr))

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct test_grammar : qi::grammar<Iterator, symbol(), qi::ascii::space_type> {
    test_grammar() : test_grammar::base_type{start} {
        start = qi::lexeme[+qi::char_("a-z")];
    }

    qi::rule<Iterator, symbol(), qi::ascii::space_type> start;
};

#include <iostream>

auto main() -> int {
    test_grammar<std::string::iterator> grammar{};
    auto input = std::string{"test"};
    auto output = symbol{};
    auto e = end(input);
    if (qi::phrase_parse(begin(input), e, grammar, qi::ascii::space, output))
        std::cout << output.repr;
}


推荐答案

链接的复制,你可以得到这个与一个良好的 qi :: eps

As you have seen from the linked dupe, you can get around this with a well-placed qi::eps.

    start = qi::eps >> qi::lexeme[+qi::char_("a-z")];

查看

See it Live On Coliru

但是,有些情况下 qi :: eps 不保存。 (以后会尝试找到链接)。因此,我赞成属性兼容性的老式方法:

However, there are cases where qi::eps doesn't save. (Will try to find links later). Therefore, I've come to favour the 'old-fashioned approach' for attribute compatibility:

#include <boost/spirit/include/qi.hpp>

struct symbol 
{ 
    std::string repr; 

    symbol(std::string repr = std::string()) : repr(std::move(repr)) {}
};

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct test_grammar : qi::grammar<Iterator, symbol(), qi::ascii::space_type> {
    test_grammar() : test_grammar::base_type(start) {
        using namespace qi;

        start = as_string[ lexeme[ +char_("a-z") ] ];
    }

    qi::rule<Iterator, symbol(), qi::ascii::space_type> start;
};

#include <iostream>

auto main() -> int {
    test_grammar<std::string::iterator> grammar{};
    auto input = std::string{"test"};
    auto output = symbol{};
    auto e = end(input);
    if (qi::phrase_parse(begin(input), e, grammar, qi::ascii::space, output))
        std::cout << output.repr;
}

这也可能在编译器上更轻。请参阅

This is also likely a bit lighter on the compiler. See it Live on Coliru as well.

如果所有的失败,你可以有你的蛋糕,并且吃它太,因为属性转换/赋值是自定义点在库中。

If all else fails you can have your cake and eat it too because attribute transformation/assignment are customization points in the library.





  • 在SO上的答案中搜索这些特征

  • Attribute Propagation and Attribute Compatibility
  • Store a Parsed Attribute Value (Qi)
  • Store Parsed Attribute Values into a Container (Qi)
  • search for these traits in answers on SO for good examples

这篇关于Adapt类包含一个字符串成员作为合成属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 06:16