讀書筆記(II) 編譯原理及實踐



點擊進入書籍詳情頁

編譯原理及實踐

作者:Kenneth C.Louden

機械工業出版社

出版年:2000-3-1

綜合評分:7.0

_________________________

果然如網上流傳的那樣,翻譯的真是和google有的一拼。難得這麼一本很重實踐的編譯原理書,就這樣被翻譯打了折扣。反過來說,如果真的用心看,翻譯的結果無非是英式文法的中文,要看也是可以看得了。這是苦了我們反覆推敲語義,這種閱讀實在不爽。問題終歸問題,對於我這個自學者來說,這是難得的好教材,結合c代碼一步一步的講解,讓讀者把握哪些是真正的重點,哪些是實現的關鍵。我覺得這樣對於自學者速成確實是很有幫助的。反之,看那本“龍書”,對於初學者抑或自學者確實有點難度。

 
近重新閱讀《編譯原理》,當初的認識仍然很淺薄,書評也寫得幼稚,如今又有些新的體會在此列出:
1. 語法分析的目標是構建語法樹,因爲計算機常用的運算是二元運算:加減乘除等等,因此構建的結構是一個二叉樹。同時,我們根據二叉樹的遍歷等等一些知識,可以認爲語法分析的任務就是根據樹的遍歷結果(程序代碼或表達式)重新構建樹;另外,我們知道我們給計算機的表達式的方式是帶有二義性的,必須定義算符的優先級以及結合規律方可以迴避二義性。考慮a+b*c,可以翻譯爲(a+b)*c或者a+(b*c),因此我們的常規表達方法爲迴避這些問題,必須要帶有"(",")",當然我們所說的常規表達式就是對語法樹的中綴遍歷結果。那麼,如果考慮計算機的計算模型是基於棧和寄存器的方式,顯然適合人類讀寫的中綴表達並不適合計算機理解運算,因此我們意外的發現,波蘭式以及逆波蘭式(對應對語法樹的前序遍歷以及後序遍歷)十分適合現代計算機的實現,而且他們的最大優點就是不需要括號以及優先級,特別適合棧和寄存器計算模型去實現。綜上所述,語法分析的任務(顯然我們將代碼生成也併入了,不過爲了說明主旨)就是根據適合人類讀寫的表達式(中序遍歷)重構完整的語法樹,並轉化成適合計算機模型計算的波蘭式或者逆波蘭式(對應於前序遍歷以及後續遍歷);當然在編譯器實現中,我們並不需要真的必須構造一個語法樹實體。
 
2. 理解語法分析的難點往往集中在對 上下文無關語言、棧、樹等知識的理解上。形式語言無需再講,對於下推自動機等等已經在算法筆記上有所涉及,這裏主要講一講,爲什麼出現LL,LR這兩種不同的語法分析方法。首先從語法分析的本質結構:二叉樹出發,我們知道對於樹的處理很多是基於其獨有的遞歸特徵進行展開的,這一點體現在對樹的遍歷、旋轉等等操作上,一般而言,我們可以通過 自頂向下 以及 自底向上 兩種方式去訪問和處理樹結構,例如在實現計算典型的樹形結構問題Fibonacci數列計算問題的時候,既可以設計遞歸計算程序,也可以反過來設計遞推程序一樣,這就對應了實現方式的不同,遞歸對應自頂向下,而遞推對應自底向上方式。同樣道理,LL以及LR就分別對應自頂向下以及自頂向上方式去訪問樹結構。
 
3. 這裏有人要問,一般樹都會講兩種自頂向下語法分析方法:遞歸下降以及LL;他們又是什麼關係呢?這一點就要從遞歸的實現說起,我們知道遞歸必將顯式或者隱式的實用棧結構,這是我們理解的基本出發點。當然,我們仍是採用自頂向下的方式去求解問題,這一點要和遞推(自底向上)區分。對於遞歸程序,系統已經幫助我們將函數的調用完成,其本質也就是一個壓棧出棧的過程,只是這些是我們看不到的。反之,如果我們構造棧結構,模擬這個過程,那麼就可以將遞歸去除,這也是爲什麼對於很多問題(如八皇后問題)往往即有遞歸算法又有非遞歸算法的原因。那麼,我們現在清楚了,遞歸下降算法就是一種隱式的棧實現,而LL就是顯式的棧實現。
 
4. 補充說明1:自頂向下代表的是對樹結構的前序遍歷,而自底向上代表後序遍歷(注:這種說法並不嚴謹,但是輔助理解還是有益的)。
_________________________
2010.11.6
最近的學習和閱讀中,特別是理解動態規劃的兩種實現:遞歸以及遞推上。我有發現了top-down以及bottom-up設計方法[wiki]和編譯原理的語法分析以及程序設計的哲學的聯繫,其本質都是針對樹結構的特點。自頂向下的分析方法[ref],掌控全局,對全局的功能實現做一個推斷,繼而細化至每一個子模塊,重複這個過程直至足夠細或者不能劃分爲止(即遞歸的base case或者數學歸納法的基本情況),這種方式顯然要求設計師擁有足夠的信息和知識、全局的洞察力和分析能力;自底向上方法[unix]鼓勵設計師設計基本元素,繼而將這些基本元素組合起來,也要依賴於設計師豐富的經驗,並且如何設計基本元素顯然是一個精益求精提煉的探索過程,當然優點就是一旦提煉出這些基本的組件和元素,重用非常的方便。當然,在實際中這兩種方案往往是混合使用的。對於自頂向下來說,將系統劃分成獨立的模塊顯然在實際中並不總是有效(因爲很難將各個模塊設計到完全獨立,往往各個模塊需要調用相同的東西:類似於動態規劃的子問題重複性),特別是軟件工程上強調的可重用性:回顧軟件設計的發展,從早期的自頂向下典型:面向過程式設計方法要求劃分程序的模塊,實現各個過程,面臨着不可重用的困境,直到面向對象出現,強調設計出元組件(這些元組件可以方便的移植到不同的模塊),在拼裝成複雜的模型,大大提高了軟件的可重用性以及開發效率。當然,兩種設計方法在實踐中都是非常重要的,各有優缺,單純的一種開發模式是不可取的。
_________________________
2010.12.05
 
上面的部分主要講解的都是詞法分析和語法分析的內容,在編譯領域,我們統稱這兩種法則爲文法。有了文法就有了語言,但是我們仍然有重要的一步:語義分析。任何一門編譯原理的書中,語義分析都是重點,通常來說,讀完了艱深的詞法分析和語法分析後,面對的語法分析同樣是一個挑戰。語義分析的內容很多,同時它也是後續產生中間代碼生成的必須過程。簡單的來說,我們可以將語義分析理解成如何根據上述兩個過程得到的語法樹進行標註。這個標註我們稱作屬性,其實這個屬性包含的東西很多,可以說變量以及過程的各種信息:名稱,值,類型等等,我們都可以稱之爲屬性。看來若我們把語法樹的信息都合理有效的標出來了,那麼似乎我們已經把語句信息合理的分析出來了,剩下的工作也就可以順利的開展了。
這裏就需要注意一個理解的要點:屬性可以分爲綜合屬性以及繼承屬性這兩種。在語法樹上理解的話,我們可以理解爲綜合屬性是需要了解子節點的屬性纔可以得到父節點的屬性,這相當於一個自底向上的過程;而對於繼承屬性,則意味着我們必須先知道父節點的屬性或者其兄弟節點的屬性纔可以判斷其屬性,這相當於一種自頂向下的思路。當然這種規定仍然對我們的編譯器實現仍很複雜,於是我們規定了兩種屬性法則:S屬性文法與L屬性文法;對於前者,我們瞭解其只包含綜合屬性;而後者並不是只包含繼承屬性,而是包含一種特殊的繼承屬性和若干的綜合屬性構成的屬性文法。這種特殊的繼承屬性是一種節點只會繼承其父代或者最左面的節點屬性的規定,其實這個我們的語句書寫有關,因爲我們總是規定先訪問左邊的節點後纔會訪問右邊的若干節點。
屬性這個詞往往比較抽象,這是爲了教授研究而進行的泛化;其實在編譯器中我們最關心兩個重要的屬性:類型和值。對於類型這個屬性來說,其可以是繼承的,也可以是綜合的。而且類型關係到我們的語義的正確性:例如我們總不能讓一個浮點數做數組的下表吧,應當在語義分析部分對類型進行檢查。
 
______________________________
2011.3.8
 


點擊進入書籍詳情頁

編譯原理及實踐

作者:Kenneth C.Louden

機械工業出版社

出版年:2000-3-1

綜合評分:7.0

_________________________

果然如網上流傳的那樣,翻譯的真是和google有的一拼。難得這麼一本很重實踐的編譯原理書,就這樣被翻譯打了折扣。反過來說,如果真的用心看,翻譯的結果無非是英式文法的中文,要看也是可以看得了。這是苦了我們反覆推敲語義,這種閱讀實在不爽。問題終歸問題,對於我這個自學者來說,這是難得的好教材,結合c代碼一步一步的講解,讓讀者把握哪些是真正的重點,哪些是實現的關鍵。我覺得這樣對於自學者速成確實是很有幫助的。反之,看那本“龍書”,對於初學者抑或自學者確實有點難度。

 
近重新閱讀《編譯原理》,當初的認識仍然很淺薄,書評也寫得幼稚,如今又有些新的體會在此列出:
1. 語法分析的目標是構建語法樹,因爲計算機常用的運算是二元運算:加減乘除等等,因此構建的結構是一個二叉樹。同時,我們根據二叉樹的遍歷等等一些知識,可以認爲語法分析的任務就是根據樹的遍歷結果(程序代碼或表達式)重新構建樹;另外,我們知道我們給計算機的表達式的方式是帶有二義性的,必須定義算符的優先級以及結合規律方可以迴避二義性。考慮a+b*c,可以翻譯爲(a+b)*c或者a+(b*c),因此我們的常規表達方法爲迴避這些問題,必須要帶有"(",")",當然我們所說的常規表達式就是對語法樹的中綴遍歷結果。那麼,如果考慮計算機的計算模型是基於棧和寄存器的方式,顯然適合人類讀寫的中綴表達並不適合計算機理解運算,因此我們意外的發現,波蘭式以及逆波蘭式(對應對語法樹的前序遍歷以及後序遍歷)十分適合現代計算機的實現,而且他們的最大優點就是不需要括號以及優先級,特別適合棧和寄存器計算模型去實現。綜上所述,語法分析的任務(顯然我們將代碼生成也併入了,不過爲了說明主旨)就是根據適合人類讀寫的表達式(中序遍歷)重構完整的語法樹,並轉化成適合計算機模型計算的波蘭式或者逆波蘭式(對應於前序遍歷以及後續遍歷);當然在編譯器實現中,我們並不需要真的必須構造一個語法樹實體。
 
2. 理解語法分析的難點往往集中在對 上下文無關語言、棧、樹等知識的理解上。形式語言無需再講,對於下推自動機等等已經在算法筆記上有所涉及,這裏主要講一講,爲什麼出現LL,LR這兩種不同的語法分析方法。首先從語法分析的本質結構:二叉樹出發,我們知道對於樹的處理很多是基於其獨有的遞歸特徵進行展開的,這一點體現在對樹的遍歷、旋轉等等操作上,一般而言,我們可以通過 自頂向下 以及 自底向上 兩種方式去訪問和處理樹結構,例如在實現計算典型的樹形結構問題Fibonacci數列計算問題的時候,既可以設計遞歸計算程序,也可以反過來設計遞推程序一樣,這就對應了實現方式的不同,遞歸對應自頂向下,而遞推對應自底向上方式。同樣道理,LL以及LR就分別對應自頂向下以及自頂向上方式去訪問樹結構。
 
3. 這裏有人要問,一般樹都會講兩種自頂向下語法分析方法:遞歸下降以及LL;他們又是什麼關係呢?這一點就要從遞歸的實現說起,我們知道遞歸必將顯式或者隱式的實用棧結構,這是我們理解的基本出發點。當然,我們仍是採用自頂向下的方式去求解問題,這一點要和遞推(自底向上)區分。對於遞歸程序,系統已經幫助我們將函數的調用完成,其本質也就是一個壓棧出棧的過程,只是這些是我們看不到的。反之,如果我們構造棧結構,模擬這個過程,那麼就可以將遞歸去除,這也是爲什麼對於很多問題(如八皇后問題)往往即有遞歸算法又有非遞歸算法的原因。那麼,我們現在清楚了,遞歸下降算法就是一種隱式的棧實現,而LL就是顯式的棧實現。
 
4. 補充說明1:自頂向下代表的是對樹結構的前序遍歷,而自底向上代表後序遍歷(注:這種說法並不嚴謹,但是輔助理解還是有益的)。
_________________________
2010.11.6
最近的學習和閱讀中,特別是理解動態規劃的兩種實現:遞歸以及遞推上。我有發現了top-down以及bottom-up設計方法[wiki]和編譯原理的語法分析以及程序設計的哲學的聯繫,其本質都是針對樹結構的特點。自頂向下的分析方法[ref],掌控全局,對全局的功能實現做一個推斷,繼而細化至每一個子模塊,重複這個過程直至足夠細或者不能劃分爲止(即遞歸的base case或者數學歸納法的基本情況),這種方式顯然要求設計師擁有足夠的信息和知識、全局的洞察力和分析能力;自底向上方法[unix]鼓勵設計師設計基本元素,繼而將這些基本元素組合起來,也要依賴於設計師豐富的經驗,並且如何設計基本元素顯然是一個精益求精提煉的探索過程,當然優點就是一旦提煉出這些基本的組件和元素,重用非常的方便。當然,在實際中這兩種方案往往是混合使用的。對於自頂向下來說,將系統劃分成獨立的模塊顯然在實際中並不總是有效(因爲很難將各個模塊設計到完全獨立,往往各個模塊需要調用相同的東西:類似於動態規劃的子問題重複性),特別是軟件工程上強調的可重用性:回顧軟件設計的發展,從早期的自頂向下典型:面向過程式設計方法要求劃分程序的模塊,實現各個過程,面臨着不可重用的困境,直到面向對象出現,強調設計出元組件(這些元組件可以方便的移植到不同的模塊),在拼裝成複雜的模型,大大提高了軟件的可重用性以及開發效率。當然,兩種設計方法在實踐中都是非常重要的,各有優缺,單純的一種開發模式是不可取的。
_________________________
2010.12.05
 
上面的部分主要講解的都是詞法分析和語法分析的內容,在編譯領域,我們統稱這兩種法則爲文法。有了文法就有了語言,但是我們仍然有重要的一步:語義分析。任何一門編譯原理的書中,語義分析都是重點,通常來說,讀完了艱深的詞法分析和語法分析後,面對的語法分析同樣是一個挑戰。語義分析的內容很多,同時它也是後續產生中間代碼生成的必須過程。簡單的來說,我們可以將語義分析理解成如何根據上述兩個過程得到的語法樹進行標註。這個標註我們稱作屬性,其實這個屬性包含的東西很多,可以說變量以及過程的各種信息:名稱,值,類型等等,我們都可以稱之爲屬性。看來若我們把語法樹的信息都合理有效的標出來了,那麼似乎我們已經把語句信息合理的分析出來了,剩下的工作也就可以順利的開展了。
這裏就需要注意一個理解的要點:屬性可以分爲綜合屬性以及繼承屬性這兩種。在語法樹上理解的話,我們可以理解爲綜合屬性是需要了解子節點的屬性纔可以得到父節點的屬性,這相當於一個自底向上的過程;而對於繼承屬性,則意味着我們必須先知道父節點的屬性或者其兄弟節點的屬性纔可以判斷其屬性,這相當於一種自頂向下的思路。當然這種規定仍然對我們的編譯器實現仍很複雜,於是我們規定了兩種屬性法則:S屬性文法與L屬性文法;對於前者,我們瞭解其只包含綜合屬性;而後者並不是只包含繼承屬性,而是包含一種特殊的繼承屬性和若干的綜合屬性構成的屬性文法。這種特殊的繼承屬性是一種節點只會繼承其父代或者最左面的節點屬性的規定,其實這個我們的語句書寫有關,因爲我們總是規定先訪問左邊的節點後纔會訪問右邊的若干節點。
屬性這個詞往往比較抽象,這是爲了教授研究而進行的泛化;其實在編譯器中我們最關心兩個重要的屬性:類型和值。對於類型這個屬性來說,其可以是繼承的,也可以是綜合的。而且類型關係到我們的語義的正確性:例如我們總不能讓一個浮點數做數組的下表吧,應當在語義分析部分對類型進行檢查。
 
______________________________
2011.3.8
 


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