5

我正在尝试使用 Spirit X3 编写解析器,但我还没有走得很远,因为我遇到了一个我无法弄清楚的编译错误。我想我知道编译器在抱怨什么,但我不明白为什么它在乎。以下代码编译(clang 3.9,Boost 1.62.0)并工作。(我意识到它的结构很差,并且有内置的常量解析器;我只是想证明这个问题。)

#define BOOST_SPIRIT_X3_DEBUG

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

using namespace std;
namespace x3 = boost::spirit::x3;

namespace lang {

    using namespace x3;

    struct Constant {
    };

    rule<class constant_id, Constant> const constant = "constant";

    auto const integer_literal = -char_('-') >> +digit;
    auto const float_literal = -char_('-') >> +digit >> -(char_('.') >> *digit);

    auto const constant_def = (integer_literal)[([](auto &ctx) { _val(ctx) = Constant(); })];

    BOOST_SPIRIT_DEFINE(constant);
}

int main(int argc, char *argv[]) {

    string s("3.14159");
    if (x3::phrase_parse(s.begin(), s.end(), lang::constant, x3::space)) {
        cout << "Ok!";
    } else {
        cout << "Error!";
    }

    return 0;
}

但是,如果我将 constant_def 更改为使用 float_literal 而不是 integer_literal:

auto const constant_def = (float_literal)[([](auto &ctx) { _val(ctx) = Constant(); })];

我开始遇到编译错误。

sequence.hpp:143:9: error: static_assert failed "Attribute does not have the expected size."
    static_assert(
    ^

查看源代码,我看到一条消息:

// If you got an error here, then you are trying to pass
// a fusion sequence with the wrong number of elements
// as that expected by the (sequence) parser.

我认为该错误与 float_literal 的定义中存在可选项有关。我相信 of 的属性类型integer_literal类似于vector<char>,但可选导致的属性float_literal类似于tuple<vector<char>, optional<vector<char>>>? 在某个地方,我试图将其强制为字符串或其他东西,但它失败了,因为它试图将 2 元组转换为 1 元组。我怀疑解决方案是将float_literal定义包装起来,raw[]以便我得到底层字符串,这是我想要的。但由于这是我的第一个 X3 解析器,我想了解编译器为什么会引发此错误,以便我可以诊断它是否出现在另一个上下文中。

我真正不明白的是为什么编译器关心float_literal. 我附加了一个语义动作,它生成了一个 Constant 的实例,它是常量规则的属性类型,没有任何对属性的引用float_literal,那么为什么编译器会关心的属性float_literal呢?它在哪里尝试进行不等长序列分配,目的是什么?

谢谢!

4

0 回答 0