Sprout.Weed で使って複数の文字列パースする

例えがちょっと分かりづらいんですが、文字列を複数読み込む場合に戻り値型がちょっと複雑だったので覚書。

[ソース]

#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION
#include <sprout/weed.hpp>
#include <sprout/string/alias.hpp>


int
main(){
    namespace w = sprout::weed;
    static constexpr auto string_max = 8;
    static constexpr auto item_num   = 3;
    static constexpr auto string     = *w::lim<string_max>(w::char_ - ',');
    static constexpr auto data       = sprout::to_string("homu,mami,mado,");
    
    // , 区切りの文字列をパースする
    {
        // as_tuple を付けない場合は、文字列が連結されて結果が返ってくる
        static constexpr auto parser = *w::lim<item_num>(string >> ',');

        static constexpr auto result = w::parse(data.begin(), data.end(), parser);
        static_assert(result.success(), "");
        static_assert(result.attr() == "homumamimado", "");
    }

    {
        static constexpr auto parser = *w::lim<3>(w::as_tuple[string] >> ',');

        static constexpr auto result = w::parse(data.begin(), data.end(), parser);
        static_assert(result.success(), "");
        
        // array<tuple<string>, 3> として返ってくる
        using attr_type = sprout::array<sprout::tuple<sprout::string<string_max>>, item_num>;
        static constexpr attr_type items = result.attr();
        
        static_assert(sprout::get<0>(items[0]) == "homu", "");
        static_assert(sprout::get<0>(items[1]) == "mami", "");
        static_assert(sprout::get<0>(items[2]) == "mado", "");
    }

    return 0;
}

上記のコードのように *lim で定義した文字列を *lim を使用して複数読み込む場合に戻り値型に注意する必要があります。


まず、複数の文字列を読み込もうとしている

*w::lim<3>(string >> ',')

ですが、このままでは string が連結されて結果が返ってくるので as_tuple を使用して

*w::lim<3>(w::as_tuple[string] >> ',')

このように定義する必要があります。


この時に as_tuple[string] は tuple 型になり *lim は array 型になるので、array といった型で返ってきます。
なので最終的な型は array や tuple ではなくて array, 3> になります。
という風になっていると予想。
これを array や tuple にする方法はあるのかなー。

[コンパイラ]

  • g++ (GCC) 4.7.0 20111210 (experimental)