Boost spirit不动点作为整数解析器

Boost spirit fixed point as integer parser

我有以下解析器,

    #define PRICE_MULT 10000
    qi::uint_parser<uint32_t, 10, 1, 6> int_part;
    qi::uint_parser<uint32_t, 10, 1, 6> dec_part;

    qi::rule<Iterator, uint64_t()> fixed_point =
         (int_part >> "." >> dec_part )[qi::_val = qi::_1 * PRICE_MULT + qi::_2];


    m_wire_msg = ( qi::as_string[*qi::alpha] >> "," // symbol
                >> qi::ulong_long >> ","        // symbol seq num
                >> qi::ulong_long >> ","        // order id
                >> (fixed_point | qi::ulong_) >> ","
                >> qi::uint_ >> ","                   // volume
                >> qi::char_ >> ","                   // side
                >> +qi::space >> ","                  // firm id
                >> qi::ushort_                        // parity split

但是解析失败,

"AAPL,1192544,16044086616349464,157.47,100,S,     ,0"

具体来说,157.47 有时可以是整数,例如。 157 本身,这就是我使用“(fixed_point | qi::ulong_)”的原因。

但是解析失败,我不是很明白。理想情况下也应该正确解析以下内容,

"AAPL,1192544,16044086616349464,157,100,S,     ,0"

非常感谢任何帮助!

如果没有小数部分,使用可选的解析器不会失败。

另外,您的 PRICE_MULT 有 4 个零,但 dec_part 最多允许 6 位数字。

#define PRICE_MULT 10000
qi::uint_parser<std::uint32_t, 10, 1, 6> int_part;
qi::uint_parser<std::uint32_t, 10, 1, 4> dec_part;

qi::rule<Iterator, std::uint64_t()> fixed_point =
      int_part[qi::_val = qi::_1 * PRICE_MULT]
    >> -('.' >> dec_part[qi::_val += qi::_1]);

https://wandbox.org/permlink/H46ujDgJ57gyE69I

正确的定点解析器可能如下所示:

constexpr std::uint64_t lut[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
constexpr int frac_digits = 6;
qi::uint_parser<std::uint32_t, 10, 1, 6> const int_part;
qi::uint_parser<std::uint32_t, 10, 1, frac_digits> const dec_part;
qi::rule<Iterator, std::uint64_t()> fixed_point
    = int_part[qi::_val = qi::_1 * lut[frac_digits]]           // parse integer part and save multiplied by lut[frac_digits]
   >> ( !qi::lit('.')                                          // do not fail on missing fractional part
      | ('.' >>  qir::iter_pos >> dec_part >> qir::iter_pos)[  // parse fraction and save/syntesize iterators before and after
                    qi::_val += qi::_2 * phx::ref(lut)[        // multiple fraction by lookuped pow10 value
                                            frac_digits - (qi::_3 - qi::_1)]]
        >> *qi::digit);                                        // consume unparsed digits

https://wandbox.org/permlink/mtdMDPzB2RjPxQlD

input          result
=====          ======
123            123000000 
123.0          123000000
123.4          123400000
123.45         123450000
123.456        123456000
123.4567       123456700
123.45678      123456780
123.456789     123456789
123.456789123  123456789
123.           fail
.123           fail

如果我想通过乘以 10000 使 157.47 成为 1574700,以下是最好的方法吗?

m_fixed_point = m_int_part[qi::_val = qi::_1 * PRICE_MULT] >>
-("." >> -(m_digit[qi::_val += qi::_1 * 1000])
>> -(m_digit[qi::_val += qi::_1 * 100])
>> -(m_digit[qi::_val += qi::_1 * 10])
>> -(m_digit[qi::_val += qi::_1 ])
);