FOR循环语句的翻译程序设计递归下降法输出三地址表示文档格式.docx
《FOR循环语句的翻译程序设计递归下降法输出三地址表示文档格式.docx》由会员分享,可在线阅读,更多相关《FOR循环语句的翻译程序设计递归下降法输出三地址表示文档格式.docx(22页珍藏版)》请在冰豆网上搜索。
6.4、主函数————————————————————-13
7、测试方法和测试结果———————————————-14
7.1测试过程————————————————————-14
7.2测试结论————————————————————-16
8、课程设计总结——————————————————-17
9、参考文献————————————————————-18
本科生课程设计成绩评定表——————————————19
课程设计任务书
学生姓名:
王嘉辛专业班级:
计算机0909班
指导教师:
高曙工作单位:
计算机科学与技术学院
题目:
FOR循环语句的翻译程序设计(递归下降法、输出三地址表示)
初始条件:
理论:
学完编译课程,掌握一种计算机高级语言的使用。
实践:
计算机实验室提供计算机及软件环境。
如果自己有计算机可以在其上进行设计。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
(1)写出符合给定的语法分析方法的文法及属性文法。
(2)完成题目要求的中间代码三地址表示的描述。
(3)写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
(4)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
(5)设计报告格式按附件要求书写。
课程设计报告书正文的内容应包括:
1系统描述(问题域描述);
2文法及属性文法的描述;
3语法分析方法描述及语法分析表设计;
4按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;
5编译系统的概要设计;
6详细的算法描述(流程图或伪代码);
7软件的测试方法和测试结果;
8研制报告(研制过程,本设计的评价、特点、不足、收获与体会等);
9参考文献(按公开发表的规范书写)。
时间安排:
设计安排一周:
周1、周2:
完成系统分析及设计。
周3、周4:
完成程序调试及测试。
周5:
撰写课程设计报告。
设计验收安排:
设计周的星期五第1节课开始到实验室进行上机验收。
设计报告书收取时间:
设计周的次周星期一上午10点。
指导教师签名:
年月日
系主任(或责任教师)签名:
FOR循环语句的翻译程序设计
——递归下降法、输出三地址表示
1、系统描述
1.1、实验思想
通过设计、编制、调试一个FOR循环语句的语法及语义分析程序,加深对语法及语义分析原理的理解,实现词法分析程序对单词序列的词法检查和分析,并且实现对单词序列的语法分析、语义分析以及中间代码生成。
1.2、设计内容
本设计按照要求设计出for语句的简单文法,并使用递归下降分析法对用户输入的程序进行分析和翻译。
对下列正确的程序输入:
fori=1step1until10dok=j#
结果程序要对该输入进行词法分析,然后利用递归下降的分析法对词法分析得到的单词序列进行语法分析,经过语法制导翻译显示出等价的三地址表示的中间代码。
对于错误的程序输入,如:
Fori=1step1until10k=j#
结果程序要指出程序出错。
1.3、翻译过程
1.3.1、词法分析:
词法分析是计算机科学中将字符序列转换为单词(Token)序列的过程。
进行语法分析的程序或者函数叫作词法分析器(Lexicalanalyzer,简称Lexer),也叫扫描器(Scanner)。
词法分析器一般以函数的形式存在,供语法分析器调用。
词法分析是编译过程中的第一个阶段,在语法分析前进行。
也可以和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。
简化设计、改进编译效率、增加编译系统的可移植性。
词法分析是编制一个读单词的过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
单词的分类主要分为五类:
1.关键字:
由程序语言定义的具有固定意义的标识符。
也称为保留字或基本字。
2.标识符:
用来表示程序中各种名字的字符串。
3.常数:
常数的类型一般有整型、实型、布尔型、文字型。
4.运算符:
如+、-、*、/等。
5.界限符:
如逗号、分号、括号等。
词法分析器输出的单词符号常表示成如下的二元式:
(单词种别,单词符号的属性值)
1.3.2、语法分析:
语法分析是编译过程的一个逻辑阶段。
语法分析的任务是在的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述.语法分析程序可以用YACC等工具自动生成。
语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作。
语法分析的主要工作:
是识别由词法分析给出的单词序列是否是给定的正确句子(程序)。
语法分析常用的方法:
自顶向下的语法分析和自底向上的语法分析两大类。
此次设计中语法分析中主要通过递归下降分析法对语法分析处理过程进行控制,使输出的三地址表示的翻译的工作有条不紊的进行,同时识别语法分析中的语法错误。
递归下降法主要采用自顶向下方法,即从文法的开始符号开始进行分析,逐渐推导的往下构造语法树,使其树叶正好构造出所给定的源程序串。
自顶向下方法的关键是确定在推导过程中选择候选式的问题。
当进行推导时,一个非终结符可能对应多个产生式,这样我们就无法事先知道应该用哪个产生式,因此实用都作了一些限制。
以便在任何情况下都能确定应该用的产生式。
自顶向下的主要思想是从开始符出发导出句型并一个符号一个符号地与给定终结符串进行匹配。
如果全部匹配成功,则表示开始符号可推导出给定的终结符串。
因此判定给定终结符号串是正确句子。
词法分析程序和语法分析程序的关系:
1.3.3、中间代码生成:
中间代码,也称中间语言,是复杂性介于源程序语言和机器语言的一种表示形式。
为了使编译程序有较高的目标程序质量,或要求从编译程序逻辑结构上把与机器无关和与机器有关的工作明显的分开来时,许多编译程序都采用了某种复杂性介于源程序语言和机器语言之间的中间语言。
中间代码(语言)是一种特殊结构的语言,编译程序所使用的中间代码有多种形式。
按其结构分常见的有逆波兰式(后缀式)、三地址代码(三元式、四元式)和树形表示(抽象语法树)、DAG表示。
本次课程设计要实现的是三地址表示。
1.3.4、属性文法:
对于文法的每个产生式都配备了一组属性的计算规则,称为语义规则。
所谓语法制导的翻译指的是在语法分析过程中,完成这些语义规则描述的动作,从而实现语义处理。
一个属性文法包含一个上下文无关文法和一系列语义规则,这些语义规则附在文法的每个产生式上。
形式上讲,属性文法是一个三元组:
A=(G,V,F),其中:
G:
是一个上下文无关文法;
V:
有穷的属性集,每个属性与文法的一个终结符或非终结符相连,这些属性代表与文法符号相关信息;
F:
关于属性的属性断言或一组属性的计算规则(称为语义规则)。
断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。
2、递归下降法
递归下降法又称递归子程序法。
在程序语言的语法定义中有许多采用递归定义。
我们在对它进行语法分析时,编制的处理程序也采取递归的方式,可使其结构简单易读。
但由于频繁地调用子程序大大地降低了分析速度。
2.1、递归下降法的主要思想:
对每个非终结符按其产生式结构写出相应语法分析子程序。
因为文法递归相应子程序也递归,子程序的结构与产生式结构几乎一致。
所以称此种方法称为递归子程序法或递归下降法。
2.2、用程序表示递归子程序的内部结构:
设A是一个非终结符:
A→β1
A→β2
┊
A→βn
则写ζ(A)ifchar∈first(β1)thenζ(β1)
elseifchar∈first(β2)thenζ(β2)
else…
ifchar∈first(βn)thenζ(βn)
elseERROR
其中ζ(βi)表示调用处理符号串βi的子程序。
对A的任一右部i设为:
βi=y1y2…yn
则定义ζ(βi)beginζ(y1);
ζ(y2);
…;
ζ(yn)end
其中yj可分为下列两种情况(j=1,…,n):
1)yj∈VT,则
ζ(yj)ifchar≠yjthenERRORelseREAD(char)
2)yj∈VN,则ζ(yj)表示调用关于yj的递归子程序。
2.3、递归下降法对文法的限制:
1、任一非终结符B都不是左递归的,否则会产生死循环。
2、对A的任意两个右部βi,βj,有:
first(βi)∩first(βj)=φ。
First(βi)表示βi所能导出串的第一个符号的集合。
显然,每个βi的first(βi)是互不相同的,否则则无法判断应执行哪个ζ(βi)。
3、三地址代码的表示:
一般形式:
x:
=yopz
如表达式x+yz翻译成的三地址代码序列是:
t1:
=yz
t2:
=x+t1
常用的三地址表示:
赋值语句x:
=yopz,x:
=opy,x:
=y
无条件转移gotoL
条件转移ifxrelopygotoL
过程调用paramx和callp,n
过程返回returny
索引赋值x:
=y[i]和x[i]:
地址和指针赋值x:
=&
y,x:
=y 和 x:
=y
三元式结构形式:
编号(OP,ARG1,ARG2)
4、语法制导翻译
4.1、翻译任务的处理过程
编译程序的整个任务就是把源程序翻译为目标程序。
实际上可以把每个编译阶段都看作是完成一定翻译任务的处理过程:
词法分析阶段把字符流翻译为单词流,语法分析阶段把单词流翻译为语法树,目标代码生成阶段把语法树翻译为汇编语言等等。
4.2、语法制导翻译:
在语法分析过程中,随着分析的步步进展,每当进行推导或归约时,同步的去执行每个产生式所附带的语义规则描述的语义动作(或语义子程序),这样进行翻译的办法称作语法制导翻译。
所谓属性依赖图是一个有向图,用于描述分析树中的属性和属性间的相互依赖关系。
4.3、基于属性文法的处理方法
输入串→语法树→依赖图→计算语义规则顺序→语法分析树遍历→执行语义规则
语义规则的计算可能产生代码,在符号表中存取信息,给出出错信息或执行其它动作。
对输入串的翻译也就是根据语义规则进行计算的结果。
5、中间代码形式的描述及中间代码序列的结构设计
本次设计,使用的中间代码为三地址码。
三元式有三个组成成分:
算符op,第一和第二运算对象ARG1和ARG2。
例如:
有中缀式a:
=b*-c+b*-c,求其等价的三元式。
三元式
编号算符左对象右对象
oparg1arg2
(1)minusc
(2)*b
(1)
(3)minusc
(4)*b(3)
(5)+(4)
(2)
(6)assigna
设计并生成的结果程序,最终需要将用户输入的程序经过词法分析和语法分析,生成如上所述的三元式表示的中间代码形式。
6、简要的分析与概要设计
程序由词法分析和语法分析两部分构成:
6.1、词法分析:
intbuffer()//载入
{
inti=0;
cout<
<
"
输入程序,以#作为结束标志。
endl;
for(intn=0;
n<
=MAX;
n++)
for(;
i<
i++)
scanf("
%c"
&
str[i]);
if(str[i]=='
#'
)
break;
//如果尾数为识别码#,则表示程序读完,跳出循环.
}
return(i);
boolIsLetter(charch)//判断是否是字母
if(ch>
=65&
&
ch<
=90||ch>
=97&
=122)
return(true);
else
return(false);
boolIsDigit(charch)//判断是否是数字
=48&
=57)
charGetChar(inti)//读取字符
charch;
ch=str[i];
return(ch);
charGetBC(charch)//判断是不是空格或者换行,如果是,直接读取下一个字符直道不再空白为止
if(ch==32||ch==10)
turn++;
ch=GetChar(turn);
ch=GetBC(ch);
//递归实现
voidConcat()//连接,即为strtoken[]赋值
strToken[n]=ch;
n++;
intReserve()//以单词为单位查找保留字,是则返回编码,不是则返回0,用来区分标志符和保留字
if(strcmp(strToken,"
DIM\0"
)==0)//调用strcmp函数实现,
return
(1);
elseif(strcmp(strToken,"
for\0"
)==0)
return
(2);
step\0"
return(3);
until\0"
return(4);
do\0"
return(5);
return(6);
voidclear()
n=0;
}
6.2、语法递归分析
intA(int*c,int&
q)
if(c[q++]==3)
if(c[q]==7)
{q++;
return1;
else{cout<
step右部出错"
return0;
}else{cout<
error'
step'
intB(int*b,int&
o)
if(b[o++]==4)
if(b[o]==7)
{o++;
until右部出错"
until'
intS2(int*d,int&
h)
if(d[h++]==6)
if(d[h++]==8)
if((d[h]==6||d[h]==7)){h++;
return1;
赋值语句右部出错"
赋值语句缺少赋值运算符"
赋值语句左部出错"
intS1(int*m,int&
n)
if(S2(m,n))
if(A(m,n))
if(B(m,n))return1;
elsereturn0;
}elsereturn0;
intS(int*a,int&
z)
if(a[z++]==2)
if(S1(a,z))
if(a[z++]==5)
if(S2(a,z))
succeed!
do'
return0;
for'
6.3、制导翻译
if(!
S(ana,j))cout<
语法出错!
{cout<
三地址码如下:
100"
;
while(record[1]->
word[i]!
='
\0'
record[1]->
word[i++];
record[2]->
word[0];
i=0;
while(record[3]->
record[3]->
101goto103"
102"
:
="
+"
while(record[5]->
record[5]->
103if"
while(record[7]->
record[7]->
goto105"
104goto107"
105"
while(record[9]->
record[9]->
while(record[11]->
record[11]->
106goto102"
107end"
6.4、主函数
voidmain()
*************产生式***************"
//forstepuntildoij=
S->
forS1doS2"
//编号2345678
S1->
S2AB"
S2->
i=j"
A->
stepj"
B->
untilj"
intnum;
turn=0;
num=buffer()-1;
intx=0;
//计识别的单词的个数
turn<
=num;
turn++)//总循环,ch存放刚读入的字符,strtoken[]存放已识别的标志付或保留字,turn是数组str[]的下标
if(IsLetter(ch))
while(IsLetter(ch)&
=num||IsDigit(ch)&
=num)
Concat();
ch=GetChar(++turn);
strToken[n]='
ch=NULL;
//此ch不是标志符中的符号
turn=turn-1;
kind=Reserve();
record[x]=newWord;
record[x]->
sort=kind;
//12345或6
("
for(inti=0;
n;
record[x]->
word[i]=strToken[i];
word[i];
//输出识别的标志符或保留字
"
kind<
)"
word[i]='
clear();
x++;
elseif(IsDigit(ch))
while(IsDigit(ch)&
ki