Giriş
Şu satırı dahil ederiz.
Birinci parametre parse edilecek iterator tipidir.
İkinci parametre doldurulması beklenen tipi belirtir, yani return type diyelim.
Üçüncü parametre token'ları ayırmak için kullanılacak parser'dır. Genelde qi::space_type kullanılır.
Iterator
Şöyle yaparız
Skipper olarak şöyle yapılır.
fusion
Şu satırı dahil ederiz.
Şöyle yaparız. Template parametresi olarak sadece iterator veririr. Diğer parametreler kodlanır.
Şöyle yaparız. Template parametresi olarak sadece iterator ve skipper verilir. Return type kodlanır.
Default parametreler verebiliriz. Şöyle yaparız.
Şöyle yaparız. Her kural = veya kural %= ile belirtilir. Farkını bilmiyorum.
Ayrıca her kural sınıfın private alanında tanımlanmalıdır.
% karakteri ile şöyle yaparız.
Şöyle yaparız.
Elimizde iki gramer olsun. İlk gramer büyük harfle başlayan stringler, ikincisi ise double'ları okur.
Şöyle yaparız.
Şu satırı dahil ederiz.
#include <boost/spirit/include/qi.hpp>
Daha rahat kullanmak için şu satırlar dahil edilir.namespace qi = boost::spirit::qi;
namespace bs = boost::spirit;
Bazen şu satır da dahil edilir.namespace ascii = boost::spirit::ascii;
Template ParametreleriBirinci parametre parse edilecek iterator tipidir.
İkinci parametre doldurulması beklenen tipi belirtir, yani return type diyelim.
Üçüncü parametre token'ları ayırmak için kullanılacak parser'dır. Genelde qi::space_type kullanılır.
Iterator
Şöyle yaparız
std::string input = "...";
typedef std::string::const_iterator Iter;
MyGrammar<Iter,...> g;
Şöyle yaparız.std::string input = "...";
auto it = input.begin();
MyGrammar<decltype(it),...> g;
SkipperSkipper olarak şöyle yapılır.
ascii::blank_type
Bazen de şöyle yapılır.ascii::space_type
İkisi arasındaki farkı tam bilmiyorum. blank_type sanırım newline karakterini atlamaz ve okur, space_type ise atlar.fusion
Şu satırı dahil ederiz.
#include <boost/fusion/include/adapt_struct.hpp>
Şu satırı dahil ederiz.using namespace boost::fusion;
Elimizde şöyle bir yapı olsun.struct Foo
{
std::string field1;
std::string field2; std::string field3;};
Şöyle yaparız.BOOST_FUSION_ADAPT_STRUCT(
MyNameSpace::Foo,
(std::string, field1)
(std::string, field2)
(std::string, field3)
)
qi::grammar struct - IteratorŞöyle yaparız. Template parametresi olarak sadece iterator veririr. Diğer parametreler kodlanır.
template <typename It>
struct MyGrammar : qi::grammar<It, Attribute()> {
MyGrammar() : MyGrammar::base_type(start) {
start = qi::skip(qi::space) [ mainRule ];
mainRule = /*....*/;
}
private:
qi::rule<It, Attribute()> start;
qi::rule<It, Attribute(), qi::space_type> mainRule;
};
qi::grammar struct - Iterator + SkipperŞöyle yaparız. Template parametresi olarak sadece iterator ve skipper verilir. Return type kodlanır.
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, Foo(), Skipper> {
...
};
qi::grammar struct - Iterator + Return Type + SkipperDefault parametreler verebiliriz. Şöyle yaparız.
template <typename Iterator, typename Result = std::vector<std::string> >
struct MyGrammar : public qi::grammar<Iterator, Result(), bs::ascii::space_type> {
};
Default parametre verdiğimiz için sınıf sadece iterator tipi ile ilklendirilir. Şöyle yaparızstd::string input = "...";
auto it = input.begin();
my_grammar<decltype(it)> g;
Constructor - kuralŞöyle yaparız. Her kural = veya kural %= ile belirtilir. Farkını bilmiyorum.
Ayrıca her kural sınıfın private alanında tanımlanmalıdır.
MyGrammar() : MyGrammar::base_type(start) {
start = ...;
}
private:
qi::rule<Iterator, Foo(), Skipper> start;
Eğer iki kural olsaydı şöyle yaparız. Bazı kurallar için Skipper tanımlanmayabiliyor. Sebebini bilmiyorumtoken = ...;
start = ...;
private:
qi::rule<Iterator, Foo(), ascii::blank_type> start;
qi::rule<Iterator,
std::string()> token;
kurallar % veya >> karakteri ile birleştirilir. Farkını bilmiyorum.% karakteri ile şöyle yaparız.
start = token % ',';
token = ...;
>> karakteri ile şöyle yaparız.token = ...;
start = "VARIABLE" >> text >> qi::eol;
ÖrnekŞöyle yaparız.
template <typename It = std::string::const_iterator>
struct parser : qi::grammar<It, AST::Record()> {
parser() : parser::base_type(start) {
using namespace qi;
start = skip(blank) [record_];
record_ = prefix_ >> fqdn_ >> int_ >> int_ >> int_ >> int_ >> sample_
>> '[' >> sample_ >> ']' >> tolerance_;
prefix_ = string("^+"); // or whatever you need to match here
fqdn_ = +graph; // or whatever additional constraints you have
sample_ = direction_ >> duration_;
duration_ = (long_ >> units_) [ _val = _1 * _2 ];
tolerance_= "+/-" >> duration_;
BOOST_SPIRIT_DEBUG_NODES(
(start)(record_)
(prefix_)(fqdn_)(sample_)(duration_)(tolerance_)
)
}
private:
struct directions : qi::symbols<char, AST::TimeSample::Direction> {
...
} direction_;
struct units : qi::symbols<char, AST::clock::duration> {
...
} units_;
using Skipper = qi::blank_type;
qi::rule<It, AST::Record()> start;
qi::rule<It, AST::Record(), Skipper> record_;
qi::rule<It, AST::TimeSample(), Skipper> sample_;
qi::rule<It, AST::clock::duration(), Skipper> duration_, tolerance_;
// lexemes:
qi::rule<It, std::string()> prefix_;
qi::rule<It, std::string()> fqdn_;
};
Örnek - grammer iki gramerden oluşuyorElimizde iki gramer olsun. İlk gramer büyük harfle başlayan stringler, ikincisi ise double'ları okur.
struct attr_1 {
std::string a;
};
BOOST_FUSION_ADAPT_STRUCT(attr_1, (std::string, a))
struct attr_2 {
double a;
};
BOOST_FUSION_ADAPT_STRUCT(attr_2, (double, a))
template <typename It = const char *>
struct grammar_1 : qi::grammar<It, attr_1()> {
grammar_1() : grammar_1::base_type{ rule_ } { rule_ = qi::eps >> +ascii::upper; }
private:
qi::rule<It, attr_1()> rule_;
};
template <typename It = std::string::const_iterator>
struct grammar_2 : qi::grammar<It, attr_2()> {
grammar_2() : grammar_2::base_type{ rule_ } { rule_ = qi::double_; }
private:
qi::rule<It, attr_2()> rule_;
};
Bu iki grameri içeren bir başka gramer yazmak için şöyle yaparız.typedef boost::variant<attr_1, attr_2> attr_comp;
template <typename It = std::string::const_iterator>
struct grammar_comp : qi::grammar<It, attr_comp()> {
grammar_comp() : grammar_comp::base_type{ rule_ } { rule_ = (g1_ | g2_); }
private:
grammar_1<It> g1_;
grammar_2<It> g2_;
qi::rule<It, attr_comp()> rule_;
};
Constructor - kural + stringŞöyle yaparız.
MyGrammar() : MyGrammar::base_type(start, "MY") { start = ...;
token = ...;
}
Hiç yorum yok:
Yorum Gönder