时间: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)的设计思路的更多相关文章

  1. (原创)通用查询实现方案(可用于DDD)[附源码] -- 设计思路

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...

  2. RBAC角色权限设计思路

    1 设计思路 为了设计一套具有较强可扩展性的用户认证管理,需要建立用户.角色和权限等数据库表,并且建立之间的关系,具体实现如下. 1.1 用户 用户仅仅是纯粹的用户,用来记录用户相关信息,如用户名.密 ...

  3. FPGA Asynchronous FIFO设计思路

    FPGA Asynchronous FIFO设计思路 将一个多位宽,且在不停变化的数据从一个时钟域传递到另一个时钟域是比较困难的. 同步FIFO的指针比较好确定,当FIFO counter达到上限值时 ...

  4. selenium 关键字驱动部分设计思路

    1 说明: 1.以下的代码亲测直接可用, 2.设计思路来自博客园的 张飞_ :http://www.cnblogs.com/zhangfei/p/5330994.html   /   http://w ...

  5. Sizzle源码分析:一 设计思路

    一.前言 DOM选择器(Sizzle)是jQuery框架中非常重要的一部分,在H5还没有流行起来的时候,jQuery为我们提供了一个简洁,方便,高效的DOM操作模式,成为那个时代的经典.虽然现在Vue ...

  6. 通用查询实现方案(可用于DDD)[附源码] -- 设计思路

    原文:通用查询实现方案(可用于DDD)[附源码] -- 设计思路 [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3988592.html).   ...

  7. TYPESDK手游聚合SDK服务端设计思路与架构之一:应用场景分析

    TYPESDK 服务端设计思路与架构之一:应用场景分析 作为一个渠道SDK统一接入框架,TYPESDK从一开始,所面对的需求场景就是多款游戏,通过一个统一的SDK服务端,能够同时接入几十个甚至几百个各 ...

  8. 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路

    最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...

  9. ENode框架单台机器在处理Command时的设计思路

    设计目标 尽量快的处理命令和事件,保证吞吐量: 处理完一个命令后不需要等待命令产生的事件持久化完成就能处理下一个命令,从而保证领域内的业务逻辑处理不依赖于持久化IO,实现真正的in-memory: 保 ...

随机推荐

  1. 20.never give up

  2. Java之属性集(Properties类)

    Properties概述 java.util.Properties类 继承于 Hashtable ,来表示一个持久的属性集.它使用键值结构存储数据,每个键及其对应值都是一个字符串.该类也被许多Java ...

  3. 【docker构建】基于docker搭建redis数据库缓存服务

    搭建redis服务 首先拉取镜像==>运行镜像为容器 # 先搜索下redis镜像 [root@VM_0_10_centos wordpress]# docker search redis # 拉 ...

  4. JS如何判断鼠标滚轮向上还是向下滚动

    前几天偶然看到某前端群有人在问:JS如何判断鼠标滚轮向上还是向下滚动? 我想了想,有点蒙蔽,心想难道不是用scrollTop来判断吗? 但我不确定,也出于好奇心,于是开始了一番探索 思路:通过even ...

  5. tensorflow-- Dataset创建数据集对象

    tf.data模块包含: experimental 模块 Dataset 类  FixedLengthRecordDataset 类 TFRecordDataset 类 TextLineDataset ...

  6. Cypress 之 环境配置

    将项目添加到cypress时,cypress.json会在项目中创建一个文件,此文件用于存储projectId,以及你提供的任何配置项. { "projectId": " ...

  7. PHP实现支付宝登录

    1.支付宝路由拼接 public function dev() { $http = 'https://openauth.alipaydev.com/oauth2/publicAppAuthorize. ...

  8. iozone - a filesystem benchmark tool 主要是用来测试文件系统 性能

    简介:    磁盘设备之上是文件系统,测试磁盘的工具往往就是调用块设备驱动的接口进行读写测试.而文件系统的测试软件就是针对文件系统层提供的功能进行测试,包括文件的打开关闭速度以及顺序读写随机位置读写的 ...

  9. Python入门基础学习(模块,包)

    Python基础学习笔记(五) 模块的概念:模块是python程序架构的一个核心概念 每个以拓展名py结尾的python源代码文件都是一个模块 模块名同样也是一个标识符,需要符合标识符的命名规则 在模 ...

  10. Navicat Premium 破解方法

    最新Navicat Premium12 破解方法,亲测可用 1.下载Navicat Premium 官网https://www.navicat.com.cn/下载最新版本下载安装(文末,网盘地址有64 ...