我一直在使用Boost Spirit进行解析,并且想知道是否有人可以帮助我实现这一点。我有一个简单的解析器,它接受每行包含一对条目的文件。类似于以下内容:
Foo 04B
Bar 1CE
Bam 456
下面我的代码解析了这个并将每一对放入std :: map中,它似乎正常工作。我真正想做的是解析每一行的第二个字符串并将其转换为整数。我查看了int_parser以及如何指定基础但是无法获得类似的编译设置。
namespace qi = boost::spirit::qi;
std::map<std::string, std::string> results;
void insert(std::pair<std::string, std::string> p) {
results[p.first] = p.second;
}
template <typename Iterator>
bool parse_numbers(Iterator first, Iterator last) {
using qi::char_;
using qi::parse;
qi::rule<Iterator, std::pair<std::string, std::string>()> assignment;
assignment = +(~char_(' ')) >> +(char_);
bool r = parse(
first,
last,
assignment[&insert]);
if (first != last)
return false;
return r;
}
int main(int argc, char* argv[]) {
std::ifstream ifs;
std::string str;
ifs.open (argv[1], std::ifstream::in);
while (getline(ifs, str)) {
if (!parse_numbers(str.begin(), str.end())) {
std::cout << "Parsing failed\n";
}
}
return 0;
}
如果直接将其解析为std :: pair <std::string, int
&gt;,我真正想要的是什么。任何帮助表示赞赏。
更多信息:
我试图声明一个与此类似的解析器:
uint_parser<unsigned, 16> hex_value;
然后我试图将规则中的+(char_)替换为+(hex_value)。
答案 0 :(得分:3)
我对那里复杂的事情感到有些困惑(尤其是语义行为[&insert]
似乎无偿地使用全局变量)。
如果您对过早使用语义操作的立场感兴趣,请参阅Boost Spirit: "Semantic actions are evil"?。
在这种情况下,你可以使用std::pair<>
#include <boost/fusion/adapted/std_pair.hpp>
现在您可以直接分配到地图中:
std::map<std::string, int> results;
if (ifs >> qi::phrase_match(
(qi::lexeme[+qi::graph] >> qi::int_parser<int, 16>{}) % qi::eol,
qi::blank, results)
)
正如你猜测我
int_parser<int,16>
std::cin
(注意您没有检查argc
...)phrase_match
作为隐式解析输入流迭代器的好方法<强> Live On Coliru 强>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_match.hpp>
#include <map>
namespace qi = boost::spirit::qi;
int main() {
std::cin.unsetf(std::ios::skipws);
std::map<std::string, int> results;
if (std::cin >> qi::phrase_match(
(qi::lexeme[+qi::graph] >> qi::int_parser<int, 16>{}) % qi::eol,
qi::blank, results)
)
{
std::cout << "Parse success:\n";
for(auto& entry : results)
std::cout << "'" << entry.first << "' -> " << entry.second << "\n";
} else {
std::cout << "Parse failed\n";
}
}
输出:
Parse success:
'Bam' -> 1110
'Bar' -> 462
'Foo' -> 75