编译原理课程设计ifelse条件语句翻译三地址简单优先法 1.docx
《编译原理课程设计ifelse条件语句翻译三地址简单优先法 1.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计ifelse条件语句翻译三地址简单优先法 1.docx(44页珍藏版)》请在冰豆网上搜索。
![编译原理课程设计ifelse条件语句翻译三地址简单优先法 1.docx](https://file1.bdocx.com/fileroot1/2023-1/24/d6466d5a-b430-449a-8179-7b5f14105e5d/d6466d5a-b430-449a-8179-7b5f14105e5d1.gif)
编译原理课程设计ifelse条件语句翻译三地址简单优先法1
课程设计任务书
题目:
IF-ELSE条件语句的翻译程序设计(简单优先法、输出三地址表示)
初始条件:
理论:
学完编译课程,掌握一种计算机高级语言的使用。
实践:
计算机实验室提供计算机及软件环境。
如果自己有计算机可以在其上进行设计。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
(1)写出符合给定的语法分析方法的文法及属性文法。
(2)完成题目要求的中间代码三地址表示的描述。
(3)写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
(4)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
(5)设计报告格式按附件要求书写。
课程设计报告书正文的内容应包括:
1系统描述(问题域描述);
2文法及属性文法的描述;
3语法分析方法描述及语法分析表设计;
4按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;
5编译系统的概要设计;
6详细的算法描述(流程图或伪代码);
7软件的测试方法和测试结果;
8研制报告(研制过程,本设计的评价、特点、不足、收获与体会等);
9参考文献(按公开发表的规范书写)。
时间安排:
设计安排一周:
周1、周2:
完成系统分析及设计。
周3、周4:
完成程序调试及测试。
周5:
撰写课程设计报告。
设计验收安排:
设计周的星期五第1节课开始到实验室进行上机验收。
设计报告书收取时间:
设计周的次周星期一上午10点。
指导教师签名:
2013年月日
系主任(或责任教师)签名:
2013年月日
IF-ELSE条件语句的翻译程序设计(简单优先法、输出三地址表示)
1系统描述
1.1题目
IF-ELSE条件语句的翻译程序设计(简单优先法、输出三地址表示)
1.2.目的
通过设计、编制、调试一个条件语句的语法及语义分析程序,加深对语法及语义分析原理的理解,并实现词法分析程序对单词序列的词法检查和分析。
1.3.设计内容及步骤
对条件语句:
IF〈布尔表达式〉THEN〈赋值语句〉ELSE〈赋值语句〉
(1)按给定的题目写出符合语法分析方法要求的文法和属性文法描述。
(2)按给定的题目给出语法分析方法的思想及分析表设计。
(3)按给定的题目给出中间代码序列的结构设计。
(4)完成相应的词法分析、语法分析和语义分析程序设计。
(5)编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
2文法及属性文法的描述
2.1文法
文法是用于描述语言的语法结构的形式规则(即语法规则)。
这些规则必须是准确的、易于理解的以及有相当强的描述能力。
由这种规则所产生的程序语言应有利于句子分析和翻译,而且,最好能通过这些规则自动产生有效的语法分析程序。
IF-ELSE条件语句的文法G[S]如下所示:
(1)S->CM
(2)S->TM
(3)M->beginLend
(4)C->ifBthen
(5)T->CMelse
其中非终结符B为布尔表达式,其文法G[B]如下:
(1)B->B1orB2
(2)B->B1andB2
(3)B->notB1
(4)B->(B1)
(5)B->id1ropid2
(6)B->true
(7)B->false
而在文法G[S]中非终结符L表示赋值语句块,其文法G[L]如下:
(1)L->L1A;
(2)L->A;
(3)A->id=M
(4)M->E
(5)E->E1+E2
(6)E->E1*E2
(7)E->-E1
(8)E->(E1)
(9)E->id
2.2属性文法
属性文法是在上下文无关文法的基础上,为每个文法符号(终结符或者非终结符)配备若干相关的“值”(与文法符号相关的属性)。
在一个属性文法中,对应于每个产生式A→a都有一套与之相关联的语义规则,每规则的形式为:
b:
=f(c1,c2,…,ck)其中f是一个函数,而且或者①b是A的一个综合属性并且c1,c2,…,ck是产生式右边文法符号的属性或者②非终结符既可有综合属性也可有继属性,文法开始符号的所有继承属性作为属性计算前的初始值[1]。
2.2.1语义变量和语义动作说明
对于文法G[L],首先对id表示的单词定义一属性id.name,用做语义变量,用Lookup(id.name)语义函数审查id.name是否出现在符号表中,如在,则返回一指向该登陆项的指针,否则返回nil。
语义过程emit表示输出四元是到输出文件上。
语义过程newtmp表示生产一临时变量,每调用一次,生成一新的临时变量。
语义变量E.place,表示存放E值的变量名在符号表的登陆项或一整数码(若此变量时一个临时变量)[2],
2.2.1给出了翻译赋值语句块到三地址的语义描述。
2.2.1G[S]的属性文法为:
(1)S->CM{S.chain:
=merge(C.chain,M.chain)}
(2)S->TM{S.chain:
=merge(T.chain,M.chain)}
(3)M->beginLend{M.chain:
=L.chain}
(4)C->ifBthen{bakpatch(B.true,nextstat)
C.chain:
=B.false}
(5)T->CMelse{q:
=nextstat
emit(‘GOTO’--)
backpatch(C.chain,nextstat)
T.chain:
=merge(M.chain,q)}
2.2.2G[B]的属性文法为:
(1)B->B1orB2{backpatch(B1.false,B2.codebgin);
B.codebegin:
=B1.codebegin;
B.true:
=merge(B1.true,B2.true);
B.false:
=B2.false}
(2)B->B1andB2{backpatch(B1.true,B2.codebegin);
B.codebegin:
=B1.codebegin;
B.true:
=B2.true;
B.false:
=merge(B1.false,B2.false);}
(3)B->notB1{B.true:
=B1.false;
B.codebegin:
=B1.codebegin;
B.false:
=B1.true;}
(4)B->(B1){B.true:
=B1.true;
B.codebegin:
=B1.codebegin;
B.false:
=B1.false;}
(5)B->id1ropid2{B.true:
=nextstat;
B.codebegin:
=nextstat;
B.false:
=nextstat+1;
emit(‘if’id1.place‘rop’id2.place‘goto’--);
emit(‘goto’--)}
(6)B->true{B.true:
=nextstat;
B.codebegin:
=nextstat;
emit(‘goto’--)}
(7)B->false{B.false:
=nextstat;
B.codebegin:
=nextstat;
emit(‘goto’--)}
其中nextstat给出在输出序列中下一三地址式子的序号。
emit过程没调用一次,nextstat增加1
2.2.3G[L]的属性文法为:
(1)L->L1A;{L.chain:
=A.chain}
(2)L->A;{L.chain:
=A.chain}
(3)A->id:
=M{p:
=lookup(id.name);
ifp≠nilthen
emit(p‘:
=’E.place);
elseerror}
(4)M->E{}
(5)E->E1+E2{E.place:
=newtemp;
emit(E.place‘:
=’E1.place‘+’E2.place)}
(6)E->E1*E2{E.place:
=newtemp;
emit(E.place‘:
=’E1.place‘*’E2.palce)}
(7)E->-E1{E.palce:
=newtemp;
emit(E.place‘:
=’‘minus’E1.place)}
(8)E->(E1){E.place:
=E1.place}
(9)E->id(6)A->num{p:
=lookup(id.name);
ifp≠nilthen
E.palce:
=p
elseerror}
3语法分析方法描述及语法分析表设计
3.1简单优先法的定义构造及优缺点
3.1.1简单优先法定义构造
一个文法G,若它不含ε产生式,也不含任何右部相同的不同产生式,并且它的任何符号对(X,Y),或者没有关系,或者存在下述三种关系:
=、<、>之一,则称该文法是一个简单优先文法。
A)X=Y当且仅当G中含有形如P→…XY…的产生式
B)XC)X>Y当且仅当Y为G的终结符,G中含有形如P→…QR…的产生式,其中Q,R为非终结符,且Q→…X,Y∈First(R)
D)对任何X,若文法开始符号S→X…,则##。
[3]
3.1.2简单优先法的优缺点
优点:
准确、规范,技术简单。
缺点:
适用的范围小,构造的分析表太大,分析效率较低。
3.2语法分析
为实现简单优先算法,可以使用工作栈.用以寄存操作数或运算结果.算法的基本思想是:
(1)置初始状态:
S
(1):
=‘#’,i:
=1,j:
=1
(2)若S(i)与T(j)无任何关系,则出错停机
(3)若S(i)=T(j)或S(i)〈T(j),则把T(j)送入S栈中,读下一符,转
(2)。
(4)若S(i)〉T(j),则从S栈顶开始往前栈串Sj1,Sj1+1,…,Si
其中Sj1为第一个使Sj1-1〈Sj1,然后用Sj1,Sj1+1,…Si去查生产式表,
若查到有相同右部的产生式即U→Sj1,Sj1+1,…Si,则从栈中退掉子串Sj1,Sj1+1,…Si,并把U进栈;然后转
(2)。
若查不到转出错处理。
(5)若T(j)=‘#’,并且S栈的内容为#Z(Z为文法开始符号)则正确停机。
否则,出错停机。
3.3语法分析表设计
3.3.1G[S]的优先关系表如表1:
表1G[S]的优先关系矩阵
S
C
T
M
begin
L
end
if
B
then
else
#
S
<
>
C
=
<
T
=
<
M
=
>
begin
<
=
L
end
>
>
if
=
B
=
then
>
>
else
>
>
#
<
<
<
<
<
<
注:
表中空白表示无优先关系,分析过程中查找到无优先关系的两个文法符号则表示出错,下同。
3.3.2G[B]的优先关系表如表2:
表2G[B]的优先关系矩阵
B
or
and
not
(
)
id
rop
true
fasle
#
B
=
=
=
>
or
<
<
<
and
<
<
not
<
>
(
)
>
id
>
>
=
>
rop
=
true
>
>
>
false
>
>
>
#
<
<
<
<
注:
表中id代表标识符,rop代表关系运算符,下同。
3.3.2G[L]的优先关系表如表3:
表3G[L]的优先关系矩阵
L
A
;
:
=
(
)
id
+
-
M
E
*
#
L
=
<
>
A
=
>
;
>
>
:
=
<
<
<
=
<
(
<
=
)
>
<
id
>
=
>
>
>
+
>
<
<
=
-
<
<
=
M
>
E
>
<
=
=
=
*
>
<
<
=
#
<
<
<
4.中间代码形式的描述及中间代码序列的结构设计
4.1中间代码形式描述
此设计要求使用的是三地址的中间代码,三地址代码是由下面一般形式构成的语句序列:
x:
=yopz;
其中x,y,z为变量名,常数或编译时产生的临时变量;op代表运算符号如标点,浮点运算符号等等。
每个语句的右边只能有一个运算符。
表达式x+y*z翻译成的三地址语句序列是:
t1:
=y*z
t2:
=x+t1
常用的三地址语句有:
赋值语句x:
=yopz,x:
=opy,x:
=y
无条件转移gotoL
条件转移ifxrelopygotoL
过程调用paramx和callp,n
过程返回returny
索引赋值x:
=y[i]和x[i]:
=y
地址和指针赋值x:
=&y,x:
=*y和*x:
=y
4.2中间代码序列的结构设计
本次课程设计采用四元式的中间代码形式,例如
赋值语句x:
=y*z*a的三地址表示如下:
001:
T1:
=a*z
002:
T2:
=T1*y
003:
x:
=T2
if-else语句块:
ifa>bandcbegin
p=q+r+s;
c=w;
end
的三地址表示如下:
001:
ifa>bgoto3
002:
goto--
003:
ifc004:
goto--
005:
T1:
=s+r
006:
T2:
=T1+q
007:
p:
=T2
008:
c:
=w
其中前面的数字表示三地址的序列号或者说是中间代码的地址,Ti为中间代码翻译过程中产生的临时变量,符号‘—’,表示在后续的翻译过程中待回填的goto语句转移地址。
5编译系统的概要设计
5.1程序总体描述
本设计体现语法制导翻译的思想,采用单遍的翻译方法,在语法分析的过程中同时完成词法分析和中间代码的翻译。
图1程序总体概要设计
5.2数据结构设计
5.2.1用于“回填”和“拉链”的链表结构设计如下:
structChain{
intlabel;//三地址代码语句的序号
Chain*next;//下一个节点指针
};
5.2.2属性单词Token的数据结构如下:
structToken{
charname[20];//名字
Classifykind;//类型
Chain*trueChain;//“真链”
Chain*falseChain;//“假链”
Chain*chain;//待“回填”的链
intcodeBegin;//非终结符的第一个三地址语句序号
intweight;//该变量用于计算归约用的的产生式序号
intpos;//文法符号在优先关系表中的位置
intplace;//属性单词在符号表中的登陆项
doublevalue;//数值型单词的值,其他类型无定义
intlineNumber;//单词所在源文件的行号
charorig[20];//如为非终结符,该变量用于保存被规约
//成该非终结符的终结符,否则无定义
}
5.2.3三地址码数据结构设计
structTripleCode{
CodeKindkind;//三地址语句格式种类
charop;//运算符
charresult[20];//运算结果
charopn1[20];//操作数1
charopn2[20];//操作数2
intdestination;//goto语句的转移地址
boolterm0;//结果变量是否是终结符
boolterm1;//操作数1是否是终结符
boolterm2;//操作数2是否是终结符
intserial0;//如结果为临时变量,用于保存该临时变量的序列号
intserial1;//如果操作数1为临时变量,用于保存该临时变量的
//序列号
intserial2;//如果操作数2为临时变量,用于保存该临时变量的
//序列号
};
根据产生式的序号和产生式右边文法符号的个数,给产生式右边每个文法符号赋予一定的weight值,在规约的时候,产生式右边各个文法符号的weight域相加的和为该产生式的序号,从而确定用哪条产生式规约。
三地址代码的格式设计为5种,分别是“if-goto”型、“goto”型、赋值型、单目运算型和双目运算型
5.3程序接口声明
5.3.1.1词法分析器类Lexical的类图
图2Lexical类
classLexical
Attributes
privatecharch
privateintU_inde
privateintlineNum
privateintlen
privateintbuffEnd
privatedoublevalue
privateifstreamfin
privateofstreamfout
privatestringoutputFile
privatestaticintserial
privatestaticintnextstat
privatecharline[100]
privatecharword[40]
privateintbuffer[MAX_BUFFER_SIZE]
privateTokentokens[MAX_SYMBOL_SIZE]
privateTripleCodecodes[MAX_CODE_NUM]
privatecharseparators[SEPARATOR_COUNT]
privatechar*keywordTable[KEYWORD_COUNT]
privatechar*operators[OPERATOR_COUNT]
Operations
publicLexical()
public~Lexical()
publicToken*getNextToken()
publicToken*getNewToken()
publicintlookup()
publicvoidemit()
publicvoidgenCode()
publicvoidprintCode()
publicvoidbackpatch()
publicvoidputBackToken()
publicvoidwriteCodeToFile()
publicstaticinlineintgetNextStat()
publicstaticintgetSerialNum()
privateintgetChar()
privatevoidgetWord()
privatevoidskipSlash()
privatevoidgetLine()
privateintfindKeyword()
privateintfindSeparator()
privatevoidreadOperator()
privatedoublestring2Double()
5.3.1.2Lexical类主要接口说明
publicToken*getNextToken()//返回源文件中的下一个属性单词的指针
publicToken*getNewToken()//返回符号表中下一个可用新项目的指针
publicintlookup()//语义函数,查找给定名字的单词是否在符号表中
publicvoidemit()//语义函数,生成一条三地址代码并保存到三地址代
//码数组中,emit过程每调用一次,nextstat增加1
publicvoidgenCode()//语义函数,作用同emit,genCode每调用一次,
//nextstat也增加1
publicvoidprintCode()//输出三地址码到屏幕
publicvoidbackpatch()//用于回填的函数
publicvoidputBackToken()//将属性单词