qi::hold
ist ein Weg, um darüber, wie richtig von @Andrzej erwähnt
Ich glaube, ich ein paar Beobachtungen, die, ebenso wie eine bessere Lösung könnte helfen.
Der Punkt ist, dass Spirit nicht 'Temp' Speicher für Attribute von Design erfordern wird. Tatsächlich kann das Attribut nicht wirklich als kopierbar angesehen werden. Dies ist der Grund hier (stellen Sie sich vor, alles in einen einzigen std :: vector <> zu kopieren und für jeden Parser-Schritt zu kopieren?).
Auf einem wesentlicheren Ebene sieht es mir, als ob es nicht das Attribut Umgang dass rückwärts hier ist, aber der Parser Ausdruck selbst: Es schlägt fehl, die Absicht zu erklären, und verursacht alle Arten von Komplexität Umgang mit Zahlendarstellungen wenn ... wirklich sollte es nicht.
Mein nehmen auf, es wäre
rule<std::string::iterator, std::string()> zeroTo255, alternatively;
alternatively %= raw [ uint_ [ _pass = (_1 <= 255) ] ];
Sie sehen: Sie lassen Geist eine Reihe analysieren, und zwar nur den Bereich verifizieren, das ist, was Sie in erster Linie tun wollte.
Die zweite Sache, die mich als typisches trifft, ist die Tatsache, dass die Regel ein std::string
Attribut aussetzt, statt unsigned char
z.B. Warum das?
Angenommen, dies war eine bewusste Design-Entscheidung, können Sie es Ihren Weg durch gezielten Einsatz von
- negativer Vorschau (
!parser
) haben -, die keine Attribute beeinflussen
- positive Vorschau (
&parser
) - die hat keinen Einfluss auf Attribute
- machen Sie sich mit
qi::as_string
, qi::raw
, qi::lexeme
und qi::no_skip
- semantischen Aktionen (nicht vertrauen auf automatische Regeln ist)
Hier ist, was zu Ihrer ursprünglichen Regel minimale Änderung gearbeitet haben würde:
zeroTo255 = raw [
("25" >> char_("0-5"))
| ('2' >> char_("0-4") >> digit)
| ('1' >> digit >> digit)
| (char_("1-9") >> digit)
| digit
];
Dies hat in etwa die gleiche Wirkung wie der Code qi::hold
verwenden, aber nicht die Leistung Nachteil von _hold_ing Attributwerten.
Hoffe, das hilft.
Voll Beispiel: Live on 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;
}
}
Ausgabe
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
Es scheint, rückwärts, aber trotzdem ... Danke für die schnelle Antwort! –
@brunonery Ich sehe, was du mit der "Extraarbeit" meinst. Ich wollte das in diesem Kommentar erklären, aber es wurde ein bisschen groß, also habe ich es als Antwort geschrieben :) – sehe
Tut mir leid Andrzej - deine Antwort ist richtig, aber die ist vollständiger. Ich vergebe ihm diesen, ok? –