詞法分析實驗報告_第1頁
詞法分析實驗報告_第2頁
詞法分析實驗報告_第3頁
詞法分析實驗報告_第4頁
詞法分析實驗報告_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、編譯原理實驗姓 名:朱彥榮學 號:專 業(yè):軟件工程 2 實驗題目:詞法分析 完成語言: C/C+ 上級系統: VC+6.0日 期: 2015/11/7詞法分析設計題目: 手工設計 c 語言的詞法分析器(可以是 c 語言的子集 )設計內容:處理 c 語言源程序, 過濾掉無用符號 ,判斷源程序中 單詞的合法性 ,并 分解出 正確的單詞 ,以 二元組形式存放在文件 中。設計目的: 了解高級語言單詞的分類,了解狀態(tài)圖以及如何表示并識別單詞規(guī)則, 掌握狀態(tài)圖到識別程序的編程。結果要求: 課程設計報告。完成日期: 第十五周提交報告一 分析要想 手工設計詞法分析器,實現 C 語言子集的識別,就要明白 什么是

2、詞法分析器 ,它的 功能是什么。詞法分析是編譯程序進行編譯時 第一個要進行的任務主要是對源程序進行編譯預處理 (去除注釋、 無用的回車換行找到包含的文件等) 之后, 對整個源程序進行分解 ,分解成 一個個單詞 ,這些單詞有且 只有五類 ,分別是 標識符、保留字、常數、運算符、界符 。以便為下面的語法分析和語義分析要定義好這五種符號的集合 。下做準備??梢哉f詞法分析面向的對象是 單個的字符 ,目的是把它們 組成有效的單 詞(字符串);而 語法的分析 則是利用詞法分析的結果作為輸入來分析是否符合語 法規(guī)則并且進行 語法制導 下的語義分析,最后產生 四元組 (中間代碼 ),進行優(yōu)化 (可有可無)之后

3、最終生成 目標代碼 ??梢娫~法分析是所有 后續(xù)工作的基礎 ,如 果這一步出錯,比如明明是 <='卻被拆分成 <'和 ='就會對下文造成不可面是我構造的一個 C 語言子集 。第一類:標識符 letter(letter | digit)*無窮集第二類:常數 (digit)+ 無窮集第三類:保留字 (32)autobreakcase charconstcontinuedefaultdodouble elseenumexternfloatforgoto ifintlongregisterreturnshort signedsizeofstaticstructswit

4、chtypedef unionunsignedvoidvolatilewhile第四類:界符 /*'、/ '、 () " " ' 等第五類:運算符 <、<=、 >、 >=、 =、 +、-、*、/、八、等挽回的影響。因此,在進行詞法分析的時候一定對所有可數符號進行編碼:<$,0><auto,1> <while,32><+,33> <-,34> <*,35> </,36> <<,37> <<=,38> <&

5、gt;,39> <>=,40> <=,41><=,42><!=,43><,44><(,45><),46><八,47><,48><",49><',50><#,51><&,52><&&,53><|,54><|,55><%,56><,57><<<,58>左移<>>,59>右移<,6

6、0><,61><,62><,63><,64><.,65><?,66><:,67><!,68>"","","",""<常數 99 ,數值 ><標識符 100 ,標識符指針 >上述二元組中左邊是單詞的符號,右邊為其 種別碼 ,其中常數和標識符有點特別,因為是無窮集合,因此常數用自身來表示,種別碼為99,標識符用標識符符號表的指針表示(當然也可用自身顯示,比較容易觀察) ,種別碼 100。根據上述

7、約定,一旦見到了種別碼syn=63就唯一確定了 '這個單詞。下面是一些變量的約定:/ 全局變量,保留字表static char reserveWord3220 = "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "e

8、xtern", "float", "for", "goto", "if", "int", "long","register", "return", "short", "signed", "sizeof", "static","struct", "switch", "typedef", &q

9、uot;union", "unsigned", "void", "volatile", "while"/ 界符運算符表 ,根據需要可以自行增加static char operatorOrDelimiter3610= "+","-","*","/","<","<=",">",">=","=","=

10、","!=",";","(",")","A",",",""","'","#","&","","",".","?",":","!";static char IDentifierTbl100050="";/ 標識符表char r

11、esourceProject10000;/ 輸入的源程序存放處,最大可以存放 10000個字符。char token20=0;每次掃描的時候存儲已經掃描的結果。int syn=-1;/syn即為種別碼,約定$'的種別碼為0,為整個源程序的結束符號一旦掃描到這個字符代表掃描結束int pProject = 0;/源程序指針,始終指向當前源程序待掃描位置。幾個重要函數:/ 查找保留字,若成功查找,則返回種別碼/ 否則返回 -1,代表查找不成功,即為標識符 int searchReserve(char reserveWord 20, char s)/* 判斷是否為字母 */ bool IsL

12、etter(char letter)/* 判斷是否為數字 */bool IsDigit(char digit)/* 編譯預處理,取出無用的字符和注釋 */ void filterResource(char r,int pProject)/*分析子程序,算法核心 */void Scanner(int &syn,char resourceProject,char token,int &pProject)面說一下整個程序的流程:1. 詞法分析程序 打開源文件, 讀取文件內容, 直至遇上 '$'文件結束符, 然后讀取結束。2. 對讀取的文件進行預處理,從頭到尾進行掃描,

13、 去除/和/*/的內容 ,以及一些無用的、影響程序執(zhí)行的符號如換行符、回車符、制表符等。但是 千萬注意不要在這個時候去除空格,因為空格在詞法分析中有用,比如說int i=3;這個語句,如果去除空格就變成了 “ inti=3”,這樣就失去了程序的本意,因此不能在這個時候去除空格。3. 選下面就要對 源文件從頭到尾進行掃描 了,從頭開始掃描, 這個時候掃描程序首先要 詢問當前的字符 是不是空格 ,若是空格,則繼續(xù)掃描下一個字符,直至不是空格,然后詢問這個字符 是不是字母 ,若是則進行標識符和保留字的識別; 若這個 字符為數字 ,則進行數字的判斷。 否則, 依次對這個 字符可能的情況進行判斷, 若是

14、將所有可能都 走了一遍還是沒有知道它是誰,則認定為 錯誤符號,輸出該錯誤符號 ,然后結束。每 次成功識別了一個單詞后,單詞都會存在 token 中。然后確定這個單詞的 種別碼 , 最后進行下一個單詞的識別。 這就是掃描程序進行的工作, 可以說這個程序徹底實現 了 確定有限自動機 的某些功能,比如說 識別標識符,識別數字 等。為了簡單起見,這 里的數字只是 整數 。4. 主控程序主要負責對每次識別的種別碼 syn進行判斷,對于不同的單詞種別做出不同 的反應, 如對于標識符則將其插入標識符表中。 對于保留字則輸出該保留字的種別碼 和助記符,等等吧。直至遇到 syn=0程序結束。二流程圖下面是程序的

15、流程圖:三運行與測試比如說,就拿這個源程序的一部分進行測試:運行程序后結果為: 同樣單詞也寫入了文件如下: 。綜上分析,達到了預期的結果。四實驗體會每做一次比較大的實驗, 都應該寫一下實驗體會, 來加深自己對知識的認識。其實這次的實驗,算法部分并不難,只要知道了 DFA這個模塊很好寫,比較麻煩的就是五種 類型的字符個數越多程序就越長。 但為了能識別大部分程序, 我還是用了比較大的子集, 結果花了一下午的功夫才寫完,雖然很累吧,但看著這個詞法分析器的處理能力,覺得 還是值得的。同時也加深了對字符的認識。程序的可讀性還算不錯。程序沒有實現的是對所有復合運算的分離,但原理是相同的,比如“+=“,只需

16、在” +“的邏輯之后向前掃描就行了, 因此就沒有再加上了。 感受最深的是學習編譯原理必須要做實驗, 寫程序, 這樣才會提高自己的動手能力,加深自己對難點的理解,對于以后的求 first,follow,fisrtVT,lastVT5 是應該如此。五源程序/ Lexical_Analysis.cpp : 定義控制臺應用程序的入口點。/#include "stdio.h"#include "stdlib.h"#include "string.h"#include "iostream"using namespace std

17、;/ 詞法分析程序/ 首先定義種別碼/*第一類:標識符letter(letter | digit)*無窮集第二類:常數(digit)+ 無窮集第三類:保留字 (32)autobreakcasecharconstcontinuedefaultdodoubleelseenumexternfloatforgotoifintlongregister returnshortsignedsizeofstaticstructswitchtypedefunionunsignedvoidvolatilewhile第四類:界符 /*'、 / '、() "II1第五類:運算符 <、&

18、lt;=、>、>=、=、+、-、*、/、八、對所有可數符號進行編碼:<$,0><auto,1><while,32><+,33><-,34><*,35></,36><<,37><<=,38><>,39><>=,40><=,41><=,42><!=,43><,44><(,45><),46><八,47><,48><",49&

19、gt;<',50><#,51><&,52><&&,53><|,54><|,55><%,56><,57><<<,58>左移<>>,59>右移<,60><,61><,62><,63><,64><.,65><?,66><:,67><!,68>"","","",&

20、quot;"<常數 99 ,數值 ><標識符 100 ,標識符指針 > */*/*/*查找保留字 */ 全局變量,保留字表static char reserveWord3220 = "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", &qu

21、ot;enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch",

22、 "typedef", "union", "unsigned", "void", "volatile", "while"/ 界符運算符表 ,根據需要可以自行增加 static char operatorOrDelimiter3610 = +", "-", "*", "/", "<", "<=", ">", ">=&

23、quot;, "=", "=","!=", ";", "(", ")", "A", ",", """, "'", "#", "&","&&", "|", "|", "%", "", "<<&quo

24、t;, ">>", "", "", "", "", "", ".", "?", ":", "!"static char IDentifierTbl100050 = "" ;/ 標識符表*int searchReserve(char reserveWord20, char s) for (int i = 0; i < 32; i+)if (strcmp(rese

25、rveWordi, s) = 0)/ 若成功查找,則返回種別碼return i + 1;/ 返回種別碼return -1;/ 否則返回 -1,代表查找不成功,即為標識符*查找保留字 *判斷是否為字母*bool IsLetter(char letter)/ 若為多行注釋“ /*0 0 0*/ ”則去除該內容/ 注意 C 語言允許下劃線也為標識符的一部分可以放在首部或其他地方if (letter >= 'a'&&letter <= 'z' | letter >= 'A'&&letter <= &

26、#39;Z'| letter='_') return true;elsereturn false;*判斷是否為字母*判斷是否為數字*bool IsDigit(char digit)if (digit >= '0'&&digit <= '9')return true;elsereturn false;*判斷是否為數字*編譯預處理,取出無用的字符和注釋*void filterResource(char r, int pProject)char tempString10000;int count = 0;for (i

27、nt i = 0; i <= pProject; i+) if (ri = '/'&&ri + 1 = '/')/ 若為單行注釋“ / ” ,則去除注釋后面的東西,直至遇到回車換行while (ri != 'n')i+;/ 向后掃描if (ri = '/'&&ri + 1 = '*')i += 2;while (ri != '*' | ri + 1 != '/')i+;/ 繼續(xù)掃描if (ri = '$')printf("

28、;注釋出錯,沒有找到*/,程序結束! ! n");exit(0);i += 2;/ 跨過“ */ ”if (ri != 'n'&&ri != 't'&&ri != 'v'&&ri != 'r')/ 若出現無用字符,則過濾;否則加載 tempStringcount+ = ri;tempStringcount = '0'strcpy(r, tempString);/產生凈化之后的源程序編譯預處理,取出無用的字符和注釋*/*分析子程序,算法核心 */void Sc

29、anner(int &syn, char resourceProject, char token, int &pProject) /根據DFA的狀態(tài)轉換圖設計int i, count = 0;/count用來做token的指示器,收集有用字符char ch;/作為判斷使用ch = resourceProjectpProject; while (ch = ' ')/ 過濾空格,防止程序因識別不了空格而結束pProject+;ch = resourceProjectpProject;for (i = 0; i<20; i+)/ 每次收集前先清零tokeni =

30、 '0'if (IsLetter(resourceProjectpProject)/ 開頭為字母tokencount+ = resourceProjectpProject;/收集pProject+;/ 下移while (IsLetter(resourceProjectpProject) | IsDigit(resourceProjectpProject)/ 后跟字母或數字tokencount+ = resourceProjectpProject;/|攵集pProject+; 下移/ 多讀了一個字符既是下次將要開始的指針位置tokencount = '0'syn

31、= searchReserve(reserveWord, token);/查表找至 U種別碼if (syn = -1)/ 若不是保留字則是標識符syn = 100;/標識符種別碼return;else if (IsDigit(resourceProjectpProject)/ 首字符為數字while (IsDigit(resourceProjectpProject)/ 后跟數字tokencount+ = resourceProjectpProject;/|攵集pProject+;/ 多讀了一個字符既是下次將要開始的指針位置tokencount = '0'syn = 99;/常數

32、種別碼else if (ch = '+' | ch = '-' | ch = '*' | ch = '/' | ch = '' | ch = '(' | ch = ')' | ch = 'A'| ch = ',' | ch = '"' | ch = ''' | ch = '' | ch = '#' | ch = '%' | ch = ''|

33、 ch = '' | ch = '' | ch = '' | ch = '' | ch = '.' | ch = '?' | ch = ':')/ 若為運算符或者界符,查表得到結果 token0 = resourceProjectpProject; token1 = '0'/ 形成單字符串 for (i = 0; i<36; i+) / 查運算符界符表if (strcmp(token, operatorOrDelimiteri) = 0)syn = 33 + i

34、;獲得種別碼,使用了一點技巧,使之呈線性映射break;/ 查到即推出pProject+;指針下移,為下一掃描做準備return;else if (resourceProjectpProject = '<')/<,<=,<<pProject+;后移,超前搜索if (resourceProjectpProject = '=')syn = 38;else if (resourceProjectpProject = '<')/ 左移pProject-; syn = 58;elsepProject-;syn = 37;

35、pProject+;指針下移 return;else if (resourceProjectpProject = '>') />,>=,>>pProject+;if (resourceProjectpProject = '=') syn = 40;else if (resourceProjectpProject = '>') syn = 59;else pProject-; syn = 39;pProject+; return;else if (resourceProjectpProject = '=&

36、#39;) /=.=pProject+;if (resourceProjectpProject = '=') syn = 42;else pProject-; syn = 41;pProject+; return;else if (resourceProjectpProject = '!') /!,!=pProject+;if (resourceProjectpProject = '=') syn = 43;else syn = 68; pProject-;pProject+;return;else if (resourceProjectpPro

37、ject = '&')/&,&&pProject+;if (resourceProjectpProject = '&')syn = 53;elsepProject-; syn = 52;pProject+;return;else if (resourceProjectpProject = '|')/|,|pProject+;if (resourceProjectpProject = '|')syn = 55;elsepProject-; syn = 54;pProject+;return;e

38、lse if (resourceProjectpProject = '$')/ 結束符syn = 0;/ 種別碼為 0 else/ 不能被以上詞法分析識別,則出錯printf("error: there is no exist %c n", ch); exit(0);int main()/ 打開一個文件,讀取其中的源程序char resourceProject10000;char token20 = 0 ;int syn = -1, i;/ 初始化int pProject = 0;/ 源程序指針FILE *fp, *fp1;if (fp = fopen(&q

39、uot;D:zyr_rc.txt", "r") = NULL)/ 打開源程序cout << "can't open this file" exit(0); resourceProjectpProject = fgetc(fp);while (resourceProjectpProject != '$')將源程序讀入 resourceProject數組 pProject+;resourceProjectpProject = fgetc(fp); resourceProject+pProject = '0'fclose(fp);cout << endl << "源程序為 :" <<

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論