編譯原理學習--詞法分析(1)


詞法分析的任務:

  首先,從階段上來看,編譯器可分為若干個中間階段:

    

  典型的,可以包含為一個前端,一個后端。前端接收源程序產生一個中間表示,后端接收中間表示繼續生成一個目標程序。所以,前端處理的是跟源語言有關的屬性,后端處理跟目標機器有關的屬性。

  更細節的,前端可以划分為若干個階段:

    

  下面我們看看詞法分析器的任務:

    

  詞法分析器讀入程序員寫的程序,然后對字符流做切分成記號流。舉個例子:

    這是一個程序員看到的字符流

  詞法分析器將字符流讀入,根據關鍵字、標識符、標點、字符串、整形數等進行划分,形成記號流(單詞):

    

  那么就會有兩個問題:1.記號的數據結構如何定義? 2.如何實現從字符流到記號流轉換的算法?

  首先看第一個問題,如何定義記號的數據結構,假如用C語言實現數據結構的定義,可以這樣實現:

    

  舉個例子:假如源語句if(x>5),則詞法分析器返回token{k=IF,lexeme=0};token{k=IPAREN,lexeme=0};token{k=ID,lexeme="X"};……

 

  【此處小結】:詞法分析器的任務:字符流到記號流。

       字符流:和被編譯語言密切相關(ASCII,Unicode,or……)

       記號流:編譯器內部定義的數據結構,編碼所識別出的詞法單元

 

  再看第二個問題,詞法分析器怎么實現呢?目前來說一般有兩種方案:

    1.手工編碼實現法。這種方法相對復雜,容易出錯,但是非常流行的方法,如GCC,LLVM等。

    2.詞法分析器的生成器。這種方法可快速原型,代碼量少,但較難控制細節。

  (1)我們先看第一種方案,手工編碼法。如何識別語言中的各種符號呢?假設我們分析一種語言,包含以下關系運算符:<=、>=、<>、=、>、<,我們可以用轉移圖對其進行識別,轉移圖如下所示:

       

   那么怎么用算法實現這個轉移圖呢?如下所示:

     

  同理,語言中其他標識符的識別也類似實現:

    

  實際上這兩張轉移圖(包括代碼)是結合在一起的。

  那么問題來了,如何區別關鍵字標識符呢?因為在很多語言中關鍵字和標識符是有交集的,但從詞法分析上看,關鍵字是標識符的一部分。以C語言為例,標識符是:以字母或下划線開頭,后跟0個或多個字母、下划線或數字。關鍵字:if、while、else……

  怎么識別關鍵字呢?這里介紹兩種方法。

  先看第一種,我們需要將上面的轉移圖稍加修改:(以識別if為例)

    此處還應注意一個問題,假如輸入ifxy呢?並不是關鍵字,因此這里還需判斷。

    

  再看第二種,使用關鍵字表,即Hash表。對語言中所有的關鍵字構建哈希表,對所有的關鍵字和標識符,先統一按標識符的轉移表進行識別,識別完成后,再查哈希表看是否為關鍵字。通過構造合理的哈希表,可以再O(1)時間內完成。

 

  (2)再看第二種方案,詞法分析器的生成器。那么怎樣自動生成呢?

    

  這種方案不需要像第一種方案那么繁瑣,只需要用正則表達式寫出程序語言中的詞法規則,然后通過自動生成工具lex,flex,jlex等,自動產生出詞法分析器,生成的詞法分析器跟第一種方案的圖轉移算法是類似的,但是,程序員只需要寫一個聲明式規范,工作量就顯著減小了。

  如何寫這種聲明式規范呢?首先我們要先學正則表達式。什么是正則表達式,其定義如下:

    

   舉個例子,對於字符集Σ={a,b},可以寫出哪些正則表達式? ε、a、b、ε|a,ε|b……εε、εa、εb、ab、a(ε|a)……ε*、a(ε|a)*……

  知道正則表達式了,那么如何用正則表達式表示程序語言的詞法規則呢?再看個例子:C語言中的關鍵字if如何用正則表達式表示?if中i∈Σ,f∈Σ,根據定義則if∈Σ。再看個復雜點的,如何用正則表達式表示C語言的標識符?可將標識符寫成兩部分,第一部分只能以字母或下划線開頭,后連接零個或多個字母、下划線、數字(閉包),則正則表達式為(a|b|c……A|B|C……|_)(a|b|c……A|B|C……|0|1|2……|_)*。但是這樣表達顯然比較繁瑣,可以引入更多的語法糖來構造正則表達式,來簡化構造:

    

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM