精神x3:本地定义的规则定义必须附加一个属性?

时间:2017-04-07 12:53:22

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

简单的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);
}

1 个答案:

答案 0 :(得分:1)

错误的症结似乎是

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

这是因为编译器看到绑定属性的实际类型(none)是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");
}