我須要定義出 tao 語言的細節,在此,須要引出文法這一律念。所謂文法,便是用於描述語言的一種工具。
例如,一個賦值語句可能寫成以下形式:工具
variable = 1 + 3遞歸
如何充分定義這個賦值語句的形式呢?若用天然語言描述,我能夠說,賦值語句最左邊是一個標示符,而後緊接一個「=」符號,而後再接一個表達式。知足這個條件的,便是賦值語句啦。語法
S → abE語言
用符號來描述的話,就是如上形式,這種形式稱之爲 S 的產生式。其中 S 表示賦值語句,a 表示一個標示符,b 是「=」符號,E 表示表達式。這裏用到了S、a、b、E 四個不一樣的字母。源代碼
等等,彷佛還有什麼沒說完,由於標示符(字母a表示)與「=」符號(字母b表示)都與 Tokenizer 生成的 Token 對應,可是表達式(字母E表示)卻沒有對應的 Token 呀。block
因而,我還要進一步描述表達式。這裏爲了避免讓問題變得過於繁瑣,我先假定表達式只出現加減號和數字。那麼表達式的定義以下。數字
E → d | E+d | E-d生成
這裏出現的「|」表示「或」,這代表表達式(字母E)能夠展開成三種不一樣的式子。同時,E 展開後的式子中可能再次出現 E 自己,這種遞歸形式足以涵蓋任意長度的表達式形式。index
因而,咱們又獲得字母 d,d 表示一個數字(也與某種 Token 對應)。ab
至此,咱們一共獲得了 S、a、b、E、d 五個不一樣的字母,其中 a、b、d 都與 Token 對應。然而,雖然 S、E 卻沒有對應的 Token,但它們都有至少有一個屬於本身的產生式。
對於 a、b、d,稱之爲終結符。即它們不會再有本身的產生式了。而 S、E,稱之爲非終結符。
當咱們爲式子中某個非終結符挑選一個特定的產生式,並用產生式的右邊部分代替這個非終結符在式子中的位置,那麼咱們將這個過程稱之爲非終結符的展開。
考慮下面這行代碼:
index = 15 + 7 - 3
其形如 abd+d-d(a 爲 "index"、b 爲"="、d 爲"15", "7", "3")
對於 S 有以下展開方式:
S → abE
→ abE-d(展開 E → E-d)
→ abE+d-d(展開 E → E+d)
→ abd+d-d(展開 E → d)
其中 S 表示一個賦值語句。既然 S 存在某種展開方式,其形式與這行代碼徹底相同,咱們說,這行代碼與 S 是匹配的。對於 Parser 而言,便可判定這行語句是一個賦值語句。
所以,Parser 讀取語言的文法定義。而後,經過找到一個展開方案以匹配源代碼。而這個展開方案中對各個非終結符產生式的選擇過程,便是對源代碼中每個部分的定性過程。這個過程讓 Parser 可以理解源代碼各個部分表示的含義,並以今生成對應的語法樹(Syntax Tree)。