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 重建《康熙字典》的编纂规则,
把三百多年前的学术记录转化为结构化资料,
使电脑得以在此基础上继续进行音韵推导、分析与解释。