Function or functor calling using sprit boost pars

2019-02-18 22:51发布

问题:

I want to parse this line and storing all hex values in functor <005F> <0061> [<00660066> <00660069> <00660066006C>] this values in txt file and m reading this fill line by line

like 005F 0061 00660066 00660069 00660066006C all values should be in vector but its not working

the spirit rule is to parse this line is

rule<> blanks = *blank_p;
rule<> parse_int = blanks >> "<" >> int_p [AddEntry] >> ">";
rule<> parse_ints = *parse_int ;
rule<> parse_range = *parse_int >>"[" >> blanks >> *parse_int >> "]";

int status = parse (line.c_str(),
*(
     parse_range 
 )
 ).full;

and my functor is this

struct AddEntry
{
    vector<int> list;   
    void operator()( int integer)
    {
        list.push_back(integer);
    }
};

回答1:

Here's a sample doing this using Spirit V2

Live On Coliru

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
namespace qi  = boost::spirit::qi;

int main() {
    typedef std::string::const_iterator It;
    std::string const line = "<005F> <0061> [<00660066> <00660069> <00660066006C>]";

    It f = line.begin(), l = line.end();

    qi::int_parser<uintmax_t, 16> hex_int;
    qi::rule<It, uintmax_t()> braced_hex = '<' >> hex_int >> '>';
    BOOST_SPIRIT_DEBUG_NODE(braced_hex);

    std::vector<uintmax_t> list;
    bool result = qi::phrase_parse(f, l, *braced_hex >> '[' >> *braced_hex >> ']', qi::space, list);

    if (result) {
        std::cout << "Parse success: " << list.size() << "\n";

        for (auto& v : list)
            std::cout << v << " ";
    }
    else {
        std::cout << "Parse failed\n";
    }

    if (f!=l) {
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
    }
}

Output:

Parse success: 5
95 97 6684774 6684777 438093348972 

Debug output (if enabled):

<braced_hex>
    <try><005F> <0061> [<0066</try>
    <success> <0061> [<00660066> </success>
    <attributes>[95]</attributes>
</braced_hex>
<braced_hex>
    <try><0061> [<00660066> <</try>
    <success> [<00660066> <006600</success>
    <attributes>[97]</attributes>
</braced_hex>
<braced_hex>
    <try>[<00660066> <0066006</try>
    <fail/>
</braced_hex>
<braced_hex>
    <try><00660066> <00660069</try>
    <success> <00660069> <0066006</success>
    <attributes>[6684774]</attributes>
</braced_hex>
<braced_hex>
    <try><00660069> <00660066</try>
    <success> <00660066006C>]</success>
    <attributes>[6684777]</attributes>
</braced_hex>
<braced_hex>
    <try><00660066006C>]</try>
    <success>]</success>
    <attributes>[438093348972]</attributes>
</braced_hex>
<braced_hex>
    <try>]</try>
    <fail/>
</braced_hex>

Note that on my system int wasn't big enough to hold those numbers, so parse would fail. For maximum range I used intmax_t but you can use other types, including arbitrary precision types:

  • 128 bit string to array using boost::spirit::*

Also note I prefer not to use semantic actions, using automatic attribute propagation. This is really prevalent in Spirit V2. See also

  • Boost Spirit: "Semantic actions are evil"?