【问题标题】:How to rewrite qi parsers with qi::_1/qi::_N in x3?如何在 x3 中用 qi::_1/qi::_N 重写 qi 解析器?
【发布时间】:2017-03-30 10:54:21
【问题描述】:

假设我们要解析一个内积表达式并得到结果。

"SUM({1, 2, 3} .* {4, 5, 6})"

qi::_1qi::_2 在解析器中引用第i 个属性非常方便。

void Test(std::string const& input) {
    qi::rule<decltype(boost::begin(input)), int(), qi::ascii::space_type> ruleSum =
        (
            qi::lit("SUM") >> '(' >>
            '{' >> (qi::int_ % ',') >> '}' >>
            ".*" >>
            '{' >> (qi::int_ % ',') >> '}' >>
            ')'
        )[qi::_pass=phx::bind(
            [](std::vector<int> const& vec1, std::vector<int> const& vec2, int& result) {
                if(vec1.size() != vec2.size())
                    return false;
                result = std::inner_product(boost::begin(vec1), boost::end(vec1), boost::begin(vec2), 0);
                return true;
            },
            qi::_1, qi::_2, qi::_val
        )];
    int attr = 0;
    if( qi::phrase_parse(boost::begin(input), boost::end(input), ruleSum >> qi::eoi, qi::ascii::space, attr) ) {
        std::cout<<"Match! result = "<<attr<<std::endl;
    } else {
        std::cout<<"Not match!"<<std::endl;
    }
}

在精神 x3 中,没有这样的 qi::_1 ... qi::_N。我应该使用一对向量作为属性吗?解析这种内积的推荐方法是什么?

namespace inner_product {
    x3::rule<struct idInnerProduct, int> const ruleInnerProduct("InnerProduct");
    auto const ruleInnerProduct_def =
        (
            x3::rule<struct _, std::pair<std::vector<int>, std::vector<int>>>{} =
                x3::lit("SUM") >> '(' >>
                '{' >> (x3::int_ % ',') >> '}' >>
                ".*" >>
                '{' >> (x3::int_ % ',') >> '}' >>
                ')'
        )[([](auto& ctx){
            if(_attr(ctx).first.size() != _attr(ctx).second.size()) {
                _pass(ctx) = false;
            } else {
                x3::_val(ctx) = std::inner_product(
                    boost::begin(x3::_attr(ctx).first),
                    boost::end(x3::_attr(ctx).first),
                    boost::begin(x3::_attr(ctx).second),
                    0
                );
            }
        })];
    BOOST_SPIRIT_DEFINE(ruleInnerProduct)
}

【问题讨论】:

    标签: c++ boost boost-spirit boost-spirit-qi boost-spirit-x3


    【解决方案1】:

    属性是一个融合序列。它的成员是vector&lt;int&gt;

    融合序列不是一对,因此不能使用.first.second

    我会写:

    void Test(std::string const& input) {
        namespace x3 = boost::spirit::x3;
    
        auto ruleSum = x3::rule<struct _, int> {} =
            (
                x3::lit("SUM") >> '(' >>
                '{' >> (x3::int_ % ',') >> '}' >> ".*" >>
                '{' >> (x3::int_ % ',') >> '}' >>
                ')'
            )[( [](auto& ctx) {
                    using boost::fusion::at_c;
                    // dissect context
                    auto& pass = x3::_pass(ctx);
                    auto& result = x3::_val(ctx);
                    std::vector<int> const& vec1 = at_c<0>(x3::_attr(ctx));
                    std::vector<int> const& vec2 = at_c<1>(x3::_attr(ctx));
    
                    // do the work
                    pass = (vec1.size() == vec2.size());
                    if (pass)
                        result = std::inner_product(boost::begin(vec1), boost::end(vec1), boost::begin(vec2), 0);
                })
            ];
    
        int attr = 0;
        if( x3::phrase_parse(boost::begin(input), boost::end(input), ruleSum >> x3::eoi, x3::ascii::space, attr) ) {
            std::cout<<"Match! result = "<<attr<<std::endl;
        } else {
            std::cout<<"Not match!"<<std::endl;
        }
    }
    

    Live On Coliru

    打印:

    Match! result = 32
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-01
      相关资源
      最近更新 更多