【編譯系統01】編譯器 - 詞法分析器(lexial)的設計思路

時間: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

相關文章
相關標籤/搜索