Boost Spirit V2: identifier separated by a space

The following boost spirit grammar tries to parse the text like “int foo;”.

template <typename Iterator>
struct test_grammar : boost::spirit::qi::grammar<Iterator, boost::spirit::qi::space_type>
{
    test_grammar() : test_grammar::base_type(start){
        using boost::spirit::qi::alpha;
        using boost::spirit::qi::lexeme;
        
        identifier = +alpha;
        start = identifier >> identifier >> ';';
    }
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::space_type> identifier;
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::space_type> start;
};

But it fails because space_type removes all the spaces. The input text is essentially “intfoo;”.

To correctly parse it, you have to use lexeme rule:

template <typename Iterator>
struct test_grammar : boost::spirit::qi::grammar<Iterator, boost::spirit::qi::space_type>
{
    test_grammar() : test_grammar::base_type(start){
        using boost::spirit::qi::alpha;
        using boost::spirit::qi::lexeme;
        
        identifier = lexeme[+alpha];
        start = identifier >> identifier >> ';';
    }
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::space_type> identifier;
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::space_type> start;
};

The full source code is here:

template <typename Iterator>
struct test_grammar : boost::spirit::qi::grammar<Iterator, boost::spirit::qi::space_type>
{
    test_grammar() : test_grammar::base_type(start){
        using boost::spirit::qi::alpha;
        using boost::spirit::qi::lexeme;
        
        identifier = lexeme[+alpha];
        start = identifier >> identifier >> ';';
    }
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::space_type> identifier;
    boost::spirit::qi::rule<Iterator, boost::spirit::qi::space_type> start;
};

int main()
{
    string input = "int foo;";
    
    std::string::const_iterator iter = input.begin();
    std::string::const_iterator end  = input.end();

    test_grammar< std::string::const_iterator > g;

    bool r = phrase_parse(iter, end, g, boost::spirit::qi::space);
    if (r && iter == end) { 
        std::cout << "Parsing succeededn";
    }else {
        std::cout << "Parsing failedn";
        std::string::const_iterator some = iter;
        std::string context(iter, end);
        std::cout << "stopped at: " << context << endl;
    }
    return 0;
}

Advertisements

About Moto

Engineer who likes coding
This entry was posted in Tips. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s