У меня есть входная строка, которую я пытаюсь проанализировать. Это может выглядеть так:
sys(error1, 2.3%)
sys(error2 , 2.4%)
sys(this error , 3%)
Обратите внимание на пробел иногда перед запятой. В моем грамматике (библиотека «Spirit Spirit») я бы хотел записать «error1», «error2» и «this error» соответственно.
Вот оригинальная грамматика, которую я должен был запечатлеть - которая поглощала место в конце имени:
name_string %= lexeme[+(char_ - ',' - '"')];
name_string.name("Systematic Error Name");
start = (lit("sys")|lit("usys")) > '('
> name_string[boost::phoenix::bind(&ErrorValue::SetName, _val, _1)] > ','
> errParser[boost::phoenix::bind(&ErrorValue::CopyErrorAndRelative, _val, _1)]
> ')';
Моя попытка исправить это была первой:
name_string %= lexeme[*(char_ - ',' - '"') > (char_ - ',' - '"' - ' ')];
однако это полностью провалилось. Похоже, не удается разобрать что-либо с пробелом посередине.
Я довольно новичок в Духе - так что, возможно, я упускаю что-то простое. Похоже, лексема отключается, пропуская на переднем крае - мне нужно что-то, что делает это на переднем и заднем фронте.
Заранее спасибо за любую помощь!
Благодаря псур ниже, я смог собрать ответ. Он не идеален (см. Ниже), но я подумал, что обновлю пост, чтобы все могли видеть его в контексте и красиво отформатировать:
qi::rule<Iterator, std::string(), ascii::space_type> name_word;
qi::rule<Iterator, std::string(), ascii::space_type> name_string;
ErrorValueParser<Iterator> errParser;
name_word %= +(qi::char_("_a-zA-Z0-9+"));
//name_string %= lexeme[name_word >> *(qi::hold[+(qi::char_(' ')) >> name_word])];
name_string %= lexeme[+(qi::char_("-_a-zA-Z0-9+")) >> *(qi::hold[+(qi::char_(' ')) >> +(qi::char_("-_a-zA-Z0-9+"))])];
start = (
lit("sys")[bind(&ErrorValue::MakeCorrelated, _val)]
|lit("usys")[bind(&ErrorValue::MakeUncorrelated, _val)]
)
>> '('
>> name_string[bind(&ErrorValue::SetName, _val, _1)] >> *qi::lit(' ')
>> ','
>> errParser[bind(&ErrorValue::CopyErrorAndRelative, _val, _1)]
>> ')';
Это работает! Ключом к этому является name_string, а в нем - оператор qi :: hold, с которым я до этого не был знаком. Это почти как подправило: все, что находится внутри qi :: hold [...], должно успешно проанализировать, чтобы оно пошло. Таким образом, выше, это позволит только пробел после слова, если есть другое слово после. В результате, если последовательность слов заканчивается пробелом, эти последние пробелы не будут проанализированы! Они могут быть поглощены следующим * qi :: lit ('') (см. Правило запуска).
Есть две вещи, которые я хотел бы выяснить, как улучшить здесь:
Было бы неплохо поместить фактический разбор строки в name_word. Проблема заключается в объявлении name_word - оно терпит неудачу, когда оно помещается в соответствующее место в определении name_string.
Было бы еще лучше, если бы name_string мог включать разбор завершающих пробелов, хотя его возвращаемое значение не учитывалось. Я думаю, я знаю, как это сделать ...
Когда / если я это выясню, я обновлю этот пост. Спасибо за помощь!