У меня есть фрагмент boost::spirit::qi
код, который может соответствовать "M7. x . y . z"
или же "M7.x.y.z"
, но я хочу парсер, который терпит неудачу на первом входе.
Я думаю, что мне нужно вставить qi::lexeme[]
или же qi::no_skip[]
там, но мне не повезло заставить его правильно скомпилировать.
РЕДАКТИРОВАТЬ упрощенное правило для переменной
Код
#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";
}
qi::lexeme[]
принимает только правила без шкипера.
Вы можете объявить идентификатор и simple_var как:
qi::rule<Iterator, std::string()> identifier,simple_var;
Теперь вы можете использовать лексему в variable
variable %= lexeme[simple_var % '.'];
Других решений пока нет …