Giriş
Şu satırı dahil ederiz.
bind metodu
Örnek
Elimizde bir yapı olsun.
Elimizde bir yapı olsun
Elimizde bir yapı olsun.
Elimizde bir rule olsun. rule eşleşince değer atamak için şöyle yaparız.
Yaklanan şeyin başına _tag_ eklemek için şöyle yaparız.
Örnek
Şöyle yaparız
Şöyle yaparız.
Derinliği 32'yi geçmemesi için şöyle yaparız.
Şu satırı dahil ederiz.
#include <boost/spirit/include/phoenix.hpp>
Bir rule için semantic action çalıştırmayı sağlar. Açıklaması şöylePhoenix, a companion library bundled with Spirit, is specifically suited for binding semantic actions. It is like Boost.Lambda on steroids, with special custom features that make it easy to integrate semantic actions with Spirit.Semantic action'lardan kaçınmak lazım deniyor. Açıklaması şöyle
Phoenix Actors are needlessly more complex than the dedicated functor. They have a sweet point (mainly simple assignment or builtin operations). But if the actor is any kind of non-trivial you'll see the complexity ramp up quickly, not just for the human but also for the compiler. This leads toAçıklaması şöyle
- slow compilation
- sub-optimal emitted code
- harder to maintain source
- new classes of error (e.g. when the expression templates hold references to locals/temporaries, something that Boost Proto (and hence Phoenix) does not prevent or signal. In fact, it encourages it by assuming all template expressions are ephemeral, but I digress).
Interestingly: Spirit X3 dropped Phoenix altogether, even though Phoenix was once the brain child of Spirit.The new style uses c++14 polymorphic lambdas, that look 90% like the helper function object in the original code, but inline as a lambda.
bind metodu
Örnek
Elimizde bir yapı olsun.
struct MyStruct {
int a;
int b;
int c;
};
Bu yapıyı kullanan bir karma grammar olsun.struct MyStructGenerator : bsk::grammar<boost::spirit::ostream_iterator, MyStruct()>
{
MyStructGenerator() : MyStructGenerator::base_type(start_)
{
start_ = '<'
<< bsk::int_[bsk::_1 = boost::phoenix::bind(&MyStruct::c, bsk::_val)]
<< ','
<< bsk::int_[bsk::_1 = boost::phoenix::bind(&MyStruct::b, bsk::_val)]
<< ','
<< bsk::int_[bsk::_1 = boost::phoenix::bind(&MyStruct::a, bsk::_val)]
<< '>';
}
~MyStructGenerator() = default;
bsk::rule<boost::spirit::ostream_iterator, MyStruct()> start_;
};
Şöyle yaparız. MyStruct ms = { 3, 2, 1 };
std::cout << boost::spirit::karma::format(MyStructGenerator(), ms) << std::endl;
Çıktı olarak şunu alırız.<1, 2, 3>
ÖrnekElimizde bir yapı olsun
struct VariableHolder {
std::string name; // contains "varName"
std::string fromFile; // contains "$(varName)" or "$varName"
};
Bu değişkenlere şöyle bind işlemi yaparız.auto _name = phoenix::bind(&VariableHolder::name, qi::_val);
auto _fromFile = phoenix::bind(&VariableHolder::fromFile, qi::_val);
Daha sonra kuralları tanımlarız. start kuralı her eşleştiğinde hem _name hem de_fromFile değişkeni atanır.variableName = qi::alpha >> +qi::alnum;
variable = '$' >> (variableName | '(' >> variableName >> ')');
start = qi::as_string [ qi::raw [ variable [ _name = qi::_1 ]]
] [_fromFile = qi::_1 ];
ÖrnekElimizde bir yapı olsun.
struct Data {
double minFrequency = 0.0;
double maxFrequency = 0.0;
double minElevation = 0.0;
double maxElevation = 0.0;
};
Eşleşme olunca alanlara değer atamak için şöyle yaparız.template <typename It, typename Skipper = qi::blank_type>
struct grammar : qi::grammar<It, Data(), Skipper> {
grammar() : grammar::base_type(start) {
using namespace qi;
auto minFrequency = bind(&Data::minFrequency, _r1);
auto maxFrequency = bind(&Data::maxFrequency, _r1);
auto minElevation = bind(&Data::minElevation, _r1);
auto maxElevation = bind(&Data::maxElevation, _r1);
known =
("FMin Antenna" >> lit('=') >> int_)[minFrequency = _1] |
("FMax Antenna" >> lit('=') >> int_)[maxFrequency = _1] |
("EMin Antenna" >> lit('=') >> int_)[minElevation = _1] |
("EMax Antenna" >> lit('=') >> int_)[maxElevation = _1]
;
unknown = +alnum >> '=' >> +alnum;
setting = (known(_r1) | unknown) >> +eol;
start =
no_case["[GENERAL]"] >> eol
>> *setting(_val);
}
private:
qi::rule<It, Data(), Skipper> start;
qi::rule<It, void(Data&), Skipper> setting, known;
qi::rule<It, Skipper> unknown;
};
ÖrnekElimizde bir rule olsun. rule eşleşince değer atamak için şöyle yaparız.
template <typename Iterator>
struct property : qi::grammar<Iterator, int()> {
property() : property::base_type(start) {
using namespace qi;
name = +(graph - char_(".][")); // not matching spaces please
qualifiedName = name % '.';
start = skip(ascii::space) ['[' >> qualifiedName >> ']']
[_val = phx::bind(lookup, phx::cref(sample), _1) ]
;
BOOST_SPIRIT_DEBUG_NODES((start)(qualifiedName)(name))
}
private:
qi::rule<Iterator, std::deque<std::string>(),
qi::ascii::space_type> qualifiedName;
qi::rule<Iterator, std::string()> name;
qi::rule<Iterator, int()> start;
};
lookup metodunu şöyle yaparız. Burada Node sınıfı bizim kodumuz.int lookup(Node const& context, std::deque<std::string> path);
function metoduYaklanan şeyin başına _tag_ eklemek için şöyle yaparız.
struct convertTag_f {
std::string operator()(std::string const& tag) const {
return "_tag_" + tag;
}
};
boost::phoenix::function<convertTag_f> convertTag;
TestGrammar() : TestGrammar::base_type(expr)
{
using namespace qi::labels;
tag = qi::as_string[+ascii::char_] [ _val += convertTag(_1) ];
expr = ascii::char_('!') >> tag;
}
BOOST_PHOENIX_ADAPT_FUNCTIONÖrnek
Şöyle yaparız
BOOST_PHOENIX_ADAPT_FUNCTION(long, stol_, std::stol, 1);
Şöyle bir rule tanımlarız.qi::rule<std::string::const_iterator, long()> weird_num;
{
using namespace qi;
weird_num = as_string[ skip(alpha) [+digit] ] [_val = stol_(_1) ];
}
Şöyle yaparız.std::string const s = "AB1234xyz5678C9";
long x = 0;
boost::spirit::qi::parse(s.begin(), s.end(), weird_num, x);
ÖrnekŞöyle yaparız.
BOOST_PHOENIX_ADAPT_FUNCTION(std::string, regex_replace_, boost::regex_replace, 4)
ri_typeDerinliği 32'yi geçmemesi için şöyle yaparız.
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
qi::rule<std::string::const_iterator, std::string(size_t depth)> term;
qi::_r1_type _depth;
term %=
qi::eps(_depth < 32) >>
qi::string("(") >> *term(_depth + 1) >> qi::string(")");
Hiç yorum yok:
Yorum Gönder