11 Ocak 2018 Perşembe

spirit qi rule Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <boost/spirit/include/qi.hpp>
Kolay kullanım için şu satırı dahil ederiz.
namespace qi = boost::spirit::qi;
Rule Olarak Kullanım
Bu sınıfı şöyle kullanırız. Üçüncü parametre olarak geçeriz.
std::string out1;
int out2;

if (qi::phrase_parse(str.begin(), str.end(), r, qi::space, out1, out2))
{
  ...
}
Şöyle kullanırız. Üçüncü parametre olarak geçeriz.
bool result =  qi::parse (str.begin(), str.end(), r);
Skipper Olarak Kullanım
Şöyle yaparız.
using Iterator = boost::spirit::istream_iterator;
using Skipper  = qi::rule<Iterator>;

Skipper block_comment, single_line_comment, skipper;

{
  using namespace qi;
  single_line_comment = "//" >> *(char_ - eol) >> (eol|eoi);
  block_comment       = ("/*" >> *(block_comment | char_ - "*/")) > "*/";

  skipper             = space | single_line_comment | block_comment;
}

Iterator f(std::cin >> std::noskipws), l;

std::vector<int> data;
bool ok = phrase_parse(f, l, *qi::int_, skipper, data);
Tanımlama - iterator
Şöyle yaparız.
qi::rule<std::string::const_iterator> r = qi::no_case [ 
     qi::lit("my_cmd1") | qi::lit("my_cmd2") 
  ];
Tanımlama - iterator + output type
output type iterator gibi () karakterleri ile bitmelidir. Şöyle yaparız.
qi::rule<std::string::const_iterator, std::string()> r;
Örnek - std::map
Elimizde şöyle bir kod olsun.
namespace Config {
  using Key = std::string;
  using Value = boost::variant<int, std::string, bool>;
  using Setting = std::pair<Key, Value>;
  using Settings = std::map<Key, Value>;
}

namespace Parser {
  using It = std::string::const_iterator;
  using namespace Config;
  namespace qi = boost::spirit::qi;

  using Skip = qi::blank_type;
  qi::rule<It, std::string()>   quoted_   = "'" >> *(
            "'" >> qi::char_("'") // double ''
          | '\\' >> qi::char_     // any character escaped
          | ~qi::char_("'")       // non-quotes
       ) >> "'";
  qi::rule<It, Key()>           key_      = +qi::char_("a-zA-Z0-9_"); // for example
  qi::rule<It, Value()>         value_    = qi::int_ | quoted_ | qi::bool_;
  qi::rule<It, Setting(), Skip> setting_  = key_ >> '(' >> value_ >> ')';
  qi::rule<It, Settings()>      settings_ = qi::skip(qi::blank) [*setting_];
}
Şu tarz girdiyi parse ederiz.
arg1('value1') arg2('value')
Örnek - std::string
Şöyle yaparız
qi::rule<std::string::const_iterator, std::string(size_t depth)> r;
Örnek - std::pair
Şöyle yaparız. Bu rule hem attribute olarak int verir, hem de raw data'yı boost::iterator_range olarak verir.
qi::rule<
    std::string::iterator,
    std::pair<int, boost::iterator_range<std::string::iterator>>(
        qi::rule<std::string::iterator, int(bool)>&
    )
> rule2 = qi::raw[
    qi::lazy(phx::bind(qi::_r1,true))[at_c<0>(qi::_val)=qi::_1]
][at_c<1>(qi::_val)=qi::_1];
Örnek - std::dequeue
Şöyle yaparız.
template <typename Iterator>
struct path : qi::grammar<Iterator, std::deque<std::string>()> {
  path() : path::base_type(start) {
    using namespace qi;

    name          = +(graph - char_(".][")); // not matching spaces please
    qualifiedName = name % '.';

    start = skip(ascii::space) ['[' >> qualifiedName >> ']'];

    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, std::deque<std::string>()> start;
};
Tanımlama - iterator + output type + skipper
Skipper olarak ascii::space_type veya ascii::blank_type kullanılıyor. Ancak ascii::space_type bende derleme hatası verdi. ascii::blank_type sorunsuz çalışıyor.

Şu tanımlama yanlış
qi::rule<Iterator, std::string, ascii::space_type> ident;
Doğrusu şöyle
qi::rule<Iterator, std::string(), ascii::space_type> ident;
alias metodu
Şöyle yaparız.
template <typename Iterator = std::string::iterator,
  typename Skipper = spirit::qi::space_type>
class ParserImpl : public spirit::qi::grammar<Iterator, expr(), Skipper>
{
public:

  ParserImpl() : ParserImpl::base_type(expr_)
  {
    using namespace boost::spirit::qi;  
    using namespace boost::phoenix;

    expr_          = props_.alias();

    props_ = (
      (lit("Acc") >> "(" >> int_ >> ")")[_val = construct<Acc>(_1)
    );        

  }

  spirit::qi::rule<Iterator, expr(), Skipper> props_;
  spirit::qi::rule<Iterator, expr(), Skipper> expr_;
};
operator %= metodu
Şöyle yaparız
r %= qi::string("(") >> *r >> qi::string(")");
Şöyle yaparız.
qi::_r1_type _depth;
r %= qi::eps(_depth < 32) >>
     qi::string("(") >> *r(_depth + 1) >> qi::string(")");

Hiç yorum yok:

Yorum Gönder