Can spirit X3 work with BOOST_FUSION_ADAPT_ADT?

自闭症网瘾萝莉.ら 提交于 2019-12-06 03:06:32

As I've been warning people before¹ you're pushing limits right on the intersection of things that frequently break Spirit's gears:

  1. single-element fusion sequences
  2. ADT adaptation in general
  3. Persistent bugs with ADT fixed in develop (after 1.67.0 release)

1. The Single-Element Conundrum

I won't spend much time on this because it's a rather old, boring, well-documented² and not essential to your question.

Let's side-step it by adding a dummy field:

struct rexpr
{
    rexpr_map i_entries;

    const rexpr_map& entries() const { return i_entries; }
    rexpr_map& entries() { return i_entries; }

    void entries(const rexpr_map& ent) { i_entries = ent; }

    int i_dummy;
    int dummy() const { return i_dummy; }
    void dummy(int i) { i_dummy = i; }
};

// ... later:
BOOST_FUSION_ADAPT_ADT(client::ast::rexpr,
    (obj.entries(), obj.entries(val))
    (obj.dummy(), obj.dummy(val))
)

// ... even later:
auto const rexpr_def =
    '{' >> *rexpr_key_value >> '}' >> x3::attr(42);

2. The ADT Proxy

The attribute-category machinery of Spirit detects the entries property as a container attribute (is_container<...>{} evaluates to true).

However the requisite container traits are not in place.

What's more, because of the restrictive interface that ADT proxies grant, the property values can only replaced whole-sale, meaning that we can only implement a very suboptimal version of it:

namespace boost { namespace spirit { namespace x3 { namespace traits {

    template <typename T, auto... Other>
    struct container_value<boost::fusion::extension::adt_attribute_proxy<T, Other...> > 
        : container_value<typename boost::fusion::extension::adt_attribute_proxy<T, Other...>::type>
    { };

    template <typename T, auto... Other>
    struct push_back_container<boost::fusion::extension::adt_attribute_proxy<T, Other...> > 
    {
        using underlying_type = typename boost::fusion::extension::adt_attribute_proxy<T, Other...>::type;

        template <typename X, typename Y>
            static bool call(X& proxy, Y&& v) {
                auto u = proxy.get();
                bool b = push_back_container<underlying_type>::call(u, std::forward<Y>(v));
                proxy = u;
                return b;
            }
    };

} } } }

3. Surprise: Old bugs fixed after 1.67.0

You require the commits:

commit ae78e1ec2431517a8b0580099aeba8f9122d8abb
Author: Nikita Kniazev <nok.raven@gmail.com>
Date:   Thu Mar 15 17:33:36 2018 +0300

    X3: sequence: Fixed reference to temporary bug

commit e7f31017ec7c0b5584d12ec1b718d8c415b26fa1
Author: Nikita Kniazev <nok.raven@gmail.com>
Date:   Wed Mar 14 18:54:35 2018 +0300

    Qi: Fixed ADT support by permutation and sequence_or operator

    This is follow-up to 0f2b3c49ce55a41a7d22cc5533e0f4ba59e491ae

These are more recent than 1.67.0 and currently in the develop branch. They (in part) fix an old issue: https://github.com/boostorg/spirit/pull/153#issuecomment-152879056. The current behaviour may also be impacted by commit

commit a0df3c098ff4e42c0958796c4f47d4d72a20c164
Merge: f73b121 fac9dfa
Author: Nikita Kniazev <nok.raven@gmail.com>
Date:   Thu Mar 1 13:44:27 2018 +0300

    Merge pull request #370 from Kojoley/x3-pass-container-attribute-through-sequence

    X3: Pass container attribute through sequence

It's hard to gauge whether the impact is positive or negative in this ... turbulent landscape.

Demo

Suffice it to say that iff you

  1. compile against ae78e1ec243151 or later (develop)
  2. Apply both the workarounds described above

then I see the expected output:

-------------------------
Parsing succeeded
-------------------------
{
    "color" = "blue"
    "position" = {
        "x" = "123"
        "y" = "456"
    }
    "size" = "29 cm."
}

(based on libs/spirit/example/x3/rexpr/rexpr_examples/a.rexpr input).

Summarizing

I hope you don't think this is "fine". Please consider filing an issue at the mailing list/github. Also take these into account:


¹ not to mention my dislike for it in most cases: Using spirit to parse into classes?

² Spirit Qi attribute propagation issue with single-member struct, X3, what is attr_gen?, boost::spirit::x3 attribute compatibility rules, intuition or code?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!