Compiler 學習之Parsing(1)

我實在是不怎麼能寫博客。。。就當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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章