1、實驗目的算法
經過設計編制調試一個具體的詞法分析程序,加深對詞法分析原理的理解,並掌握在對程序設計語言源程序進行掃描過程當中將其分解爲各種單詞的詞法分析方法。編制一個讀單詞過程,從輸入的源程序中,識別出各個具備獨立意義的單詞,即基本保留字、標識符、常數、運算符、分隔符五大類,並依次輸出各個單詞的內部編碼及單詞符號自身值。函數
2、實驗內容和要求測試
實驗內容:用C語言對源程序進行詞法分析。經過輸入源程序從左到右對字符串進行掃描和分解,依次輸出各個單詞的內部編碼及單詞符號自身值;若遇到錯誤則顯示「Error」,而後跳過錯誤部分繼續顯示;同時進行標識符登記符號表的管理。編碼
如下是實現詞法分析設計的主要工做:(1)從源程序文件中讀入字符(2)統計行數和列數用於錯誤單詞的定位。(3)刪除空格類字符,包括回車、製表符空格。(4)按拼寫單詞,並用(內碼,屬性)二元式表示。(屬性值——token的機內表示)(5)若是發現錯誤則報告出錯(6)根據須要是否填寫標識符表供之後各階段使用。spa
實驗要求:命令行
1.待分析的簡單的詞法設計
(1)保留字:if,else, for, while, do, int ,read, write,real,char 調試
(2)純單分界符:+ — * (){};:, code
(3)雙分界符:> < = ! ,&&,||blog
2.實現功能:
(1)在命令行中輸入源程序文件名(包括文件名路徑)
(2)輸入目標文件名(包括文件名路徑)
(3)調用所編詞法分析代碼將分析結果寫入目標文件代碼(編譯完成)
3、 實驗方法、步驟及結果測試
1. 源程序名:詞法分析.zip 中源程序名:詞法分析.c
可執行程序名:詞法分析.exe
2. 原理分析及流程圖
主要算法:算法的基本任務是從輸入的字符串表示的源程序中識別出具備獨立意義的單詞符號,其基本思想是根據掃描到單詞符號的第一個字符的種類,拼出相應的單詞符號。
存儲結構:順序存儲結構
關鍵函數的實現:經過掃描函數對輸入的字符串進行一一掃描
注:關鍵字做爲特殊標識符處理,把它們預先安排在一張表格中(稱爲關鍵字表),當掃描程序識別出標識符時,查關鍵字表。如能查到匹配的單詞,則該單詞爲關鍵字,不然爲通常標識符。
3. 流程圖:
4.主要程序段及其解釋:
void scaner()
{ /*共分爲三大塊,分別是標示符、數字、符號,對應下面的 if else if 和 else */ for(n=0;n<7;n++) TOken[n]=0;//每次循環完就清零 ch=A[i]; while(ch==' '||ch=='\n')//若是字符是空格或者回車,跳過 { i++; ch=A[i]; } if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) //多是標示符或者變量名 { m=0; while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))//找到一個變量名或者關鍵字,直到遇到空格爲止 { TOken[m]=ch;m++; i++;ch=A[i]; } TOken[m]='\0';//將識別出來的字符和已定義的標示符做比較, //由於定義的begin爲1,if爲2...... if(strcmp(TOken,r1)==0){syn=1;} else if(strcmp(TOken,r2)==0){syn=2; } else if(strcmp(TOken,r3)==0){syn=3;} else if(strcmp(TOken,r4)==0){syn=4;} else if(strcmp(TOken,r5)==0){syn=5;} else if(strcmp(TOken,r6)==0){syn=6;} else if(strcmp(TOken,r7)==0){syn=7;} else if(strcmp(r8,TOken)==0){syn=8;} else if(strcmp(r9,TOken)==0){syn=9;} else if(strcmp(r10,TOken)==0){syn=10;} else if(strcmp(r11,TOken)==0){syn=11;} else if(strcmp(r12,TOken)==0){syn=12;} else if(strcmp(r13,TOken)==0){syn=13;} else if(strcmp(r14,TOken)==0){syn=14;} else if(strcmp(r15,TOken)==0){syn=15;} else if(strcmp(r16,TOken)==0){syn=16;} else if(strcmp(r17,TOken)==0){syn=17;} else if(strcmp(r18,TOken)==0){syn=18;} else if(strcmp(r19,TOken)==0){syn=19;} else if(strcmp(r20,TOken)==0){syn=20;} else if(strcmp(r21,TOken)==0){syn=21;} else if(strcmp(r22,TOken)==0){syn=22;} else if(strcmp(r23,TOken)==0){syn=23;} else if(strcmp(r24,TOken)==0){syn=24;} else if(strcmp(r25,TOken)==0){syn=25;} else if(strcmp(r26,TOken)==0){syn=26;} else if(strcmp(r27,TOken)==0){syn=27;} else if(strcmp(r28,TOken)==0){syn=28;} else if(strcmp(r29,TOken)==0){syn=29;} else if(strcmp(r30,TOken)==0){syn=30;} else if(strcmp(r31,TOken)==0){syn=31;} else if(strcmp(r32,TOken)==0){syn=32;} else if(strcmp(r33,TOken)==0){syn=33;} else if(strcmp(r34,TOken)==0){syn=34;} else if(strcmp(r35,TOken)==0){syn=35;} else if(strcmp(r36,TOken)==0){syn=36;} else if(strcmp(r37,TOken)==0){syn=37;} else if(strcmp(r38,TOken)==0){syn=38;} else{syn=100;} //變量名 } else if((ch>='0'&&ch<='9')) //數字 { sum=0; while((ch>='0'&&ch<='9')) { sum=sum*10+ch-'0';//顯示其數字sum i++; ch=A[i]; } syn=40; } else switch(ch) //其餘字符 { case'<':m=0;TOken[m]=ch;m++; i++;ch=A[i]; if(ch=='=')//<>爲22 { syn=41; TOken[m]=ch;m++;i++; } else { syn=46; } break; case'>':m=0;TOken[m]=ch;m++; i++;ch=A[i]; if(ch=='=') { syn=42; TOken[m]=ch;m++;i++; } else { syn=47; } break; case':':m=0;TOken[m]=ch;m++; i++;ch=A[i]; if(ch=='=') { syn=44; TOken[m]=ch;m++;i++; } else { syn=49; } break; case'@':syn=0; TOken[0]=ch; i++; break; case'=':syn=48; TOken[0]=ch; i++; break; case'#':syn=50; TOken[0]=ch; i++; break; case'+':syn=50; TOken[0]=ch; i++; break; case'-':syn=51; TOken[0]=ch; i++; break; case'*':syn=52; TOken[0]=ch; i++; break; case'/':syn=53; TOken[0]=ch; i++; break; case'(':syn=54; TOken[0]=ch; i++; break; case')':syn=55; TOken[0]=ch; i++; break; case'{':syn=56; TOken[0]=ch; i++; break; case'}':syn=57; TOken[0]=ch; i++; break; case';':syn=58; TOken[0]=ch; i++; break; case'.':syn=59; TOken[0]=ch; i++; break; case'\'':syn=60; TOken[0]=ch; i++; break; case'\n': syn=-2; break; default: syn=-1; break; } }
5. 運行結果及分析