Eine Möglichkeit ist zum qi::uint_
Parser eine semantische Aktion anschließen, die das Attribut der Parser überprüft und setzt den dritten Parameter semantischen Aktion entsprechend:
#include <iostream>
#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
qi::rule<std::string::const_iterator, unsigned(), qi::ascii::space_type> rule;
const auto not_greater_than_12345 = [](const unsigned& attr, auto&, bool& pass) {
pass = !(attr > 12345U);
};
rule %= qi::uint_[not_greater_than_12345];
std::vector<std::string> numbers{"0", "123", "1234", "12345", "12346", "123456"};
for (const auto& number : numbers) {
unsigned result;
auto iter = number.cbegin();
if (qi::phrase_parse(iter, number.cend(), rule, qi::ascii::space, result) &&
iter == number.cend()) {
std::cout << result << '\n'; // 0 123 1234 12345
}
}
}
Live on Wandbox
Die semantische Aktion kann prägnanter geschrieben werden mit the Phoenix placeholders _pass
and _1
:
#include <iostream>
#include <string>
#include <vector>
#include <boost/phoenix/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main() {
qi::rule<std::string::const_iterator, unsigned(), qi::ascii::space_type> rule;
rule %= qi::uint_[qi::_pass = !(qi::_1 > 12345U)];
std::vector<std::string> numbers{"0", "123", "1234", "12345", "12346", "123456"};
for (const auto& number : numbers) {
unsigned result;
auto iter = number.cbegin();
if (qi::phrase_parse(iter, number.cend(), rule, qi::ascii::space, result) &&
iter == number.cend()) {
std::cout << result << '\n'; // 0 123 1234 12345
}
}
}
Live on Wandbox
Von Semantic Actions with Parsers
Die möglichen Signaturen für Funktionen als semantische Aktionen verwendet werden sollen:
...
template <typename Attrib, typename Context>
void fa(Attrib& attr, Context& context, bool& pass);
... Hier Attrib
ist der Attributtyp des Parsers an den angeschlossenen semantische Aktion. ... Der dritte Parameter pass
kann von der semantischen Aktion verwendet werden, um den zugehörigen Parser zum Fehlschlagen zu zwingen. Wenn pass
auf false gesetzt ist, gibt der Aktionsparser sofort auch false zurück, während p nicht aufgerufen wird und keine Ausgabe generiert wird.