我實在是不怎麼能寫博客。。。就當Coursera課程的筆記了。
parsing是繼lexical analysis之後的第二個內容,在我們完成了Lexical analysis之後,我們需要將輸入的token對組成一個Parse Tree,爲後來的語義分析做準備。那麼Parsing到底有哪些內容呢?
Context Free Grammar,Derviation, Recursive Decent Algorithm, Bottom-up Parsing等等,我們一個一個看。
一: Context Free Grammar 又叫 CFG, 根據 CFG的定義,它包含以下幾個方面:
{
a set of terminals;
a set of non-terminals;
a start symbol (non-terminals);
a set of production (can be anything);
}
先解釋以下terminal 和non-terminal的問題,terminal是parsing中的最後單元,它不能被解釋成其它東西了,好比說數字 int(我們不關心int的具體值),操作符(*+-/),關鍵字。而non-terminal是一種抽象的標號,它可以被解釋成terminal或者non-terminal。看一個例子:
E -> E + E | E - E | E * E | E / E | int | epsilon
這句話的意思就是 E可以被解釋成以下集中形式 E + E, E - E ..., 其中包括 int這樣的 terminal還有一個特殊的符號 epsilon(它表示空)。 值得注意的是這種解釋方法和Regular Expr很相近,其中的 '|' 和 Regular Expr 當中的 '|' 有相同的作用,“可以將E替換成右邊的任何一種 production”。
總結以下,對CFG的操作:
1:從 Start Symbol開始(通常叫S);
2:將左邊的任何一個non-terminal 替換爲Production;
3:重複第二步知道沒有全部都爲terminal位置;
順便我們可以定義CFG的 語言 L(G): 所有可以被G規則解釋出來的字符串,我們就認爲它在G的語言中(In the language of G)。
不幸的是,識別兩種Grammar是否相同是一種non-trival的工作。由於很多時候你不能窮舉所有在Language中的String,所以我們只能取寫出一個足夠好的Grammar,讓它識別String是否在L(G)中。
二:Derviation:這是我們得到Parse Tree的方法。
一般構建的方法有兩種,left most 和 right most, 它們是指我們要從當前的Production中的最左邊的non-terminal開始還是從最右邊的開始,該non-terminal可以被展開爲Grammar當中的任何一種規則。
由於之前的CFG只能告訴我們一個string是否在L(G)中,我們確實需要一種方法來構建Parse樹,還是舉個例子:
假設我們的CFG爲 "E -> E + E | E * E | (E) | id", 要匹配的string是 id * id + id, 則我們可以這樣構建
E E
-> E + E / \
-> E * E + E E + E
-> id * E + E / \ |
-> id * id + E E * E id
-> id * id + id | |
id id
同時我們又可以這麼構建:
E E
-> E * E / \
-> E * E + E E * E
-> id * E + E | / \
-> id * id + E id E + E
-> id * id + id | |
id id
這樣就帶了了ambiguity, and ambiguity is BAD! 下一篇我們在討論ambiguity