Boost
新闻
arrow_drop_down

解析库的审查今天开始

Louis Tatta
Louis Tatta
2024 年 2 月 19 日

Zach Laine 提出的 Boost.Parser 库评审今日开始,并将于 2 月 28 日结束。

来自文档的介绍页面

Boost.Parser 是一个解析器组合子库。也就是说,它由一组低级原始解析器组成,以及用于将这些解析器组合成更复杂解析器的操作。

存在解析 epsilon(空字符串)、字符、整数、浮点数等的原始解析器。

存在一些操作可以将解析器组合起来以创建新的解析器。例如,Kleene 星号操作接受一个现有的解析器 p 并创建一个新的解析器,该解析器匹配 p 所匹配内容的零个或多个实例。可调用对象和运算符重载都用于组合操作。例如,operator*() 用于 Kleene 星号,您也可以写 repeat(n)[p] 来创建一个精确匹配 p n 次的解析器。

Boost.Parser 还努力适应人们经常想要从其解析代码中获取解析结果的多种方式。一些解析最好通过返回一个代表解析结果的对象来完成。其他解析最好通过填充预先存在的数据结构来完成。还有一些解析最好通过解析大型文档的小节,并通过回调报告子解析器完成的结果。Boost.Parser 能够适应所有这些工作方式,甚至可以通过不重写任何代码(只需将顶级调用从 parse() 更改为 callback_parse())来实现基于回调或非基于回调的解析。

Boost.Parser 的所有公共接口都与 sentinel 和 range 兼容,就像 std::ranges 中的接口一样。

Boost.Parser 从头到尾都具备 Unicode 感知能力。当您解析 char 的范围时,Boost.Parser 不会假定任何特定的编码——无论是 Unicode 还是其他任何编码。对非纯 char 输入的解析假定输入是 Unicode。在 Unicode 感知代码路径中,所有解析都是通过匹配码点来完成的。这意味着您可以将 UTF-8 字符串输入到 Boost.Parser 中,无论是作为输入还是在您的解析器内部,都会发生正确的匹配。例如,如果您的解析器试图匹配 char '\xcc' 的重复(这是 UTF-8 序列中的一个前导字节,如果后面没有适当的 UTF-8 单元,则是一个格式错误的 UTF-8),它不会匹配 "\xcc\x80" 的开头(UTF-8 表示码点 U+0300)。Boost.Parser 知道匹配必须是完整的码点,因此它将 char '\xcc' 解释为码点 U+00CC。

错误报告的正确性非常重要,尤其要让最终用户容易理解错误。Boost.Parser 生成的运行时解析错误消息与使用 GCC 和 Clang 编译时获得的诊断信息非常相似(甚至支持不使解析失败的警告)。与诊断相关的确切 token 可以报告给用户,并引用包含该 token 的行,并带有指向该 token 的标记。Boost.Parser 会为您处理这些,您的解析器无需包含任何特殊代码来实现这一点。当然,如果错误处理程序不适合您的需求,您也可以完全替换它。

调试复杂的解析器可能是一场噩梦。Boost.Parser 可以轻而易举地获得您整个解析过程的跟踪信息,其中包含易于阅读(且非常详细)的指示,说明跟踪的每个部分在解析中的位置,解析产生的值的状态等。同样,您无需编写任何代码来实现这一点——只需将一个参数传递给 parse()。

GitHub
https://github.com/tzlaine/parser

文档
https://tzlaine.github.io/parser