Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 精神语法解析问题_C++_Boost Spirit_Boost Spirit Qi - Fatal编程技术网

C++ 精神语法解析问题

C++ 精神语法解析问题,c++,boost-spirit,boost-spirit-qi,C++,Boost Spirit,Boost Spirit Qi,我有以下几点, class BATSTradeMsg : public BATSMessageBase { BATSTradeMsg(int timestamp, char msgtype, uint64_t orderId, char side, uint32_t shares, std::string const &symbol, uint64_t price, uint64_t execId) : BATSM

我有以下几点,

class BATSTradeMsg : public BATSMessageBase
{

    BATSTradeMsg(int timestamp, char msgtype, uint64_t orderId, char side, uint32_t shares,
                    std::string const &symbol, uint64_t price, uint64_t execId) :
            BATSMessageBase(timestamp, msgtype),
            m_orderId(orderId),
            m_side(side),
            m_shares(shares),
            m_symbol(symbol),
            m_price(price),
            m_execId(execId)
    {
    }

    uint64_t    m_orderId; // Base 36 Numeric values come over the wire in ascii
    char        m_side;
    uint32_t    m_shares;
    std::string m_symbol;
    uint64_t    m_price;
    uint64_t    m_execId; // Base 36 Numeric values come over the wire in ascii

};

// order and execution ids are 12 characters base 36
qi::uint_parser< uint64_t, 36, 12, 12 > p_orderId;
qi::uint_parser< uint64_t, 36, 12, 12 > p_execId;
qi::uint_parser< uint32_t, 10,  6,  6 > p_shares;
qi::uint_parser< uint32_t, 10, 10, 10 > m_price;
qi::uint_parser< uint32_t, 10,  8,  8 > p_ts;

if (msgtype == BATSTradeMsg::longMsgCode)
    m_wire_msg = ( p_ts >> qi::char_(msgtype)
                        >> p_orderId
                        >> qi::char_(BATSTradeMsg::sideFlag)
                        >> p_shares
                        >> qi::as_string[qi::repeat(8)[qi::char_]]
                        >> m_price
                        >> p_execId )
            [qi::_val = phi::construct<BATSTradeMsg>(
                    qi::_1, qi::_2, qi::_3, qi::_4, qi::_5, qi::_6, qi::_7, qi::_8)];

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

以下是我的建议:

数据类型 然后使用简单的融合适应,而不是语义动作ª:

BOOST_FUSION_ADAPT_STRUCT(BATS::TradeMsg, timestamp, msgtype, orderId, side, shares, symbol, price, execId)
分析器 然后,解析器基本上变成:

我假设“side”可以是“B”或“S”(用于买入或卖出)

演示程序 下面是3个被剖析的测试用例:

  • 问题中的“简短”示例(错误)
  • 我试图修复“短”示例
  • 问题中的“长”示例
  • int main() {
        using It = std::string::const_iterator;
        Parser<It> const parser;
    
        for (std::string const input : {
                "28800168P1K27GA00000YB000300AAPL  00018319001K27GA00000Z",
                "28800168r1K27GA00000YB000300AAPLSPOT00018319001K27GA00000Z" })
        {
            std::cout << "Input: " << std::quoted(input) << "\n";
    
            It f = begin(input), l = end(input);
    
            BATS::TradeMsg msg;
            if (parse(f, l, parser, msg)) {
                std::cout << "Parsed\n";
            } else {
                std::cout << "Parse failed\n";
            }
    
            if (f!=l)
                std::cout << "Remaining data: " << std::quoted(std::string(f,l), '\'') << "\n";
        }
    }
    


    如果您提供一个完整(几乎?)的可编译示例(包含所需的输入和预期的结果),您将有更好的机会获得帮助。第一个示例消息中是否缺少字符?我们怎么知道
    P
    r
    是“短”还是“长”的代码?我们是否必须猜测“side”可以是“[B]uy”或“[S]ell”?很抱歉造成混淆,我不知道为什么,但上面带有“…AAPL00018…”的msg格式似乎只有一个空格,而不是正确的两个空格。让我把它改成代码吧,难怪大家都感到困惑。很抱歉。我已经搞定了。事实上完整的来源在这里。如果您查看测试用例test_parse_trade,您可以看到它检查BATS规范中的长MSG和短MSG是否正确解析。第一个测试用例parse(“2880016P1K27GA0000YB0000300AAPL 00018319001K27GA0000Z”)与第二个测试用例parse(“2880016R1K27GA0000YB0000300AAPLSPOT00018319001K27GA0000Z”)不同股票符号只需多出2个字符。因此,我的问题是,为什么我不能使用下面这样的OR构造(qi::as_string[qi::repeat(6)[qi::char_]]| qi::as_string[qi::repeat(8)[qi::char_]])来解析它们?让我们暂时撇开语义行为是否是邪恶的不谈……这不起作用,因为
    qi::repeat(6)[qi::char\uquo]
    qi::repeat(8)[qi::char\uquo]
    通常都会成功。如果在
    a
    b
    始终匹配时写入
    a | b
    ,则永远不会执行
    b
    分支。
    namespace BATS {
        enum class MessageCode : char { Long = 'r', Short = 'P' };
    
        struct MessageBase {
            int         timestamp;
            MessageCode msgtype;
        };
    
        struct TradeMsg : MessageBase {
            uint64_t    orderId; // Base 36 Numeric values come over the wire in ascii
            char        side;
            uint32_t    shares;
            std::string symbol;
            uint64_t    price;
            uint64_t    execId;  // Base 36 Numeric values come over the wire in ascii
        };
    }
    
    BOOST_FUSION_ADAPT_STRUCT(BATS::TradeMsg, timestamp, msgtype, orderId, side, shares, symbol, price, execId)
    
    template <typename It> 
    struct Parser : qi::grammar<It, BATS::TradeMsg()> {
        Parser() : Parser::base_type(r_wire_msg) {
    
            // see below
    
            r_wire_msg 
                = r_long_wire_msg
                | r_short_wire_msg
                ;
    
            BOOST_SPIRIT_DEBUG_NODES((r_wire_msg)(r_short_wire_msg)(r_long_wire_msg))
        }
    
      private:
        // order and execution ids are 12 characters base 36
        qi::uint_parser<uint64_t, 36, 12, 12> p_orderId;
        qi::uint_parser<uint64_t, 36, 12, 12> p_execId;
        qi::uint_parser<uint32_t, 10,  6,  6> p_shares;
        qi::uint_parser<uint32_t, 10, 10, 10> p_price;
        qi::uint_parser<uint32_t, 10,  8,  8> p_ts;
        qi::rule<It, BATS::TradeMsg()> r_wire_msg, r_long_wire_msg, r_short_wire_msg;
    };
    
            r_long_wire_msg
                 = p_ts 
                >> qi::char_(BATS::MessageCode::Long)
                >> p_orderId
                >> qi::char_("BS")
                >> p_shares
                >> qi::as_string[qi::repeat(8)[qi::char_]]
                >> p_price
                >> p_execId 
                ;
    
            r_short_wire_msg
                 = p_ts 
                >> qi::char_(BATS::MessageCode::Short)
                >> p_orderId
                >> qi::char_("BS")
                >> p_shares
                >> qi::as_string[qi::repeat(6)[qi::char_]]
                >> p_price
                >> p_execId 
                ;
    
    int main() {
        using It = std::string::const_iterator;
        Parser<It> const parser;
    
        for (std::string const input : {
                "28800168P1K27GA00000YB000300AAPL  00018319001K27GA00000Z",
                "28800168r1K27GA00000YB000300AAPLSPOT00018319001K27GA00000Z" })
        {
            std::cout << "Input: " << std::quoted(input) << "\n";
    
            It f = begin(input), l = end(input);
    
            BATS::TradeMsg msg;
            if (parse(f, l, parser, msg)) {
                std::cout << "Parsed\n";
            } else {
                std::cout << "Parse failed\n";
            }
    
            if (f!=l)
                std::cout << "Remaining data: " << std::quoted(std::string(f,l), '\'') << "\n";
        }
    }
    
    Input: "28800168P1K27GA00000YB000300AAPL  00018319001K27GA00000Z"
    Parsed
    Input: "28800168r1K27GA00000YB000300AAPLSPOT00018319001K27GA00000Z"
    Parsed