Boost.Spirit Parsing Optional Prefix

后端 未结 1 1341
伪装坚强ぢ
伪装坚强ぢ 2021-01-20 06:24

I\'m attempting to parse a string of whitespace-delimited, optionally-tagged keywords. For example

descr:expense type:receivable customer 27.3
相关标签:
1条回答
  • 2021-01-20 06:55

    Rather, it's got a copy of the value. The second part of the pair has the value as well.

    This is the common pitfall with container attributes and backtracking: use qi::hold, e.g. Understanding Boost.spirit's string parser

        pair  = -qi::hold[field >> ':'] >> value;
    

    Complete sample Live On Coliru

    #include <boost/spirit/include/qi.hpp>
    #include <boost/fusion/adapted/std_pair.hpp>
    #include <boost/optional/optional_io.hpp>
    #include <iostream>
    
    namespace qi    = boost::spirit::qi;
    
    typedef std::pair<boost::optional<std::string>, std::string> pair_type;
    typedef std::vector<pair_type> pairs_type;
    
    template <typename Iterator>
    struct Grammar : qi::grammar<Iterator, pairs_type()>
    {
        Grammar() : Grammar::base_type(query) {
            query =  pair % ' ';
            pair  = -qi::hold[field >> ':'] >> value;
            field = +qi::char_("a-zA-Z0-9");
            value = +qi::char_("a-zA-Z0-9+-\\.");
        }
      private:
        qi::rule<Iterator, pairs_type()> query;
        qi::rule<Iterator, pair_type()> pair;
        qi::rule<Iterator, std::string()> field, value;
    };
    
    int main()
    {
        using It = std::string::const_iterator;
    
        for (std::string const input : {
                "descr:expense type:receivable customer 27.3",
                "expense type:receivable customer 27.3",
                "descr:expense receivable customer 27.3",
                "expense receivable customer 27.3",
        }) {
            It f = input.begin(), l = input.end();
    
            std::cout << "==== '" << input << "' =============\n";
            pairs_type data;
            if (qi::parse(f, l, Grammar<It>(), data)) {
                std::cout << "Parsed: \n";
                for (auto& p : data) {
                    std::cout << p.first << "\t->'" << p.second << "'\n";
                }
            } else {
                std::cout << "Parse failed\n";
            }
    
            if (f != l)
                std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
        }
    }
    

    Printing

    ==== 'descr:expense type:receivable customer 27.3' =============
    Parsed: 
     descr  ->'expense'
     type   ->'receivable'
    --  ->'customer'
    --  ->'27.3'
    ==== 'expense type:receivable customer 27.3' =============
    Parsed: 
    --  ->'expense'
     type   ->'receivable'
    --  ->'customer'
    --  ->'27.3'
    ==== 'descr:expense receivable customer 27.3' =============
    Parsed: 
     descr  ->'expense'
    --  ->'receivable'
    --  ->'customer'
    --  ->'27.3'
    ==== 'expense receivable customer 27.3' =============
    Parsed: 
    --  ->'expense'
    --  ->'receivable'
    --  ->'customer'
    --  ->'27.3'
    
    0 讨论(0)
提交回复
热议问题