使用Boost Spirit解析十六进制值

Parsing hex values with Boost Spirit

本文关键字:十六进制 Boost Spirit 使用      更新时间:2023-10-16

我一直在用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 failedn";
        }
    }
    return 0;
}

我真正想要的是将其直接解析为std::pair <std::string, int>。感谢您的帮助。

更多信息:

我试图声明一个与此类似的解析器:uint_parser<unsigned, 16> hex_value;然后我试图将规则中的+(char_)替换为+(hex_value)。

我对那里发生的一切都有点困惑(尤其是语义动作[&insert],它似乎无端地使用了一个全局变量)。

参见Boost Spirit:";语义行为是邪恶的"?如果你对我对过早使用语义动作的立场感兴趣的话。

在这种情况下,您可以只使用std::pair<> 的Boost Fusion自适应

#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)
            )

Demo

正如你所猜测的,我

  • 使用的int_parser<int,16>
  • 为简便起见,将输入文件替换为std::cin注意您没有检查argc…)
  • 使用phrase_match作为隐式解析输入流迭代器的好方法
  • 一次解析多行

在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 failedn";
    }
}

输出:

Parse success:
'Bam' -> 1110
'Bar' -> 462
'Foo' -> 75