29 Ocak 2018 Pazartesi

spirit x3

Giriş
Şu satırı dahil ederiz.
#include <boost/spirit/home/x3.hpp>
Şu satırı dahil ederiz.
namespace x3 = boost::spirit::x3;
C++11 ile gelen yenilikleri kullanabilmemizi sağlar.

parser isim alanı
Şöyle yaparız. Eski spirit kütüphanesindeki gibi qi::gramer yapısından kalıtmaya gerek yoktur.
namespace parser
{
  namespace x3 = boost::spirit::x3;
  using x3::char_;
  using x3::raw;

  const auto str_vec  = *(raw[ +~char_('_')] >> '_');
}
Şöyle kullanırız.
std::string input = "hello_world_";

std::vector<std::string> strVec; 
parse (input.data(), input.data()+input.size(), parser::str_vec, strVec);
char_ parser
x3 char_parser yazısına taşıdım.

eps parser
eps parser Auxilary Parser olarak geçiyor.
Gramere başlarken ilk çağrılacak metodu belirtmek için kullanılır. Şöyle yaparız.
namespace parser
{
  using x3::eps;

  auto set_zero = [&](auto& ctx){ _val(ctx) = 0; };

  x3::rule<class roman, unsigned> const roman = "roman";
  
  auto const roman_def =
        eps                 [set_zero]
        >>
        ...
    ;

  BOOST_SPIRIT_DEFINE(roman);
}
Örnek
Bazı kodlarda hiçbir iş yapmamasına rağmen gramer eps ile başlıyor. Sebebini bilmiyorum. Elimizde şu girdi ve çıktı olsun.
std::string const str("x123x");
boost::iterator_range<std::string::const_iterator> attr;
Şöyle yaparız.
parse(boost::begin(str), boost::end(str), x3::eps >> x3::raw[+x3::digit], attr);
Örnek
Şöyle yaparız.
using namespace boost::spirit::x3;

class version_number_id;
rule<version_number_id, ast::version_number> version_number = "version_number";
auto const version_number_def = eps
        >> int_
        >> "."
        >> int_
        ;
BOOST_SPIRIT_DEFINE(version_number)
lit parser - char
Elimizde şöyle bir yapı olsun.
BOOST_FUSION_DEFINE_STRUCT(
  , employee,
  (std::string, name)
  (int, age)
)
Şöyle yaparız.
std::string const input("{Bob, 35} {Tom, 40}");
std::vector<employee> attr;
if (x3::phrase_parse(boost::begin(input), boost::end(input),
  +(
    x3::lit('{') >>
    +x3::alpha >>
    x3::lit(',') >>
    x3::int_ >>
    x3::lit('}')
    ) >> x3::eoi,
  x3::ascii::space,
  attr
)) {
  std::cout<<"Match!"<<std::endl;
}
else {
  std::cout<<"Not match!"<<std::endl; 
}
int_ parser
Şöyle yaparız.
using boost::spirit::x3::int_;
using boost::spirit::x3::parse;


// example using C++14 lambda

char const *first = "{44}", *last = first + std::strlen (first);
auto f = [](auto& ctx) { std::cout << _attr(ctx) << std::endl; };
parse(first, last, '{' >> int_[f] >> '}');
lexeme directive
İki tane delimiter belirterek arasındaki kuralı tanımlamak isteyelim. Eğer aradaki kural içinde whitespace varsa lexeme'i kullanarak whitespace'in dikkate alınmamasını sağlarız. Şöyle yaparız.
using x3::lexeme;
Örnek
Şöyle yaparız.
return rule<struct _, std::string, true> {} = lexeme [... >> ... >> ....]; 
Örnek
Şöyle yaparız.
auto const nested_identifier_def =
  x3::lexeme[
      (+(id_string >> "::") >> +(id_string >> ".") > id_string)
    | (+(id_string >> "::") >> VEC_ATR > id_string)
    | (VEC_ATR >> +(id_string >> ".") > id_string)
    | identifier

  ];
omit directive
Şöyle yaparız.
const char prefix = '<';
const char postfix = '>';

return rule<struct _, std::string, true> {} = lexeme [ 
        omit[prefix] >> *(char_ - postfix) >> omit[postfix] 
    ];
raw directive
Örnek 1
Elimizde şu girdi ve çıktı olsun.
std::string const str("x123x");
boost::iterator_range<std::string::const_iterator> attr;
Şöyle yaparız.
#include <iostream>
#include <boost/spirit/home/x3.hpp>

namespace x3 = boost::spirit::x3;

int main() {
  std::string const str("x123x");
  boost::iterator_range<std::string::const_iterator> attr;
  if(x3::parse(boost::begin(str), boost::end(str), x3::raw[+x3::digit], attr)) {
    std::cout<<"Match! attr = "<<attr<<std::endl;
  } else {
    std::cout<<"Not match!"<<std::endl;
  }
}
Çıktı olarak "Not match!" alırız.

Şöyle yaparız.
parse(boost::begin(str), boost::end(str), x3::raw[+x3::digit] >> x3::eps, attr);
uint_parser
Şöyle yaparız.
x3::uint_parser<unsigned int, 10, 1, 3> uint_;
ulong_ parser
Şöyle yaparız
namespace x3 = boost::spirit::x3;
using x3::ulong_;

Hiç yorum yok:

Yorum Gönder