实验要求
要求:阐述词法分析系统所要完成的功能
词法分析程序的主要任务是将源程序根据单词进行切分,输出相应的token序列。具体地,本程序完成的功能如下:
基本功能:
能够识别以下内容:
1.标识符:(由大小写字母、数字以及下划线组成,但必须以字母或者下划 线开头)
2.关键字:(
①类型关键字:整型、浮点型、布尔型、记录型;
②分支结构 中的if和else;
③循环结构中的do和while;
④过程声明和调用中的关键字)
3.运算符:(①算术运算符;②关系运算符;③逻辑运算)
4.界符:(
①用于赋值语句的界符,如“=”;
②用于句子结尾的界符,如“;”;
③用于数组表示的界符,如“[”和“]”;
④用于浮点数表示的界符“.”)
5.常数:(无符号整数(含八进制和十六进制数)、浮点数(含科学计数法)、 字符串常等)
6.字符:(包括转义字符),字符串
7.注释:
识别两种风格的注释:一种是使用双斜线“∥”进行单行注释, 在这种情况下,该行在“//”符号之后的所有字符都将作为注释内容而直 接被词法分析程序丢弃掉;另一种是使用“/”以及“/”进行多行注释, 在这种情况下,在“/”与之后最先遇到的“/”之间的所有字符都被视 作注释内容而直接被词法分析程序丢弃掉。
额外功能:
1.具有一定的错误处理能力
2.从文件读取内容,并将分析结果保存到excel文件中
过程分析
程序流程图:
识别十进制整数,浮点数,八进制,已经十六进制的状态转换图:
识别字符的状态转换图:
识别注释的状态转换图:
识别字符串的状态状态转换图
总体结构:
扫描器的核心代码:
//扫描分析核心代码
public static void analyze(){
String[] texts = text.toString().split("\n");
boolean hasNote = false;//判断是否存在多行注释
for(int m = 0; m < texts.length; m++) {
String str = texts[m];//每行
if (str.equals(" ") ||str.equals("") )//跳过空行
continue;
char[] strline = str.toCharArray(); //将字符串转化为字符串数组
int index =0;
if(hasNote){
//如果有多行注释 找到多行注释的结尾
for (; index < strline.length; index++) {
if(strline[index] == '*'){
if(index<strline.length-1 && strline[index] == '/'){
//找到
index +=2;//跳过两个
hasNote =false;
break;
}
}
}
}
else {
//开始分析
for(int i = index; i < strline.length; i++){
//每个字符
//遍历strline中的每个字符
char ch = strline[i];
//初始化token字符串为空
StringBuilder token = new StringBuilder();
//判断标识和关键字 //以字母开头
if (isAlpha(ch)){
// 判断关键字和标识符
do {
token.append(ch);
i++;
if(i >= strline.length) break;
ch = strline[i];
} while (ch != '\0' && (isAlpha(ch) || isDigit(ch)));//连续的字母,下划线和数字
--i; //由于指针加1,指针回退
//是关键字
if (isMatchKeyword(token.toString()))//是关键字
{
ansList.add(new Patten(m+1,keyWorldMap.get(token.toString()),token.toString(),"关键字") );
}
else{
//是标识符
ansList.add(new Patten(m+1,7,token.toString(),"标识符") );
}
}
//判断数字常量 包括 8进制 和16进制
else if(isDigit(ch)){
int state = 0;
//boolean isfloat = false;
if(ch == '0'){
//以0开头
state=7;
i++;
if (i >= strline.length) {
ansList.add(new Patten(m+1,1,"0","整型常量") );
break;
}
token.append(ch);
ch = strline[i];
while ( (ch !=' ')&&(ch != '\0') && !isSingleOp(ch) && !symbolMap.containsKey(String.valueOf(ch)) && state !=11){
switch (state){
case 7: