25 Ağustos 2017 Cuma

spirit qi Numeric Parser Sınıfları

qi::bool_
Şöyle yaparız
spectrum_start %= qi::bool_ > qi::double_ > qi::int_ > qi::double_;
qi::double_
Örnek
Şöyle yaparız.
bool parse_line(std::string const& line, std::string& name, double& a, double& b,
 double& c) {
  using It = std::string::const_iterator;
  qi::rule<It, std::string()> quoted = '"' >> *~qi::char_('"') >> '"';

  It f = line.begin(), l = line.end();
  return qi::phrase_parse(f, l, quoted >> qi::double_ >> qi::double_ >> qi::double_,
 qi::blank, name, a, b, c);
}


std::string name;
double a, b, c;

if (parse_line("\"this is a name\" 39.789876 -83.997978 30.000000", name, a, b, c)) {
  std::cout << "Parsed: \n"
            << " Name '" << name << "'\n"
            << " (a,b,c): (" << a << ", " << b << ", " << c << ")\n";
}
Çıktı olarak şunu alırız.
Parsed:
 Name 'this is a name'
 (a,b,c): (39.7899, -83.998, 30)
Örnek
Elimizde şöyle bir string olsun.
['BTC_BBR','0.00069501','0.00074346','0.00069501','-0.00742634','8.63286802',
  '11983.47150109',0,'0.00107920','0.00045422']
Yakalanan sayıyı bir struct içinde saklamak için şöyle yaparız.
struct TickerEntry {
    std::string symbol;
    double a, b, c, d, e, f; // I have no clue,
    int i;                   // but already my names are
    double x, y;             // better than Arr1 and Arr2!
};

BOOST_FUSION_ADAPT_STRUCT(TickerEntry, symbol, a, b, c, d, e, f, i, x, y)

TickerEntry parse_ticker_entry(std::string const& input) {
  TickerEntry result;

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

  rule<It, double()>      qdouble_ = "'" >> double_ >> "'";
  rule<It, std::string()> qstring  = "'" >> *~char_("'") >> "'";

  if (phrase_parse(input.begin(), input.end(),
                   '[' >> qstring >> ','
                    >> qdouble_ >> ',' >> qdouble_ >> ',' >> qdouble_ >> ','
                    >> qdouble_ >> ',' >> qdouble_ >> ',' >> qdouble_ >> ','
                    >> int_ >> ','
                    >> qdouble_ >> ',' >> qdouble_ >> ']' >> eoi,
                    space, result))
   {
     return result;
   }
  }

  throw std::runtime_error("parse failed");
}
Örnek
Yakalanan sayıyı bir alanda saklamak için şöyle yaparız.
namespace phoenix = boost::phoenix;
namespace spirit = boost::spirit;
namespace qi = boost::spirit::qi;

struct quantity {
  double factor;
  ...
};


auto quantity_factor_field = phoenix::bind(&quantity::factor, qi::_val);

qi::rule<std::string::const_iterator, quantity()> numeric_value_expression;
numeric_value_expression = qi::double_[quantity_factor_field = qi::_1];
qi::int_
Şöyle yaparız. out parametresi olarak bir sayı verir.
qi::int_
Şöyle yaparız. Başında eksi olduğu için out parametresi bir şey vermez.
-qi::int_
Örnek
Şöyle yaparız.
"123, 4, 5; 78, 8, 9;\n888, 8, 8;";

std::vector<std::vector<int> > parsed;
bool ok = qi::phrase_parse(f, l, *(qi::int_ % ',' >> ';'), qi::space, parsed);
x % y şu anlama gelir. Yani (parser + ayraç) + bitiş karakteri
Match one or more occurrences of x, separated by occurrences of y.
Çıktı olarak şunu alırız
123 4 5 ;
78 8 9 ;
888 8 8 ;
Örnek
Şöyle yaparız. Eğer parse edilen değer "n/a" ise default değer -1 atanır.
qi::int_ | no_case["n/a"] >> attr(-1);
qi::int_parser
Şöyle yaparız.
qi::int_parser<sint64, 10> dec64;
const qi::rule<const char *, sint64()> sRule = dec64 >> qi::lit("s");
const qi::rule<const char *, sint64()> mRule = dec64 >> qi::lit("m");
const qi::rule<const char *, sint64()> hRule = dec64 >> qi::lit("h");
qi::real_parser
Şöyle yaparız.
template <typename T>
struct de_numpolicy : qi::ureal_policies<T>
{
  //  No exponent
  template <typename It>
  static bool parse_exp(It&, It const&)          {...}

  template <typename It, typename Attr>
  static bool parse_exp_n(It&, It const&, Attr&) {...}

  //  Thousands separated numbers
  template <typename It, typename Attr>
  static bool parse_n(It& first, It const& last, Attr& attr)
  {
    ...
    return false;
  }

  template <typename It>
  static bool parse_dot(It& first, It const& last) {
    ...
  }
};
Şöyle yaparız
qi::real_parser<double, de_numpolicy<double> > mynum;
qi::ulong_long
Şu satırı dahil ederiz.
#include <boost/spirit/include/qi.hpp>
Şöyle yaparız.
namespace qi = boost::spirit::qi;

std::wstring s(L"4398046511104");

unsigned long long n = 0;
qi::parse( begin(s), end(s), qi::ulong_long, n );

std::cout << n << std::endl;
qi::uint_
Şöyle yaparız.
for (std::string const str : {"", ",", ",345", "1,,2,3,4,"}) {
  std::vector<int> v;
  bool ok = qi::parse(str.begin(), str.end(), -qi::uint_ % ',',qi::space, v);
}