Boost.Spirit.Qi: Nehmen Sie ein Attribut der Regel und legen Sie es als ein Feld eines struct-Attribut des einschließe Regel?

StackOverflow https://stackoverflow.com/questions/4620016

Frage

Wie viele dieser Fragen, Ich versuche, eine einfache Grammatik in einen Baum von Strukturen mit Boost.Spirit.Qi zu analysieren.

Ich werde versuchen zu destillieren, was ich versuche zu möglichst einfachen Fall zu tun. Ich habe:

struct Integer {
  int value;
};
BOOST_FUSION_ADAPT_STRUCT(Integer, (int, value))

Später innerhalb einer Grammatik struct, ich habe folgende Membervariable:

qi::rule<Iterator, Integer> integer;

, die, mit denen ich die Definition

integer = qi::int_;

Wenn ich versuche, um tatsächlich eine ganze Zahl zu analysieren, jedoch mit

qi::phrase_parse(iter, end, g, space, myInteger);

myInteger.value wird immer nach einem erfolgreichen Parse nicht initialisiert. In ähnlicher Weise habe ich die folgenden Definitionen versucht (natürlich diejenigen, die nicht die Kompilierung zu tun sind falsch):

integer = qi::int_[qi::_val = qi::_1]; //compiles, uninitialized value
integer = qi::int_[qi::_r1 = qi::_1]; //doesn't compile
integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1]; //doesn't
integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; //doesn't

Klar bin ich Missverständnis etwas über Geist, Phoenix, oder etwas anderes. Mein Verständnis ist, dass qi::_1 das erste Attribut von qi::int_ ist, hier und sollte die geparsten ganze Zahl darstellen, wenn das Teil in den eckigen Klammern als Funktion Objekt ausgeführt wird. Ich gehe davon aus, dass dann die Funktion Objekt nehmen Sie die umschließenden integer Attribut qi::_val und versuchen, die geparsten ganze Zahl zuweisen. Meine Vermutung war, dass wegen meines BOOST_FUSION_ADAPT_STRUCT Anrufs, das zwei kompatibel sein würde, und das scheint sicher der Fall von einer statischen Analyse Perspektive zu sein, aber die Daten nicht erhalten werden.

Gibt es eine Referenz (&) Bezeichnung ich irgendwo bin etwas fehlt?

War es hilfreich?

Lösung

Wenn Integer sollte das Attribut von der Regel ausgesetzt sein, müssen Sie es erklären, wie:

qi::rule<Iterator, Integer()> integer; 

(beachten Sie die Klammern). Geist erfordert die Funktionsdeklaration Syntax zu verwenden, um die Herrschaft der ‚Schnittstelle‘ zu beschreiben. Es ist nicht nur in Geist verwendet, sondern von mehreren anderen Bibliotheken als auch (siehe boost :: Funktion zum Beispiel).

Der Hauptgrund dafür ist, dass es ist eine nette prägnante Art und Weise eine Funktionsschnittstelle anzugeben. Wenn Sie darüber nachdenken, was eine Regel ist, merkt man schnell, dass es wie eine Funktion ist: es einen Wert zurückgeben kann (das geparsten Ergebnis, das heißt synthetisierte Attribut). Zusätzlich kann es dauern, ein oder mehr Argumente (die geerbten Attribute).

Ein zweite, aber kleinerer Grund ist, dass Geist muss in der Lage sein, den verschiedenen Template-Parameter einer Regel zu unterscheiden. Die Template-Parameter können in beliebiger Reihenfolge (mit Ausnahme des Iterator) angegeben werden, so braucht es einige Mittel, herauszufinden, was was ist. Die Funktionsdeklaration Syntax ist ausreichend verschieden von dem Skipper oder die Kodierung (die anderen beiden möglichen Template-Parameter), damit sie zum Zeitpunkt der Kompilierung erkannt werden.

haben wir einen Blick auf Ihre verschiedenen Versuche:

Dies kann an der Arbeit gemacht werden, wenn Sie die Regel-Definition ändern, wie oben beschrieben.

integer = qi::int_[qi::_val = qi::_1]; 

Die _val bezieht sich auf Ihre Integer, während der _1 auf ein int bezieht. Daher müssen Sie einen Zuweisungsoperator von int definieren, um diese Arbeit zu machen:

struct Integer {
    int value;
    Integer& operator=(int) {...}
};                    

Sie brauchen nicht Ihre Art als Fusionssequenz in diesem Fall anzupassen.

Aber man kann es schreiben noch einfacher:

integer = qi::int_ >> qi::eps;

, die 100% entspricht (das EPS ist ein Trick verwendet, um die rechte Seite in einen Parser-Sequenz zu konvertieren, die das nutzen können Attributausbreitungs integrierte Zuordnungs die Elemente Ihrer angepasst Fusion Sequenz zu den Attributen der Elemente die Sequenz).

Dieses:

integer = qi::int_[qi::_r1 = qi::_1]; 

wird nicht als _r1 Arbeit bezieht sich auf die erste geerbt Attribut einer Regel. Allerdings hat die Regel nicht inherted Attribute.

Dies funktioniert:

integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1];

aber erfordert nicht Ihre Art als Fusionssequenz anzupassen.

Und so wird diese:

integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top