3

简单的 x3 代码无法编译,因为第二个 ruleTest 或整个解析器没有附加任何内容。即使我们放x3::omit[ruleTest]第二个ruleTest,它仍然无法编译。

void Test(std::string const& str) {
    auto const ruleTest = x3::rule<struct _, std::string>{} =
        *(x3::char_ - ' ')[([](auto& ctx){x3::_val(ctx)+='x';})];
    x3::parse(boost::begin(str), boost::end(str), 
        ruleTest[([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >>
        ' ' >>
        ruleTest
    );
} 

只有当我们将 lambda 或属性附加到 x3::parse 或使用 BOOST_SPIRIT_DEFINE 全局定义 ruleTest 时才能解决问题。

void Test(std::string const& str) {
    auto const ruleTest = x3::rule<struct _, std::string>{} =
        *(x3::char_ - ' ')[([](auto& ctx){x3::_val(ctx)+='x';})];
    std::string attr;
    x3::parse(boost::begin(str), boost::end(str), 
        ruleTest[([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] >>
        ' ' >>
        ruleTest, attr);
}
4

1 回答 1

1

错误的症结似乎是

test.cpp|9 col 59| error: no match for ‘operator+=’ (operand types are ‘boost::spirit::x3::unused_type’ and ‘char’)

这是因为编译器看到绑定属性的实际类型(无)是x3::unused_type,因此语义操作不会编译。

我什至不确定您希望它如何工作,因为您无法将字符更新到'x'不存在的属性中。

这是一个建议的“修复”:

struct { 
    void operator()(std::string& s, char c) const { s += c; }
    void operator()(...)                    const { }
} ll;

auto const ruleTest 
    = x3::rule<struct _, std::string>{} 
    = *(x3::char_ - ' ') [([ll](auto& ctx){ ll(x3::_val(ctx), 'x');})]
    ;

看见Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>

void Test(std::string const& str) {
    namespace x3 = boost::spirit::x3;

    struct { 
        void operator()(std::string& s, char c) const { s += c; }
        void operator()(...)                    const { }
    } ll;

    auto const ruleTest 
        = x3::rule<struct _, std::string>{} 
        = *(x3::char_ - ' ') [([ll](auto& ctx){ ll(x3::_val(ctx), 'x');})]
        ;

    //std::string attr;
    auto f = begin(str), l = end(str);
    bool ok = x3::parse(f, l, 
            ruleTest [([](auto& ctx){std::cout<<x3::_attr(ctx)<<std::endl;})] 
            >> ' ' >> ruleTest);

    if (ok)     std::cout << "Parse success\n";
    else        std::cout << "Parse failed\n";
    if (f != l) std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}

int main() {
    Test("abc def");
}
于 2017-04-07T14:32:43.973 回答