時間:2019/11/29數組
首先,詞法分析器由一個掃描器與狀態機組成。數據結構
一. 詞法分析器總體設計流程測試
2、設計細節
spa
1. code.txt:設計
咱們假設讀取下面文本3d
2.符號類型的設計code
咱們使用 enum 數據結構,其好處有兩點:
blog
1. 只能選取其成員中的一個。
ci
2. 能夠直接用符號的名字命名變量。 字符串
1 enum symbol { 2 KW_MAIN, KW_IF, KW_ELSE, KW_WHILE, KW_INT, KW_COUT, KW_CIN, KW_ENDL, KW_RETURN, // 關鍵字 3 LBRACE, RBRACE, LPAREN, RPAREN, SEMI, COMMA, // 界符 4 ASSIGN, ADD, MINUS, TIMES, DIVIDE, // 運算 5 EQ, NE, G, GE, B, BE, IN, OUT, // 判斷標誌位 6 STR, NUM, ID, // 字符串,數字,標識符 7 END // 文件結尾 8 };
3. 掃描器
掃描器會僅僅讀取一個字符,先將舊的字符保存,再將讀取的字符存儲在全局變量ch中,若是讀取成功,返回0,不然返回1.
1 int getCh() { 2 oldch = ch; 3 if (fscanf_s(fin, "%c", &ch) == EOF) { 4 return 0; 5 } 6 else { 7 return 1; 8 } 9 }
4.有限狀態機:
其經過當前所讀取的字符 ch 來判斷其種類。
1)數字:好比若是爲 '0',則表示數字,依次"讀取-計算-存儲"直到不是數字時再退出,將值保存在num中,sym賦值NUM,以後返回。
1 else if(ch>='0' && ch<='9') 2 { 3 int value = 0; 4 do { 5 value = value * 10 + ch -'0'; 6 f = getCh(); 7 } while (ch >= '0' && ch <= '9'); // 判斷條件必定要明確 8 9 sym = NUM; 10 num = value; 11 12 }
2) ‘=’ 與 ‘==’的區分:當遇到 = 時,超前讀取一個字符,來判斷。 若是是 == ,在繼續讀取一個字符(供以後判斷使用),不然不用讀取。
1 case '=': 2 f = getCh(); 3 if (ch == '=') { 4 sym = EQ; 5 // 再往前讀一行 6 f = getCh(); 7 } 8 else { 9 sym = ASSIGN; 10 } 11 break;
3) 變量名 與 關鍵字以前的區分:咱們設計了一個數組,當爲 變量名或關鍵字時進行判斷。
1 /* 2 關鍵字檢索器:將標識符與id區分開來,並打上標記 sym; 3 */ 4 const int arrLen = 9; 5 const char * keyWords[arrLen] = { "main","if","else","while","int","cout","cin","endl","return" }; 6 const enum symbol keySymbols[arrLen] = { KW_MAIN, KW_IF, KW_ELSE, KW_WHILE, KW_INT, KW_COUT, KW_CIN, KW_ENDL, KW_RETURN }; 7 8 void checkKeyWord() { 9 // 將id來遍歷 keyWords[] 數組,打上標籤 10 int flag = 0; // 標記是不是關鍵字 11 for (int i = 0; i < arrLen; i++) { 12 if (strcmp(id, keyWords[i]) == 0) { 13 sym = keySymbols[i]; // 完成賦值 14 flag = 1; 15 break; 16 } 17 } 18 if (flag == 0) 19 sym = ID; 20 }
3、驗證檢查的可靠性
1. 咱們先簡單地寫了一下測試代碼:
// // 測試詞法掃描器 // string filename = "C:\\Users\\97905\\source\\repos\\T編譯器\\Debug\\abc.txt"; int ErrorCode = fopen_s(&fin, filename.c_str(), "r"); if (0 == ErrorCode) { cout << "打開文件成功" << endl; } else { cout << "錯誤碼: " << ErrorCode << endl; return 0; } // 循環解析符號 getCh(); // 啓動時必須先讀取第一個字符 while (getSym()) { if (sym == STR) { // 輸出字符串 cout << "(string," << str << ")"<< endl; } else if (sym == NUM) { // 輸出數字 cout << "(NUM," << num << ")" << endl; } else if (sym == ID) { cout << "(ID," << id << ")" << endl; } else { cout <<"(關鍵字或字符," << symbolName[sym] <<")" << endl; } } if (sym == END) { cout << "文件讀取結束" << endl; } return 0;
2. 將上面那個代碼填入進去,最終的測試結果以下。
符合測試要求
4、下一步計劃
寫一個簡單的 "int i;" 與 "i = 3;"的 語法分析程序 與 語義分析程序。
"int i;" 時創建變量記錄表
"i = 3;" 時在變量表中查詢變量,而且賦值。
這個計劃用 MAP 數據結構來實現(畢竟查找比較方便)
預計更新日期:2019/11/30