In boost::spirit
, how can I read in a string
, immediately look up its int
value in a database and have boost::spirit
assign the value to an int
? So the attribute of the rule would be an int
, even though it is parsed as a string.
For example, this input
myCoolKey 3.4
could be parsed as a (int,double)
pair: (87, 3.4), where the string "myCoolKey" is mapped to 87
through a (Berkeley) DB lookup.
I would want code like this:
typedef std::pair<int, double> Entry;
qi::rule<Iterator, Entry(), Skipper> entry;
entry %= +qi::char_[qi::_val = mylookup(qi::_1)]
>> qi::double_;
Here is a full code example. How would I call the function that looks up the parsed string, and make boost::spirit
assign the looked up value to an 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;
}