Boost-Geist-Regel mit benutzerdefinierten Attribut Parsing
-
30-09-2019 - |
Frage
Ich bin eine Boost Geist Grammatik parst Text in einen Vektor dieses structs schreiben:
struct Pair
{
double a;
double b;
};
BOOST_FUSION_ADAPT_STRUCT(
Pair,
(double, a)
(double, a)
)
Diese Grammatik hat eine Regel wie folgt aus:
qi::rule<Iterator, Pair()> pairSequence;
die eigentliche Grammatik pairSequence
Dies ist jedoch:
double_ % separator
Ich mag diese Grammatik eine Pair
mit a
herzustellen gleich den doppelten und b
bis zu einem gewissen konstant gleich. Ich möchte so etwas wie dies tun:
pairSequence = double_[_val = Pair(_1, DEFAULT_B)] % separator;
Das oben nicht kompilieren, natürlich. Ich habe versucht, einen Konstruktor Pair
hinzufügen, aber ich bekomme immer noch Kompilierungsfehler ( keine passende Funktion für Aufruf von 'Pair :: Pair (const boost :: Phoenix :: Schauspieler> &, double) ).
Lösung
Zunächst einmal die Unterschrift von pairSequence
muss sein:
qi::rule<Iterator, std::vector<Pair>()> pairSequence;
als die Liste Operator stellt einen std::vector<Pair>
als Attribut.
Alle aus dem Inneren einer semantischen Aktion aufgerufenen Funktionen müssen sein ‚faul‘, so dass Sie phoenix nutzen müssen:
namespace phx = boost::phoenix;
pairSequence =
double_[
phx::push_back(_val,
phx::construct<Pair>(_1, phx::val(DEFAULT_B))
)
] % separator
;
Eine weitere Möglichkeit, einen (nicht explizit) Konstruktor Pair
hinzuzufügen wäre:
struct Pair
{
Pair(double a) : a(a), b(DEFAULT_B) {}
double a;
double b;
};
, die die Grammatik vereinfachen kann:
pairSequence = double_ % separator;
und verlässt sich voll und ganz auf Geist-internen Attribut Propagierungsregeln.
BTW, für irgendetwas davon zu arbeiten, brauchen Sie nicht Pair
als Fusionssequenz anzupassen.