Wednesday 15 April 2015

c++ - Parsing delimited list of tokens using Boost Spirit Qi -



c++ - Parsing delimited list of tokens using Boost Spirit Qi -

using boost::spirit::qi i'm trying parse lines consisting of label followed variable number of delimited tokens. i'm calling grammar phrase_parse , using provided blank parser skip parser preserve newlines need create sure label first item on each line.

the simple base of operations case:

label token, token, token

can parsed grammar:

line = label >> (token % ',') >> eol;

the problem facing grammar should take 0 or more tokens , tokens may empty. grammar should take next lines:

label label , label , token label token, , token,

i have not managed create grammar accepts examples above. suggestions on how solve this?

edit:

thanks sehe input on problem stated above. fun part forgot include... grammar should take empty lines , split lines. (tokens without label) when seek create label optional, infinite loop matching empty string.

label label token token

you should able take empty list with

line = label >> -(token % ',') >> eol;

note eol won't work if skipper skips eol (so don't utilize qi::space e.g. qi::blank purpose)

also, depending on definition of token should maybe alter take "empty" token well

in response comment: working sample live on coliru

#include <boost/spirit/include/qi.hpp> namespace qi = boost::spirit::qi; int main() { using namespace qi; using = std::string::const_iterator; using token = std::string; using tokens = std::vector<token>; rule<it, blank_type> label = lexeme[+~char_(":")] >> ':' ; rule<it, token(), blank_type> token = lexeme[*~char_(",\n")]; ; rule<it, tokens(), blank_type> line = label >> -(token % ',') >> eol ; (std::string const input : { "my first label: 123, 234, 345 spaces\n", "1:\n", "2: \n", "3: ,,,\n", "4: , \t ,,\n", "5: , \t , something,\n", }) { std::cout << std::string(40, '=') << "\nparsing: '" << input << "'\n"; tokens parsed; auto f = input.begin(), l = input.end(); bool ok = phrase_parse(f, l, line, blank, parsed); if (ok) { std::cout << "tokens parsed successfully, number parsed: " << parsed.size() << "\n"; (auto token : parsed) std::cout << "token value '" << token << "'\n"; } else std::cout << "parse failed\n"; if (f != l) std::cout << "remaining input: '" << std::string(f, l) << "'\n"; } }

output:

======================================== parsing: 'my first label: 123, 234, 345 spaces ' tokens parsed successfully, number parsed: 3 token value '123' token value '234' token value '345 spaces' ======================================== parsing: '1: ' tokens parsed successfully, number parsed: 1 token value '' ======================================== parsing: '2: ' tokens parsed successfully, number parsed: 1 token value '' ======================================== parsing: '3: ,,, ' tokens parsed successfully, number parsed: 4 token value '' token value '' token value '' token value '' ======================================== parsing: '4: , ,, ' tokens parsed successfully, number parsed: 4 token value '' token value '' token value '' token value '' ======================================== parsing: '5: , , something, ' tokens parsed successfully, number parsed: 4 token value '' token value '' token value 'something something' token value ''

c++ parsing boost boost-spirit-qi

No comments:

Post a Comment