編譯原理課程設計——語法分析器


實驗目的

  了解掌握算符優先分析的基本方法、內容;學會科學思考並解決問題,提高程序設計能力。

實驗內容與要求

  用算符優先分析方法設計一個分析解釋程序,對輸入的賦值語句、輸出語句、清除語句進行詞法分析、語法分析、表達式求值並存儲於指定變量中;若存在錯誤,提示錯誤相關信息。

文法表示  

    S -> v=E | E? | clear

    E -> E+T | E–T | T

    T -> T*F | T/F | F

    F -> (E) | v | c

問題分析

  由於要求用算符優先分析方法來進行程序的語法分析,所以我們要根據給出的文法來設計優先關系表。對每個非終結符,求出:

    FIRSTVT(S) = { v , ? , clear }                 LASTVT(S) = { ? , clear }

    FIRSTVT(F) = { ( , v , c }                       LASTVT(F) = { ) , v , c }

    FIRSTVT(T) = {* , / , ( , v , c }               LASTVT(T) = {* , / , ) , v , c }

    FIRSTVT(E) = {+ , - , * , / , ( , v , c}       LASTVT(E) = {+ , - , * , / , } , v , c}

  符號的種別碼如下表所示:

   

  優先關系表如下:

       

先簡要分析一下語法分析的大致流程:

         當有句子要進行處理時,首先要對其進行詞法分析來分解出該句子中的每個符號,然后將該句子按照算符優先算法壓入歸約棧中,如果可以順利歸約,則說明這是一個合法的句子,否則該句子非法。

         這里有一個需要考慮的地方,就是如何進行歸約。由於文法已經給定,所以我們考慮設計一個文法表,文法表中的內容就是可歸約串的種別碼的順序,比如v=E可以表示為9,1,13。這樣的話當我們要進行一次歸約時,只用按順序存儲最左素短語中符號的種別碼,然后拿這個種別碼序列與文法表進行匹配,就可知道當前歸約需要執行哪些操作。

         還有一點需要注意,就是如何對一個表達式進行求值。這里需要我們設計一個二元組的變量名表,這個變量名表可以根據變量的名稱來返回變量的數據。變量名表的具體設計見詳細設計部分。

         由於是簡化分析,所以這個程序只考慮整數的處理。

         有了上面的分析,可以構造出算符優先分析算法的流程圖,如下圖所示。   

詳細設計

(1)詞法分析部分

  由於詞法分析的內容在課程設計1中已經介紹,並且這次的狀態轉換圖與課程設計1中的非常相似,所以這里就不過多介紹。

(2)優先關系表

  在程序中我們用一個二維數組priTable[][]來存儲算符間的優先關系。priTable[a][b]=1表示a>b; 。priTable[a][b]=0表示a=b; 。priTable[a][b]=-1表示a<b;

(3)歸約棧的設計

  由於真正要設計一個棧來處理問題有些麻煩,所以這里可以用一個數組s[]來代替棧,如圖2.1所示,i就代表棧頂指針,s[i]就代表棧頂的元素。歸約棧中的結點,構造一個數據結構Node來表示,Node中有三個元素,算符的單詞名str、算符的種別碼type、算符的數值num。當我們詞法分析來掃描出一個單詞的時候,就可以填充Node結點的單詞名、種別碼和數值。

(4)歸約過程

  在問題分析中我們介紹到用文法表來進行歸約,文法表graTable是一個二維數組,保存文法中算符的種別碼。歸約的時候,只要最左素短語的種別碼匹配到文法表中的某一項,就可以按照那個歸約操作來進行歸約。歸約的步驟參照流程圖中的操作,設置棧頂指針,將棧頂結點的種別碼設為非終結符,並且還要保存這一次歸約產生的結果。舉個例子,比如E->E+T 這次歸約,E+T會產生一個結果,這個結果最終就保存在棧頂結點的數值域中。需要注意的是,Node結點中數值域的主要作用就是在歸約中保存結果。

(5)變量名表

  變量名表varTable的作用是根據變量名來返回該變量的數值,是一個二元組的序列,為了方便這里采用STL模板中的map來實現。變量名表的主要用處也就是在賦值語句和表達式求值當中,比如說當有賦值語句a=5需要歸約時,檢查變量a是否存在於變量名表中,如果不存在就將a和5添加至變量名表,如果a存在那么就可以更新變量名表中a的數值。並且在有F->v這樣的歸約中,如果查找到v不在變量名表中,說明v就是一個未賦值的變量,這樣就產生異常。

輸入與輸出

  程序的輸出有:判斷語法是否正確;輸出表達式求值的結果;輸出錯誤信息。

樣例輸入(輸入來自文件in.txt):

  a = 5

  b = a + 10

  b?

  b + a * a?

  a = (a + b) * (b - a) + 5 + 4 / 2

  a?

  clear

  ab =

樣例輸出(輸出至文件out.txt):

  a = 5 為合法句子,執行成功

  b = a + 10 為合法句子,執行成功

  b? 為合法句子,執行成功

  b 的值為 15

  b + a * a? 為合法句子,執行成功

  b + a * a 的值為 40

  a = (a + b) * (b - a) + 5 + 4 / 2 為合法句子,執行成功

  a? 為合法句子,執行成功

  a 的值為 207

  clear 為合法句子,執行成功

  ab =  語句出現語法錯誤!

結語

  寒假在家想嘗試着做一個C語言的編譯器,這幾天在家里研究編譯原理的龍書,順帶就把上學期編譯原理的課程設計整理下發到BLOG上。

  說實話龍書里面的內容挺難的,我學過編譯原理的,但是還在在第二章就卡住了,所以說我們的課程知識還是學得很淺的。這段時間還是先把基礎打的牢固些吧,研究龍書一段時間,然后考慮如何做這個編譯器。過幾天應該就要開始着手做了,到時候開發的文檔和學到的一些新知識應該都會更新到BLOG上,也算是對自己的一種總結吧。

 


免責聲明!

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



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