從零開始寫個編譯器吧 - LL(1)

上一章中,我說 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) 文法。

  1. 對於全部不能導出 ε 的表達式 α、β、γ……,都有,FIRST(α)、FIRST(β)、FIRST(γ)……兩兩互不相交。

  2. 最多隻有一個表達式能夠導出 ε。

  3. 若是有一個表達式能夠導出 ε,那麼對於其餘不能夠導出 ε 的表達式 ξ,有,FIRST(ξ) ∩ FOLLOW(A) = Φ。

最後一條有加粗,固然並不是由於它對 LL(1) 自己很重要,而是由於我在實現 Parser 的時候並無徹底遵照這一條。某種意義上說,tao 語言的 Parser 並不是嚴格遵照 LL(1) 文法,所以在此加粗這條,以便與後面的章節呼應。

相關文章
相關標籤/搜索