1

boost::spirit、 を読み込みstring、すぐにintデータベースでその値を検索し、その値をboost::spiritに割り当てるにはどうすればよいintですか? そのため、ルールの属性はint文字列として解析されますが、 になります。

たとえば、この入力

myCoolKey 3.4

(int,double)(87, 3.4)のペアとして解析できます。ここで、文字列 "myCoolKey" は87(バークレー) DB ルックアップを介してマップされます。

次のようなコードが必要です。

typedef std::pair<int, double> Entry;
qi::rule<Iterator, Entry(), Skipper> entry;
entry %= +qi::char_[qi::_val = mylookup(qi::_1)]
         >> qi::double_;

完全なコード例を次に示します。解析された文字列を検索する関数を呼び出し、検索しboost::spiritた値を に割り当てるにはどうすればよいでしょうintか?

#include <iostream>
#include <boost/foreach.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;

typedef std::pair<int, double> Entry;

struct Lookup {
  MyDB db;
  int lookup(std::string const& str) {
    return db.lookup(str);
  }
};

template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, std::vector<Entry>(), Skipper> {
  MyGrammar() : MyGrammar::base_type(entries) {
    entry %= +qi::char_[qi::_val = myLookup.lookup(qi::_1)]
        >> qi::double_;
    entries = +entry;
  }
  Lookup myLookup;
  qi::rule<Iterator, Entry(), Skipper> entry;
  qi::rule<Iterator, std::vector<Entry>(), Skipper> entries;
};

int main() {
  typedef boost::spirit::istream_iterator It;
  std::cin.unsetf(std::ios::skipws);
  It it(std::cin), end;

  MyGrammar<It, qi::space_type> entry_grammar;
  std::vector<Entry> entries;
  if (qi::phrase_parse(it, end, entry_grammar, qi::space, entries)
      && it == end) {
    BOOST_FOREACH(Entry const& entry, entries) {
      std::cout << entry.first << " and " << entry.second << std::endl;
    }
  }
  else {
    std::cerr << "FAIL" << std::endl;
    exit(1);
  }
  return 0;
}
4

1 に答える 1

1

最も簡単な方法は、phoenix bind を使用することです

qi::_val = phx::bind(&Lookup::lookup, myLookup, qi::_1)

融合関数または「多形呼び出し可能オブジェクト」を使用したより洗練されたソリューションがありますが、今のところドキュメントを参照してください。

編集コードの残りの部分がコンパイルされないことがわかりました(他の理由により)。以下は、コンパイルのサンプルです (スタブ ルックアップ関数を使用)。

#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;
//  ...

template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, std::vector<Entry>(), Skipper>
{
    MyGrammar() : MyGrammar::base_type(entries)
    {
        using namespace qi;
        intpart = as_string [+char_] 
                 [ _val = phx::bind(&Lookup::lookup, myLookup, _1) ];
        entry = intpart >> double_;
        entries = +entry;
    }
  private:
    Lookup myLookup;
    qi::rule<Iterator, int(), Skipper> intpart;
    qi::rule<Iterator, Entry(), Skipper> entry;
    qi::rule<Iterator, std::vector<Entry>(), Skipper> entries;
};

実行または魔法使いintpartによる追加のルールを回避できますが、率直に言って、この方法の方がはるかに読みやすいです。qi::as<>qi::attr_cast<>

于 2012-05-21T09:10:35.000 に答える