29 Ekim 2017 Pazar

spirit qi phrase_parse metodu

Giriş
Şu satırı dahil ederiz.
#include <boost/spirit/include/qi.hpp>
Kolay kullanım için şu satırları dahil ederiz.
namespace spirit = boost::spirit;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
İmzası
Metodun imzası şöyle
template <typename Iterator, typename Expr, typename Skipper>
inline bool
phrase_parse(
    Iterator& first
  , Iterator last
  , Expr const& expr
  , Skipper const& skipper
  , BOOST_SCOPED_ENUM(skip_flag) post_skip = skip_flag::postskip);
Şöyle yaparız
boost::spirit::phrase_parse(begin, end, grammar, space, obj)
Iterator Parametresi
begin ve end iteratorlerinin backtracking yüzünden ForwardIterator olması gerekir.

Return Type
bool döner. Iterator'leri alırız.
iterator_type iter = input.begin();
iterator_type end  = input.end();
Şöyle yaparız.
std::string input;
if (phrase_parse(iter, end, ...)) {
  ...
}
Aynı zamanda iteratorler de değişir. Açıklaması şöyle
The first iterator is passed by reference. On a successful parse, the iterator is repositioned to the rightmost position consumed by the parser. If this becomes equal to last, the we have a full match, if not then we have a partial match. A partial match happens when the parser is only able to parse a portion of the input.
Şöyle yaparız.
std::cout << "Bytes left = " << std::distance(iter, end); 
std::cout << (iter == end) ? "SUCCEEDED" : "FAILED";
skip parser parametresi 
Bu parametre olarak genelde ascii::space yani qi::space kullanılır. Açıklaması şöyle
It is a very simple parser that simply recognizes whitespace. The skip parser is the one responsible for skipping characters in between parser elements such as double_ and char_
phrase_parse - out Struct
Birinci parametre iterator, ikinci parametre iterator, üçüncü parametre grammar, dördüncü parametre skipper, diğer parametreler sonuçlardır.
Örnek
Şöyle yaparız.
typedef std::string::const_iterator iterator_type;
MyParser myParser;
MyStruct myStruct;

std::string str = ...;

std::string::const_iterator begin_iter = storedString.begin();
std::string::const_iterator end_iter = storedString.end();
//Invoke the parser
bool r = phrase_parse(begin_iter, end_iter, myParser, ascii::space, myStruct);
if (r && begin_iter == end_iter)
{
    std::cout << "Parsing succeeded\n";
} else {
    std::cout << "Parsing failed\n";
}
phrase_parse - out param1 + out param2
Örnek
Elimizde şu girdiler olsun
nam12 = 34.24
nam56 = 43.65
Şöyle yaparız.
std::string input = ...;
std::string name;
double value;

using namespace boost::spirit::qi;
if (phrase_parse(input.begin(), input.end(),
  lexeme[+alnum] >> '=' >> double_, space, name, value))
  std::cout << "Parsed: name = '" << name << "' and value = " << value << "\n";
}
Çıktı olarak şunu alırız.
Parsed: name = 'nam12' and value = 34.24
Parsed: name = 'nam56' and value = 43.65
Örnek
Eliimizde şu generic kod olsun. Bu kod kaç tane out parametresi verilirse verilsin çalışır.
template <typename Parser,typename... Attrs>
void parse(const std::string& str, const Parser& parser, Attrs&... attrs)
{
  std::string::const_iterator iter=std::begin(str), end=std::end(str);
  bool result = qi::phrase_parse(iter,end,parser,qi::space,attrs...);
  if(result && iter==end) {
    std::cout << "Success.";
    int ignore[] = {(print(attrs),0)...};
    std::cout << "\n";
  } else {
    std::cout << "Something failed. Unparsed: \"" << std::string(iter,end) << "\"\n";
  }
}
Bu generic kodu sarmalayarak çağıran kodlar olsun
template <typename Parser>
void parse_with_nodes(const std::string& str, const Parser& parser) 
{
  std::vector<std::string> nodes;
  parse(str,parser,nodes);
}

template <typename Parser>
void parse_with_nodes_and_attr(const std::string& str, const Parser& parser) 
{
  std::vector<std::string> nodes;
  std::pair<std::string,double> attr_pair;
  parse(str,parser,nodes,attr_pair);
}
Elimizde şu iki gramer olsun.
qi::rule<std::string::const_iterator,std::string()> node=+qi::alnum;
qi::rule<std::string::const_iterator,std::pair<std::string,double>(),qi::space_type> attr=
  +qi::alpha >> '=' >> qi::double_;
Bu gramerleri karıştırarak kullanabiliriz. Şöyle yaparız.
parse_with_nodes("node1->node2", node % "->");

parse_with_nodes_and_attr("node1->node2 arrowsize=1.0", node % "->" >> attr);

parse_with_nodes("node1->node2", node >> +("->" >> node));

qi::rule<std::string::const_iterator,std::vector<std::string>(),qi::space_type>
  at_least_two_nodes = node >> +("->" >> node);
parse_with_nodes_and_attr("node1->node2 arrowsize=1.0", at_least_two_nodes >> attr);
phrase_parse - out param1 + out param2 + out param3
Elimizde 3 değişken olsun
int a, b;
boost::optional<int> c;
Şöyle yaparız.
if (!qi::phrase_parse(s.begin(), s.end(),
  qi::lit("A:") >> qi::int_ >> "B:" >> qi::int_ >> -("C:" >> qi::int_), qi::space,
  a, b, c)) {...}

Hiç yorum yok:

Yorum Gönder