SQLite 的 SQL 语言解析器是使用名为“Lemon”的代码生成器程序生成的。Lemon 程序读取输入语言的语法,并输出 C 代码来实现该语言的解析器。
Lemon 没有自己的源代码仓库。相反,Lemon 由 SQLite 源代码树中的几个文件组成。
lemon.html → Lemon 的原始详细使用文档和程序员参考。
lemon.c → 读取语法文件并生成相应解析器 C 代码的实用程序的源代码。
lempar.c → 生成的解析器 C 代码的模板。“lemon”实用程序读取此模板并插入其他代码以生成解析器。
Lemon 生成一个 LALR(1) 解析器。它的操作类似于更常见的工具 Yacc 和 Bison,但 Lemon 添加了重要的改进,包括
语法更不容易出错 - 使用符号名称表示语义值,而不是 Yacc 的“$1”样式的位置表示法。
在 Lemon 中,词法分析器调用语法分析器。Yacc 的操作方式相反,语法分析器调用词法分析器。Lemon 的方法是可重入的和线程安全的,而 Yacc 使用全局变量,因此既不是可重入的也不是线程安全的。可重入性对于 SQLite 尤其重要,因为某些 SQL 语句会对解析器进行递归调用。例如,在解析 CREATE TABLE 语句时,SQLite 会递归调用解析器以生成 INSERT 语句,以便在 sqlite_schema 表中创建新条目。
Lemon 具有非终结符析构函数的概念,可用于在语法错误或其他中止解析后回收内存或其他资源。
Lemon 在 SQLite 中有两个应用场景。
Lemon 的主要用途是创建 SQL 语言解析器。语法文件 (parse.y) 由 Lemon 编译成 parse.c 和 parse.h。parse.c 文件被纳入 amalgamation 且无需进一步修改。
Lemon 还用于为 FTS5 扩展中的查询模式表达式生成解析器。在这种情况下,输入语法文件为 fts5parse.y。
将代码生成器工具作为项目的一部分托管的优势之一是,可以优化这些工具以满足整个项目的特定需求。Lemon 受益于这种效果。多年来,Lemon 语法分析器生成器得到了扩展和增强,为 SQLite 提供了新的功能和改进的性能。一些专门为 SQLite 设计的 Lemon 的特定增强功能包括
Lemon 具有“回退”标记的概念。SQL 语言包含大量关键字,这些关键字有可能与标识符名称发生冲突。Lemon 能够指定某些关键字可以“回退”到标识符。如果关键字出现在输入标记流中,在其他情况下会导致语法错误,则在引发语法错误之前,该标记会自动转换为其回退。此功能允许解析器非常宽容地对待用作标识符的保留字,这是 SQL 语言中经常出现的问题。
为了支持 SQLite 的 100% MC/DC 测试 目标,Lemon 生成的解析器代码没有无法到达的分支,并且包含额外的(编译时选择)检测,这些检测可用于测量测试覆盖率。
Lemon 支持语法文件规则的条件编译,以便根据编译时选项生成不同的解析器。
作为性能优化,Lemon 输入语法中的规约动作允许包含“/*A-overwrites-Z*/”形式的注释,以指示规则右侧的语义值“A”允许直接覆盖左侧的语义值“Z”。此简单的优化减少了用于解析输入语法的下推自动机中的堆栈操作次数,从而提高了解析器的性能。它还使生成的代码更小。
SQL 语句的解析是任何 SQL 数据库引擎中 CPU 周期的一个重要消耗者。持续的 SQLite 优化工作导致开发人员花费大量时间调整 Lemon 以生成更快的解析器。这些努力使所有 Lemon 语法分析器生成器的用户受益,而不仅仅是 SQLite。但是,如果 Lemon 是一个单独维护的工具,那么协调更改 SQLite 和 Lemon 会更加困难,因此不会实现那么多的优化。因此,解析器生成器工具包含在 SQLite 的源代码树中的事实已证明对工具本身和 SQLite 都有益。
Lemon 最初由 D. Richard Hipp(也是 SQLite 的创建者)在 1987 年至 1992 年期间在杜克大学攻读研究生期间编写。Lemon 的原始创建日期已丢失,但可能是在 1990 年左右。Lemon 生成一个 LALR(1) 解析器。还有一个名为“Lime”的配套 LL(1) 解析器生成器工具,但 Lime 的源代码已丢失。
Lemon 源代码最初编写为单独的源文件,后来才合并到单个“lemon.c”源文件中。
Lemon 和 SQLite 的作者(Hipp)报告说,通过研究 John Ousterhout 的 Tcl 原始源代码,他的 C 编程技能得到了极大的提高。Hipp 于 1993 年发现并研究了 Tcl。Lemon 在那之前编写,SQLite 在那之后编写。这两个产品的编码风格存在明显的差异,SQLite 似乎更简洁、更易读且更易于维护。