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

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

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

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

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

4、chtypedef unionunsignedvoidvolatilewhile第四類:界符 /*'、/ '、 () " " ' 等第五類:運算符 <、<=、 >、 >=、 =、 +、-、*、/、八、等挽回的影響。因此,在進行詞法分析的時候一定對所有可數(shù)符號進行編碼:<$,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>"","","",""<常數(shù) 99 ,數(shù)值 ><標(biāo)識符 100 ,標(biāo)識符指針 >上述二元組中左邊是單詞的符號,右邊為其 種別碼 ,其中常數(shù)和標(biāo)識符有點特別,因為是無窮集合,因此常數(shù)用自身來表示,種別碼為99,標(biāo)識符用標(biāo)識符符號表的指針表示(當(dāng)然也可用自身顯示,比較容易觀察) ,種別碼 100。根據(jù)上述

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"/ 界符運算符表 ,根據(jù)需要可以自行增加static char operatorOrDelimiter3610= "+","-","*","/","<","<=",">",">=","=","=

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

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

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

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

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

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

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

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

18、lt;=、>、>=、=、+、-、*、/、八、對所有可數(shù)符號進行編碼:<$,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;"<常數(shù) 99 ,數(shù)值 ><標(biāo)識符 100 ,標(biāo)識符指針 > */*/*/*查找保留字 */ 全局變量,保留字表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"/ 界符運算符表 ,根據(jù)需要可以自行增加 static char operatorOrDelimiter3610 = +", "-", "*", "/", "<", "<=", ">", ">=&

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

24、t;, ">>", "", "", "", "", "", ".", "?", ":", "!"static char IDentifierTbl100050 = "" ;/ 標(biāo)識符表*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,代表查找不成功,即為標(biāo)識符*查找保留字 *判斷是否為字母*bool IsLetter(char letter)/ 若為多行注釋“ /*0 0 0*/ ”則去除該內(nèi)容/ 注意 C 語言允許下劃線也為標(biāo)識符的一部分可以放在首部或其他地方if (letter >= 'a'&&letter <= 'z' | letter >= 'A'&&letter <= &

26、#39;Z'| letter='_') return true;elsereturn false;*判斷是否為字母*判斷是否為數(shù)字*bool IsDigit(char digit)if (digit >= '0'&&digit <= '9')return true;elsereturn false;*判斷是否為數(shù)字*編譯預(yù)處理,取出無用的字符和注釋*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、;注釋出錯,沒有找到*/,程序結(jié)束! ! n");exit(0);i += 2;/ 跨過“ */ ”if (ri != 'n'&&ri != 't'&&ri != 'v'&&ri != 'r')/ 若出現(xiàn)無用字符,則過濾;否則加載 tempStringcount+ = ri;tempStringcount = '0'strcpy(r, tempString);/產(chǎn)生凈化之后的源程序編譯預(yù)處理,取出無用的字符和注釋*/*分析子程序,算法核心 */void Sc

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

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

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

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 = ':')/ 若為運算符或者界符,查表得到結(jié)果 token0 = resourceProjectpProject; token1 = '0'/ 形成單字符串 for (i = 0; i<36; i+) / 查運算符界符表if (strcmp(token, operatorOrDelimiteri) = 0)syn = 33 + i

34、;獲得種別碼,使用了一點技巧,使之呈線性映射break;/ 查到即推出pProject+;指針下移,為下一掃描做準(zhǔn)備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 = '$')/ 結(jié)束符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數(shù)組 pProject+;resourceProjectpProject = fgetc(fp); resourceProject+pProject = '0'fclose(fp);cout << endl << "源程序為 :" <<

溫馨提示

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

評論

0/150

提交評論