Прежде всего, грамматические спецификации, в которых я обычно вижу подобные требования, являются (всегда?) RFC. В 99% случаев проблем нет, рассмотрим, например ::100100
myrule = skip(space) [ uint_ >> uint_ ];
Это уже неявно требует как минимум 1 пробел между цифрами, по той простой причине, что в противном случае было бы 1 число. Такое же упрощение происходит в удивительно многих случаях (см., Например, упрощения, сделанные в отношении повсеместного производства ПОБВ в этом ответе на прошлой неделе Вектор последовательности значений Ци Boost.Spirit ).
Учитывая это, шкиперы применяют ноль или более раз по определению, так что нет никакого способа получить то, что вы хотите, с помощью существующей директивы с состоянием, такой как skip()
. См. Также http://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965 или документы - под lexeme
, [no_]skip
и skip_flag::dont_postskip
).
Глядя на вашу конкретную грамматику, я бы сделал это:
bool r = qi::phrase_parse(iter, end, token >> token, qi::blank);
Здесь вы можете добавить отрицательное предположение в лексеме, чтобы утверждать, что «достигнут конец токена» - что в вашем синтаксическом анализаторе будет обозначено как !qi::graph
:
auto token = qi::copy(qi::lexeme [ qi::char_ >> !qi::graph ]);
См. Демонстрацию:
Live On Coliru
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const str : { "ab", " ab ", " a b ", "a b" }) {
auto iter = str.begin(), end = str.end();
auto token = qi::copy(qi::lexeme [ qi::char_ >> !qi::graph ]);
bool r = qi::phrase_parse(iter, end, token >> token, qi::blank);
std::cout << " --- " << std::quoted(str) << " --- ";
if (r) {
std::cout << "parse succeeded.";
} else {
std::cout << "parse failed.";
}
if (iter != end) {
std::cout << " Remaining unparsed: " << std::string(iter, str.end());
}
std::cout << std::endl;
}
}
Печать
--- "ab" --- parse failed. Remaining unparsed: ab
--- " ab " --- parse failed. Remaining unparsed: ab
--- " a b " --- parse succeeded.
--- "a b" --- parse succeeded.
БОНУС Обзор заметок
Мои рекомендации:
- ваш шкипер должен отвечать за грамматику. Грустно, что все образцы ци заставляют людей поверить, что вам нужно разрешить звонящему решить, что
- проверка конца итератора делает не равной проверкой ошибок. Очень возможно правильно разобрать вещи без использования всего ввода . Вот почему сообщение об «оставшихся входных данных» должно происходить не только в случае неудачного анализа.
- Если конечный неразобранный ввод является ошибкой, расшифрует его :
Live On Coliru
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
for (std::string const str : { "ab", " ab ", " a b ", "a b happy trees are trailing" }) {
auto iter = str.begin(), end = str.end();
auto token = qi::copy(qi::lexeme [ qi::char_ >> !qi::graph ]);
bool r = qi::parse(iter, end, qi::skip(qi::space) [ token >> token >> qi::eoi ]);
std::cout << " --- " << std::quoted(str) << " --- ";
if (r) {
std::cout << "parse succeeded.";
} else {
std::cout << "parse failed.";
}
if (iter != end) {
std::cout << " Remaining unparsed: " << std::quoted(std::string(iter, str.end()));
}
std::cout << std::endl;
}
}
печать
--- "ab" --- parse failed. Remaining unparsed: "ab"
--- " ab " --- parse failed. Remaining unparsed: " ab "
--- " a b " --- parse succeeded.
--- "a b happy trees are trailing" --- parse failed. Remaining unparsed: "a b happy trees are trailing"