【编译系统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

相关文章
相关标签/搜索