Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning parsers to auto variables

Are spirit parsers not meant to be used with auto?

A simple parser works fine when passed to qi::parse() inline, but crashes with segfault if passed via an auto variable:

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

using namespace std;

namespace qi = boost::spirit::qi;

int main()
{
    string line = "[z]";

    auto bracketed_z = '[' >> +qi::char_('z') >> ']';

    auto p = line.cbegin();
    printf("%d", qi::parse(p, line.cend(), '[' >> +qi::char_('z') >> ']'));  // Works

    p = line.cbegin();
    printf("%d", qi::parse(p, line.cend(), bracketed_z));                    // Crashes
}

Reproes with g++-4.8 and VC13.

Update: an error was fixed in the original code (p was not re-initialized before the second call to parse()).

like image 509
mstone Avatar asked Feb 25 '14 19:02

mstone


2 Answers

Spirit Parsers are not designed to be used with auto in Spirit V2.

This is because the underlying Proto expression templates hold references to the temporaries.

You can use

  • qi::copy() (existing in the trunk after boost_1_55_0, not in any released version at this time)
  • boost::proto::deep_copy
  • or BOOST_SPIRIT_AUTO (first coined here)

I've written about these things more often on SO: https://stackoverflow.com/search?q=user%3A85371+deep_copy, specifically, this:

  • boost spirit V2 qi bug associated with optimization level

Boost Spirit X3 will not have this limitation.

like image 60
sehe Avatar answered Sep 18 '22 09:09

sehe


Boost.Spirit uses expression templates and does not work with auto. A workaround is to use boost::proto::deep_copy:

auto bracketed_z = proto::deep_copy('[' >> +qi::char_('z') >> ']');
like image 35
Juraj Blaho Avatar answered Sep 18 '22 09:09

Juraj Blaho