最近重新学习了Java,虽然才看到核心卷的继承篇,但是感觉Java的封装与复用十分便利,于是准备改用Java进行编译原理实验的开发。
实验要求:
实验三:词法分析器2—自动机方法
实验目的:
通过编写一个扫描器(词法分析器),掌握词法分析器的构造方法之一: 自动机方法(模拟DFA法)。
实验要求:
1、本词法分析器的任务:
(1)进行C语言子集LC程序的词法分析,C语言的子集LC={C语言常用的关键字10-15个 }∪{常数}∪{变量,即标识符}∪{关系运算符}∪{其它运算符}∪{界符}。输入为任意的C语言程序源文件,经过分析后产生一个.txt中间文件,供后续语法分析使用,该分析器设定6种数据类型,分别为关键字、标识符、常数、关系运算符、其它运算符和界符,每种类型包含的关键字个数和符号自行定义,C语言常用的关键字和符号都要包含在内,(注:若按其它方式进行类型划分请在实验报告中注明类型划分方案)。
(2)其中关系运算符、标识符和常数的识别用模拟DFA算法,其它符号自行选择方法。常数限定构词规则为如下格式:数字.数字,标识符限定构词规则为:字符后接字符或数字,关系运算符按课堂讲述的构词规则构成。
(3)输出以源程序代码的一行为输出的一行进行输出。输出结果可以与实验2相同。也可以按不同的分类方式输出。
(4)给出标识符符号表内容,对出现的标识符分别标记为id0, id1,id2……。
(5)给出至少2种错误提示:如非法word(err1)、小数点后无数字(err2)、注释符号不配对(err3)、其它你认为目前编译器应该给出的词法错误提示,参考教材P16。
2、实验报告要求:
(1)进行词法分析器的测试:测试例程(一段C语言源程序)、测试结果与测试结果分析。
(2)实验报告中要给出正规式设计、NFA、DFA、DFA最小化、状态转换矩阵(以上各项写在实验原理中)、代码编写、测试例子4个(如下例给出的2个例子)、测试结果与测试结果分析逐项给予说明。
第一段:
(1)/*测试用例
(2)for (i=1;i<=100;i++)
(3){ printf("%d ", i );
(4)}
over
运行词法分析程序后,得到显示结果如下的.txt文件:
(1) (/*,30)(?err1)
(2) (for,16) ((,err) (i,id0) (=,31) (1,41) (;,22) (i , id0) (<=,err) (100,42) (;,22) (i , id 0) (++,37) (),err)
(3) ({,err) (Printf, id1) ((,err) (" ,21) (%,36) (d, id2) (" ,21) (,,err) (i, id 0) ( ),err) ( ;,22)
(4)( },err)
over
变量表(标识符表)中的内容为:
id 0,i:
id1,printf,
id 2,d
一、文件的读写
首先进行对txt文本的读写:
import java.io.*;
import java.util.ArrayList;
public class IoTxt {
static ArrayList<String> inTxt(String s) {
ArrayList<String> al=new ArrayList<String>();
String pathname = s; // 绝对路径或相对路径都可以,写入文件时演示相对路径,读取以上路径的input.txt文件
try (FileReader reader = new FileReader(pathname);
BufferedReader br = new BufferedReader(reader) // 建立一个对象,它把文件内容转成计算机能读懂的语言
)
{
String line;
while ((line = br.readLine()) != null) {
// 一次读入一行数据
al.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return al;
}
static void outTxt(String s) {
try {
File writeName = new File("D:\\output.txt"); // 绝对路径,如果没有则要建立一个新的output.txt文件
writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
try (FileWriter writer = new FileWriter(writeName);
BufferedWriter out = new BufferedWriter(writer)
) {
out.write(s);
out.flush(); // 把缓存区内容压入文件
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//测试函数
public static void main(String[] args) {
// TODO Auto-generated method stub
IoTxt.outTxt("HelloWorld!");
ArrayList<String> al=IoTxt.inTxt("D:\\output.txt");
for(String s:al) {
System.out.println(s);
}
}
}
以上是1.0版本,在IoTxt类中写了两个静态方法inTxt和outTxt,一个用来将输入地址参数的txt文本逐行转换成String类型置入一个ArrayList中并返回,一个将输入的String参数写入D:\\output.txt中。
1.0版本有一个存在问题:output文本中每次都是用一个String重写文本,而实验需求将每行的分析结果(String)写入,即多个String。
2.0版本的outTxt方法以及测试方法:
static void outTxt(ArrayList<String> al) {
try {
File writeName = new File("D:\\output.txt"); // 绝对路径,如果没有则要建立一个新的output.txt文件
writeName.createNewFile(); // 创建新文件,有同名的文件的话直接覆盖
try (FileWriter writer = new FileWriter(writeName);
BufferedWriter out = new BufferedWriter(writer)
) {
for(String s:al) {
out.write(s+"\r\n"); // \r\n即为换行
}
out.flush(); // 把缓存区内容压入文件
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//测试函数
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> al=new ArrayList<String>();
al.add("Hello");
al.add("World!");
IoTxt.outTxt(al);
al=IoTxt.inTxt("D:\\output.txt");
for(String s:al) {
System.out.println(s);
}
}
实现功能需求。
参考链接:Java读取txt文件和写入txt文件
https://blog.csdn.net/nickwong_/article/details/51502969
二、DFA类的设计
功能需求:将文本读到的ArrayList里面保存的每行数据进行词法分析。
未完待续