【编译系统01】编译器 - 词法分析器(lexial)的设计思路
2024-10-18 07:19:56
时间:2019/11/29
首先,词法分析器由一个扫描器与状态机组成。
一. 词法分析器整体设计流程
二、设计细节
1. code.txt:
我们假设读取下面文本
2.符号类型的设计
我们使用 enum 数据结构,其好处有两点:
1. 只能选取其成员中的一个。
2. 可以直接用符号的名字命名变量。
enum symbol {
KW_MAIN, KW_IF, KW_ELSE, KW_WHILE, KW_INT, KW_COUT, KW_CIN, KW_ENDL, KW_RETURN, // 关键字
LBRACE, RBRACE, LPAREN, RPAREN, SEMI, COMMA, // 界符
ASSIGN, ADD, MINUS, TIMES, DIVIDE, // 运算
EQ, NE, G, GE, B, BE, IN, OUT, // 判断标志位
STR, NUM, ID, // 字符串,数字,标识符
END // 文件结尾
};
3. 扫描器
扫描器会仅仅读取一个字符,先将旧的字符保存,再将读取的字符存储在全局变量ch中,如果读取成功,返回0,否则返回1.
int getCh() {
oldch = ch;
if (fscanf_s(fin, "%c", &ch) == EOF) {
return ;
}
else {
return ;
}
}
4.有限状态机:
其通过当前所读取的字符 ch 来判断其种类。
1)数字:比如如果为 '0',则表示数字,依次"读取-计算-存储"直到不是数字时再退出,将值保存在num中,sym赋值NUM,之后返回。
else if(ch>='' && ch<='')
{
int value = ;
do {
value = value * + ch -'';
f = getCh();
} while (ch >= '' && ch <= ''); // 判断条件一定要明确 sym = NUM;
num = value; }
2) ‘=’ 与 ‘==’的区分:当遇到 = 时,超前读取一个字符,来判断。 如果是 == ,在继续读取一个字符(供之后判断使用),否则不用读取。
case '=':
f = getCh();
if (ch == '=') {
sym = EQ;
// 再往前读一行
f = getCh();
}
else {
sym = ASSIGN;
}
break;
3) 变量名 与 关键字之前的区分:我们设计了一个数组,当为 变量名或关键字时进行判断。
/*
关键字检索器:将标识符与id区分开来,并打上标记 sym;
*/
const int arrLen = ;
const char * keyWords[arrLen] = { "main","if","else","while","int","cout","cin","endl","return" };
const enum symbol keySymbols[arrLen] = { KW_MAIN, KW_IF, KW_ELSE, KW_WHILE, KW_INT, KW_COUT, KW_CIN, KW_ENDL, KW_RETURN }; void checkKeyWord() {
// 将id来遍历 keyWords[] 数组,打上标签
int flag = ; // 标记是否是关键字
for (int i = ; i < arrLen; i++) {
if (strcmp(id, keyWords[i]) == ) {
sym = keySymbols[i]; // 完成赋值
flag = ;
break;
}
}
if (flag == )
sym = ID;
}
三、验证检查的可靠性
1. 我们先简单地写了一下测试代码:
//
// 测试词法扫描器
// string filename = "C:\\Users\\97905\\source\\repos\\T编译器\\Debug\\abc.txt";
int ErrorCode = fopen_s(&fin, filename.c_str(), "r");
if ( == ErrorCode) {
cout << "打开文件成功" << endl;
}
else {
cout << "错误码: " << ErrorCode << endl;
return ;
}
// 循环解析符号
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 ;
2. 将上面那个代码填入进去,最终的测试结果如下。
符合测试要求
四、下一步计划
写一个简单的 "int i;" 与 "i = 3;"的 语法分析程序 与 语义分析程序。
"int i;" 时建立变量记录表
"i = 3;" 时在变量表中查询变量,并且赋值。
这个计划用 MAP 数据结构来实现(毕竟查找比较方便)
预计更新日期:2019/11/30
最新文章
- java web学习总结(二十一) -------------------模拟Servlet3.0使用注解的方式配置Servlet
- VS使用的一些备忘东西
- SDcard
- Cube Stacking
- Sketchup+ArcGIS三维建模与管理
- jquery的监听事件和触发事件
- C#之你懂得的序列化/反序列化
- shell切换用户执行后面语句 su与su -的区别
- 总结:常用的Linux系统监控命令
- Java中4种权限的理解
- 2014.3.5-C语言学习小结
- invalid types &#39;int[int]&#39; for array subscript// EOF 输入多组数据//如何键盘输入EOF
- 20.DOM
- 深入分析synchronized的实现原理
- Python练习:九九乘法表
- WGAN讲解
- oracle权限列表
- centos-0 基础
- falsk sqlalchemy 自关联创建评论回复数据库
- 搭建持续集成接口测试平台(jenkins+ant+jmeter)