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

Boost spirit grammar issue


I have some simple code to parse some msg as below,

if (msgtype == BATSAddOrderMsg::longMsgCode)
    m_wire_msg = ( p_ts >> qi::char_(BATSAddOrderMsg::longMsgCode)
                        >> p_orderId
                        >> qi::char_(BATSAddOrderMsg::sideFlag)
                        >> p_shares
                        >> qi::as_string[qi::repeat(6)[qi::char_]]
                        >> m_price
                        >> qi::char_(BATSAddOrderMsg::displayFlag)
                        >> qi::as_string[qi::repeat(4)[qi::char_]] )
                        [qi::_val = phi::construct<BATSAddOrderMsg>(
                                qi::_1, qi::_2, qi::_3, qi::_4, qi::_5, qi::_6, qi::_7, qi::_8, qi::_9)];
else if (msgtype == BATSAddOrderMsg::shortMsgCode)
    m_wire_msg = ( p_ts >> qi::char_(BATSAddOrderMsg::shortMsgCode)
                        >> p_orderId
                        >> qi::char_(BATSAddOrderMsg::sideFlag)
                        >> p_shares
                        >> qi::as_string[qi::repeat(6)[qi::char_]]
                        >> m_price
                        >> qi::char_(BATSAddOrderMsg::displayFlag) )
                        [qi::_val = phi::construct<BATSAddOrderMsg>(
                                qi::_1, qi::_2, qi::_3, qi::_4, qi::_5, qi::_6, qi::_7, qi::_8, "")];

In the above, the long msg type is just the short msg type with one additional field qi::as_string[qi::repeat(4)[qi::char_]]

When I tried to refactor into the below,

auto shared = p_ts >> qi::char_(BATSAddOrderMsg::longMsgCode)
                   >> p_orderId
                   >> qi::char_(BATSAddOrderMsg::sideFlag)
                   >> p_shares
                   >> qi::as_string[qi::repeat(6)[qi::char_]]
                   >> m_price
                   >> qi::char_(BATSAddOrderMsg::displayFlag);
if (msgtype == BATSAddOrderMsg::longMsgCode)
   m_wire_msg = shared >> qi::as_string[qi::repeat(4)[qi::char_]] )
                       [qi::_val = phi::construct<BATSAddOrderMsg>(
                              qi::_1, qi::_2, qi::_3, qi::_4, qi::_5, qi::_6, qi::_7, qi::_8, qi::_9)];

else if (msgtype == BATSAddOrderMsg::shortMsgCode)
    m_wire_msg = shared[qi::_val = phi::construct<BATSAddOrderMsg>(                                
    qi::_1, qi::_2, qi::_3, qi::_4, qi::_5, qi::_6, qi::_7, qi::_8, "")];

The code would compile, but when i run my unittests, it would die with a runtime exception.

Anyone knows why this behavoir from Boost Spirit?


Solution

  • You can't use auto safely with Spirit Parser Expressions. See e.g. boost spirit V2 qi bug associated with optimization level

    However, it also looks like