Boost.Spirit.Qi はじめました

はじめてみました。

[ソース]

#include <iostream>
#include <vector>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

namespace qi      = boost::spirit::qi;
namespace fusion  = boost::fusion;


struct birthday{
    std::string name;
    int year;
    int month;
    int day;
};

BOOST_FUSION_ADAPT_STRUCT(
    birthday,
    (std::string, name)
    (int, year)
    (int, month)
    (int, day)
)

void
disp(birthday const& rhs){
    std::cout << fusion::as_vector(rhs) << std::endl;
}

int
main(){
    std::string data =
        "Arnold Alois Schwarzenegger:1947/07/30\n"
        "Walter Bruce Willis:1955/03/19\n"
        "Sylvester Gardenzio Stallone:1946/07/06\n";
    
    std::vector<birthday> result;
    
    if(qi::parse(
        boost::begin(data),
        boost::end(data),
        (+(qi::char_ -':') >> ':' >> qi::int_ >> '/' >> qi::int_ >> '/' >> qi::int_) % qi::eol,
        result
    ) == false){
        std::cout << "failed" << std::endl;
        return 1;
    }
    
    boost::for_each(result, disp);
    
    return 0;
}

[出力]

(Arnold Alois Schwarzenegger 1947 7 30)
(Walter Bruce Willis 1955 3 19)
(Sylvester Gardenzio Stallone 1946 7 6)


正規表現よりも構文が直感的でわかりやすいですね。
簡単な構文解析ならサクっと出来そうです。
Boost.Fusion が使えるのがすごく強力ですね……。


ただ、コンパイル時間(とコード補完)が長いのがちょっとネック。
あとエラー時の原因を調べるのもちょっと辛いかな。
まぁこっちは慣れればどうにかなりそうですが。
1.47.0 もリリースされたので Boost.Phoenix も試してみたいですね。

[boost]

  • ver 1.47.0