0

Attempting to learn Boost::Spirit and want to tackle a simple example for c-style identifiers. The grammar below doesn't compile claiming 'incompatible_start_rule'. The goal is for this grammar to return a string instead of a vector of strings, as the default attribute propagation rules would.

template <typename IT>
struct cppIdentifier : qi::grammar<IT, std::string, space_type()>
{

    cppIdentifier() : cppIdentifier::base_type(start)
    {
        start = char_("a-zA-Z_")[boost::phoenix::push_back(_val, _1)]
                >> *(char_("a-zA-Z0-9_")[boost::phoenix::push_back(_val, _1)]);
    }

    qi::rule<IT, std::string, space_type> start;
};

What do I have to do to achieve this?

Also please note that I am well aware that there are likely a host of alternative, more convenient options for this particular problem, but I am academically interested in how to manipulate the attribute type of a custom grammar, so please leave those in the comments instead of the answers.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Alex Court
  • 148
  • 11

1 Answers1

2

First off, you need to use the function-signature-style template parameter to specify the output attribute type of the rule (and inherited attribute types, if any). Instead of qi::grammar<IT, std::string, space_type()>, try qi::grammar<IT, std::string(), space_type>.

Second, you don't really need semantic actions here - but if you're planning to use phrase parser, you'll need lexeme[] directive:

template <typename IT>
struct cppIdentifier : qi::grammar<IT, std::string(), qi::space_type>
{
    cppIdentifier() : cppIdentifier::base_type(start)
    {
        start = qi::lexeme[char_("a-zA-Z_") >> *(char_("a-zA-Z0-9_"))];
    }

    qi::rule<IT, std::string(), qi::space_type> start;
};

Finally, make sure that you are passing a compatible skipper object to the phrase_parse:

std::string s = "HELLO 123";

cppIdentifier < std::string::const_iterator> id;

std::string ident;

qi::phrase_parse(s.cbegin(), s.cend(), id, qi::space_type(), ident);

// without lexeme[], ident becomes "HELLO123", not "HELLO"
Boris Glick
  • 202
  • 1
  • 4
  • 1
    Welcome, new contributor in the [SO] tag of [tag:boost-spirit]. Your help is much appreciated! – sehe Feb 20 '17 at 21:49
  • 1
    Thank you so much! I learned a lot from the site, including from your answers, so If I can help in small way, I try. I also find that I learn quite a bit from writing my own answers. – Boris Glick Feb 21 '17 at 14:52
  • Yes! That works, thank you. Clearly I need to dig deeper into the rule and grammar template arguments. – Alex Court Feb 21 '17 at 15:45