编译报告.docx
- 文档编号:24886864
- 上传时间:2023-06-02
- 格式:DOCX
- 页数:21
- 大小:171.87KB
编译报告.docx
《编译报告.docx》由会员分享,可在线阅读,更多相关《编译报告.docx(21页珍藏版)》请在冰豆网上搜索。
编译报告
编译原理
实验报告
课程名称
编译原理
实验项目名称
编译器程序
学号
2013061227
班级
20130612
姓名
杨磊
专业
计算机科学与技术
学生所在学院
计算机学院
指导教师
张菁
实验室名称地点
21B376
哈尔滨工程大学
计算机科学与技术学院
一、实验概述
1.实验名称
编译器程序实验
2.实验目的
分析理解一个教学型编译程序(如PL/0)的基础上,对其词法分析程序、语法分析程序和语义处理程序进行部分修改扩充。
达到进一步了解程序编译过程的基本原理和基本实现方法的目的。
3.实验类型
设计
4.实验内容
(1)词法分析器
(2)语法分析器
(3)中间代码生成器
(4)目标代码生成器
二、实验环境
Windows7、Devc++、c++
三、实验过程
1.设计思路和流程图
(1)
词法分析器
词法分析程序的输入是字符串形式的源程序,词和词之间可以用空白字符(空格、回车、制表符)隔开。
词法分析程序的输入是一个二元组,形式为:
(单词种别码,单词自身的值)。
若输入的字符串带有不合法的字符,则对应的字符(串)在输出中不以二元组的形式显示,而以“error!
!
”表示出错。
例如:
输入mainwhileif123.455e+123#
输出:
(1,main)
(9,while)
(6,if)
(20,1.23455e+125)
(0,#)
(2)语法分析器
P()函数B()函数
语法分析程序的输入与词法分析的输入一致,即字符串形式的源程序,词和词之间可以用空白字符(空格、回车、制表符)隔开。
语法程序的输出是判断所输入字符串是否是该语言的句子的结果,也即“success!
”或者“fail!
”,分别表示所输入的字符串是该语言的一个句子和字符串不是该语言的一个句子。
出错时结果为“fail!
”。
例如:
输入123.345e+123+(1*3+(2+4)/212)+12#
结果为“success!
”
(3)语意分析即中间代码生成
1、首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
2、读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
3、从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
4、如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:
将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
5、重复上述操作1-2直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
(4)目标代码生成
目标代码生成阶段的任务是把中间代码变换成特定机器上的绝对指令代码或可重定位的指令代码或汇编指令代码。
这是编译的最后阶段,它的工作与硬件系统结构和指令含义有关,这个阶段的工作很复杂,涉及到硬件系统功能部件的运用、机器指令的选择、各种数据类型变量的存储空间分配以及寄存器和后缓寄存器的调度等。
2.算法实现即相应的数据结构
1>.词法分析器
1.Designtheregulargrammar.
2.Designtheregularexpression.
3.ConstructtheDFA.
4.Writetheprogram.
数据结构
typedefstruct
{
inttype;
chartoken[size];
}symbol;
Char*keywords[keywordsnum]={"auto","break","case","char","const","continue","default","do",
"double","else","enum","extern","float","for","goto","if","int","long","register","return",
"short","signed","sizeof","static","struct","switch","typedef","printf","union","unsigned",
"void","volatile","while","main","include","using","namespace","std","bool","cin","cout","iostream","endl"};
char*operators[operatorsnum]={"+","-","*","/","++","--","%"};
char*jiefu[jiefunum]={",",";",".","(",")","{","}","[","]","|"};
char*luoji[luojinum]={"<",">","=","<=",">=","==","!
=","&&","||","!
"};
char*teshu[teshunum]={"@","#","$","&","^","~","<<",">>"};
char*zhushi[zhushinum]={"//","/*","*/"};
char*str[8]={"关键字","操作符","界符","逻辑运算符","特殊符","注释符","常量","标识符"};
*通过读文件的形式一个字符一个字符读入进行分析
*下面是词法分析的主要函数
voidlex(char*filename)
{
interror=0;
intflag=0;
charch;
fp.open(filename);
intlinenum=1;
inti,j;
i=0;
intx=0;
ch=fp.get();
while(!
fp.eof())
{
if(ch==''||ch=='\t')
{
x=0;
ch=fp.get();
}
elseif(ch=='\n')
{
x=0;
linenum++;
ch=fp.get();
}
elseif(isalpha(ch)==1)
{
table[i].token[x]=ch;
ch=fp.get();
if(isalpha(ch)==0&&isdigit(ch)==0&&ch!
='_')
{
table[i].token[++x]='\0';
i++;
flag=0;
x=0;
}
elseif(isdigit(ch)==1||isalpha(ch)==1||ch=='_')
x++;
}
elseif(isdigit(ch)==1)
{
table[i].token[x]=ch;
ch=fp.get();
if(isdigit(ch)==1)
x++;
elseif(ch=='.'&&flag==0)
{
table[i].token[++x]=ch;
flag=1;
x++;
ch=fp.get();
}
elseif(ch=='.'&&flag==1)
{
cout<<"("< f<<"("< error++; flag=0; } if(isdigit(ch)==0) { table[i].token[++x]='\0'; i++; x=0; flag=0; } } elseif(ch=='_') { table[i].token[x]=ch; ch=fp.get(); if(isalpha(ch)==1||isdigit(ch)==1||ch=='_') x++; else { table[i].token[++x]='\0'; i++; } } else { charch2=fp.get(); if(ist(ch,ch2)==1) { table[i].token[0]=ch; table[i].token[1]=ch2; table[i].token[2]='\0'; x=0; i++; ch=fp.get(); } else { table[i].token[0]=ch; table[i].token[1]='\0'; x=0; i++; ch=ch2; } } } for(j=0;j { intn=typenum(table[j].token); table[j].type=n; } cout< f< f<<"----------------"< cout<<"----------------"< for(j=0;j { cout< f< sf(table[j].type); } } 2>.语法分析器 1).自顶向下的LL (1)分析 2).先求first、follow、select集构造分析表 3).进行语法分析 4).本实验采用静态存分析表的方式 5).可以分析算符表达式 *分析栈 *和剩余串 *进栈和匹配操作 3>.语言表达式翻译程序 *完成中间代码的生成, *转成四元式的形式。 *利用两个栈进行四元式的产生 *其一栈为算符栈根据优先关系进栈和出栈 *另一个为操作数或变量栈 *当剩余串算符优先级比算符栈低时出栈生成相应的四元式 *再根据四元式转化成汇编代码 四元式结构体 structTR { charw; charopr1[5]; charopr2[5]; charT[5]; }; 汇编结构体 structAS { charL[5]; charoperation[5]; charA[5]; charB[5]; }; v->voidmain t->int d->标识符 e->常量 w->while i->if 3.需要解决的问题及解答 (1)词法分析功能: 对代码进行分词操作,分出以下5类单词: 关键字、标识符、常量、运算符、分隔符。 (2) 算术表达式、关系表达式和逻辑表达式的分析与化简: 提取代码中的所有算术表达式,可用LL (1)分析或算符优先分析算术表达式。 关系表达式和逻辑表达式也可用算术表达式的程序进行分析。 分析成功后进行化简操作,方便语法分析程序分析。 (3)LL (1)语法分析: 自己写的简单C语言的方法,支持赋值语句、判断语句、循环语句, 用自顶向下的分析方法,对化简之后的单词流进行分析。 (4)四元式生成与后缀式。 对词法分析分词后的单词流生成中间代码。 其中算术表达式先生成后缀式。 然后再根据后缀式的结果生成四元式。 对多条逻辑表达式采用先计算再跳转的操作。 对if语句判断跳转,if中的表达式支持多条逻辑表达式,但不支持嵌套。 while和if相同。 (5)汇编语言生成: 根据四元式生成汇编语言。 6.程序运行时的初值和运行结果 测试用例 词法分析结果输出 中间代码生成 目标代码生成(汇编语言) 四、代码(由于整个编译器程序代码较长,只提供中间代码生成器部分) #include #include #include #include usingnamespacestd; #defineMAX100 intm=0,sum=0;//sum用于计算运算符的个数 //m用于标记输入表达式中字符的个数? charJG='A'; charstr[MAX];//用于存输入表达式 inttoken=0;//左括号的标志 /***********用于更改计算后数组中的值**************/ voidchange(inte) { intf=e+2; charch=str[f]; if(ch>='A'&&ch<='Z') { for(intl=0;l { if(str[l]==ch) str[l]=JG; } } if(str[e]>='A'&&str[e]<='Z') { for(inti=0;i { if(str[i]==str[e]) str[i]=JG; } } } voidchengchuchuli(inti,intm) { i++; for(;i<=m-1;i++)//处理乘除运算 { if(str[i]=='*'||str[i]=='/') { cout<<"("< change(i-1); str[i-1]=str[i]=str[i+1]=JG; sum--; JG=(char)(int)JG++; } } } voidjiajianchuli(intj,intm) { j++; for(;j<=m-1;j++)//处理加减运算 { if(str[j]=='+'||str[j]=='-') { cout<<"("< change(j-1); str[j-1]=str[j]=str[j+1]=JG; sum--; JG=(char)(int)JG++; } } } /*扫描遍从文件中D读入表达式*/ voidscan(FILE*fin) { intp[MAX]; charch='a'; intc=-1,q=0; while(ch! =EOF) { ch=getc(fin); while(ch==''||ch=='\n'||ch=='\t')ch=getc(fin);//消除空格和换行符 str[m++]=ch; if(ch=='='||ch=='+'||ch=='-'||ch=='*'||ch=='/')sum++; elseif(ch=='(') { p[++c]=m-1; } elseif(ch==')') { q=m-1; chengchuchuli(p[c],q);//从左括号处理到又括号 jiajianchuli(p[c],q); JG=(char)(int)JG--; str[p[c]]=str[m-1]=JG; c--; JG=(char)(int)JG++; } } } voidsanyuanshi() { for(inti=0;i<=m-1;i++)//处理乘除运算 { if(str[i]=='*'||str[i]=='/') { cout<<"("< change(i-1); str[i-1]=str[i]=str[i+1]=JG; sum--; JG=(char)(int)JG++; } } for(intj=0;j<=m-1;j++)//处理加减运算 { if(str[j]=='+'||str[j]=='-') { cout<<"("< change(j-1); str[j-1]=str[j]=str[j+1]=JG; sum--; JG=(char)(int)JG++; } } for(intk=0;k<=m-1;k++)//处理赋值运算 { if(str[k]=='=') { JG=(char)(int)--JG; cout<<"("< sum--; change(k+1); str[k-1]=JG; } } } intmain(){ charin[MAX];//用于接收输入输出文件名? FILE*fin;//用于指向输入输出文件的指针 cout<<"请输入源文件名(包括后缀名)"< //scanf("%s",in); cin>>in;; if((fin=fopen(in,"r"))==NULL)//判断输入文件名是否正确 { cout<<"打开词法分析输入文件出错! "< } cout<<"*********三元式如下*********"< scan(fin);//调用函数从文件中读入表达式 sanyuanshi(); if(sum==0)printf("成功! "); elseprintf("有错误! "); //关闭文件 fclose(fin); system("pause"); } 四、实验体会 深入了解编译程序的运行原理,通过设计一个小型的编译器,加深对课堂学习内容的理解,更深刻的领会编译器的基本工作原理和实现方法。 实验中模拟了词法分析,语法分析,语义分析,中间代码以及目标代码生成。 从中真正学习到了编译的精髓,虽然其中有熬夜编代码的疲惫,但是真正做成的时候就会发现,做成成品的喜悦远比辛劳要重要得多,有志者事竟成。 如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。 copyright@ 2008-2022 冰点文档网站版权所有 经营许可证编号:鄂ICP备2022015515号-1