编译原理【实验1——扫描器的设计与实现】
目錄
一、實驗?zāi)康?/p>
二、實驗內(nèi)容
三、實驗過程與結(jié)果
實驗代碼
data.txt文件
代碼運行截圖
四、總結(jié)與體會
一、實驗?zāi)康?/span>
通過設(shè)計、編制并調(diào)試一個具體的詞法分析程序,加深對詞法分析原理的理解。掌握在對程序設(shè)計語言源程序進(jìn)行掃描過程中,將其分解為各類單詞的詞法分析方法。
理解詞法分析在編譯程序中的作用;加深對有窮自動機(jī)模型的理解;掌握詞法分析程序的實現(xiàn)方法和技術(shù)。
二、實驗內(nèi)容
自定義一種程序設(shè)計語言,或者選擇已有的一種高級語言,編制它的詞法分析程序。詞法分析程序的實現(xiàn)可以采用任何一種編程語言和編程工具。
設(shè)計詞法分析程序,從輸入的源程序中,識別出各個具有獨立意義的單詞,即關(guān)鍵字、標(biāo)識符、常數(shù)、運算符、界符,并依次輸出各個單詞的內(nèi)部編碼及單詞符號自身值(遇到錯誤時可顯示“Error”,然后跳過錯誤部分繼續(xù)顯示)。
(軟件、硬件)環(huán)境:
軟件環(huán)境:Visual Studio Code、CodeBlocks 17.12 編寫、調(diào)試并執(zhí)行實驗代碼
硬件環(huán)境:“Windows 10教育版”計算機(jī)
三、實驗過程與結(jié)果
修改課本P212表C.1,將其擴(kuò)充為C語言的保留字表,如下所示:
char *rwtab[] = {"int", "long", "short", "float", "double", "char", "unsigned", "signed", "const", "void", "volatile", "enum", "struct", "union","if", "else", "goto", "switch", "case", "do", "while", "for", "continue", "break", "return", "default", "typedef","auto", "register", "extern", "static", "sizeof", "begin", "then", "end", "cout", "main", _KEY_WORD_END};
實驗代碼
參考P212附錄C,編寫源程序,實驗代碼如下所示:
/*需要的庫和全局變量、函數(shù)及主程序*/ #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #define _KEY_WORD_END "waiting for your expanding"using namespace std;typedef struct //詞的結(jié)構(gòu),二元組形式(單詞種別,單詞自身的值) {int typenum; //單詞種別char *word; } WORD; char input[255]; char token[255] = ""; int p_input; //指針 int p_token; char ch; char *rwtab[] = {"int", "long", "short", "float", "double", "char", "unsigned", "signed", "const", "void", "volatile", "enum", "struct", "union","if", "else", "goto", "switch", "case", "do", "while", "for", "continue", "break", "return", "default", "typedef","auto", "register", "extern", "static", "sizeof", "begin", "then", "end", "cout", "main", _KEY_WORD_END}; WORD *scanner(); //掃描 int main() {int over = 1;WORD *oneword = new WORD;//實現(xiàn)從文件讀取代碼段cout << "read something from data.txt" << endl;FILE *fp;if ((fp = freopen("data.txt", "r", stdin)) == NULL){printf("Not found file!\n");return 0;}else{while ((scanf("%[^#]s", &input)) != EOF){p_input = 0;printf("your words:\n%s\n", input);while (over < 1000 && over != -1){oneword = scanner();if (oneword->typenum < 1000){if (oneword->typenum != 999)cout << "[ " << oneword->typenum << "\t" << oneword->word << " ]" << endl;}over = oneword->typenum;}scanf("%[^#]s", input);}}return 0; } //從輸入緩沖區(qū)讀取一個字符到ch中 char m_getch() {ch = input[p_input];p_input++; // p_input = p_input + 1;return (ch); } //去掉空白符號 void getbc() {while (ch == ' ' || ch == 10){ch = input[p_input];p_input++; // p_input = p_input + 1;} } //拼接單詞 void concat() {token[p_token] = ch;p_token++; // p_token = p_token + 1;token[p_token] = '\0'; } //判斷是否字母 int letter() {if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')return 1;elsereturn 0; } //判斷是否數(shù)字 int digit() {if (ch >= '0' && ch <= '9')return 1;elsereturn 0; }//檢索關(guān)鍵字表格 int reserve() {int i = 0;while (strcmp(rwtab[i], _KEY_WORD_END)){if (!strcmp(rwtab[i], token))return i + 1;i++;}return 10; // 如果不是關(guān)鍵字,則返回種別碼10 } //回退一個字符 void retract() {p_input--; // p_input = p_input - 1; }//詞法掃描程序 WORD *scanner() {WORD *myword = new WORD;myword->typenum = 10; // 初始值myword->word = "";p_token = 0; //單詞緩沖區(qū)指針m_getch();getbc(); //去掉空白if (letter()) //判斷讀取到的首字母是字母{//如intwhile (letter() || digit()){concat(); //連接m_getch();}retract(); //回退一個字符myword->typenum = reserve(); //判斷是否為關(guān)鍵字,返回種別碼myword->word = token;return (myword);}else if (digit()) //判斷讀取到的單詞首字符是數(shù)字{while (digit()) //所有數(shù)字連接起來{concat();m_getch();}retract();//數(shù)字單詞種別碼統(tǒng)一為20,單詞自身的值為數(shù)字本身myword->typenum = 20;myword->word = token;return (myword);}elseswitch (ch){case '=':m_getch(); //首字符為=,再讀取下一個字符判斷if (ch == '='){myword->typenum = 39;myword->word = "==";return (myword);}retract(); //讀取到的下個字符不是=,則要回退,直接輸出=myword->typenum = 21;myword->word = "=";return (myword);break;case '+':myword->typenum = 22;myword->word = "+";return (myword);break;case '-':myword->typenum = 23;myword->word = "-";return (myword);break;case '/': //讀取到該符號之后,要判斷下一個字符是什么符號,判斷是否為注釋m_getch(); //首字符為/,再讀取下一個字符判斷if (ch == '*') // 說明讀取到的是注釋{m_getch();while (ch != '*'){m_getch(); //注釋沒結(jié)束之前一直讀取注釋,但不輸出if (ch == '*'){m_getch();if (ch == '/') //注釋結(jié)束{myword->typenum = 999;myword->word = "注釋";return (myword);break;}}}}else{retract(); //讀取到的下個字符不是*,即不是注釋,則要回退,直接輸出/myword->typenum = 25;myword->word = "/";return (myword);break;}case '*':myword->typenum = 24;myword->word = "*";return (myword);break;case '(':myword->typenum = 26;myword->word = "(";return (myword);break;case ')':myword->typenum = 27;myword->word = ")";return (myword);break;case '[':myword->typenum = 28;myword->word = "[";return (myword);break;case ']':myword->typenum = 29;myword->word = "]";return (myword);break;case '{':myword->typenum = 30;myword->word = "{";return (myword);break;case '}':myword->typenum = 31;myword->word = "}";return (myword);break;case ',':myword->typenum = 32;myword->word = ",";return (myword);break;case ':':m_getch();if (ch == '='){myword->typenum = 18;myword->word = ":=";return (myword);break;}else{retract();myword->typenum = 33;myword->word = ":";return (myword);break;}case ';':myword->typenum = 34;myword->word = ";";return (myword);break;case '>':m_getch();if (ch == '='){myword->typenum = 37;myword->word = ">=";return (myword);break;}retract();myword->typenum = 35;myword->word = ">";return (myword);break;case '<':m_getch();if (ch == '='){myword->typenum = 38;myword->word = "<=";return (myword);break;}else if (ch == '<'){myword->typenum = 42;myword->word = "<<";return (myword);break;}else{retract();myword->typenum = 36;myword->word = "<";return (myword);}case '!':m_getch();if (ch == '='){myword->typenum = 40;myword->word = "!=";return (myword);break;}retract();myword->typenum = -1;myword->word = "ERROR";return (myword);break;case ' " ':myword->typenum = 41;myword->word = " \" ";return (myword);break;case '\0':myword->typenum = 1000;myword->word = "OVER";return (myword);break;case '#':myword->typenum = 0;myword->word = "#";return (myword);break;default:myword->typenum = -1;myword->word = "ERROR";return (myword);break;} }data.txt文件
int main() {int a = 1, b = 2;b / a;/*測試注釋和除號*/b > a;cout << "lwx!!!" << endl;return 0; }data.txt 文件截圖:
?
代碼運行截圖
詞法分析器,實驗運行截圖:
四、總結(jié)與體會
此次實驗,參照課本編寫了掃描器的設(shè)計,并將其實現(xiàn)。實驗過程中,遇到了諸多困難,但都一一解決,加深了我對課本概念的理解,收獲甚多。
使用文件操作的方式,從data.txt文件中讀入要分析的程序,C語言中的文件操作并不難以實現(xiàn),使用文件操作可以提升用戶的體驗感。編程時,將各個基本功能用函數(shù)來實現(xiàn),使得程序的條理性增強(qiáng)了;全局變量的使用也使得數(shù)據(jù)在函數(shù)間的傳遞更加方便。
本次實驗結(jié)合書本上的理論知識,我進(jìn)一步了解詞法分析程序構(gòu)造的一些細(xì)節(jié)。在實驗中,發(fā)現(xiàn)了自身的許多不足,課下我會多加努力。
總結(jié)
以上是生活随笔為你收集整理的编译原理【实验1——扫描器的设计与实现】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统 第二章【记录型信号量机制、独木
- 下一篇: 数学建模必备算法之模拟退火算法