如果有结构

struct price
{
   int chicken;
   int cow;
   bool in_stock;
   std::string place;
};

使用boost::fusion进行了改编。
是否需要解析,但可选地解析in_stock和位置。例如
template <typename it, typename skipper = qi::space_type>
struct p : qi::grammar<it, price(), skipper>
{
    p() : p::base_type(p_instance)
    {
        using namespace qi;
        psr %= int_ > int_ > -bool_ > -('"' > char_ % ',' > '"');
    }
  private:
      qi::rule<it,price(),skipper> limit;
};

但是,这不起作用。如果输入是"2 3 \"Chili\"",则会引发异常。
有什么解决办法?

最佳答案

首先

我猜想您有太多的>期望点,这些期望点可能/应该是>>序列运算符。

我想说的是,使您的语法更加明确,例如通过说

bool_ | attr(false)

以确保如果bool_失败,将出现公开的false属性值。这样,暴露的属性是bool,而不是boost::optional<bool>,它与目标struct(price)更兼容。

演示:
template <typename It, typename Skipper = qi::space_type>
    struct parser : qi::grammar<It, price(), Skipper>
{
    parser() : parser::base_type(start)
    {
        using namespace qi;

        in_stock = bool_ | attr(false);
        start    = int_ > int_ > in_stock > -('"' >> char_ % ',' > '"');
    }

  private:
    qi::rule<It, price(), Skipper> start;
    qi::rule<It, bool()> in_stock;
};

其次

然后,
('"' > char_ % ',' > '"')

只会匹配"a""b,c,d"等字符串。如果要解析"Chili",则应将其更改为以下内容:
    place    = '"' >> *~char_('"') > '"';
    start    = int_ > int_ > in_stock > (place | attr(""));

这意味着解析任何以'"'分隔的字符串(~char_("abc)表示:除[abc]之外的任何字符)。

sample 溶液

这是一个完整的演示,显示:
  • 结构
  • 的融合改编
  • 以上调整后的语法
  • 使用BOOST_SPIRIT_DEBUG调试的
  • 捕获qi::expectation_failure以在解析失败时打印诊断信息
  • 使用Spirit Karma以人类可读的形式打印解析结果

  • 测试程序输出如下:

    代码
    #define BOOST_SPIRIT_DEBUG
    #include <boost/fusion/adapted/struct.hpp>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    
    namespace qi    = boost::spirit::qi;
    namespace karma = boost::spirit::karma;
    namespace phx   = boost::phoenix;
    
    struct price
    {
        int chicken;
        int cow;
        bool in_stock;
        std::string place;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(price,
            (int, chicken)
            (int, cow)
            (bool, in_stock)
            (std::string, place))
    
    template <typename It, typename Skipper = qi::space_type>
        struct parser : qi::grammar<It, price(), Skipper>
    {
        parser() : parser::base_type(start)
        {
            using namespace qi;
    
            in_stock = bool_ | attr(false);
    #if 0
            start    = int_ > int_ > in_stock > -('"' >> char_ % ',' > '"');
    #else
            place    = '"' >> *~char_('"') > '"';
            start    = int_ > int_ > in_stock > (place | attr(""));
    #endif
    
            BOOST_SPIRIT_DEBUG_NODE(start);
            BOOST_SPIRIT_DEBUG_NODE(place);
            BOOST_SPIRIT_DEBUG_NODE(in_stock);
        }
    
      private:
        qi::rule<It, price(), Skipper> start;
        //
        qi::rule<It, bool()>            in_stock;
        qi::rule<It, std::string()>     place; // no skipper
    };
    
    bool doParse(const std::string& input)
    {
        typedef std::string::const_iterator It;
        auto f(begin(input)), l(end(input));
    
        parser<It, qi::space_type> p;
        price data;
    
        try
        {
            bool ok = qi::phrase_parse(f,l,p,qi::space,data);
            if (ok)
            {
                std::cout << "parse success: '" << input << "'\n";
                std::cout << "data: " << karma::format_delimited(karma::eps <<
                        "chicken:"  << karma::int_  <<
                        "cow:"      << karma::int_  <<
                        "in_stock:" << karma::bool_ <<
                        "place:"    << karma::auto_,
                        " ", data) << "\n";
            }
            else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
    
            if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
            return ok;
        } catch(const qi::expectation_failure<It>& e)
        {
            std::string frag(e.first, e.last);
            std::cerr << e.what() << "'" << frag << "'\n";
        }
    
        return false;
    }
    
    int main()
    {
        doParse("1 2 true \"a,b,c,d,e,f\"");
        doParse("3 4 \"a,b,c,d,e,f\"");
        doParse("5 6");
        doParse("7 8 false");
    }
    

    输出
    <start>
      <try>1 2 true "a,b,c,d,e,</try>
      <in_stock>
        <try>true "a,b,c,d,e,f"</try>
        <success> "a,b,c,d,e,f"</success>
        <attributes>[1]</attributes>
      </in_stock>
      <place>
        <try>"a,b,c,d,e,f"</try>
        <success></success>
        <attributes>[[a, ,, b, ,, c, ,, d, ,, e, ,, f]]</attributes>
      </place>
      <success></success>
      <attributes>[[1, 2, 1, [a, ,, b, ,, c, ,, d, ,, e, ,, f]]]</attributes>
    </start>
    parse success: '1 2 true "a,b,c,d,e,f"'
    data:  chicken: 1 cow: 2 in_stock: true place: a,b,c,d,e,f
    <start>
      <try>3 4 "a,b,c,d,e,f"</try>
      <in_stock>
        <try>"a,b,c,d,e,f"</try>
        <success>"a,b,c,d,e,f"</success>
        <attributes>[0]</attributes>
      </in_stock>
      <place>
        <try>"a,b,c,d,e,f"</try>
        <success></success>
        <attributes>[[a, ,, b, ,, c, ,, d, ,, e, ,, f]]</attributes>
      </place>
      <success></success>
      <attributes>[[3, 4, 0, [a, ,, b, ,, c, ,, d, ,, e, ,, f]]]</attributes>
    </start>
    parse success: '3 4 "a,b,c,d,e,f"'
    data:  chicken: 3 cow: 4 in_stock: false place: a,b,c,d,e,f
    <start>
      <try>5 6</try>
      <in_stock>
        <try></try>
        <success></success>
        <attributes>[0]</attributes>
      </in_stock>
      <place>
        <try></try>
        <fail/>
      </place>
      <success></success>
      <attributes>[[5, 6, 0, []]]</attributes>
    </start>
    parse success: '5 6'
    data:  chicken: 5 cow: 6 in_stock: false place:
    <start>
      <try>7 8 false</try>
      <in_stock>
        <try>false</try>
        <success></success>
        <attributes>[0]</attributes>
      </in_stock>
      <place>
        <try></try>
        <fail/>
      </place>
      <success></success>
      <attributes>[[7, 8, 0, []]]</attributes>
    </start>
    parse success: '7 8 false'
    data:  chicken: 7 cow: 8 in_stock: false place:
    

    09-05 23:58
    查看更多