Using std :: array as Attribute for boost :: spirit :: x3

I am trying to parse a list of numbers into a container with a fixed size std::array using boost :: spirit latest release x3 (as included in boost 1.54). Since std::array has the necessary functions, it is defined as a Container, but there is no insert function in it, which makes it incompatible. Here is a brief example of what I'm trying to accomplish:

 #include <boost/spirit/home/x3.hpp> #include <array> #include <iostream> #include <string> namespace x3 = boost::spirit::x3; namespace ascii = boost::spirit::x3::ascii; typedef std::array<double, 3> Vertex; int main(int, char**) { using x3::double_; using ascii::blank; std::string input = "3.1415 42 23.5"; auto iter = input.begin(); auto vertex = x3::rule<class vertex, Vertex>{} = double_ >> double_ >> double_; Vertex v; bool const res = x3::phrase_parse(iter, input.end(), vertex, blank, v); if (!res || iter != input.end()) return EXIT_FAILURE; std::cout << "Match:" << std::endl; for (auto vi : v) std::cout << vi << std::endl; return EXIT_SUCCESS; } 

This will not compile since std::array does not have an insert function. As a workaround, I used semantic actions:

 auto vertex() { using namespace x3; return rule<class vertex_id, Vertex>{} = double_[([](auto &c) { _val(c)[0] = _attr(c); })] >> double_[([](auto &c) { _val(c)[1] = _attr(c); })] >> double_[([](auto &c) { _val(c)[2] = _attr(c); })]; } 

and then call

 x3::phrase_parse(iter, input.end(), vertex(), blank, v); 

instead of this. This works (using clang 3.6.0 with -std = C ++ 14), but I think this solution is very inelegant and hard to read.

So, I tried to adapt std :: array as a merge sequence using BOOST_FUSION_ADAPT_ADT as follows:

 BOOST_FUSION_ADAPT_ADT( Vertex, (double, double, obj[0], obj[0] = val) (double, double, obj[1], obj[1] = val) (double, double, obj[2], obj[2] = val)) 

and then specializing x3::traits::is_container for Vertex to tell x3 not to treat std :: array as a container:

 namespace boost { namespace spirit { namespace x3 { namespace traits { template<> struct is_container<Vertex> : public mpl::false_ {}; }}}} 

But this will not compile in conjunction with x3. Is this a mistake or am I using it incorrectly? A call, for example. fusion::front(v) without compiling and running all x3 code, so I think my code is not quite right.

However, I am sure that there is a pure solution with x3 that does not include any adapters or semantic actions for this simple problem.

+5
source share
1 answer

The code you posted is riddled with careless errors. There is no reason to expect anything to compile, really.

Despite this, I cleaned it up. Of course you should have included

 #include <boost/fusion/adapted/array.hpp> 

Unfortunately, this just doesn't work. I came to the same conclusion: (having tried the same thing that you mentioned before reading about it :)).

This is a usability issue with Spirit X3, which is still in an experimental phase. You can report this on the [spirit-general] mailing list. The answer is usually pretty quick.


ยน if you want to see that I worked with http://paste.ubuntu.com/12764268/ ; I also used x3::repeat(3)[x3::double_] for comparison.

0
source

Source: https://habr.com/ru/post/1233525/


All Articles