Search code examples
c++boostboost-spiritboost-spirit-qi

Extracting Values from string using spirit parser


i have following line /90pv-RKSJ-UCS2C usecmap

std::string const line = "/90pv-RKSJ-UCS2C usecmap";

auto first = line.begin(), last = line.end();

std::string label, token;
bool ok = qi::phrase_parse(
        first, last, 
        qi::lexeme [ "/" >> +~qi::char_(" ") ] >> ' ' >>  qi::lexeme[+~qi::char_(' ')] , qi::space, label, token);


if (ok)
    std::cout << "Parse success: label='" << label << "', token='" << token << "'\n";
else
    std::cout << "Parse failed\n";

if (first!=last)
    std::cout << "Remaining unparsed input: '" << std::string(first, last) << "'\n";

I want to 90pv-RKSJ-UCS2C in label and usecmap in token variable.

I extract 90pv-RKSJ-UCS2C value but not usecmap


Solution

  • With space the skipper, you cannot ever match ' ' (it is skipped!). See also: Boost spirit skipper issues

    So, either don't use a skipper, or allow the skipper to eat it:

    bool ok = qi::phrase_parse(
            first, last, 
            qi::lexeme [ "/" >> +qi::graph ] >> qi::lexeme[+qi::graph], qi::blank, label, token);
    

    Notes:

    • I used qi::graph instead of the ~qi::char_(" ") formulation
    • I used blank_type because you said

      i have following line

      Which implies that line-ends should not be skipped

    Demo

    Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    
    namespace qi = boost::spirit::qi;
    
    int main()
    {
        std::string const line = "/90pv-rksj-ucs2c usecmap";
    
        auto first = line.begin(), last = line.end();
    
        std::string label, token;
        bool ok = qi::phrase_parse(
                first, last, 
                qi::lexeme [ "/" >> +qi::graph ] >> qi::lexeme[+qi::graph], qi::blank, label, token);
    
        if (ok)
            std::cout << "parse success: label='" << label << "', token='" << token << "'\n";
        else
            std::cout << "parse failed\n";
    
        if (first!=last)
            std::cout << "remaining unparsed input: '" << std::string(first, last) << "'\n";
    }
    

    Prints:

    parse success: label='90pv-rksj-ucs2c', token='usecmap'