提升精神气:在轻微的规则变化时编译错误

时间:2016-04-04 14:36:40

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

我只是为了好玩而编写一个小编译器,并且我使用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 = ...行。)

为什么这个改变没有编译?我宁愿寻找解释来了解正在发生的事情而不是解决方法。

1 个答案:

答案 0 :(得分:2)

好的,所以在仔细观察之后,你试图在你的function_call_t类型中插入多个字符串,这是一个可以从单个std :: string转换的融合序列。但是,您可能会遇到power_call规则的问题,因为它的属性实际上是tuple <std::string, optional <vector <std::string>>>。我认为精神正在解决这个结构的问题并导致你的问题,但是,我目前还没有编译器来测试它。