文章目录
1. 实验目的
通过实验,掌握词法分析的算法,如NFA到DFA、状态的最小化和程序编写。
2. 实验内容
通过实验完成给定的C语言子集的单词符号划分和二元组输出。完成相应的报错功能。
3. 实验要求
(1)给出各单词符号的类别编码;
(2)词法分析程序应能发现输入串中的错误;
(3)词法分析作为单独一遍编写,词法分析结果为二元式序列组成的中间文件;
(4)设计两个测试用例(尽可能完备),并给出测试结果。
4. 程序实现
4.1. 相关环境介绍
操作系统:window 10 21H2
开发环境:Clion-2022.2.1-Windows
编译器:mwing-10.0
4.2. 主要数据结构
主要是识别出的单词,建立了一个struct
01:struct Keyword{
02: string notation;
03: int class_num;
04: int line;
05: Keyword(string str, int num, int line_){
06: notation = str;
07: class_num = num;
08: line = line_;
09: }
10: Keyword(char* str, int num, int line_){
11: notation = string(str);
12: class_num = num;
13: line = line_;
14: }
15: Keyword(char str, int num, int line_){
16: notation = str;
17: class_num = num;
18: line = line_;
19: }
20:};
其中notation为单词的值,class_num 为单词所属的类别,line是单词在源程序中的行号。
4.3. 程序结构描述
4.3.1. 设计方法
参照课程所讲述的过程,首先由每一类的单词构建NFA,然后是确定化,得到DFA,最后可以适当地进行状态的最小化,这样我们就可以得到,所有情况的状态转化图。由此可以进行代码的编写。
我们把所有的保留字,存在reserved_word.txt文件中,在主程序中进行文件读写,创建保留字的相关类型编号矩阵,这样做,程序不失一般性。Txt文件中只需要空格分割保留字即可,简单易懂。之后我们可以配合其他,给出相应的函数文件,方便单词的划分,给与了扩展空间。
实验的输入是一个文本文件,按行读入,这样做有利于保留行号信息,方便报错。遇到空格和制表符、换行符就跳过。
词法分析函数,主要是通过状态转化图,使用if-else,Switch-case进行控制转移。
4.3.2. 函数定义
int init()
实验初始化函数,主要是读取reserved_word.txt文件创建保留字表。
int lexical_analysis(string file_path)
词法分析函数,也是本实验的核心函数,传入参数,file_path为待分析的源程序路径。
函数中主要使用全局变量vector output ,每次完成单词的匹配,则
output.emplace_back(Keyword(word, class_num, line),即写入单词的值、类别、行号到输出vector。
int main()
主函数主要完成,基本的参数设定,包括输入输出文件路径、保留字路径和文件的读入写出等等。
5. 程序测试
Test1.txt:
21:#include <iostream>
22:
23:int main(){
24: int a = 1;
25: int b = 3;
26: int c = a+b;
27: int 2434acb343;
28: printf("%d", c);
29:}
这里可以看出,程序圆满的完成了要求,并且,给出了相应的报错,为变量定义错误。
测试样例2使用了本词法分析器程序本身,输出文件为out2.txt。
样例2本身代码语法是完全正确的,但是在词法分析程序中,我们加入了每行最多字符限制80,这也是比较老的C++标准,但是词法分析程序是按照C++14编写的,行字符上限是120,所以会有这样的报错信息。
这样看来实验结果完成正确。
6. 实验汇总
6.1. 技术难点及解决方案
实验本身编码没有太多的难度,主要是前期的DFA和状态转化图的绘制比较繁琐。状态转换图也就是一个程序流程图,可以帮助我们不遗漏部分单词。
6.2. 实验感想和经验总结
实验主要是按照课堂上所讲述的算法和流程进行编写,锻炼了编码能力,以及了解编译的全过程,对本人的学习十分有帮助。