Я пишу небольшой компилятор просто для удовольствия и использую 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 = ...
.)
Почему это изменение не компилируется? Я скорее ищу объяснение, чтобы понять, что происходит, чем обходной путь.