編譯原理課程設計詞法分析任務書 5)參考文獻: (1)張素琴,呂映芝. 編譯原理[M]., 清華大學出版社 (2)蔣立源、康慕寧等,編譯原理(第2版)[M],西安:西北工業大學出版社 6)課程設計進度安排 1.準備階段(4學時):選擇設計題目、瞭解設計目的要求、查閱相關資料 2.程式模塊設計分析階段 ...
編譯原理課程設計詞法分析任務書
5)參考文獻:
(1)張素琴,呂映芝. 編譯原理[M]., 清華大學出版社
(2)蔣立源、康慕寧等,編譯原理(第2版)[M],西安:西北工業大學出版社
6)課程設計進度安排
1.準備階段(4學時):選擇設計題目、瞭解設計目的要求、查閱相關資料
2.程式模塊設計分析階段(4學時):程式總體設計、詳細設計
3.代碼編寫調試階段(8學時):程式模塊代碼編寫、調試、測試
4.撰寫論文階段(4學時):總結課程設計任務和設計內容,撰寫課程設計論文
學生簽名:
2019 年 5 月 9 日
課程設計(論文)評審意見
(1)學習態度(20分):優( )、良( )、中( )、一般( )、差( );
(2)系統設計(20分):優( )、良( )、中( )、一般( )、差( );
(3)編程調試(20分):優( )、良( )、中( )、一般( )、差( );
(4)回答問題(20分):優( )、良( )、中( )、一般( )、差( );
(5)論文撰寫(20分):優( )、良( )、中( )、一般( )、差( );
評閱人: 職稱: 講師
2019 年 5 月 10 日
中文摘要
實現功能及實現:
主要實現對文本中的程式進行詞法分析,把程式中的單詞分為五大類(基本保留字[1]、標識符[2]、常數[3]、運算符[4]、分隔符[5])並與相應的區域數字來對應輸出.
之前利用Java中的BufferedReader緩衝器對象來存儲讀取程式的文件,在劉立月老師指導下,較大程式文件的時有超時的情況,後更改成一行編譯讀取方式.利用兩個異常處理,文件讀取異常和輸出異常時列印ERROR.
背景和意義:
詞法分析的過程是線性的從頭至尾掃描一遍,複雜度較低,易實現。能完成電腦翻譯過程的關鍵階段,它為後面的語法分析、語義分析做好準備,打好基礎,以便快速地、高質量地生成目標語言程式。
關鍵字: 詞法分析、文件異常、目標語言程式
一、課程設計任務及要求
1.1、目的
通過使用一個通用的能夠自動根據正規表達式生成詞法分析程式的工具程式設計一個簡單語言的詞法分析器,使學生充分理解課程理論內容和工具軟體的使用技巧,掌握所涉及的典型數據結構,演算法及方法,為今後在大型軟體系統實踐中設計性能優良的軟體系統打下基礎。
1.2、任務與要求
【基本要求】
編製一個讀單詞過程,從輸入的源程式中,識別出各個具有獨立意義的單詞,即基本保留字、標識符、常數、運算符、分隔符五大類。並依次輸 出各個單詞的內部編碼及單詞符號自身值。(遇到錯誤時可顯示“Error”,然後跳過錯誤部分繼續顯示)
【測試數據】
如源程式為C語言。輸入如下一段:
1 main(){ 2 3 int a,b; 4 5 a = 10; 6 7 b = a + 20; 8 9 }
測試數據
1 (2,”main”) (2,”a”) 2 3 (5,”(“) (4,”=”) 4 5 (5,”)“) (3,”10”) 6 7 (5,”{“) (5,”;”) 8 9 (1,”int”) (2,”b”) 10 11 (2,”a”) (4,”=”) 12 13 (5,”,”) (2,”a”) 14 15 (2,”b”) (4,”+”) 16 17 (5,”;”) (3,”20”)
二、需求分析
2.1、分析
通過修改代碼使得自動機能夠更多的實現運算符號的識別功能,使用TINY語言調試一個程式,加深同學對詞法分析的認識以及理解。另外,同時增強編寫和調試程式的能力。
2.2、問題解決
對讀取的文件進行預處理,從頭到尾進行掃描,去除//和/* */的內容,以及一些無用的、影響程式執行的符號如換行符、回車符、製表符等。但是千萬註意不要在這個時候去除空格,因為空格在詞法分析中有用,比如說int i=3;這個語句,如果去除空格就變成了“inti=3”,這樣就失去了程式的本意,因此不能在這個時候去除空格。
2.3、解決步驟
對源文件從頭到尾進行掃描了,從頭開始掃描,主控程式主要負責系統建立一個文件保存四個表,這四個表分別存儲關鍵字、運算符、界符、過濾符。而標識符和常數則用正則表達式判斷。建立了多個布爾類,當系統讀取代碼時,用空格或製表符作為標誌符,當遇到空格就輸出之前檢索的字元串進行判斷(規定每個單詞符號之間都有空格),判斷字元串時,系統會通過順序查找依次調用布爾類與之匹配來判斷其屬性並輸出,如沒有匹配成功,則說明所檢索的字元串不合法,系統則會輸出非法字元串。直到最後一個字元串匹配完畢之後系統結束。
三、設計思路
3.1、總體思路分析
程式的關鍵點在於對給出一段程式中的各種單詞的分離。在每段程式中,單詞種類可以分為:關鍵字,分界符,算術運算符,關係運算符,標識符和常數。關鍵字的判斷則是通過與已知數組中列出的元素進行對比,得出該單詞是否為關鍵字;分解符,算術運算符,關係運算符的判斷與接受到的字元進行比較,得出該字元是否為分解符,算術運算符或者為關係運算符。
狀態圖
圖3-1-1:功能模塊分解圖
總控程式流程圖:
圖3-1-2:控制流程圖
3.2、設計原理
主要任務如下:
識別出輸入的源程式中的單詞,輸出二元組形式的單詞序列。
刪除無用的空白字元、回車符等沒有實質意義的字元。
圖3-2:正規式和狀態轉換圖
實驗步驟:
PL/0語言文法的EBNF表示如下:
1 <程式>::=begin<語句串>end 2 3 4 5 <語句串>::=<語句>{;<語句>} 6 7 <語句>::=<賦值語句> 8 9 10 11 <賦值語句>::=ID:=<表達式> 12 13 14 15 <表達式>::=<項>{+<項> | -<項>} 16 17 18 19 <項>::=<因數>{*<因數> | /<因數> 20 21 22 23 <因數>::=ID | NUM | (<表達式>)
3.3實現方法
本次實驗是設計詞法分析器,其中核心函數是cifa(),分析的語言是PL/0,首先,採用迴圈遍歷的方法讀取用戶輸入的一段代碼,跳過源程式中的空格字元,然後if語句配合switch語句對讀入的代碼挨個判斷,最後以二元組的形式輸出結果。
四、詳細設計
4.1、項目設計步驟
a) 創建存放識別程式文件
圖4-1:待編譯程式文件test.txt
b) 讀取文件單詞並存儲
讀取文件test.txt文件:
1 br = new BufferedReader(new FileReader("tests.txt"));
存放構成單詞符號的字元串:
1 public StringBuffer strToken = new StringBuffer();
基本保留字(關鍵字)
1 public String [] retainWord = new String[]{"int","if","else","return","main","void","while","break"};
c) 識別不同程式單詞
基本保留字
-
1 for(int i = 0;i < retainWord.length;i++){//是否為關鍵字,,是返回1 2 if(strToken.toString().equals(retainWord[i])){ 3 4 return 1; 5 6 } 7 8 }
-
1 if(code == 1){//關鍵字 2 System.out.println("('"+1+"','"+strToken+"')"); 3 4 }
標識符
1 for(int i = 0;i < retainWord.length;i++){//是否為關鍵字,,是返回1 2 if(strToken.toString().equals(retainWord[i])){ 3 4 return 1; 5 6 } 7 8 } 9 10 if(strToken.length() != 0){ 11 12 ...... 13 14 } 15 16 return 2; 17 18 } 19 20 21 22 else if(code == 2){//非數字,關鍵字 23 System.out.println("('"+2+"','"+strToken+"')"); 24 25 } 26 27 28 29 30 31 常數 32 33 if(strToken.charAt(0)>='0' && strToken.charAt(0)<='9'){//第一個是否為數字返回3 34 return 3; 35 36 } 37 38 39 40 else if(code == 3){//數字 41 System.out.println("('"+3+"','"+strToken+"')"); 42 43 }
運算符
1 else if(ch == 43){ 2 Retract(); 3 4 System.out.println("('"+4+"','"+(char) ch+"')"); 5 6 7 8 }else if(ch == 45){ 9 Retract(); 10 11 System.out.println("('"+4+"','"+(char) ch+"')"); 12 13 14 15 }else if(ch == 42){ 16 Retract(); 17 18 System.out.println("('"+4+"','"+(char) ch+"')"); 19 20 21 22 }else if(ch == 47){ 23 Retract(); 24 25 System.out.println("('"+4+"','"+(char) ch+"')");
分隔符
1 System.out.println("('"+5+"','"+(char) ch+"')"); 2 }else if((char) ch == '('){ 3 4 Retract(); 5 6 System.out.println("('"+5+"','"+(char) ch+"')"); 7 }else if((char) ch == ')'){ 8 9 Retract(); 10 11 12 13 System.out.println("('"+5+"','"+(char) ch+"')"); 14 }else if((char) ch == '{'){ 15 16 Retract(); 17 18 19 20 System.out.println("('"+5+"','"+(char) ch+"')"); 21 }else if((char) ch == '}'){ 22 23 Retract(); 24 25 26 27 System.out.println("('"+5+"','"+(char) ch+"')"); 28 }else if((char) ch == ','){
d) 語言單詞編碼
表4-4:語言單詞編碼
五、運行調試與分析討論
程式運行環境為Win10系統,在IDEA/ECLIPSE上運行
運行結果分析如下:
5.1、當在文本文件test.txt中輸入文法:
圖5-1-1:類型號和單詞輸出結果
5.2輸出異常處理:
a) 文件路徑異常
圖5-1-2:獲取程式文件異常
b) 程式中未識別單詞異常
圖5-1-3:不能識別程式單詞報錯
六、設計體會與小結
心得體會:
這個程式實現了課設的所有要求(由於我是31號做第一題詞法分析模擬,但同時實現了擴展功能對於註釋的文字進行忽視編譯),雖然可能還存在些不足,像之前劉立月老師提出的我的程式對於簡短的程式是完全可以的,我的讀取方式是對象全部讀取.但是對於一些比較大的項目來進行對象讀取時間比較長.於是在我的程式當中進行了一定量的修改,更改成行的讀取.用編譯原理的知識自己獨立完成這樣一個程式我覺得還不錯了,畢竟做這樣的課設可以學到不少東西.
學習心得:
一開始對編寫詞法分析毫無頭緒,不知如何下手。上網查資料是我們邁開的第一步,然後查閱相關資料,小組裡相互討論幫助,在多次的調試和改進中終於把程式完成了。通過這次的程式實驗我對編譯原理這門課程有了進一步的深層次瞭解,而且在自已動手體驗的情況下,更加透徹地理解了詞法分析的過程。在設計過程中,要發揚團體合作的精神,互幫互助,共同進步。善於發問,善於思考。
七、參考文獻
1 [1] 張素琴.編譯原理. 北京:清華大學出版社,2005 2 3 [2] 付京周.JAVA 程式設計語言. 北京:人民郵電出版社,2007 4 5 [3]黃賢英,王珂珂.編譯原理及實踐教程.北京:清華大學出版社,2008 6 7 [4]黃賢英,王珂珂,劉潔,曹瓊.編譯原理重點難點分析.習題解析·實驗指導.北京:機械 8 9 工業出版社,2008 10 11 [5]陳媛,何波,塗曉紅,塗飛演算法與數據結構.北京:清華大學出版社,2005[4]劉恆洋,楊巨集雨.演算法與數據結構.北京:機械工業出版社,2010 12 13 [6]陳火旺,《程式設計語言編譯原理》(第3版),北京:國防工業出版社.2000. 14 15 [7]美Alfred V. Aho Ravi Sethi Jeffrey D. Ullman著.李建中,薑守旭譯.《編譯原理》. 北京:機械工業出版社.2003. 16 17 [8]美KennethC. Louden著.馮博琴等譯.《編譯原理及實踐》.北京:機械工業出版社.2002. 18 19 [9]金成植著.《編譯程式構造原理和實現技術》.北京:高等教育出版社.2002.
掃碼公眾號--回覆“詞法分析”獲取源碼: