提升精神气:轻微规则更改编译错误
Boost Spirit Qi: Compile error on slight rule change
我正在编写一个小编译器只是为了好玩,我正在使用 Boost Spirit Qi 来描述我的语法。现在我想对语法做一个小改动,以准备一些进一步的补充。不幸的是,这些更改无法编译,我想了解为什么会这样。
这是我要更改的代码片段。我希望提供的信息足以理解这个想法。完整的代码有点大,但是如果你想看一下甚至测试一下(提供了Makefile和Travis CI),请参阅https://github.com/Kruecke/BFGenerator/blob/8f66aa5/bf/compiler.cpp#L433.
typedef boost::variant<
function_call_t,
variable_declaration_t,
variable_assignment_t,
// ...
> instruction_t;
struct grammar : qi::grammar<iterator, program_t(), ascii::space_type> {
grammar() : grammar::base_type(program) {
instruction = function_call
| variable_declaration
| variable_assignment
// | ...
;
function_call = function_name >> '(' > -(variable_name % ',') > ')' > ';';
// ...
}
qi::rule<iterator, instruction::instruction_t(), ascii::space_type> instruction;
qi::rule<iterator, instruction::function_call_t(), ascii::space_type> function_call;
// ...
};
到目前为止,一切正常。现在我想将尾随分号 (> ';'
) 的解析从 function_call
规则移动到 instruction
规则。我的代码现在看起来像这样:
struct grammar : qi::grammar<iterator, program_t(), ascii::space_type> {
grammar() : grammar::base_type(program) {
instruction = (function_call > ';') // Added trailing semicolon
| variable_declaration
| variable_assignment
// | ...
;
// Removed trailing semicolon here:
function_call = function_name >> '(' > -(variable_name % ',') > ')';
// ...
}
根据我的理解,规则并没有真正改变,因为字符解析器 ';'
不产生任何属性,所以这个解析器的位置应该无关紧要。但是,此更改不会编译:
/usr/include/boost/spirit/home/support/container.hpp:278:13: error: no matching function for call to ‘std::basic_string<char>::insert(std::basic_string<char>::iterator, const bf::instruction::function_call_t&)’
c.insert(c.end(), val);
^
(此错误来自 instruction = ...
行。)
为什么这个更改没有编译?我宁愿寻找一个解释来理解发生了什么,而不是寻找解决方法。
好的,所以在仔细查看之后,您正在尝试将多个字符串插入到您的 function_call_t 类型中,这是一个可以从单个 std::string 转换为的融合序列。但是,您可能 运行 会遇到 function_call 规则的问题,因为它的属性实际上是 tuple <std::string, optional <vector <std::string>>>
。我想 spirit 在将该结构展平时遇到问题,这导致了您的问题,但是,我目前没有编译器来测试它。
我正在编写一个小编译器只是为了好玩,我正在使用 Boost Spirit Qi 来描述我的语法。现在我想对语法做一个小改动,以准备一些进一步的补充。不幸的是,这些更改无法编译,我想了解为什么会这样。
这是我要更改的代码片段。我希望提供的信息足以理解这个想法。完整的代码有点大,但是如果你想看一下甚至测试一下(提供了Makefile和Travis CI),请参阅https://github.com/Kruecke/BFGenerator/blob/8f66aa5/bf/compiler.cpp#L433.
typedef boost::variant<
function_call_t,
variable_declaration_t,
variable_assignment_t,
// ...
> instruction_t;
struct grammar : qi::grammar<iterator, program_t(), ascii::space_type> {
grammar() : grammar::base_type(program) {
instruction = function_call
| variable_declaration
| variable_assignment
// | ...
;
function_call = function_name >> '(' > -(variable_name % ',') > ')' > ';';
// ...
}
qi::rule<iterator, instruction::instruction_t(), ascii::space_type> instruction;
qi::rule<iterator, instruction::function_call_t(), ascii::space_type> function_call;
// ...
};
到目前为止,一切正常。现在我想将尾随分号 (> ';'
) 的解析从 function_call
规则移动到 instruction
规则。我的代码现在看起来像这样:
struct grammar : qi::grammar<iterator, program_t(), ascii::space_type> {
grammar() : grammar::base_type(program) {
instruction = (function_call > ';') // Added trailing semicolon
| variable_declaration
| variable_assignment
// | ...
;
// Removed trailing semicolon here:
function_call = function_name >> '(' > -(variable_name % ',') > ')';
// ...
}
根据我的理解,规则并没有真正改变,因为字符解析器 ';'
不产生任何属性,所以这个解析器的位置应该无关紧要。但是,此更改不会编译:
/usr/include/boost/spirit/home/support/container.hpp:278:13: error: no matching function for call to ‘std::basic_string<char>::insert(std::basic_string<char>::iterator, const bf::instruction::function_call_t&)’
c.insert(c.end(), val);
^
(此错误来自 instruction = ...
行。)
为什么这个更改没有编译?我宁愿寻找一个解释来理解发生了什么,而不是寻找解决方法。
好的,所以在仔细查看之后,您正在尝试将多个字符串插入到您的 function_call_t 类型中,这是一个可以从单个 std::string 转换为的融合序列。但是,您可能 运行 会遇到 function_call 规则的问题,因为它的属性实际上是 tuple <std::string, optional <vector <std::string>>>
。我想 spirit 在将该结构展平时遇到问题,这导致了您的问题,但是,我目前没有编译器来测试它。