简体   繁体   English

使用Boost Spirit解析十六进制值

[英]Parsing hex values with Boost Spirit

I have been playing around with parsing with Boost Spirit and was wondering if anyone could help me get this to work. 我一直在与Boost Spirit进行解析,并且想知道是否有人可以帮助我使其正常工作。 I have a simple parser that takes a file containing a pair of entries on each line. 我有一个简单的解析器,该解析器接受一个文件,每行包含一对条目。 Something similar to the following: 类似于以下内容:

Foo 04B
Bar 1CE
Bam 456

My code below currently parses this out and places each pair into a std::map and it seems to work correctly. 我下面的代码目前对此进行了解析,并将每对放入std :: map中,并且似乎可以正常工作。 What I really want to do is parse out the second string on each line and convert it to an integer. 我真正想做的是解析每一行的第二个字符串,并将其转换为整数。 I have looked at int_parser and how you can specify the base but have been unable to get a similar setup to compile. 我看过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;
}

What I would really like if to parse it out directly as a std::pair <std::string, int >. 我真正想将其解析为std :: pair <std::string, int >的内容。 Any help is appreciated. 任何帮助表示赞赏。

More information: 更多信息:

I was trying to declare a parser similar to this one: uint_parser<unsigned, 16> hex_value; 我试图声明一个与此类似的解析器: uint_parser<unsigned, 16> hex_value; and then I was trying to replace the +(char_) in my rule to +(hex_value). 然后我尝试将规则中的+(char_)替换为+(hex_value)。

I'm a little confused with everything complicated going on there (especially the semantic action [&insert] which seems to gratuitously use a global variable). 我对那里发生的一切复杂情况感到有些困惑(尤其是语义动作[&insert]似乎无意中使用了全局变量)。

See Boost Spirit: "Semantic actions are evil"? 参见Boost Spirit:“语义行为是邪恶的”? if you're interested in my stance on premature use of semantic actions. 如果您对我过早使用语义动作的立场感兴趣。

In this case you could just use Boost Fusion adaptation of std::pair<> 在这种情况下,您可以只使用Boost Fusion修改std::pair<>

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

and now you can simply assign directly into a 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)
            )

Demo 演示版

As you surmised I 你猜我

  • used int_parser<int,16> 用过int_parser<int,16>
  • replaced the input file with std::cin for simplicity ( NOTE you didn't check argc ...) 为简单起见,将输入文件替换为std::cin注意,您没有检查argc ...)
  • uses phrase_match as a nice way to parse from input stream iterators implicitly 使用phrase_match作为从输入流迭代器隐式解析的好方法
  • parsers multiple lines in one swoop 一键解析多行

Live On Coliru 生活在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";
    }
}

Output: 输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM