c++ - 使用 Boost Spirit 解析十六进制值

标签 c++ parsing boost

我一直在尝试使用 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,我真的很想知道 >。任何帮助表示赞赏。

更多信息:

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

最佳答案

我对那里发生的所有复杂事情感到有点困惑(尤其是语义操作 [&insert],它似乎无缘无故地使用了一个全局变量)。

See Boost Spirit: "Semantic actions are evil"? if you're interested in my stance on premature use of semantic actions.

在这种情况下,您可以只使用 std::pair<> 的 Boost Fusion 改编版

#include <boost/fusion/adapted/std_pair.hpp>

现在您可以简单地直接分配到 map 中:

    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

关于c++ - 使用 Boost Spirit 解析十六进制值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31124830/

相关文章:

c++ - Firebreath OpenGl 窗口闪烁

c++ - 为什么在std::condition_variable notify_all的运行速度比notify_one更快(在随机请求上)?

c++ - Boost GIL 图像构造函数

parsing - 如何在 Parsec 的一元上下文中返回多个解析失败?

java - Xtext解析规则不完整

java - 数据java的XML解析

c++ - int main() argv 参数问题

c++ - 在 iOS 上使用 C++ 代码,创建静态库或与 Objective C 混合使用?

c++ - 使用默认构造函数的显式转换

c++ - 关于在系统中表示路径的数据结构的建议