boostorg / spirit

Boost.org spirit module
http://boost.org/libs/spirit
392 stars 161 forks source link

How to get a vector of values using a parser that operates on the `fusion::view`? #728

Open denzor200 opened 2 years ago

denzor200 commented 2 years ago

Example code https://godbolt.org/z/W8vsTPM6f

Current behaviour Won't compile because fusion::reverse_view has no default constructor.

Expected behaviour To print:

10 3.141
20 4.555

Hello. Is it possible to implement support for this functionality on the Boost Spirit side? Thanks.

denzor200 commented 2 years ago

It works good, when i need to get one element(not a vector): https://godbolt.org/z/qo74dG47z

djowel commented 2 years ago

I don't think so. You need a mutable sequence. Views are not.

Edit: Disregard.

djowel commented 2 years ago

It works good, when i need to get one element(not a vector): https://godbolt.org/z/qo74dG47z

I see. So it's not really about mutability, but the requirement of std::vector to be able to default construct its elements.

denzor200 commented 2 years ago

but the requirement of std::vector to be able to default construct its elements

We just need to disable this requirement on the Spirit side. And i suppose, we can do it only for sequence of some views

Kojoley commented 2 years ago

What does it mean for a rule to produce a view. Where that view will point to?

denzor200 commented 2 years ago

What does it mean for a rule to produce a view.

I can't understand. You mean that this issue not possible?

Where that view will point to?

I suppose that view won't have a long lifetime, it will be created just to be passed into child parse function as Attribute, and it will be point to element of user passed container from outside as Attribute.

djowel commented 2 years ago

Again, the issue here is that std::vector requires default constructible elements. Fusion views are not. Typically, they hold a reference to a fusion container.

denzor200 commented 2 years ago

fix for it looks like very easy https://godbolt.org/z/hEhP4W6jz

denzor200 commented 2 years ago

But i don't tested: -How it works with another operators(for example - optional), with not only kleene star. -How it works with fusion::view<fusion::view<fusion::view<...>>>.

I may create a PR, if you are interesting.

djowel commented 2 years ago

fix for it looks like very easy https://godbolt.org/z/hEhP4W6jz

Interesting trick!

Kojoley commented 2 years ago

What does it mean for a rule to produce a view.

I can't understand. You mean that this issue not possible?

Look at rules like they are functions witch returns values. What does it mean to return a view from a function? Assuming it is a stateless function -- It means it has received a view (a reference) as an argument. It is a an implementation detail that parsers receive a reference to the attribute, it could be done in another way, by returning values. Usually, Spirit parsers create a temporary to parse value to, and after parsing is done the value is is copied to the destination, parsing directly into the destination is just an optimization.

Where that view will point to?

I suppose that view won't have a long lifetime, it will be created just to be passed into child parse function as Attribute, and it will be point to element of user passed container from outside as Attribute.

Multiple question surfaces from this: 1) Why we want short-lived attributes? 2) How we can ensure it lifetime?

fix for it looks like very easy godbolt.org/z/hEhP4W6jz

See, I understand there might be uses for producing views from rules, but your question looks like xyproblem. If your intention is to be able to reorder/slice fields, I think, it is better to find ways to express it inside the grammar, something like slice(&TwoFields::second, &TwoFields::first)[double_ >> int_] or even double_ = &TwoFields::second >> int_ = &TwoFields::first.

But i don't tested: -How it works with another operators(for example - optional), with not only kleene star.

Or parsing into an optional.

denzor200 commented 2 years ago

If your intention is to be able to reorder/slice fields

No, it's not a my intention. I answered this question not for reorder/slice fields, I do it for https://github.com/boostorg/fusion/pull/241, and real examples will have fusion::pfr_fields_view instead of fusion::reverse_view.

denzor200 commented 2 years ago

Another words, answer for this question need for me to get rid of BOOST_FUSION_ADAPT_STRUCT macro. You can see details in my PRs into Fusion.

Kojoley commented 2 years ago

If your intention is to be able to reorder/slice fields

No, it's not a my intention. I answered this question not for reorder/slice fields, I do it for boostorg/fusion#241, and real examples will have fusion::pfr_fields_view instead of fusion::reverse_view.

Another words, answer for this question need for me to get rid of BOOST_FUSION_ADAPT_STRUCT macro. You can see details in my PRs into Fusion.

Sequence parser internally converts a tuple into a fusion view, it should not require anything from Spirit to enable that. I would expect that adding PRF support to Fusion means that fusion::begin(attribute) is working out-of-the box (without BOOST_FUSION_ADAPT_STRUCT, maybe by including some enabling header).

denzor200 commented 2 years ago

Sequence parser internally converts a tuple into a fusion view, it should not require anything from Spirit to enable that. I would expect that adding PRF support to Fusion means that fusion::begin(attribute) is working out-of-the box (without BOOST_FUSION_ADAPT_STRUCT, maybe by including some enabling header).

Totally agree with you. But decltype(attribute) in most cases will be fusion::pfr_fields_view<AnUserDefinedStructure>, that's why i raised this issue.

denzor200 commented 2 years ago

Why we want short-lived attributes?

We have no choice when user need to parse into a container of AnUserDefinedStructure, he can't wrap it(or it's nonexistent elements) into view, but we can wrap each new element inside x3::parse call(by create our short-lived attribute), and then put new element into container.

We don't want short-lived attribute when user need to parse into one AnUserDefinedStructure, he just can do wrapping into view manually, like here: https://godbolt.org/z/qo74dG47z

denzor200 commented 2 years ago

How we can ensure it lifetime?

It was create inside an 'x3::parse' call and it will die here. There is no links to it outside the call

Kojoley commented 2 years ago

You just going the wrong way. I see no point for rules to have a view attribute, it also does not make logical sense to me. The only reason you want them is to workaround something that you are not telling here (UPD: I think I have found which https://github.com/boostorg/fusion/pull/241#issuecomment-1183653223). If you want to make Fusion interop with PRF -- you should make Fusion functions on views to work with that new Fusion view type. Spirit should work out-of-the box when you implement all necessary Fusion stuff (and if it does not - file an issue about that).

djowel commented 2 years ago

After thinking about it, I think I am with @Kojoley here. Special case should be avoided as much as possible. There ought to be another solution that does not require special handling for a particular type/attribute without any workarounds?