2

I have a snippet of boost::spirit::qi code which can match "M7. x . y . z" or "M7.x.y.z", but I want a parser which fails on the former input.

I think I need to insert qi::lexeme[] or qi::no_skip[] in there, but I'm having no luck getting it to compile properly.

EDIT simplified rule for variable

Code

#define BOOST_SPIRIT_DEBUG

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>

#include <string>
namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;

    template <typename Iterator>
    struct my_parser : qi::grammar<Iterator, std::vector<std::string>(), 
        ascii::space_type>
    {
      my_parser() : 
            my_parser::base_type( variable )
        {
            using qi::int_;
            using qi::lit;
            using qi::double_;
            using qi::lexeme;
            using ascii::char_;

            identifier %= 
                char_( "[a-z_]" )
                >> *char_( "*[a-zA-Z0-9_]" )
            ;

            variable %= simple_var % '.'   // <----- need fix here
            ;

            simple_var %= qi::string("M7") | identifier;

            BOOST_SPIRIT_DEBUG_NODE( variable );
            BOOST_SPIRIT_DEBUG_NODE( identifier );
        }

        qi::rule<Iterator, std::string(), ascii::space_type> 
            identifier, simple_var;

        qi::rule<Iterator, std::vector<std::string>(), ascii::space_type> 
            variable;
    };
}

int main( int argc, char* argv[] )
{
    using boost::spirit::ascii::space;

    typedef std::string::const_iterator iterator_type;
    typedef client::my_parser<iterator_type> my_parser;

    my_parser       g; 

    std::vector< std::string >    result;
    std::string input( "M7. x . y . z" );  // want this to FAIL!!!

    std::string::const_iterator iter = input.begin();
    std::string::const_iterator end  = input.end();

    if (phrase_parse( iter, end, g, space, result ) && iter == end)
        std::cout << "Parsing succeeded\n";
    else
        std::cout << "Parsing failed\n";
}
kfmfe04
  • 14,936
  • 14
  • 74
  • 140
  • Possible duplicate of [How do I grok...](http://stackoverflow.com/questions/13000730/how-do-i-grok-boost-spirit-compiler-errors). –  Nov 29 '12 at 19:59
  • [Interesting article](http://boost-spirit.com/home/2010/02/24/parsing-skippers-and-skipping-parsers/) about skippers. –  Nov 29 '12 at 20:16

1 Answers1

3

qi::lexeme[] accets only no-skipper rules.

You can declare identifier and simple_var as:

qi::rule<Iterator, std::string()> identifier,simple_var;

Now you can use lexeme in variable

variable %= lexeme[simple_var % '.'];
sbabbi
  • 11,070
  • 2
  • 29
  • 57