2014-02-18 2 views
0

Я разбираю некоторые данные, которые смутно структурированы как код C-ish. Как это:Дух Ци: полностью игнорирование вывода некоторых правил

Name0 
{ 
Name1 
{ 
    //A COMMENT!! 

    Param0 *= 2 
    Param2 = "lol" 
} 
} 

Частично это комментарии, которые я хочу, чтобы полностью игнорировать (и это не работает). Я считаю, что две вещи должны быть node, названные области (category правило), как Name0 {}, и значения (param правило), как Param0 *= 2 ... тогда есть comment. Я попытался установить вещи, как это:

typedef boost::variant<boost::recursive_wrapper<Category>, Param> Node; 

qi::rule<Iterator, Node(), ascii::space_type> node; 

Так node правило ставит либо Category или Param в variant. Здесь другие правила (я опустил некоторые правила, которые на самом деле не важны для этого):

qi::rule<Iterator> comment; //comment has no return type 

qi::rule<Iterator, Category(), ascii::space_type> category; 
qi::rule<Iterator, Param(), ascii::space_type> param; 

И их фактический код:

comment = "//" >> *(char_ - eol); 

param %= 
tagstring 
>> operators 
>> value; 

category %= 
tagstring 
>> '{' 
>> *node 
> '}'; 

node %= comment | category | param; 

comment является установка использовать = вместо %= , и он не имеет типа возврата. Тем не менее, комментарии заканчиваются созданием нулевого Category s в моем выходе Node s, где бы они ни появлялись. Я пытался двигаться comment из node правила и в category так:

category %= 
tagstring 
>> '{' 
>> *(comment | node) 
> '}'; 

и различные другие вещи, но эти пустые записи держать выскакивают. Я должен был сделать comment вывод строки и поставить std::string в мой Nodevariant просто, чтобы сортировать их, но это испортило мою способность придерживаться комментариев в других частях моих правил (если я фактически не захватил строку в каждом месте).

Как я могу полностью игнорировать comment и не показывать его каким-либо образом?

редактировать: Можно подумать, что omit бы это сделать, но, похоже, ничего не менять ...

редактировать 2: Реферирование this SO answer, у меня есть шаткое решение в этом:

node %= category | param; 

category %= 
tagstring 
>> '{' 
>> *comment >> *(node >> *comment) 
> '}'; 

Тем не менее, я хочу попытаться вставить комментарии во всевозможные места (между tagstring и {, в моем не показанном root правиле между корнем category и т. Д.). Существует ли более простой метод? Я надеялся, что это можно сделать с помощью простого >> commentwrapper, подключенного туда, где я хотел ...

+1

Шкиперы - это путь. Пожалуйста, посмотрите на этот вопрос для примера: http://stackoverflow.com/questions/21672316/boost-spirit-skipper-compile-time-error –

+0

@MikeM Спасибо за эту ссылку! Исправлена ​​проблема, и я точно описал, как в моем ответе. – user173342

ответ

2

Хорошо, поэтому сделать свой собственный шкипер не так уж плохо. И он элегантно решает эту проблему комментариев, как сказал Майк М. Я определяю свои правила в структуре, называемой Parser, которая построена с шаблоном Iterator. Пришлось внести некоторые корректировки в использование шкипера. Во-первых, здесь есть шкипер, который определен в Parser со всеми другими моими правилами:

typedef qi::rule<Iterator> Skipper; 
Skipper skipper; 

Так skipper является правилом типа Skipper.Вот что моя структура Parser выглядела как первоначально, где использовалось правило ascii::space типа ascii::space_type в качестве его шкипера, который НЕ является тем же самым типом, что и qi::rule<Iterator>, что основано на skipper!

struct Parser : qi::grammar<Iterator, std::vector<Category>(), ascii::space_type> 
{ 
qi::rule<Iterator, std::vector<Category>(), ascii::space_type> root; 

... 

Таким образом, каждый экземпляр ascii::space_type в шаблонах правила должны быть заменены Skipper! Это включает другие правила, кроме root, которые показаны здесь, например param и category из моего вопроса. Оставляя остатки старого ascii::space_type позади, возникают критические ошибки компилятора.

struct Parser : qi::grammar<Iterator, std::vector<Category>(), qi::rule<Iterator>> 
{ 
typedef qi::rule<Iterator> Skipper; 
Skipper skipper; 

qi::rule<Iterator, std::vector<Category>(), Skipper> root; 

... 

Оригинальный шкипер был просто space, шахта теперь является альтернативой space и comment. Никакая старая функциональность (пропуски пространства) не теряется.

skipper = space | comment; 

Тогда phrase_parse вызов должен быть отрегулирован от этой старой версии, которая используется ascii::space:

bool r = phrase_parse(iter, end, parser, ascii::space, result); 

в

bool r = phrase_parse(iter, end, parser, parser.skipper, result); 

А теперь комментарии исчезают так же легко, как пустое пространство. Потрясающие.

+1

Выглядит хорошо. Вы могли бы дополнительно использовать аргумент шаблона для шкипера, поэтому в будущем он будет немного более гибким. '' template struct Parser: qi :: grammar '' –

+0

@MikeM Я действительно решил определить шкипера внутри структуры, чтобы консолидировать определения правил, а не определять только шкипера в другая функция. Возможно, это не лучший выбор, но мне кажется, что это наиболее удобно для меня в этом случае. – user173342

Смежные вопросы