Boost Spirit Qi Восстановление пропуска с пользовательской грамматикой пропуска - PullRequest
7 голосов
/ 18 февраля 2011

У меня есть грамматика, которая до сих пор использовала стандартный boost::spirit::ascii::space / boost::spirit::ascii::space_type шкипер.

У меня есть некоторые правила, которые используют шкипер, а некоторые нет, например

qi::rule<Iterator, PTR<Expression>(), ascii::space_type> expression;
qi::rule<Iterator, PTR<Term>()> term;

Когда я использую не пропускающий нетерминал (например, term) внутри пропускающего нетерминала (например, expression), все работает так, как я и ожидал - пробел имеет значение только внутри term нетерминала.

Кроме того, до сих пор у меня все было в порядке, включая нетерминалы, которые используют шкипер внутри нетерминалов, которые не используют qi::skip для восстановления пропуска, например

index = (qi::lit('[') >> qi::skip(ascii::space)[explist >> qi::lit(']')]);

ThisКстати, пробелы не являются значительными внутри скобок [], но находятся за их пределами.

Однако теперь я хочу добавить свой собственный шкипер (я хочу сделать новые строки значительными, а позже добавить пропуск комментариев).Моя грамматика шкипера выглядит следующим образом:

struct skip_grammar : qi::grammar<Iterator> {
  qi::rule<Iterator> start;
  skip_grammar() : skip_grammar::base_type(start) {
    start = qi::char_("\t\r ");
  }
};

Я смог добавить ее в свои определения правил так же хорошо, как

qi::rule<Iterator, PTR<Expression>(), skip_grammar> expression;

Но я не могу понять, как использоватьмоя пропущенная грамматика в качестве аргумента qi::skip (и замена ascii::space).Я попытался использовать тип, локальную переменную экземпляра и глобальную переменную экземпляра.Самое большее, что я получил, - это заставил clang пожаловаться на то, что моему skip_grammar нужен конструктор копирования.Поэтому я попытался добавить конструктор копирования в мою пропущенную грамматику, но, очевидно, базовый класс boost::noncopyable существует по какой-то причине, потому что мой двоичный файл вышел из строя почти сразу.

Как мне использовать это?

Спасибо

1 Ответ

7 голосов
/ 18 февраля 2011

A qi::grammar - это просто контейнер для qi::rules.У него нет конструктора копирования, потому что это может непреднамеренно создать висячие ссылки в выражениях синтаксического анализатора в правой части этих правил.

Использование грамматики в качестве пропуска, как вы хотите сделать, немного сложнее иравносильно передаче правила запуска грамматики в парсер пропуска.Для этого может быть проще просто создать экземпляр правила (особенно, если у вас есть один шкипер правила).

В любом случае правило должно быть передано шкиперу в качестве ссылки (путем вызова правилафункция-член alias()):

skip_grammar skippper;
index = '[' >> qi::skip(skipper.start.alias())[explist >> ']'];

или просто:

rule<iterator> skipper = qi::char_("\t\r ");
index = '[' >> qi::skip(skipper.alias())[explist >> ']'];

Псевдоним необходим из-за особенностей копирования правила.Более подробно это описано в FAQ's Spirit здесь .

...