生啃“編譯原理”(一)——引論

開篇:

        做爲軟件工程專業的一員,在本科時候,關於《編譯原理》這門課,沒有開,沒有開,沒有開。。。只能通過自己學習來深入瞭解編譯原理。並希望能夠達到實現一個簡單編譯器的地步。


  • 1 語言處理器

   關於語言處理器,其本身就是一個大程序,而這個大程序的主要目的在於翻譯源程序。

   以Java爲例,有時候,我們可能會有疑問,當寫完一段或複雜或簡單的業務邏輯程序之後,計算機是如何去執行這段源程序的?

   這時候,就需要語言處理器去將源程序翻譯爲目標機器代碼供計算機執行。在計算機誕生之初,機器代碼過於晦澀難懂,不易理解和上手使用,所以誕生了更接近人類自然語言的高級程序設計語言(早期的Fortran和C),那麼問題就來了,計算機並不能讀懂這些高級程序設計語言,或者說,計算機並不能理解這些高級程序設計語言的語法和語義。因此就需要語言處理器去翻譯和處理,並在最後執行這些源程序。

  語言處理器總體上分爲兩類:編譯器和解釋器  

  •    編譯器:本身編譯器即爲一個程序,只將源程序翻譯成機器可以理解的目標機器代碼,同時收集與源程序相關的變量信息存放於指定位置供後續翻譯使用,而這個指定位置叫做符號表,翻譯完畢之後,編譯器會將目標機器代碼作爲輸出,供後續使用。整個翻譯的過程較爲複雜,這裏只做總體認識。
  •    解釋器:解釋器相比於編譯器,有一個很大的不同之處就在於,他並不像編譯器那樣對源程序進行翻譯,而是直接將源程序配合用戶的輸入通過解釋器去一步步執行源程序,並直接產生結果輸出。
  •    兩者的優劣:從上述對比其實可以發現,編譯器並不執行源程序,僅僅是一個翻譯的過程,所以從速度上來說,編譯器會快於解釋器,但是相反,由於解釋器會直接執行源程序,所以在執行過程中,對源程序的語義和語法的檢查將比編譯器更加精確。

    而在實際生產環境中,源程序往往是分佈於各個獨立的文件之中,這些獨立的文件需要經過一個叫做“聚合”的階段,才能進行下一步的編譯操作。而負責聚合操作的對象,叫做所謂的預處理器。而預處理器的聚合操作僅僅是語言處理系統的第一步。

預處理器的主要作用就是對源程序進行聚合操作,得到聚合源程序後,再又彙編器生成目標彙編程序,彙編程序再又彙編器生成可重定位的機器代碼(因爲大型程序都是通過多部分各自編譯的方式進行的),最後利用鏈接器將可重定位的機器代碼與庫文件及可重定位對象文件進行鏈接,並交由加載器將最終得到的機器代碼放置內存中運行。

這裏需要強調幾個概念:

  • 彙編器:由於彙編程序易於輸出和調試,因此在大型程序中會首選彙編器將源程序先翻譯成彙編語言。彙編器也是編譯器的一種。
  • 鏈接器:由於大型程序會被分成多個部分進行編譯,因此生成的機器代碼必須是可重定向的,因爲後續需要將其與庫文件和可重定向的其他目標文件鏈接到一起。
  • 加載器:負責將所有的可執行的目標文件放到內存中執行。

  • 2 編譯器結構
在上一節中提到,編譯器最主要的作用是翻譯程序,那麼編譯器裏面的結構到底是怎麼樣的?
       首先,編譯器其實可以分爲兩部分:分析部分(前端)和綜合部分(後端)。
       分析部分:分析部分會將源程序分解爲多個組成要素,並在組成要素上語法結構,並用這個結構來創建一箇中間表示,同時提供語義上的檢查信息。此外,分析部分還會收集有關源程序的信息,並把信息存放於符號表中。最後分析部分將符號表和中間表示形式一併傳給綜合部分。
      綜合部分:根據分析部分傳入的符號表和中間表示形式創建用戶期待的目標程序。
如果更詳細的研究一下編譯過程,實際上編譯器是順序地執行了一組步驟。每個步驟把源程序從一種表示轉化成另一種表示。

1.詞法分析:將源程序轉化成字符流,並組織成有意義的詞素序列,對於每個詞素,詞法分析會產生詞法單元。
2.語法分析:利用詞法單元的第一個分量創建樹形的中間表示。常用的中間表示是語法樹
3.語義分析:在上一階段得到語法樹之後,需要結合符號表中的信息來檢查源程序是否和語言定義的語義保持一致。
4.中間代碼生成器:一個編譯器可能構造出一個或多箇中間表示。語法樹就是其中之一,而且語法樹通常在語法分析和語義分析中使用,在語法分析和語義分析完成之後,編譯器會生成一個明確的低級的或者類機器語言中間表示。這個中間表示應該易於生成且能夠被輕鬆地翻譯爲目標機器上的語言。
5.機器無關代碼優化器:機器無關的代碼優化目的在於改進中間代碼以便生成更好的目標代碼。
6.代碼生成器:以源程序的中間表示作爲輸入,並把它們映射到目標語言。如果目標語言是機器代碼,則必須爲程序使用的每個變量選擇寄存器或者內存位置。而代碼生成的至關重要的一個方面就是合理分配寄存器以存放變量值。
7.機器相關代碼優化器:機器相關代碼優化,其操作內容與5相似,後續將做介紹。
  • 3 程序設計語言發展
以下僅介紹三種分類方式。
   第一種:按語言的代來分代。
第一代:機器語言
第二代:彙編語言
第三代:Fortran,C,Cobol,C++,C#,Java等高級程序設計語言
第四代:SQL,PostScript等特定應用設計的語言
第五代:基於邏輯和約束的語言,比如OPS5
   第二種:按照程序完成計算任務的方式劃分。
強制式:指明如何完成一個計算任務,C++,C#,Java
聲明式:要進行哪些計算,Haskell
   第三種:按照術語劃分。
馮諾依曼語言:以馮諾依曼計算機體系結構爲計算模型的程序設計語言。如C
面嚮對象語言:C++,C#,Java
腳本語言:Awk,JavaScript,PHP,Python
發佈了54 篇原創文章 · 獲贊 87 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章