spirit x3
C++11 ile gelen özelliklerin kullanılabilmesini sağlar. Şöyle kullanılıyor.
Parse işleminde struct gibi nesnelerin kolayca doldurulabilmesini sağlar. Şu satırı dahil ederiz.
boost spirit qi yazısına taşıdım.
eol
Satır sonunu belirtir.
qi::int_ - parser
qi::int_ ile şöyle yaparız.
Verilen string'i birebir eşleşir. Şöyle yaparız.
Belirtilen örüntüyü dikkate almaz.
Şöyle yaparız.
Belirtilen örüntüye kadar yürür.
Örnek ver.
qi::uint_ - parser
Semantic action tanımlanabilir. Şöyle yaparız.
Parser'ların arka arkaya sıralanması gibi düşünülebilir. Şöyle yaparız.
grammar template olarak tanımlanabilir. Şöyle yaparız.
struct içinde tanımlı bir qi::rule ata sınıfa geçilir. Şöyle yaparız.
Şöyle yaparız. Önce begin ve end iterator tanımlanır.
parse metodu
Bu metod begin iterator + end iterator + rule + output şeklinde düşünülebilir.
Delimeter
Bir string'i delimeter/separator ile ikiye ayırma örneği şöyle. Biraz düzenli ifadeye benziyor.
*~char_ ile delimeter'a kadar tüme karakterleri alır. Daha sonra separator gelir. Takiben yine tüm karakterleri alıyor. Yakalanan karakterler left ve right stringlerine dolduruluyor.
C++11 ile gelen özelliklerin kullanılabilmesini sağlar. Şöyle kullanılıyor.
namespace x3 = boost::spirit::x3;
Şu satırı dahil ederiz.#include <boost/spirit/home/x3.hpp>
fusionParse işleminde struct gibi nesnelerin kolayca doldurulabilmesini sağlar. Şu satırı dahil ederiz.
#include <boost/fusion/adapted/struct.hpp>
Şöyle yaparız.struct Point { double x, y, z; };
BOOST_FUSION_ADAPT_STRUCT(Point,x,y,z)
qiboost spirit qi yazısına taşıdım.
eol
Satır sonunu belirtir.
qi::int_ - parser
qi::int_ ile şöyle yaparız.
char const* b = "66";
char const* e = b + strlen("66");
int32_t res = 0;
bool valid = boost::spirit::qi::parse(b, e, boost::spirit::qi::int_, res);
qi::int_parser<> ile şöyle yaparız.int res = 0;
namespace qi = boost::spirit::qi;
bool valid = qi::parse(b, e, qi::int_parser<int, 10>(), res);
qi::lexemeVerilen string'i birebir eşleşir. Şöyle yaparız.
qi::lexeme["self"]
omitBelirtilen örüntüyü dikkate almaz.
omit[',' >> double_]
rawŞöyle yaparız.
qi::raw[qi::lexeme["self"]]
seekBelirtilen örüntüye kadar yürür.
seek[ eps >> 'x' >> 'y' >> 'z' >> eol ]
str_p - parserÖrnek ver.
qi::uint_ - parser
Semantic action tanımlanabilir. Şöyle yaparız.
auto not_greater_than_12345 = [](const unsigned& attr, auto&, bool& pass) {
pass = !(attr > 12345U);
};
qi::uint_[not_greater_than_12345]
ruleParser'ların arka arkaya sıralanması gibi düşünülebilir. Şöyle yaparız.
if_rule=str_p(IF)>>ch_p("(")>>if_mem>>*("and"|"or">>if_mem)>>ch_p(")");
grammargrammar template olarak tanımlanabilir. Şöyle yaparız.
template <typename Iterator, typename Skipper>
struct grammar : qi::grammar<Iterator, MyType(), Skipper>
{
...
}
Şöyle yaparız.template <typename Iterator>
struct grammar : qi::grammar<Iterator, MyType(),ascii::space_type>
{
...
}
constructorstruct içinde tanımlı bir qi::rule ata sınıfa geçilir. Şöyle yaparız.
template <typename Iterator, typename Skipper>
struct grammar : qi::grammar<Iterator, MyType(), Skipper>
{
grammar() : grammar::base_type(object)
{
..
}
private:
qi::rule<Iterator, QVariant(), Skipper> object;
...
};
phrase_parseŞöyle yaparız. Önce begin ve end iterator tanımlanır.
using It = std::string::const_iterator;
std::string input = "...";
It begin = input.begin(), end = input.end();
Daha sonra beklenen çıktı tipi ile çağrılır.Foo foo;
bool ok = qi::phrase_parse
(begin, end, grammar<It, qi::space_type>{}, qi::space, foo);
Benzer metod x3 ile şöyle kullanılır. Önce begin ve end iterator tanımlanır. Bu sefer dosyadan okuma yapacağımız için memory mapped file tanımlıyoruz.std::string const fname = ...;
boost::iostreams::mapped_file mm(fname);
Daha sonra bir vector tanımlarız.std::vector<Point> v;
Ve dosyayı okuruz.return phrase_parse(mm.begin(), mm.end(),
..., //grameri yazmadım
blank, v);
Çağrı sonucunu şöyle işleriz.auto f = input.begin(), l = input.end();
bool ok = qi::phrase_parse(f, l, grammar, qi::space);
if (ok)
std::cout << "Parse success\n";
else
std::cout << "Parse failed\n";
if (f!=l)
std::cout << "Trailing unparsed input: '" << std::string(f, l) << "'\n";
parse metodu
Bu metod begin iterator + end iterator + rule + output şeklinde düşünülebilir.
Delimeter
Bir string'i delimeter/separator ile ikiye ayırma örneği şöyle. Biraz düzenli ifadeye benziyor.
*~char_ ile delimeter'a kadar tüme karakterleri alır. Daha sonra separator gelir. Takiben yine tüm karakterleri alıyor. Yakalanan karakterler left ve right stringlerine dolduruluyor.
#include <boost/spirit/include/qi.hpp>
struct misc {
static void split(const std::string &input,
std::string &left, std::string &right, char separator)
{
using namespace boost::spirit::qi;
parse(input.begin(), input.end(), *~char_(separator) >>
separator >> *char_, left, right);
}
};
Hiç yorum yok:
Yorum Gönder