1

boost::spirit,我怎样才能读入一个,立即在数据库中string查找它的值并将值分配给一个?因此,即使它被解析为字符串,规则的属性也会是。intboost::spiritintint

例如,这个输入

myCoolKey 3.4

可以解析为一对:(87, 3.4),其中字符串“myCoolKey”通过(伯克利)数据库查找(int,double)映射到。87

我想要这样的代码:

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 回答