我熟悉fparsec的一些基础知识,但似乎是面向文本文件或流。
还有其他可以有效解析二进制文件的F#库吗?或者可以很容易地修改fparsec以便有效地使用二进制流?
答案 0 :(得分:12)
您可能对 pickler combinators 感兴趣。这些有点像解析器组合,但更侧重于更简单的二进制格式( picklers 允许您生成二进制数据, unpicklers 解析它们)。 Andrew Kennedy(计量单位的作者)有quite readable article about the idea(PDF)。
我自己没有太多经验,但我才意识到这可能与你有关。这个想法在F#编译器中用于生成一些二进制资源(如存储在资源中的引用)。虽然,我不确定F# compiler implementation是否有用(这是F#编译器早期的其中之一)。
答案 1 :(得分:6)
使用二进制流的问题本身并不是解析器问题,这是一个棘手的问题。词法分析器将原始数据转换为解析可以处理的元素。
大多数解析系统都没有问题让你提供自己的词法分析器,如果是这样的话,你可以理想地编写一个适用于你的二进制流的兼容词法分析器。
然而,问题在于,今天的大多数解析和lexing系统本身都是从更高级别的工具创建的。而这个工具很可能不适用于二进制流。也就是说,指定可用于创建后续解析器和词法分析器的二进制流的标记和语法是不切实际的。此外,对于您可能在二进制流中遇到的多字节二进制数(short,long,float等)的更高级概念,也可能没有任何支持,生成的解析器也可能无法正常工作如果你真的需要处理它们的实际值,那么再次因为系统主要是为基于文本的标记设计的,而底层运行时处理转换该文本的细节,这是机器可以使用的东西(例如ascii数字到实际的序列)二进制整数)。
所有这一切,你可能实际上可以使用该工具的解析部分,因为解析器更多地工作在由词法分析器提供它们的抽象令牌上。在符号级别创建语法后,您需要重做词法分析器以从二进制流创建问题标记以提供给解析器。
这实际上很好,因为解析器往往比基本词法分析器复杂得多,因此工具包将为您处理大部分“难点”。但是你仍然需要处理创建自己的词法分析器并将其正确地连接到生成的解析器。这不是一项不可逾越的任务,如果语法具有任何真正的复杂性,那么从长远来看,这可能是值得的。
如果这一切都非常简单,那么你最好还是亲手做好自己。在我的头脑中,很难想象一个困难的二进制语法,因为二进制格式的主要卖点是它更接近机器,这与大多数解析器设计使用的文本相矛盾。但我不知道你的用例。
但考虑一下反汇编的情况。这是一个简单的词法分析器,它可以在不同的指令类型(例如那些没有参数的操作数,那些将单个字节作为参数或单词的操作数)置于高级别,并将其提供给解析器然后可以用于将指令转换为普通汇编语法中的助记符和操作数,以及处理标签引用等。
这是一个人为的案例,因为反汇编程序通常不会将lexing和解析阶段分开,它通常不够复杂,但是这是查看问题的一种方法。
附录:
如果您有足够的信息将二进制流转换为文本以提供给引擎,那么您有足够的信息而不是创建文本,您可以创建解析器希望从词法分析器中看到的实际标记
那就是说,你能做的就是采用你的文本格式,将它作为你的解析工具和语法的基础,并让它为你创建词法分析器和解析器机器,然后,手动,你可以测试你的解析器及其使用“文本测试”的处理。
但是当你开始阅读二进制文件时,不是创建文本然后进行修改和解析,只需创建词法分析器将创建的标记(这些应该是简单的对象),并直接抽取解析器。这将节省你的lex步骤并节省一些处理时间。