合肥工业大学 编译原理实验报告.docx
《合肥工业大学 编译原理实验报告.docx》由会员分享,可在线阅读,更多相关《合肥工业大学 编译原理实验报告.docx(63页珍藏版)》请在冰点文库上搜索。
合肥工业大学编译原理实验报告
合肥工业大学编译原理实验报告
合肥工业大学计算机与信息学院
编译原理实验报告
专业:
学号:
姓名:
指导老师:
完成时间:
实验一词法分析设计
一、实验目的
通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整和清楚的理解,并且能够正确和熟练地运用。
二、实验环境
Windows8.1、VisualStudio2013、C++
三、实验原理
(1)实验数据结构说明
stringstr[40]存储string
intstrcount存储string的数目
stringname存储type名
Table()构造函数
~Table()析构函数
Table
voidsetname(stringstrTemp)设置name值
stringgetname()获取name值
voidupdate(stringstrTemp)添加strTemp的值
voidinit(stringfilename)初始化table
intsearch(stringstrTemp)在table中查询strTemp
stringvalue存储分析单词的值
inttypeType的编号
intpointer单词的位置
OutToken
stringtyname存储在表中位置
intline分析单词的行的值
introw分析单词的列的值
OutToken(stringval,intt,intp,stringtn,int有参数构造函数l,intr)
~OutToken()析构函数friendostream&operator<<(ostream&output,重载<<函数OutToken&ot)
TableKeywordType1:
C++关键字TableSeperatorType2:
分界符TablesumoperatorType3:
算术运算符TablereloperatorType4:
关系运算符TableconstantType5:
常数TableidentifierType6:
标识符OutTokenouttoken二元式TokenAnalyzer
TokenAnalyzer()构造函数~TokenAnalyzer()析构函数voidinittable()初始化表voiddisplay()输出所有单词二元式voidstrsearch(stringstrin,intline,introw)分析strinvoidreadcode()读取源代码
(2)实验算法描述
1)词法分析设计流程图
2)词法分析程序框图
3)统计字符位置程序框图
四、实验内容
使用C++语言实现对C++语言字集的源程序进行词法分析。
通过输入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单词符号自身值;若遇到错误则显示ERROR,然后跳过错误部分继续显示;同时进行标识符登记符号表的管理。
词法分析设计主要工作:
(1)从源程序中读取字符
(2)统计行数和列数用于错误单词的定位
(3)删除空格类字符,包括回车、制表符空格
(4)按拼写单词,并用(内码,属性)二元式来表示,(属性值—Token的
机内表示)
(5)如果发现错误则报告出错
(6)根据需要是否填写标识符供以后各阶段使用
单词的基本分类:
(1)关键字:
由各程序语言具有的固定意义的标识符(保留字例)
(2)标识符:
用以表示各种名字的变量名、数组名、函数名
(3)常数:
任何数值常数
(4)运算符:
+、-、*、/
(5)关系运算符:
<、<=、=、>、>=、<>、|
(6)分界符:
;、,、(、)、[、]、{、}
五、实验要求
1、编程时注意编程风格:
空行的使用、注释的使用、缩进的使用等2、标识符填写的符号表需提供给编译程序的以后各阶段使用3、根据测试数据进行测试。
测试实例分为三部分:
(1)各种合法输入
(2)各种组合输入
(3)有记号组成的句子
4、词法分析程序设计要求输出形式
单词二元序列类型位置(行,列)
for(1,for)关键字(1,1)
六、实验结果
(1)分析代码
(2)分析结果
七、实验总结
通过此次实验的编程实践加强了自己对词法分析的任务的理解,在一定
程度上初步掌握了词法分析程序设计的原理和构造,并且在对编译的基本概
念、原理和概念方法有更清楚的认识。
在实验过程中自己对词法分析程序中
的算法理解出现了一定的偏差,认为其中的标识符是程序执行之前必须都由
自己手动构造,导致自己在程序的验收阶段出现了问题。
事实上,在词法分
析程序中,若识别的字符串是首字符字母,则在关键字表中查询是否存在,
如果不存在则将新造入标识符表中。
对于在源代码中注释问题,由于本程序
是以行为单位从TXT文件中读取代码,当自己将注释的判断程序放置扫描每
一行的动作前,导致了添加在有效合法语句后的注释语句全部被分析为
Error,所以之后将判断注释的语句放置在以一个单位取字符串之前,当某
一行的字符串中含有//或/*时,则将其后的字符串全部忽略,即跳出本行的
后续的分析步骤,重新执行下一行的代码读取和分析操作。
八、实验代码
#include
#include
#include
#include
usingnamespacestd;
classTable
{
private:
stringstr[40];
intstrcount;
stringname;
public:
Table();
~Table();
voidsetname(stringstrTemp);
stringgetname();
voidupdate(stringstrTemp);
voidinit(stringfilename);
intsearch(stringstrTemp);};
Table:
:
Table()
{
for(inti=0;i<40;i++)
str[i]="";
strcount=0;
name="";
}
Table:
:
~Table()
{
}
voidTable:
:
setname(stringstrTemp){
name=strTemp;
}
stringTable:
:
getname()
{
returnname;
}
voidTable:
:
update(stringstrTemp){
str[++strcount]=strTemp;}
voidTable:
:
init(stringfilename){
stringstrin;
ifstreaminfiles(filename);
if(!
infiles)
cout<<"打开"<while(getline(infiles,strin))
update(strin);
infiles.close();
}
intTable:
:
search(stringstrTemp){
for(inti=1;i<=strcount;i++)
{
if(str[i]==strTemp)
returni;
}
return0;
}
classOutToken
{
private:
stringvalue;
inttype;
intpointer;
stringtyname;
intline;
introw;
public:
OutToken(stringval="",intt=0,intp=0,stringtn="",intl=0,intr=0);
~OutToken();
friendostream&operator<<(ostream&output,OutToken&ot);
};
OutToken:
:
OutToken(stringval,intt,intp,stringtn,intl,intr)
{
value=val;
type=t;
pointer=p;
tyname=tn;
line=l;
row=r;
}
OutToken:
:
~OutToken(){
}
ostream&operator<<(ostream&output,OutToken&ot){
if(ot.type!
=0)
output<:
left)<<<"("<(2)<(2)<<","<(2)<<<")"
<<<"("<else
output<:
left)<<<<<"("<returnoutput;
}
classTokenAnalyzer
{
private:
Tablekeyword;
Tableseperator;
Tablesumoperator;
Tablereloperator;
Tableconstant;
Tableidentifer;
OutTokenouttoken[100];
intoutcount;
public:
TokenAnalyzer();
~TokenAnalyzer();
voidinittable();
voiddisplay();
voidstrsearch(stringstrin,intline,introw);
voidreadcode();
};
TokenAnalyzer:
:
TokenAnalyzer(){
keyword.setname("关键字");
seperator.setname("分界符");
sumoperator.setname("运算符");
reloperator.setname("关系运算符");
constant.setname("常数");
identifer.setname("标识符");
outcount=0;
}
TokenAnalyzer:
:
~TokenAnalyzer(){
}
voidTokenAnalyzer:
:
inittable(){
seperator.init("seperator.txt");
reloperator.init("reloperator.txt");
sumoperator.init("sumoperator.txt");
constant.init("constant.txt");
keyword.init("keyword.txt");
}
voidTokenAnalyzer:
:
display()
{
for(inti=1;i<=outcount;i++)
cout<}
voidTokenAnalyzer:
:
strsearch(stringstrin,intline,introw){
if((strin[0]>='a'&&strin[0]<='z')||(strin[0]>='a'&&strin[0]<='z'))
{
if(keyword.search(strin))
outtoken[++outcount]=OutToken(strin,1,keyword.search(strin),
keyword.getname(),line,row);
else
{
if(identifer.search(strin))
outtoken[++outcount]=OutToken(strin,6,identifer.search(strin),
identifer.getname(),line,row);
else
{
identifer.update(strin);
outtoken[++outcount]=OutToken(strin,6,identifer.search(strin),
identifer.getname(),line,row);
}
}
}
else
{
if(strin[0]>='0'&&strin[0]<='9')
{
if(constant.search(strin))
outtoken[++outcount]=OutToken(strin,5,constant.search(strin),
constant.getname(),line,row);
else
{
constant.update(strin);
outtoken[++outcount]=OutToken(strin,5,constant.search(strin),
constant.getname(),line,row);
}
}
else
{
if(seperator.search(strin))
outtoken[++outcount]=OutToken(strin,2,seperator.search(strin),
seperator.getname(),line,row);
else
{
if(reloperator.search(strin))
outtoken[++outcount]=OutToken(strin,4,reloperator.search(strin),
reloperator.getname(),line,row);
else
{
if(sumoperator.search(strin))
outtoken[++outcount]=OutToken(strin,4,
sumoperator.search(strin),sumoperator.getname(),line,row);
else
outtoken[++outcount]=OutToken(strin,0,0,"ERROR",line,row);
}
}
}
}
}
voidTokenAnalyzer:
:
readcode()
{
ifstreaminfile("code.txt");
if(!
infile)
cout<<"打开失败~"<stringstrin;
intline;
introw;
line=0;
while(getline(infile,strin))
{
line++;
row=0;
if(strin!
="")
{
stringstrtemp="";
while(strin[0]==''&&strin.length()>1)
strin=strin.substr(1,strin.length());
if(strin[0]=='/'&&strin[1]=='/')
continue;
if(strin=="")
strin="";
while(strin!
=""&&strin!
=strtemp)
{
row++;
if(strin.find(""))
strtemp=strin.substr(0,strin.find(""));
else
strtemp=strin;
if(strin[0]=='/'&&strin[1]=='/')
continue;
strsearch(strtemp,line,row);
if(strin.find(""))
strin=strin.substr(strin.find("")+1,strin.length());
while(strin[0]==''&&strin.length()>1)
strin=strin.substr(1,strin.length());
if(strin=="")
strin="";
}
}
}
infile.close();
}
voidmain(void)
{
TokenAnalyzerT;
T.inittable();
T.readcode();
T.display();}
实验二LL
(1)分析文法一、实验目的
通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。
使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。
有利于提高学生的专业素质,为培养适应社会多方面需要的能力。
二、实验环境
Windows8.1、VisualStudio2013、C++
三、实验原理
(1)实验数据结构说明
存储栈符号charcharstack[30]
存储的符号个数intcount
Stack()构造函数
~Stack()析构函数Stack
voidpush(charch)将ch压栈
voidpop()栈顶出栈
chargettop()将栈顶元素弹栈返回
voiddisplay()打印栈内容
charTerminalSymbol[20]终结符
charNonTerminalSymbol[20]非终结符
charlinechar[20]M表行表头
charrowchar[20]M表列表头
LLAnalyzerintM[20][20]状态表
stringGrammar[20]文法
stringFirstset[20]First集
stringFollowset[20]Follow集
stackchars符号栈
LLAnalyzer()构造函数~LLAnalyzer()析构函数voidinit()初始化
voidinitM()初始化M表intsearch(chararray[],charch)查询ch返回位置voidreadfile()读取文法存入Grammar中stringgetfirst(charch)生成字符ch的First集stringgetfirststr(stringstr)生成字符串strFirst集voidsetfirstset()所有文法生成First集stringgetfollow(charch)生成字符ch的First集stringlinkstring(stringstr,stringstrt)两字符串不同的符连接stringchartostring(charch)字符转换成字符串返回voidsetfollow()生成所有文法Follow集voidsetM()生成M表intsearchstr(stringarray[],stringstrt)查询字strt返回位置boolLanalyzer(stringstrin)文法分析voidpushstring(intstrno)产生式逆序压栈
(2)实验算法思想描述
1)LL
(1)文法程序框图
四、实验内容
(1)根据某一文法编制调试LL
(1)分析程序,以便对任何输入的符号串进行分析
(2)构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序
(3)分析法的功能是利用LL
(1)控制程序根据显示栈顶内容、向前看符号以及LL
(1)分析表,对输入符号串自上而下的分析过程
五、实验要求
1、编程时注意风格:
空行的使用释缩进等。
2、如果遇到错误的表达式,应输出提示信息。
3、对下列文法,用LL
(1)分析法对任意输入的符号串进行分析
(1)E->TG
(2)G->+TG|—TG
(3)G->ε
(4)T->FS
(5)S->*FS|/FS
(6)S->ε
(7)F->(E)
(8)F->i
输出格式
步骤分析栈剩余输入串所用产生式动作
0#Ei+i*i#初始化
六、实验结果
(1)构建First和Follow集
(2)构建状态转移表M
(3)LL
(1)分析测试实例
1)正确实例
2)错误实例
七、实验总结
通过完成预测LL
(1)分析法的语法分析程序,自己了解了预测分析法
和递归子程序法的区别和联系。
使自己了解了语法分析的功能,掌握语法分
析程序设计的原理和构造方法,并且使自己对基本的程序应用的开发具有更
进一步的理解。
但是在此次编程实验中,由于自己对First集的构建算法理
解上出现了一定的失误,导致前期的实验中总是达不到自己预测的输出,后
通过断点调试一步一步找出了程序中的错误。
八、实验代码
#include
#include
#include
#include
usingnamespacestd;
classstack
{
private:
charcharstack[30];
intcount;
public:
stack();
~stack();
voidpush(charch);
voi