合肥工业大学编译原理实验.docx
《合肥工业大学编译原理实验.docx》由会员分享,可在线阅读,更多相关《合肥工业大学编译原理实验.docx(40页珍藏版)》请在冰豆网上搜索。
合肥工业大学编译原理实验
宣城校区
实验报告
课程名称编译原理
专业班级计算机0001班
学生姓名及学号赵保飞2015216768
指导教师李芒宏
实验地点计算机中心楼第四机房
2017~2018学年第一学期
《编译原理》课程实验报告
实验名称
词法分析设计
姓名
赵保飞
系院专业
计算机科学与技术
班级
计算机01班
学号
2015216768
实验日期
2017.10.18
指导教师
李芒宏
成绩
一、实验目的和要求
通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设
计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的
理解,并能正确地、熟练地运用。
二、实验原理
(1)实验数据结构说明
K[]String数组-关键字表;s[]char数组—分界符;m[]char数组—算术运算符;r[]String数组—关系运算符;ArrayList型String数组ci—常数;ArrayList型String数组id—标识符
(2)实验算法描述
(3)算法流程图
三、源程序代码和测试结果
packagelexicalAnalysis;
importjava.util.*;
importjava.io.*;
publicclasslexicalAnalysis{
staticStringk[]={"for","main","if","while","void","public","static","printf","scanf","asm","do","return","typedef","auto","double","break","short","using","default","long"};//关键字
staticchars[]={',',';','(',')','[',']','{','}'};//2分界符
staticcharm[]={'+','-','*','/'};//3算术运算符
staticStringr[]={"<","<=","=",">",">=","<>"};//4关系运算符
ArrayListci=newArrayList();//5常数
ArrayListid=newArrayList();//6标识符
StringtempToken="";//临时存放组成一个“词”单位串
intpint,row=1,line=1;//当前指针指示,行数,列数
charch;//存放最新读入源程序字符
Stringinstring;//存放输入de源程序代码
publicstaticvoidmain(String[]args)throwsException{
//TODOAuto-generatedmethodstub
lexicalAnalysisone=newlexicalAnalysis();
System.out.println("单词"+"\t二元序列"+"\t类型"+"\t位置(行,列)");
one.readtext();
}
booleanisdigit(charc){//判断所读字符是否为数字,是则返回ture,否则返回false
if(c>=48&&c<=57)
returntrue;
else
returnfalse;
}
booleanisletter(charc){//判断所读字符是否为字母,是则返回true,否则返回false
if((c>64&&c<91)||(c>96&&c<123))
returntrue;
else
returnfalse;
}
booleanisline(charc){//判断字符c是否是下划线"_"
if(c=='_')
returntrue;
else
returnfalse;
}
booleanremove(){//用于在判断关系运算符时,判断是否是要再读一个字符
charb=instring.charAt(pint+1);//string类charAt()方法用于返回指定索引处的字符。
索引范围为从0到length()-1
if(b=='='||b=='>')//当其后的字符是=或>时,要再读一个字符。
否则不要再读。
returntrue;
else
returnfalse;
}
voidclearBlank(){//检查空白直到读入字符非空白
while(ch==''){
getchar();
}
}
voidgetchar(){
pint++;
if(pint<=instring.length()-1){
ch=instring.charAt(pint);
if(ch=='\n'){
change_row_line();
getchar();
}
}
else
ch='';//instring数据读取完,需重新读入
}
voidretract(){//读入前一个字符
pint--;
ch=instring.charAt(pint);
}
voiddistinguishLeter(){//识别字符串
tempToken="";//清空
while(isletter(ch)||isdigit(ch)||isline(ch)){//字母,数字,下划线仍是字符串合法组成,继续识别
tempToken=tempToken+ch;
getchar();
}
}
voiddistinguishDigit(){//识别数字串
tempToken="";//先将strtoken置空
while(isdigit(ch)){//当数字时继续识别数字串
tempToken=tempToken+ch;//将新识别的字符加到strtoken后
getchar();
}
if(isletter(ch)||isline(ch)){//识别完数字串而其后是字母,下划线时出错处理
while(isletter(ch)||isline(ch)||isdigit(ch)){//当是字母,数字,下划线时继续识别错误数字串
tempToken=tempToken+ch;//将新识别的字符加到strtoken后
getchar();
}
display(0,tempToken,'');//输出错误数字串
tempToken="";//将strtoken置空返回
}
}
voiddisplay(inti,Strings,chara){//各种输出处理
switch(i){
case-1:
System.out.println(a+"\tError"+"\tError"+"\t"+row+","+line+")");
break;
case0:
System.out.println(s+"\tError"+"\tError"+"\t("+row+","+line+")");
break;
case1:
System.out.println(s+"\t(1,"+s+")"+"\t关键字"+"\t("+row+","+line+")");
break;
case2:
System.out.println(a+"\t(2,"+a+")"+"\t分界符"+"\t("+row+","+line+")");
break;
case3:
System.out.println(a+"\t(3,"+a+")"+"\t算术运算符"+"\t("+row+","+line+")");
break;
case4:
System.out.println(s+"\t(4,"+s+")"+"\t关系运算符"+"\t("+row+","+line+")");
break;
case5:
System.out.println(s+"\t(5,"+s+")"+"\t常数"+"\t"+"("+row+","+line+")");
break;
case6:
System.out.println(s+"\t(6,"+s+")"+"\t标识符"+"\t("+row+","+line+")");
break;
}
line++;//列数加一
}
voidchange_row_line(){//改变行数和列数
row++;
line=1;
}
voidhandleString(){//输入串处理
pint=-1;//将搜索指示器置-1
System.out.println("要处理的语句为:
"+instring);
getchar();//读入一个字符
while(pintclearBlank();//检查空白直到读入读入非空
if(isdigit(ch)){//当ch为数字时进行数字串识别
distinguishDigit();//数字串识别
if(tempToken.length()!
=0){//经过数字串识别后,如果strtoken不为空
if(reseverci(tempToken)==-1){//如果strtoken不在ci表中,将strtoken加入ci表中
ci.add(tempToken);//将strtoken加入ci表中
display(5,tempToken,'');//输出数字串
}
else{//如果strtoken在ci表中,仅输出
display(5,tempToken,'');//输出数字串
}
}
}
elseif(isletter(ch)){//当ch为字母时进行字符串识别
distinguishLeter();//字符串识别
if(reserve(tempToken)==-1){//如果strtoken不在k表中
if(reseverid(tempToken)==-1){//如果strtoken不在id表中
id.add(tempToken);//将strtoken加入id表中
display(6,tempToken,'');//输出标识串
}
else{//如果strtoken在id表中
display(6,tempToken,'');//输出标识串
}
}
else{//如果strtoken在关键字表
display(1,tempToken,'');//输出关键字
}
}
elseif(in_s(ch)!
=-1){//分界符处理包含在one.in_s(one.ch)中
}
elseif(in_m(ch)!
=-1){//算术运算符处理包含在one.in_m(one.ch)中
}
elseif(in_k(ch)!
=-1){//关系运算符处理包含在one.in_k(one.ch)中
}
else{
display(-1,"",ch);//error
getchar();//读下一位
}
}
}
intreserve(Strings){//判断字符串是否是保留字
inti;
for(i=0;iif(s.equals(k[i])){
returni;//是保留字,就返回编码
}
}
return-1;//不是保留字,就返回-1
}
intreseverid(Strings){//判断识别的标志符是否已经在id表中
inti;
for(i=0;iif(s.equals(id.get(i)))
returni;//识别的标志符已经在id表中,返回位置
}
return-1;//识别的标志符不在id表中,返回-1
}
intreseverci(Strings){//判断识别的数字串是否已经在ci表中
inti;
for(i=0;iif(s.equals(ci.get(i)))
returni;//识别的数字串已经在ci表中,返回位置
}
return-1;//识别的数字串不在ci表中,返回-1
}
intin_s(charc){//确认分界符
inti;
for(i=0;iif(c==s[i]){//与某个分界符配备时
display(2,"",c);//输出分界符
getchar();//读下一位
returni;//返回所在位置
}
return-1;//不在分界符表中
}
intin_m(charc){//查找算术运算符
inti;
for(i=0;iif(c==m[i]){//与某个算术运算符配备时
display(3,"",c);//输出算术运算符
getchar();//读下一位
returni;//返回所在位置
}
return-1;//不在算术运算符表中
}
intin_k(charb){//查找关系运算符
inti;
if(remove()==false){//读下一位为假时,进行一位关系运算符识别
for(i=0;iif(r[i].length()==1){//当关系运算符为一位时,尝试匹配
if(r[i].equals(Character.toString(b))){
display(4,r[i],'');//输出关系运算符
getchar();//读下一位
returni;//返回所在位置
}
}
}else{//读下一位为假时,进行两位关系运算符识别
chara[]=newchar[2];//将两位字符放入a中
a[0]=b;
getchar();
a[1]=ch;
for(i=0;iif(r[i].length()==2){//当关系运算符为两位时,尝试匹配
if(r[i].equals(String.copyValueOf(a))){
display(4,r[i],'');//输出关系运算符
getchar();//读下一位
returni;//返回所在位置
}
}
retract();//两位关系运算符匹配失败,读入前一个字符
}
return-1;//不在关系运算表中
}
voidreadtext()throwsException{//从文本读入源程序
Stringpathname="C:
\\Users\\Yoda\\Desktop\\code.txt";
Filefilename=newFile(pathname);
InputStreamReaderreader=newInputStreamReader(newFileInputStream(filename));
BufferedReaderbr=newBufferedReader(reader);
instring="";
instring=br.readLine();
while(instring!
=null){
handleString();//处理读入的源程序
change_row_line();
instring=br.readLine();
}
}
}
四、实验评价、收获与体会
纸上得来终觉浅,虽然词法分析器是理论上实行最简单的,但是编写程序实现时却也遇到了不少的问题。
使用JAVA来写是因为这学期正在开这门课,数据的读入还是自己提前看才实现的,读入的一条源代码看似简单,首先要储存,储存后要清楚空格直到读到字符为止,还是以C++的思维来写java程序,其中很多细节均是通过函数来实现。
这也许自己没有深刻理解java设计思维的原因。
希望以后能改进。
《编译原理》课程实验报告
实验名称
LL
(1)分析法
姓名
赵保飞
系院专业
计算机科学与技术
班级
计算机01班
学号
2015216768
实验日期
10.25
指导教师
李芒宏
成绩
一、实验目的和要求
复变函数。
。
编译原理实验和预习。
。
java作业和实验。
。
操作系统复习。
。
通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区
别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方
法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培
养适应社会多方面需要的能力。
二、实验原理
文法为
(1)E->TG
(2)G->+TG|-TG
(3)G->ε
(4)T->FS
(5)S->*FS|/FS
(6)S->ε
(7)F->(E)
(8)F->i
(1)实验数据结构说明
Char数组-Vn数组--非终结符表;char数组-Vt数组--终结符;String数组-Gr数组--文法;
Boolean型FIRST[][]二维数组对应每个非终结符的first集,初始化均为false;
Boolean型FOLLOW[][]二维数组对应每个非终结符的Follow集,初始化均为false;
String型M[][]二维数组对应预测分析表
(2)实验算法描述
算法总的来讲不是很复杂,但是细节上可能有点复杂。
总的是依据本实验的数据结构FIRST[][]和FOLLOW[][]集,这两个数据结构虽然浪费了不少空间但是确实让程序的实现变得更简单。
First()总的来求所有的非终结符的first集,first1()分工为具体求某一个具体非终结符的first集;first2()则是求某一个集体的产生式的first集。
通过这三个函数的逐级分工来实现求所有的非终结符的first集。
Follow集来说相对难求一点,但把它放到first集后面求来说相对简单一点。
通过上面的分布设计就可以实现了。
(3)算法流程图
三、源程序代码和测试结果
packageexp3;
importjavax.swing.*;
importjava.awt.*;
importjava.awt.GridLayout.*;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
classWinGridextendsJFrame{
GridLayoutgrid;
JPanelchessboard;
JTextFieldtext;
JTextAreatextShow;
JButtonbutton;
ReaderListenlistener;
WinGrid(){
init();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
voidinit(){
setLayout(newFlowLayout());
text=newJTextField(10);
setBounds(466,166,500,400);
button=newJButton("读取");
textShow=newJTextArea(9,30);
listener=newReaderListen();
listener.setJTextField(text);
listener.setJTextArea(textShow);
text.addActionListener(listener);
button.addActionListener(listener);
add(text);
add(button);
add(newJScrollPane(textShow));
}
}
classReaderListenimplementsActionListener{
JTextFieldtext;
JTextAreatextShow;
LLone=newLL();
Strings;
Stringtemp1[][]=newString[18][6];
publicvoidsetJTextField(JTextFieldtext){
this.text=text;
}
publicvoidsetJTextArea(JTextAreatextShow){
this.textShow=textShow;
}
publicStringS(){
Stringt=text.getText();
returnt;
}
@Override
publicvoidactionPerformed(ActionEvente){
try{
Strings=text.getText()+"#";
textShow.append(s+"\n");
textShow.append("步骤"+"\t"+"分析栈"+"\t"+"剩余输入串"+"\t"+"所用产生式"+"\t"+"动作"+"\n");
one.right(s,temp1);
for(inti=0;i<18;i++){