Spirit X3,两条规则合二为一不编译
Spirit X3, two rules do not compile after being combined into one
我目前正在学习如何使用 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(
^~~~~~~~~~~~~
header 文件还在 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>
,这样它就可以兼容[=21] =].同样的逻辑适用于更冗长的 three-rule 版本,唯一的区别是我专门为内部部分声明了一个规则,并明确声明其属性需要是 vector<ast::Expression>
类型。
Spirit x3 可能将内联规则的结果视为两个单独的 ast::Expression
,而不是 ast::FunctionExpression
结构所需的 std::vector<ast::Expression>
。
为了解决这个问题,我们可以使用另一个 中提到的助手 as
lambda 来指定子规则的 return 类型。
修改后的 range_def 将变为:
auto const range_def = attr("computeRange") >> '{' >> as<std::vector<ast::Expression>>(basic_exp >> ',' >> basic_exp) >> '}';
我目前正在学习如何使用 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(
^~~~~~~~~~~~~
header 文件还在 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>
,这样它就可以兼容[=21] =].同样的逻辑适用于更冗长的 three-rule 版本,唯一的区别是我专门为内部部分声明了一个规则,并明确声明其属性需要是 vector<ast::Expression>
类型。
Spirit x3 可能将内联规则的结果视为两个单独的 ast::Expression
,而不是 ast::FunctionExpression
结构所需的 std::vector<ast::Expression>
。
为了解决这个问题,我们可以使用另一个 as
lambda 来指定子规则的 return 类型。
修改后的 range_def 将变为:
auto const range_def = attr("computeRange") >> '{' >> as<std::vector<ast::Expression>>(basic_exp >> ',' >> basic_exp) >> '}';