使用 boost Spirit 解析带有二进制信封的文本文件

Posted

技术标签:

【中文标题】使用 boost Spirit 解析带有二进制信封的文本文件【英文标题】:Parsing text file with binary envelope using boost Spririt 【发布时间】:2015-03-19 12:39:32 【问题描述】:

我目前正在尝试为一个 ASCII 文本文件编写一个解析器,该文件被一个带有校验和的小信封包围。

文件的基本结构是:

我想在另一个字符串中提取有效负载以将其提供给 下一个解析器。

我用来解析这个信封的解析器表达式是:

qi::phrase_parse(
    first, last,
    char_('\x02') >> *print >> char_('\x02') >> *xdigit,
    space
);

输入已被消耗...我已经尝试转储负载:

qi::phrase_parse(
    first, last,
    char_('\x02') >> *print[cout << _1] >> char_('\x02') >> *xdigit,
    space
);

但问题是每个换行符、空格等都被省略了!

现在我的问题:

    如何提取 0x02/0x03 (ETX/STX) 字节之间的内容 正确地不省略空格、换行符等。

    我的方法是先删除信封,然后解析 有效载荷好还是我应该使用其他更好的方法?

【问题讨论】:

【参考方案1】:

使用例如qi::seek/qi::confix 帮助您入门(存储库的一部分 http://www.boost.org/doc/libs/1_57_0/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/confix.html)。

但问题是每个换行符、空格等都被省略了!

嗯,那是what a skipper does。不要使用一个,或者:

使用qi::raw[]

要提取中间文本,我建议使用qi::raw。尽管我不确定您是否真的要将其复制到字符串中(复制听起来很昂贵)。当源是流(或输入迭代器的其他源)时,您可能会这样做。

基本规则:

myrule = '\x02' > raw [ *(char_ - '\x03') ] > '\x03';

您可以添加校验和:

myrule = '\x02' > raw [ *(char_ - '\x03') ] [ _a = _checksum(_1) ] > '\x03' >> qi::word(_a);

假设

qi::locals&lt;uint16_t&gt; _checksum 是一个合适的 Phoenix 仿函数,它接受一对源迭代器并返回 uint16_t

当然,您可能更喜欢在解析器之外保持校验和。

【讨论】:

非常感谢!到目前为止,我错过了“confix”一章,这对我来说似乎是最好的方法。最后我更喜欢直接将文件解析成程序的数据结构。但是:我可以这样做并同时计算校验和吗?调用两个函子? 没问题。只是,按照我的说明做,不要忘记 %= 分配给规则 好的...谢谢。我会尽量听从你的建议!在我必须编写词法分析器之前,我猜。让我们看看在不问愚蠢问题的情况下我能走多远。 :-) 最后一个问题:使用 boost Qi 和 Spirit.Lex 开发解析器的最佳方法是什么?先从词法分析器开始还是为标记实现解析器? 好吧,如果您要在令牌流上构建解析器,您最好有一个令牌流:) 也就是说,我通常不建议将 Lexer 分离出来。它增加了足够的复杂性来让你的解析器在 Qi 使用的最佳位置上崩溃

以上是关于使用 boost Spirit 解析带有二进制信封的文本文件的主要内容,如果未能解决你的问题,请参考以下文章

Boost::Spirit 表达式解析器,带有定义的函数

boost::spirit 算术公式解析器无法编译

如何在带有 Boost Spirit 的 AST 中使用只有一个属性的类?

约束现有的 Boost.Spirit real_parser(带有策略)

使用 boost-spirit 解析 ipv4 地址

使用 boost::spirit::x3 解析成向量<boost::string_view>