简体   繁体   中英

Can't compile a boost::spirit::x3 parser with lambda parameters

Based on an answer here , I wrote the following parser:

#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

#include <fstream>
#include <iostream>
#include <vector>

namespace x3 = boost::spirit::x3;

int main() {

    std::ifstream input("input.txt");
    boost::spirit::istream_iterator begin(input >> std::noskipws), end;

    std::vector<float> data1, data2;
    auto capture1 = [&](auto& ctx){ data1.emplace_back(_attr(ctx)); };
    auto capture2 = [&](auto& ctx){ data2.emplace_back(_attr(ctx)); };

    auto sequence1 =  "v" >> x3::float_[capture1] >> x3::float_[capture1] >> x3::float_[capture1];
    auto sequence2 =  "vn" >> x3::float_[capture2] >> x3::float_[capture2] >> x3::float_[capture2];

    auto skipper = x3::blank | '#' >> *(x3::char_ - x3::eol) >> (x3::eol|x3::eoi);
    auto rule = x3::skip(skipper) [ *x3::eol >> 
        *( +(sequence1 >> (x3::eoi|+x3::eol) ) >>
           *(sequence2 >> (x3::eoi|+x3::eol) ) )
    ];

    if (x3::parse(begin, end, rule)) {

        std::cout << "data1 size: " << data1.size() << "\n";

        for(float& i:data1)
            std::cout << i << ", ";
        std::cout << '\n';

        std::cout << "data2 size: " << data2.size() << "\n";
        for(float& i:data2)
            std::cout << i << ", ";
        std::cout << '\n';

    } else 
        std::cout << "failed to parse!\n";
    
    if(begin!=end)
        std::cerr<< "did not parsed completely!";


    //---------------------------------
    std::cout << "\ndone!\n";
    return EXIT_SUCCESS;
}

And my input file looks something like this:


# group 1

v -111.11 -0.017928 0.005579
v -0.014504 -0.017928 0.010577
v -0.010538 -0.017928 0.014543
v -0.005540 -0.017928 0.017090

vn -111.11 -0.017928 0.005579
vn -0.014504 -0.017928 0.010577
vn -0.010538 -0.017928 0.014543


# group 2

v 0.005540 -0.017928 0.017090
v 0.010538 -0.017928 0.014543
v 0.014504 -0.017928 0.010577

vn 0.014504 -0.017928 0.010577
vn 0.017050 -0.017928 0.005579
vn 0.017928 -0.017928 0.000039
vn -0.010538 -0.017928 0.014543


# group 3  
# and so on..

The same code was compiled and parsed correctly with the following settings:

  • on windows 10 with boost-1.67.0 and gcc by MinGW-W64 7.3.0 "compiled and parsed fine!"
  • on debian 9 with boost-1.62.0 and gcc 6.3.0 "compiled and parsed fine!"

However I was not able to compile it on ubuntu 18.04 with boost-1.65.1 and gcc ( 7.5.0 , 9.3.0 , and 10.1.0 ) with ( c++14 , c++17 or c++20 ).

Here is a part of error msg:

In file included from /usr/include/boost/spirit/home/x3/directive/expect.hpp:12,
                 from /usr/include/boost/spirit/home/x3/auxiliary/guard.hpp:11,
                 from /usr/include/boost/spirit/home/x3/auxiliary.hpp:13,
                 from /usr/include/boost/spirit/home/x3.hpp:14,
                 from parser.cpp:1:
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp: In instantiation of 'static bool boost::spirit::x3::detail::parse_into_container_impl<Parser, Context, RContext, typename boost::enable_if<boost::spirit::x3::traits::handles_container<Parser, Context> >::type>::call(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&, mpl_::true_) [with Iterator = boost::spirit::basic_istream_iterator<char>; Attribute = const boost::spirit::x3::unused_type; Parser = boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type; mpl_::true_ = mpl_::bool_<true>]':
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:281:24:   required from 'static bool boost::spirit::x3::detail::parse_into_container_impl<Parser, Context, RContext, typename boost::enable_if<boost::spirit::x3::traits::handles_container<Parser, Context> >::type>::call(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&) [with Iterator = boost::spirit::basic_istream_iterator<char>; Attribute = const boost::spirit::x3::unused_type; Parser = boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type]'
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:293:74:   required from 'bool boost::spirit::x3::detail::parse_into_container(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&) [with Parser = boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >; Iterator = boost::spirit::basic_istream_iterator<char>; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type; Attribute = const boost::spirit::x3::unused_type]'
/usr/include/boost/spirit/home/x3/operator/detail/sequence.hpp:378:33:   required from 'bool boost::spirit::x3::detail::parse_sequence(const Parser&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&, boost::spirit::x3::traits::container_attribute) [with Parser = boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > >; Iterator = boost::spirit::basic_istream_iterator<char>; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type; Attribute = const boost::spirit::x3::unused_type]'
/usr/include/boost/spirit/home/x3/operator/detail/sequence.hpp:463:32:   required from 'static bool boost::spirit::x3::detail::parse_into_container_impl<boost::spirit::x3::sequence<L, R>, Context, RContext>::call(const parser_type&, Iterator&, const Iterator&, const Context&, RContext&, Attribute&, mpl_::false_) [with Iterator = boost::spirit::basic_istream_iterator<char>; Attribute = const boost::spirit::x3::unused_type; Left = boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >; Right = boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type; boost::spirit::x3::detail::parse_into_container_impl<boost::spirit::x3::sequence<L, R>, Context, RContext>::parser_type = boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > >; mpl_::false_ = mpl_::bool_<false>]'
/usr/include/boost/spirit/home/x3/operator/detail/sequence.hpp:496:24:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/spirit/home/x3/operator/kleene.hpp:32:48:   required from 'bool boost::spirit::x3::kleene<Subject>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = boost::spirit::basic_istream_iterator<char>; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type; Attribute = const boost::spirit::x3::unused_type; Subject = boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > >]'
/usr/include/boost/spirit/home/x3/operator/sequence.hpp:32:37:   required from 'bool boost::spirit::x3::sequence<Left, Right>::parse(Iterator&, const Iterator&, const Context&, RContext&, boost::spirit::x3::unused_type) const [with Iterator = boost::spirit::basic_istream_iterator<char>; Context = boost::spirit::x3::context<boost::spirit::x3::skipper_tag, const boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >, boost::spirit::x3::unused_type>; RContext = const boost::spirit::x3::unused_type; Left = boost::spirit::x3::kleene<boost::spirit::x3::eol_parser>; Right = boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > > >]'
/usr/include/boost/spirit/home/x3/directive/skip.hpp:75:39:   required from 'bool boost::spirit::x3::skip_directive<Subject, Skipper>::parse(Iterator&, const Iterator&, const Context&, RContext&, Attribute&) const [with Iterator = boost::spirit::basic_istream_iterator<char>; Context = boost::spirit::x3::unused_type; RContext = const boost::spirit::x3::unused_type; Attribute = const boost::spirit::x3::unused_type; Subject = boost::spirit::x3::sequence<boost::spirit::x3::kleene<boost::spirit::x3::eol_parser>, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > > > >; Skipper = boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > >]'
/usr/include/boost/spirit/home/x3/core/parse.hpp:35:34:   required from 'bool boost::spirit::x3::parse_main(Iterator&, Iterator, const Parser&, Attribute&) [with Iterator = boost::spirit::basic_istream_iterator<char>; Parser = boost::spirit::x3::skip_directive<boost::spirit::x3::sequence<boost::spirit::x3::kleene<boost::spirit::x3::eol_parser>, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > > > >, boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > > >; Attribute = const boost::spirit::x3::unused_type]'
/usr/include/boost/spirit/home/x3/core/parse.hpp:71:26:   required from 'bool boost::spirit::x3::parse(Iterator&, Iterator, const Parser&) [with Iterator = boost::spirit::basic_istream_iterator<char>; Parser = boost::spirit::x3::skip_directive<boost::spirit::x3::sequence<boost::spirit::x3::kleene<boost::spirit::x3::eol_parser>, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::plus<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:1&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > >, boost::spirit::x3::kleene<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_string<const char*, boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::action<boost::spirit::x3::real_parser<float>, main()::<lambda(auto:2&)> > >, boost::spirit::x3::alternative<boost::spirit::x3::eoi_parser, boost::spirit::x3::plus<boost::spirit::x3::eol_parser> > > > > > >, boost::spirit::x3::alternative<boost::spirit::x3::char_class<boost::spirit::char_encoding::standard, boost::spirit::x3::blank_tag>, boost::spirit::x3::sequence<boost::spirit::x3::sequence<boost::spirit::x3::literal_char<boost::spirit::char_encoding::standard, boost::spirit::x3::unused_type>, boost::spirit::x3::kleene<boost::spirit::x3::difference<boost::spirit::x3::any_char<boost::spirit::char_encoding::standard>, boost::spirit::x3::eol_parser> > >, boost::spirit::x3::alternative<boost::spirit::x3::eol_parser, boost::spirit::x3::eoi_parser> > > >]'
parser.cpp:28:35:   required from here
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:254:22: error: 'const struct boost::spirit::x3::unused_type' has no member named 'empty'
  254 |             if (attr.empty())
      |                 ~~~~~^~~~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:22: error: 'const struct boost::spirit::x3::unused_type' has no member named 'insert'
  259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
      |                 ~~~~~^~~~~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:34: error: 'const struct boost::spirit::x3::unused_type' has no member named 'end'
  259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
      |                             ~~~~~^~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:46: error: 'const struct boost::spirit::x3::unused_type' has no member named 'begin'
  259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
      |                                         ~~~~~^~~~~
/usr/include/boost/spirit/home/x3/core/detail/parse_into_container.hpp:259:60: error: 'const struct boost::spirit::x3::unused_type' has no member named 'end'
  259 |                 attr.insert(attr.end(), rest.begin(), rest.end());
      |

.
.
.
.

I also tried a suggestion as in this answer , but it still won't compile!

Can someone point out where I'm doing it wrong, or at least what MIGHT BE causing this? Thanks

It's a known and fixed bug in 1.65.0, 1.65.1 and 1.66

See it for yourself: https://wandbox.org/permlink/32WK3LoPb8yqmfsV (switch boost versions on the left).

Workaround?

Here's a simplified version - the parser is unchanged but more readable (that's me reviewing the code) and the input is hard-coded for Compiler Explorer :

#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

#include <fstream>
#include <fmt/ranges.h>

namespace x3 = boost::spirit::x3;

int main() {
    std::string const& input = R"(# group 1
v -111.11 -0.017928 0.005579
vn -111.11 -0.017928 0.005579
# group 2
v 0.005540 -0.017928 0.017090
vn 0.014504 -0.017928 0.010577
# and so on..)";

    auto triplet = [](auto id, auto& v) {
        auto action = [&v](auto& ctx){ v.emplace_back(x3::_attr(ctx)); };
        return id >> x3::repeat(3) [x3::double_ [action]];
    };

    auto NL = x3::eoi|+x3::eol;
    auto skipper = x3::blank | '#' >> *(x3::char_ - x3::eol) >> NL;

    std::vector<float> v, vn;
    auto rule = x3::skip(skipper) [ -NL >> 
        *( +(triplet("v",  v)  >> NL) >>
        *(triplet("vn", vn) >> NL) )
    ];

    if (x3::parse(begin(input), end(input), rule >> x3::eoi)) {
        fmt::print("v: {}\nvn: {}\n", v, vn);
    }
}

Prints

v: {-111.11, -0.017928, 0.005579, 0.00554, -0.017928, 0.01709}
vn: {-111.11, -0.017928, 0.005579, 0.014504, -0.017928, 0.010577}

Note how this, due the semantic actions, conflates data sequences from different groups. Compare to below!

Now switching to 1.66.0 also fails: https://godbolt.org/z/bjvETE

However, here's even further simplified but without any semantic actions:

Live On Compiler Explorer

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>

#include <fstream>
#include <fmt/ranges.h>

namespace x3 = boost::spirit::x3;

int main() {
    std::string const& input = R"(# group 1
v -111.11 -0.017928 0.005579
vn -111.11 -0.017928 0.005579
# group 2
v 0.005540 -0.017928 0.017090
vn 0.014504 -0.017928 0.010577
# and so on..)";

    auto NL = x3::eoi|+x3::eol;
    auto skipper = x3::blank | '#' >> *(x3::char_ - x3::eol) >> NL;
    auto triplet = x3::repeat(3) [x3::double_];

    using V = std::vector<float>;
    using VN = std::vector<float>;
    using Group = std::tuple<V, VN>;

    auto group
        = x3::rule<struct rule_id, Group> {"group"}
        = +("v" >> triplet >> NL) >>
        *("vn" >> triplet >> NL)
        ;

    auto rule = x3::skip(skipper) [ -NL >> *group ];

    std::vector<Group> groups;
    if (x3::parse(begin(input), end(input), rule >> x3::eoi, groups)) {
        fmt::print("{}\n", fmt::join(groups, "\n"));
    }
}

Most importantly, it no longer conflates groups :

({-111.11, -0.017928, 0.005579}, {-111.11, -0.017928, 0.005579})
({0.00554, -0.017928, 0.01709}, {0.014504, -0.017928, 0.010577})

Printing the data without libfmt ( Live On Coliru )

for (auto& [v,vn] : groups) {
    std::cout << "\nv"; for  (auto&& f : v)  std::cout << " " << f;
    std::cout << "\nvn"; for (auto&& f : vn) std::cout << " " << f;
}

Output:

v -111.11 -0.017928 0.005579
vn -111.11 -0.017928 0.005579
v 0.00554 -0.017928 0.01709
vn 0.014504 -0.017928 0.010577

TL;DR

Just upgrade your boost version. Spirit is entirely header-only, so you might just be able to drop in 1.67.0 headers from boost/spirit/x3 into a project folder if you need.

Off-topic: Semantic actions have drawbacks: Boost Spirit: "Semantic actions are evil"? .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM