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