在boost::spirit
中,如何阅读string
,立即在数据库中查找其int
值并boost::spirit
将值分配给int
}}?因此规则的属性将是int
,即使它被解析为字符串。
例如,此输入
myCoolKey 3.4
可以解析为(int,double)
对:(87,3.4),其中字符串“myCoolKey”通过(Berkeley)数据库查找映射到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;
}
答案 0 :(得分:1)
最快的方法是使用phoenix bind
qi::_val = phx::bind(&Lookup::lookup, myLookup, qi::_1)
使用融合函数或'Polymorphic Calleable Objects'有更优雅的解决方案,但我现在参考文档:
编辑我发现你的其余代码无法编译(因为其他原因)。这是一个编译示例(带有存根查找功能):
#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<>
的额外规则,但坦率地说,这种方式更具可读性。