【编译系统01】编译器 - 词法分析器(lexial)的设计思路
时间: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
【编译系统01】编译器 - 词法分析器(lexial)的设计思路的更多相关文章
- (原创)通用查询实现方案(可用于DDD)[附源码] -- 设计思路
[声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html). [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...
- RBAC角色权限设计思路
1 设计思路 为了设计一套具有较强可扩展性的用户认证管理,需要建立用户.角色和权限等数据库表,并且建立之间的关系,具体实现如下. 1.1 用户 用户仅仅是纯粹的用户,用来记录用户相关信息,如用户名.密 ...
- FPGA Asynchronous FIFO设计思路
FPGA Asynchronous FIFO设计思路 将一个多位宽,且在不停变化的数据从一个时钟域传递到另一个时钟域是比较困难的. 同步FIFO的指针比较好确定,当FIFO counter达到上限值时 ...
- selenium 关键字驱动部分设计思路
1 说明: 1.以下的代码亲测直接可用, 2.设计思路来自博客园的 张飞_ :http://www.cnblogs.com/zhangfei/p/5330994.html / http://w ...
- Sizzle源码分析:一 设计思路
一.前言 DOM选择器(Sizzle)是jQuery框架中非常重要的一部分,在H5还没有流行起来的时候,jQuery为我们提供了一个简洁,方便,高效的DOM操作模式,成为那个时代的经典.虽然现在Vue ...
- 通用查询实现方案(可用于DDD)[附源码] -- 设计思路
原文:通用查询实现方案(可用于DDD)[附源码] -- 设计思路 [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html). ...
- TYPESDK手游聚合SDK服务端设计思路与架构之一:应用场景分析
TYPESDK 服务端设计思路与架构之一:应用场景分析 作为一个渠道SDK统一接入框架,TYPESDK从一开始,所面对的需求场景就是多款游戏,通过一个统一的SDK服务端,能够同时接入几十个甚至几百个各 ...
- 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路
最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...
- ENode框架单台机器在处理Command时的设计思路
设计目标 尽量快的处理命令和事件,保证吞吐量: 处理完一个命令后不需要等待命令产生的事件持久化完成就能处理下一个命令,从而保证领域内的业务逻辑处理不依赖于持久化IO,实现真正的in-memory: 保 ...
随机推荐
- 为什么有的插件安装需要用Vue.use()方法
问题 相信很多人在用Vue使用别人的组件时,会用到 Vue.use() .例如:Vue.use(VueRouter).Vue.use(MintUI).但是用 axios时,就不需要用 Vue.use( ...
- Python实现图片的base64编码
import base64 if __name__ == "__main__": dir='image.jpg' basef=open(dir.split('.')[0]+'_ba ...
- GO-结构体(类似python中的类)
一.结构体有名属性 package main import "fmt" func main(){ type Sb struct { name string //属性名,数据类型 a ...
- PHP简单判断当前使用的是什么浏览器
PHP简单判断当前使用的是什么浏览器,判断浏览器类型的方法,方便统计网站访问用户使用浏览器的比例. 判断浏览器类型方法 function userBrowser() { $user_OSagent = ...
- 清新淡雅教育教学工作课件PPT模板
模板来源:http://ppt.dede58.com/jiaoxuekejian/26240.html
- Unitest自动化测试基于HTMLTestRunner报告案例
报告效果如下: HTMLTestRunner脚本代码如下: #coding=utf-8 # URL: http://tungwaiyip.info/software/HTMLTestRunner.ht ...
- 百度地图API----搜索地址,获取该点的位置坐标并转换成WebMercator
function doFind(){ LoadBaiduMapScript().then(BaiduMap).then(function () { //查询并获取坐标 var myGeo = new ...
- OpenCV:图像的颜色空间转换
导包: import numpy as np import cv2 import matplotlib.pyplot as plt def show(image): plt.imshow(image) ...
- 服务器返回的数据将Unicode码转成汉字
当我们请求接口的时候,服务器会返回一些数据,当我们打印的时候就会发现,打印出来的是unicode码,不是汉字. 这时候需要我们自己手动处理一下,让打印的时候输出汉字的格式. 方法如下: 新增一个分类, ...
- mysql主从配置实现一主一从读写分离
主从介绍Mysql主从又叫Replication.AB复制.简单讲就是A与B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,实现数据实时同步mysql主从是基于binlog,主上需开启bin ...