用 PEG 替代正则:Lisp 解析 Org 转 HTML

Parsing Expression Grammar vs. Regexes: Building Org Parser in Lisp, Export HTML

用 PEG 替代正则:Lisp 解析 Org 转 HTML

我曾尝试用正则表达式解析 Org mode,但很快发现面对嵌套列表和复杂标记时,这种方法简直是在描述解析器的 bug 历史。于是,我转向了 Parsing Expression Grammars (PEG),利用 Guile Scheme 中的 (ice-9 peg) 模块开发了 OrgWebAlchemy。这个项目不仅能将 Org 文档解析为 AST 并渲染为 HTML,更重要的是,它让语法定义本身成为了文档,摆脱了对 Emacs 的依赖。通过 SXML 构建 HTML 树,我实现了一个轻量、可定制且完全开源的解析器,让 Lisp 程序员能更优雅地处理文本转换。

这不再是在描述一种语言,而是在描述你的解析器 bug 的历史。
  1. zelphirkalt

    哈哈,这挺有意思的。

    我很久以前就启动过这样一个针对 org 语法的 PEG 项目,不过没做多远。在我看来,org 文件里的内容无法一次性解析和理解。例如,TODO 关键字可以在 org 文件顶部定义,然后影响文档中标题的解析方式。这仅靠 PEG 是无法实现的。

    另一个棘手点是嵌套的内联标记。粗体在斜体里?代码块在粗体里,而粗体又在斜体里?诸如此类。如果能通过递归规则支持所有有意义的组合就好了。org 有很多内联标记元素,甚至包括特定编程语言的标记。

    还有一个问题是,Guile 的 PEG 库在使用语法规则的非字符串形式时,由于存在 bug,不允许相互递归的语法规则(在这方面它不算优秀,但在其他方面很棒!)。不得不使用字符串形式的规则,这很不幸地让使用体验大打折扣。希望这个问题某天能被修复,因为除了这点,我很喜欢这个库。而且它就在标准库中,无需安装任何依赖。比如我就想拿它来解析 AoC(Advent of Code)谜题的输入。

    看看他们能做到什么程度会很有趣。

    编辑:另外,拥有一个基于语法的 org 解析器将非常棒。这将有助于为其他工具创建解析器,例如解析 Git 托管平台上仓库中 README 文件的解析器。

  2. overthenexttwod

    多年来,我在工作中和个人项目中无数次实现过解析器,所以从零手写递归下降解析器对我来说已经成了第二天性。一旦理解了其机制,手写解析器就很简单,而且优势明显,特别是在错误处理和报告方面拥有更大的灵活性。正因如此,我一直认为 PEG 和解析器生成器主要是给那些因环境或技能限制而无法手写解析器的人准备的。(如果你看看那些既不缺人也不缺技术的项目,会发现手写递归下降解析器非常普遍:Clang、Go、Rust、TypeScript、Swift 和 Lua 全部采用手写解析器。)

    大语言模型(LLM)改变了这一局面。过去,我为一个中等复杂度的语法写解析器需要 2-3 个小时。现在,如果我给 LLM 一个粗略编写的类 BNF 语法,并让它生成递归下降解析器,它五分钟就能搞定。到了这一步,手写解析器很难再被证明是合理的。模型不仅快得多,而且最近往往比我自己写得更好。

    这让我不禁想问:现在 PEG 或解析器生成器的吸引力在哪里?过去在手写不现实时它们很有意义,但今天还有什么 compelling 的理由去使用它们呢?

  3. remywang

    关于 PEG 的一个有趣事实是:它们是否能解析所有上下文无关语言,目前仍是一个未解的开放问题。

同日更多故事

2026-09-26