为什么《康熙字典》Parser 比 HTML Parser 更困难?逆向工程一部三百多年古籍的历程

Series 2 · 第 10 篇——《康熙字典》Parser 与 HTML Parser:Reverse Engineering 上一篇:为什么一个汉字会有多个反切?

为什么《康熙字典》Parser 比 HTML Parser 更困难?逆向工程一部三百多年古籍的历程

一提到「Parser」,许多程式设计师首先想到的都是 HTML、XML、JSON 或 Markdown。这些格式都有明确定义的语法(Grammar),只要依照官方规范便能实作 Parser。然而,Quizzman Fanqie Engine 面对的是完全不同的问题:如何让电脑理解《康熙字典》这部十八世纪初以文言文编纂、没有正式 Grammar、没有技术规格,并充满各种音韵注记方式的古代字典。 这也是 Fanqie Engine 开发过程中最耗时的研究工作之一。

HTML Parser 有一项巨大优势

如果要开发一个 HTML Parser,

工作流程其实十分清楚。

HTML 具有:

  • 官方 Specification;
  • 正式 Grammar;
  • 标签巢状规则;
  • 开闭标签规则;
  • 错误恢复机制。

例如:

<div class="card">
    <h1>Hello</h1>
</div>

Parser 很清楚知道:

  • 哪里是开始标签;
  • 哪里是结束标签;
  • 哪里是属性;
  • 哪里是内容。

整套 Grammar 都已公开定义。

程式设计师需要做的,

只是忠实实作这套 Grammar。


但《康熙字典》没有 Grammar

《康熙字典》完全不同。

没有任何文件会告诉你:

遇到这种文字,就应该这样理解。

没有 BNF。

没有 EBNF。

没有 RFC。

也没有专门描述反切的 Unicode 标准。

每一条字头,

都是三百多年前学者依照当时学术惯例所编写。

因此,

在写 Parser 之前,

必须先回答一个更困难的问题:

古人究竟依照什么规律来记录这些资料?


不能一开始就写 Parser

最容易犯的错误就是:

打开《康熙字典》。

直接开始写 Regex。

例如:

(.)(.)切

看起来似乎足够。

但只分析几百条资料后,

Parser 就会开始失败。

因为资料并没有统一格式。

例如:

  • AB切
  • AB切某声
  • AB切又音
  • AB切读若……
  • 读若……
  • 叶某韵
  • 俗音……
  • 又作……
  • 古作……

如果全部都视为标准反切,

整份资料都会被错误解析。


第一步不是写程式,而是做调查

因此,

Quizzman 并没有立即开始写 Parser。

而是先进行一项更接近语言学研究的工作。

也就是调查数万条字头,

分析:

  • 哪些 Pattern 最常出现;
  • 哪些内容属于音韵资料;
  • 哪些只是编者注解。

整个流程可以表示为:

《康熙字典》

观察

统计

Pattern

Grammar

Parser

Parser 只是最后一步。


第一个目标:辨识资料来源

《康熙字典》的每一条字头,

通常不只包含一个反切。

还会引用多部韵书。

例如:

《广韵》

……

《集韵》

……

《唐韵》

……

对读者而言,

这只是注解。

对 Quizzman 而言,

却是极为重要的 Metadata。

Parser 必须知道:

  • 反切来自哪一部韵书;
  • 正在引用哪个来源;
  • 哪一个是主要反切;
  • 哪一些只是补充资料。

如果来源辨识错误,

Candidate Ranking 将失去重要依据。


并非所有「切」都代表同一种意思

另一个困难,

就在反切本身。

很多人认为,

只要看到:

就直接取前面两个字即可。

实际上,

经过大量调查,

Quizzman 发现存在许多不同 Pattern。

例如:

AB切

这是最标准的反切格式。

但还有:

  • AB切某声
  • AB切又音
  • AB切音某
  • AB切读若……

虽然都包含「切」,

它们的语义却完全不同。


最困难的是「AB切某声」

这是建立 Parser 过程中的重要发现之一。

第一眼看起来,

AB切某声

似乎只是:

AB切

再加上一段说明。

但经过大量样本分析,

Quizzman 发现事实并非如此。

许多情况下,

「某声」

并不是附注。

它实际上会修改整个音韵资讯。

换句话说,

Parser 必须理解:

  • 声母仍来自反切;
  • 韵母仍来自反切;
  • 声调则必须依照后面的注记覆写(Tone Override)。

如果忽略这个细节,

Middle Chinese Reconstruction 从第一步就会错误。


「读若」不是反切

另一组容易混淆的 Pattern 是:

读若……

字面意思只是:

「读音近似……」

它并没有完整描述:

  • 声母;
  • 韵母;
  • 声调。

因此,

它不能直接用来重建 Middle Chinese。

Parser 必须辨识:

读若

Phonetic Hint

而不是:

读若

Fanqie


「叶韵」也不是标准读音

另一种特殊情况是:

  • 叶韵
  • 协韵

这些注记主要出现在诗歌中。

它们描述的是:

  • 为了押韵而调整读音;
  • 或特殊文学用途的变体。

如果 Parser 将它们视为标准发音,

Engine 就会产生大量错误资料。

因此,

Quizzman 将它们独立分类为:

叶韵

Rhyme Annotation

不会送入 Hán Việt Projection Pipeline。


Parser 本质上是一个 Grammar Classifier

经过多次重构,

Quizzman 已不再把 Parser 视为 Regex 集合。

Parser 更接近一个 Grammar Classifier。

例如:

| Pattern | 分类 | |----------|------| | AB切 | Fanqie | | AB切某声 | Fanqie + Tone Override | | 读若 | Phonetic Hint | | 叶韵 | Rhyme Annotation | | 又音 | Alternate Reading | | 古音 | Historical Reading | | 俗音 | Colloquial Reading |

只有完成分类之后,

Engine 才知道应采用哪一种处理流程。


与其说是 Parsing,不如说是 Reverse Engineering

Quizzman 最大的特殊之处在于:

开发团队一开始根本没有官方 Grammar 可以参考。

整套 Grammar,

都是反向推导出来的。

数万条字头

观察

统计

发现规律

抽象化

Grammar

Parser

在电脑科学中,

这个过程称为:

Reverse Engineering(逆向工程)

并不是实作既有规格,

而是:

从资料本身重建规格。


Parser 决定整个 Fanqie Engine 的品质

很多人认为,

Quizzman Fanqie Engine 最困难的是 Hán Việt Projection。

事实上,

所有后续演算法,

都建立在 Parser 的结果之上。

如果 Parser 对《康熙字典》的理解出错:

  • Fanqie Record 会错;
  • Middle Chinese Profile 会错;
  • Tone Resolution 会错;
  • Candidate Ranking 也会错。

因此,

Parser 并不是单纯的资料读取工具,

而是整个系统的基础。

Quizzman Fanqie Engine 与其他工具最大的不同,

不只是能够解析反切,

更重要的是透过 Reverse Engineering 重建《康熙字典》的编纂规则,

把三百多年前的学术记录转化为结构化资料,

使电脑得以在此基础上继续进行音韵推导、分析与解释。