时间: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

最新文章

  1. java web学习总结(二十一) -------------------模拟Servlet3.0使用注解的方式配置Servlet
  2. VS使用的一些备忘东西
  3. SDcard
  4. Cube Stacking
  5. Sketchup+ArcGIS三维建模与管理
  6. jquery的监听事件和触发事件
  7. C#之你懂得的序列化/反序列化
  8. shell切换用户执行后面语句 su与su -的区别
  9. 总结:常用的Linux系统监控命令
  10. Java中4种权限的理解
  11. 2014.3.5-C语言学习小结
  12. invalid types &#39;int[int]&#39; for array subscript// EOF 输入多组数据//如何键盘输入EOF
  13. 20.DOM
  14. 深入分析synchronized的实现原理
  15. Python练习:九九乘法表
  16. WGAN讲解
  17. oracle权限列表
  18. centos-0 基础
  19. falsk sqlalchemy 自关联创建评论回复数据库
  20. 搭建持续集成接口测试平台(jenkins+ant+jmeter)

热门文章

  1. 在浏览器地址栏输入www.baidu.com到打开百度首页这期间到底发生了什么?
  2. P3747 [六省联考2017]相逢是问候
  3. JavPlayer:AI破坏马赛克,大量马赛克破坏版影片流出
  4. 上手Neo4j
  5. Cypress 之 环境配置
  6. idea中tomcat乱码
  7. Python:有参装饰器与多个装饰器装饰一个函数
  8. ios中友盟集成好使用总结
  9. OC深浅复制
  10. MySQL基础之数据管理【5】