西安邮电大学
(计算机学院)
课内实验报告
实验名称:词法分析器的实现
专业名称:软件工程
班级:
学生姓名:
学号(8位):
指导教师:王曙燕
实验日期:2015年4月10日
一. 实验目的
1.深入理解有限自动机及其应用
2.掌握根据语言的词法规则构造识别其单词的有限自动机的方法
3.基本掌握词法分析程序的开发。
二. 实验内容
1、词法分析器的功能和输出格式
词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示
成以下的二元式(单词种别码,单词符号的属性值)。本实验中,采用的是一类符号
一种别码的方式。
2、单词的BNF表示
<标识符>-> <字母><字母数字串>
<字母数字串>-><字母><字母数字串>|<数字><字母数字串>|
<下划线><字母数字串>|ε
<无符号整数>-> <数字><数字串>
<数字串>-> <数字><数字串> |ε
<加法运算符>-> +
<减法运算符>-> -
<大于关系运算符>-> >
<大于等于关系运算符>-> >=
3、“超前搜索”方法
词法分析时,常常会用到超前搜索方法。如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器倒底是将其分析为大于关系运算符还是大于等于关系运算符呢?
显然,只有知道下一个字符是什么才能下结论。于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。在分析标识符,无符号整数等时也有类似情况。
4、
三.方案设计
1、词法形式化描述
使用正则文法进行描述,则可以得到如下的正规式:
其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。
A→(ID | NUM | RES | DEL | OPR) *
ID→letter(letter | didit)*
NUM→digit digit*
letter→a | … | z | A | … | Z
digit→ 0 | … | 9
RES→ program | begin | end | var | int | and | or | not | if | then | else | while | do
DEL→( | ) | . | ; | ,
OPR→+ | * | := | > | < | = | >= | <= | <>
如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一
个空格作间隔。空格由空白、制表符和换行符组成。
2、单词种别定义;
3、状态转换图;
语言A的词法分析的状态转换图如下所示:
空格符,制表符
或回车符字母或数字
四.测试数据及运行结果
五.总结
1.实验过程中遇到的问题及解决办法;
在实验中也遇到很多的错误,比如刚开时不能读写含有数字和不能识别的单词的语句,直接程序运行出错,经过很长时间的调试和分析,最后用单步调试方法找到了原因所在
2.对设计及调试过程的心得体会。
通过本次试验,我加深了对编译原理中的词法分析的理解,同时通过动手,更加锻炼了自己。本次试验由于使用的刚刚学习的java语言,通过这次机会加强了自己对java语言的熟悉的使用。
六.实验程序的源代码如下:
package Analysis;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class A {
private static char ch;
private static String strToken;
private static int index = 0;
private static int line = 1;
private static boolean noteTag=false;
private Map< Integer,String > keywords;
private HashMap
private static ArrayList
private static ArrayList
// get and set 函数
public char getCh() {
return ch;
}
public void setCh(char ch) {
A.ch = ch;
}
public String getStrToken() {
return strToken;
}
public void setStrToken(String strToken) {
A.strToken = strToken;
}
public void setPunctuations(HashMap
}
public Map
return punctuations;
}
public void setKeywords(Map
this.keywords = keywords;
}
public Map
return keywords;
}
// 构造函数
public A() {
this.keywords = new HashMap< Integer,String >();
keywords.put(1,"Program");
keywords.put(2,"begin");
keywords.put(3,"end");
keywords.put(4,"var");
keywords.put(5,"int");
keywords.put(6,"and");
keywords.put(7,"or");
keywords.put(8,"not");
keywords.put(9,"if");
keywords.put(10,"then");
keywords.put(11,"else");
keywords.put(12,"while");
keywords.put(13,"do");
this.punctuations = new HashMap
punctuations.put("+", 16);
punctuations.put("*", 17);
punctuations.put("(", 18);
punctuations.put(")", 19);
punctuations.put(",", 20);
punctuations.put(";", 21);
punctuations.put(":=", 22);
punctuations.put(">", 23);
punctuations.put(">=", 24);
punctuations.put("<", 25);
punctuations.put("<=", 26);
punctuations.put(".", 27);
punctuations.put("<>", 28);
punctuations.put("=", 29);
}
// 函数定义(词法分析函数)
public boolean Analyse(char[] strArray) {
index = 0;// 每次分析一行完成后就将index置0
char temp1;
int rowLength = strArray.length;
outer:while (index < rowLength) {
strToken = "";
ch = GetChar(strArray);
if (ch == ';'){
System.out.println("(21,;) ");
}
else if(ch==':')
{
index++;
System.out.println("(22,:=)");
}
else if(ch=='.')
{
System.out.println("(27,.)");
}
else if(ch=='>')
{
if(( temp1=this.getNextChar(strArray))=='=') System.out.println("(24,>=)");
else
{
index--;
System.out.println("(23,>)");
}
}
else if(ch=='<')
{
if(( temp1=this.getNextChar(strArray))=='=') System.out.println("(26,<=)");
else if(temp1=='>')
System.out.println("(28,<>)");
else
{
index--;
System.out.println("(25,<)");
}
}
else if(ch=='*'&& noteTag==false)
{
System.out.println("(17,*)");
}
else if (https://www.wendangku.net/doc/f84216398.html,ng.Character.isLetter(ch)&¬eTag==false) {
strToken = contact(strToken, ch);
ch = getNextChar(strArray);
while ((https://www.wendangku.net/doc/f84216398.html,ng.Character.isLetter(ch))
|| (https://www.wendangku.net/doc/f84216398.html,ng.Character.isDigit(ch))) {
strToken = contact(strToken, ch);
ch = getNextChar(strArray);
}
index--;
// System.err.println("!!!"+strToken);
if (findKeyword(strToken)) {
//System.out.println("(15," + strToken.toString() + ")\n");
int i=getKeyWordKey(strToken);
System.out.println("("+i+",--)");
} else
{
if(!exist(p,strToken))
p.add(strToken);
int i=getindex(p,strToken);
//System.out.println("(14," + strToken.toString() + ")\n");
System.out.println("(14,"+i+")");
}
} else if (https://www.wendangku.net/doc/f84216398.html,ng.Character.isDigit(ch)&¬eTag==false) {
strToken = this.contact(strToken, ch);
ch = this.getNextChar(strArray);
while (https://www.wendangku.net/doc/f84216398.html,ng.Character.isDigit(ch)) {
strToken = this.contact(strToken, ch);
ch = this.getNextChar(strArray);
}
index--;
//System.out.println("(15," + strToken.toString() + ")\n");
if(!exist(q,strToken))
q.add(strToken);
int i=getindex(q,strToken);
System.out.println("(15,"+i+")");
strToken = "";
} else if (ch == '/'||noteTag==true) {
int startj=index; //注释起始位置标记
int starti=line;
if(noteTag==false){
//System.out.println("该部分是注释注释,从第"+starti+"行第"+startj+"列开始");
}
char temp = this.getNextChar(strArray);
if (temp == '*'&¬eTag==false) {
temp = this.getNextChar(strArray);
while(index temp = this.getNextChar(strArray); if(temp=='*'&&( temp1=this.getNextChar(strArray))=='/') { index--; break; } if(index>=rowLength) { noteTag=true; break outer; } } } else if(noteTag==true&&ch!='*') { while(index temp = this.getNextChar(strArray); if(temp=='*'&&(temp1=this.getNextChar(strArray))=='/') { noteTag=false; break; } } } else if(temp=='/') { while(true) { index++; if(index>=rowLength) break outer; } } else return false; } else { String key = String.valueOf(ch); if (this.findPunctuation(key)) { System.out.println("("+this.getPunctuation(key)+"," + key + ")"); } else if (key.equals(" ") || key.equals(" ")) { break; } else return false; //System.out.println( "[未知符号] " + key + "\n"); //strToken = ""; } } return true; } public char GetChar(char[] array) { try { while ((array[index]) == ' ') { index++; } index++;// 提前指向下一个字符 } catch (ArrayIndexOutOfBoundsException e) { return ' '; } return array[index - 1]; } public char getNextChar(char[] strChar) { index++; return strChar[index - 1]; } public String contact(String token, char ch) { return token + String.valueOf(ch); } public boolean findKeyword(String str) { for(int i=0;i<13;i++){ if(str.equalsIgnoreCase(this.keywords.get(i))) return true; } return false; } public boolean findPunctuation(String str) { if (this.punctuations.containsKey(str)) { return true; } else return false; } public int getPunctuation(String str) { return this.punctuations.get(str); } public boolean Clean() { return true; } public void callError(int line) { System.out.println("出现错误,错误位置在第" + line + "行,第" + index + "列"); } public boolean exist(ArrayList { if(p.contains(getStrToken())) return true; else return false; } public int getKeyWordKey(String str) { for(int i=1;i<=13;i++) { if(str.equalsIgnoreCase(this.keywords.get(i))) return i; } return 10000; } public int getindex(ArrayList { return https://www.wendangku.net/doc/f84216398.html,stIndexOf(Str)+1; /*int j=0; for(int i=0;i { if(p.get(i).equals(Str)) j++; } return j;*/ } public static void main(String args[]) { File file = new File("F:\\sample.txt"); A a = new A(); char[] strChar = new char[100];// 限制每行代码字符数不超过100 BufferedReader reader = null; try { //System.out.println("以行为单位读取文件内容,一次读一整行:"); reader = new BufferedReader(new FileReader(file)); String tempString = null; // int line = 1; // 一次读入一行,直到读入null为文件结束 while ((tempString = reader.readLine()) != null) { // 显示行号 //System.out.println("line " + line + ": " + tempString); strChar = tempString.toCharArray(); boolean flag = a.Analyse(strChar); if (flag == true) line++; else { a.callError(line); break; } } System.out.println("标示符表"); System.out.println(p.toString()); System.out.println("常数表"); System.out.println(q.toString()); reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) try { reader.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } }