qi::hold
jest jeden sposób, o tym, jak prawidłowo wymieniony przez @Andrzej
Chyba mam kilka uwag, które mogą pomóc, jak również lepsze rozwiązanie.
Chodzi o to, że Duch nie będzie wymagał przechowywania "temp" dla atrybutów według projektu. W rzeczywistości nie może tak naprawdę zakładać, że atrybut będzie mógł być kopiowany w pierwszej kolejności. To jest powód tutaj (wyobraź sobie analizowanie wszystkiego w jednym std :: vector <> i kopiowanie dla każdego kroku parsera?).
Na bardziej istotnego poziomu, to wygląda mi się, że nie jest to obsługa, która jest wstecznie tutaj atrybut, lecz wyrazem parser sama: To nie zgłasza intencję i ponosi wszystkie rodzaje złożoność czynienia z reprezentacje numeryczne kiedy ... naprawdę nie powinno.
My się na to byłoby
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
Zobaczysz: niech Duch analizować liczbę, a nawet po prostu zweryfikować zakres, który jest co chcieliśmy zrobić w pierwszej kolejności.
Drugą rzeczą, która wydaje mi się typowa, jest fakt, że reguła ujawnia atrybut std::string
, zamiast unsigned char
, np. Dlaczego?
Zakładając To była świadoma decyzja projektowa, można mieć to na swój sposób przez rozsądnego korzystania z
- negatywnej uprzedzona (
!parser
) - który nie ma wpływu atrybutów
- pozytywny uprzedzona (
&parser
) - co nie wpływa na atrybuty
- Zapoznaj się z
qi::as_string
, qi::raw
, qi::lexeme
i qi::no_skip
- działań semantycznych (nie polegać na automatycznych reguł)
Oto co minimalna zmiana pierwotnej reguły musiałby pracował:
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
ta ma mniej więcej taki sam efekt jak kod za pomocą qi::hold
ale nie wadę wydajności wartości atrybutów _hold_ing.
Mam nadzieję, że to pomoże.
Pełna próbka: Żyją na http://liveworkspace.org/code/4v4CQW$0:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
int main()
{
using namespace qi;
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
for (auto& input : std::vector<std::string> { "255", "249", "178", "30", "4" })
{
std::string output;
std::cout << "zeroTo255:\t" << std::boolalpha
<< parse(std::begin(input), std::end(input), zeroTo255, output)
<< ": " << output << std::endl;
output.clear();
std::cout << "alternatively:\t" << std::boolalpha
<< parse(std::begin(input), std::end(input), alternatively, output)
<< ": " << output << std::endl;
}
}
Wyjście
zeroTo255: true: 255
alternatively: true: 255
zeroTo255: true: 249
alternatively: true: 249
zeroTo255: true: 178
alternatively: true: 178
zeroTo255: true: 30
alternatively: true: 30
zeroTo255: true: 4
alternatively: true: 4
Wydaje się do tyłu, ale i tak ... dziękuję za szybką odpowiedź! –
@brunonery Widzę, co masz na myśli mówiąc o "dodatkowej pracy". Miałem wyjaśnić w tym komentarzu, ale zrobiło się trochę duże, więc zamiast tego napisałem to jako odpowiedź :) – sehe
Przepraszam Andrzej - odpowiedź jest poprawna, ale sehe's jest bardziej kompletny. Przyznam mu to, ok? –