上一章中,我说 Parser 的工做就是依据文法定义,找到一个与源代码匹配的展开方案就能够了。听起来咱们只要先给出一个 tao 语言的文法定义,而后写一个找匹配方案的的程序就能够了。
然而事情状况并不是如此简单。由于假如咱们不对文法定义的形式加诸任何限制的话,让 Parser 找到匹配方案并不是很轻易的事情。语法
所以,我规定,tao 语言的将用 LL(1) 文法来定义。程序
在简单介绍 LL(1) 文法以前,我还要说明一种比较特别的产生式。语言
A → ε集合
希腊字母 ε 表示“空”,这个产生式代表非终结符 A 能够产生一个空。具体来讲,若是有以下文法。源代码
S → αAβblock
A → ε工作
那么:
S → αβ
非终结符能够产生空这一特性,令文法的形式更加复杂,可是倒是必不可少的。少了这一特征,就很难描述 tao 语言的语法细节了。
此外,对于一个文法之中的非终结符,还有 FIRST 集、FOLLOW 集的概念。
对于一个非终结符 A 而言,它的 FIRST 集指 A 可能展开的各类形式中,位于第一的全部终结符所组成的集合。记为 FIRST(A)。
而 FOLLOW 集,指在整个文法中,非终结符 A 后面可能接的全部终结符组成的集合。记为 FOLLOW(A)。
这么描述可能有点绕,细节先无论,但有一点很重要,即不管是 FIRST 集仍是 FOLLOW 集,它们都只能包含终结符。
那么,LL(1) 又是怎样一种文法呢?
对于一个文法而言,若是它的每个非终结符的产生式
A → α | β | γ ……
都知足以下三个条件,则将这个文法称之为 LL(1) 文法。
对于全部不能导出 ε 的表达式 α、β、γ……,都有,FIRST(α)、FIRST(β)、FIRST(γ)……两两互不相交。
最多只有一个表达式能够导出 ε。
若是有一个表达式能够导出 ε,那么对于其余不能够导出 ε 的表达式 ξ,有,FIRST(ξ) ∩ FOLLOW(A) = Φ。
最后一条有加粗,固然并不是由于它对 LL(1) 自己很重要,而是由于我在实现 Parser 的时候并无彻底遵照这一条。某种意义上说,tao 语言的 Parser 并不是严格遵照 LL(1) 文法,所以在此加粗这条,以便与后面的章节呼应。