c++ - Spirit X3,两条规则合二为一不编译

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

我目前正在学习如何使用 x3。正如标题所述,我已经成功地创建了一个具有一些简单规则的语法,但是在将这些规则中的两个合并为一个时,代码不再编译。这是 AST 部分的代码:

namespace x3 = boost::spirit::x3;

struct Expression;

struct FunctionExpression {
    std::string functionName;
    std::vector<x3::forward_ast<Expression>> inputs;
};

struct Expression: x3::variant<int, double, bool, FunctionExpression> {
    using base_type::base_type;
    using base_type::operator=;
};

我创建的规则解析格式为 {rangeMin, rangeMax} 的输入:

rule<struct basic_exp_class, ast::Expression> const
    basic_exp = "basic_exp";
rule<struct exp_pair_class, std::vector<ast::Expression>> const 
    exp_pair = "exp_pair";
rule<struct range_class, ast::FunctionExpression> const 
    range = "range";

auto const basic_exp_def = double_ | int_ | bool_;
auto const exp_pair_def = basic_expr >> ',' >> basic_expr;
auto const range_def = attr("computeRange") >> '{' >> exp_pair >> '}';

BOOST_SPIRIT_DEFINE(basic_expr, exp_pair_def, range_def);

这段代码编译得很好。但是,如果我尝试内联 exp_pair规则进入range_def规则,像这样:

rule<struct basic_exp_class, ast::Expression> const
    basic_exp = "basic_exp";
rule<struct range_class, ast::FunctionExpression> const 
    range = "range";

auto const basic_exp_def = double_ | int_ | bool_;
auto const range_def = attr("computeRange") >> '{' >> (
    basic_exp >> ',' >> basic_exp
) >> '}';

BOOST_SPIRIT_DEFINE(basic_expr, range_def);

代码编译失败,出现很长的模板错误,以以下行结尾:

spirit/include/boost/spirit/home/x3/operator/detail/sequence.hpp:149:9: error: static assertion failed: Size of the passed attribute is less than expected.
     static_assert(
     ^~~~~~~~~~~~~

头文件还在 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.

但我不明白为什么代码会失败。根据 x3 的 compound attribute rules , 括号中的内联部分应具有 vector<ast::Expression> 类型的属性, 使整个规则的类型为 tuple<string, vector<ast::Expression> ,以便它与 ast::FunctionExpression 兼容.同样的逻辑适用于更冗长的三规则版本,唯一的区别是我专门为内部部分声明了一个规则,并明确声明其属性需要为 vector<ast::Expression> 类型。 .

最佳答案

Spirit x3 可能将内联规则的结果视为两个独立的 ast::Expression而不是 std::vector<ast::Expression> ast::FunctionExpression 要求结构。

为了解决这个问题,我们可以使用一个助手 as另一个answer中提到的lambda指定子规则的返回类型。

修改后的 range_def 将变为:

auto const range_def = attr("computeRange") >> '{' >> as<std::vector<ast::Expression>>(basic_exp >> ',' >> basic_exp) >> '}';

关于c++ - Spirit X3,两条规则合二为一不编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53425339/

相关文章:

c++ - 返回数组中最小元素的索引

c++ - 我可以将 BOOST_FUSION_ADAPT_STRUCT 与继承的东西一起使用吗?

c++ - 如何捕获由 boost::spirit::x3 解析器解析的值以在语义操作体内使用​​?

c++ - 如何减少C++程序的崩溃

c++ - 我丢失的 Edge 在哪里?

c++ - C++ 'class'尚未声明-将类传递给类

c++ - Boost Spirit 和抽象语法树设计

c++ - 支持具有固定数组的对象的 BOOST_FUSION_ADAPT_STRUCT?

c++ - 精神X3 : parser with internal state