学 号: 0120810340605
课 程 设 计
IF-ELSE 条件语句的翻译程
题 目
序设计(LL(1)法、输出三
地址表示)
学 院
计算机科学与技术学院
专 业
计算机科学与技术
班 级
姓 名
指导教师
0806
周雪
郭羽成
2010 年 1 月 6 日
课程设计任务书
学生姓名: 周 雪
专业班级:
计算机 0806 班
指导教师: 郭 羽 成 工作单位:计算机科学与技术学院
题目: IF-ELSE 条件语句的翻译程序设计(LL(1)法、输出三地址表
示)
初始条件:
理论:学完编译课程,掌握一种计算机高级语言的使用。
实践:计算机实验室提供计算机及软件环境。如果自己有计算机可以在其上进
行设计。
要求完成的主要任务: (包括课程设计工作量及其技术要求,以及说明书撰写等具体
要求)
(1) 写出符合给定的语法分析方法的文法及属性文法。
(2) 完成题目要求的中间代码三地址表示的描述。
(3) 写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
(4) 编制好分析程序后,设计若干用例,上机测试并通过所设计的分析程序。
(5) 设计报告格式按附件要求书写。课程设计报告书正文的内容应包括:
1 系统描述(问题域描述);
2 文法及属性文法的描述;
3 语法分析方法描述及语法分析表设计;
4 按给定的题目给出中间代码形式的描述及中间代码序列的结构设计;
5 编译系统的概要设计;
6 详细的算法描述(流程图或伪代码);
7 软件的测试方法和测试结果;
8 研制报告(研制过程,本设计的评价、特点、不足、收获与体会等);
9 参考文献(按公开发表的规范书写)。
时间安排:
设计安排一周:周 1、周 2:完成系统分析及设计。
周 3、周 4:完成程序调试及测试。
周 5:撰写课程设计报告。
设计验收安排:设计周的星期五第 1 节课开始到实验室进行上机验收。
设计报告书收取时间:设计周的次周星期一上午 10 点。
指导教师签名:
2010 年 11 月 23 日
系主任(或责任教师)签名:
2010 年 11 月 23 日
1 问题描述
要求用 LL(1)自顶向下分析方法及三地址中间代码,对 IF-THEN-ELSE 条件语句完成
编译各阶段过程,包括词法、语法、语义等分析。
2 问题分析及编译系统的概要设计
编译过程一般分为六个阶段的过程,可以由六个模块完成,它们称为词法分析程
序、语法分析程序、语义分析程序、中间代码生成程序、代码优化程序、目标代码生成
程序,此外,一个完整编译程序还必须包括“表格管理程序”和“出错处理程序”。
这次实验涉及到词法分析、语法分析、语义分析及表格管理和出错管理。其中,
词法分析至少要能识别关键字“if”、“then”和“else”,标识符(即自定义变量),数
字,和运算符等等;语法分析要分析程序结构的合法性,即是否为文法的句子;语义分
析要能够语法制导翻译出中间代码(三地址)并将其输出;表格管理是指符号表;出错
处理是指在语法分析时,所有非文法句子的错误类型处理.
3 文法及属性文法的定义
3.1 文法:
文法是用于描述语言的语法结构的形式规则(即语法规则)。这些规则必须是准确
的、易于理解的以及有相当强的描述能力。由这种规则所产生的程序语言应有利于句子
分析和翻译,而且,最好能通过这些规则自动产生有效的语法分析程序.
IF-ELSE 条件语句的文法如下所示:
0.A->EB
1.B->+EB|-EB|ε
2.E->FT
3.T->*FT|/FT|ε
4.F->i|(E)
或者能够更简洁一点:
0.S->if A THEN B ELSE C
1.A->m rop n
2.B->x=m arop n
3.C->x=n arop m
4.rop->=|<|>
5.arop->+|-|*|/
3.2 属性文法:
属性文法是在上下文无关文法的基础上,为每个文法符号(终结符或者非终结符)
配备若干相关的“值”(与文法符号相关的属性)。
在一个属性文法中,对应于每个产生式 A→a 都有一套与之相关联的语义规则,
每规则的形式为:b:=f(c1,c2,…,ck)其中 f 是一个函数,而且或者①b 是 A 的一个
综合属性并且 c1,c2,…,ck 是产生式右边文法符号的属性或者②非终结符既可有综合
属性也可有继属性,文法开始符号的所有继承属性作为属性计算前的初始值。
属性文法为:
0.S->if A THEN B ELSE C
{ S.chain:=merge(A.chain,B.chain, C.chain)}
1.A->m rop n
{ A.true:=nextstat;
A.false=nextstat+1;
backpatch(A.chain,nextstat);
emit(“if p” rop “q goto —”)
emit(“goto —”) ; }
2.B->x=m arop n
{ backpatch(B.chain,nextstat);
emit(“ x:= m” arop “n”);
emit(“goto —”); }
3.C->x=n arop m
{ backpatch(C.chain,nextstat);
emit(“ x:= n” arop “m”);
emit(“goto —”); }
4.rop -> = { emit(“ = ”); }
5. rop -> <{ emit(“ < ”); }
6. rop -> >{ emit(“ > ”); }
7. arop -> +{ emit(“ + ”); }
8. arop-> - { emit(“ - ”); }
9.arop-> *{ emit(“ * ”); }
10.arop-> /{ emit(“ / ”); }
4 词法分析
首 先 应 该 创 建 一 个 枚 举 类 型 的 变 量 来 存 放 一 些 关 键 字 , enum
keyword{$right_paren,$left_paren,$mul,$div,$add,$sub,$fenhao,$equal,$IF,$THEN,$EL
SE,$greater,$less,$id,$num,$end};
再创建一个结构体,用来存放词法分析的结果,共有两个域,一个关键字域,表
明他是什么类型,以及它自身的内容。
这个词法分析程序比较简单,因为本身的程序就局限在 if-else 语句,所以保留
字的类型我就只写了 if、then 和 else 三个;碰到数字开头的除了关键字就是标识
符;碰到数字开头的就是数字;碰到界限符和操作符(因为引入的类型也很少),
所以也很容易区别。
在词法分析结束之后,就应该把分析的结果输出来。输出的格式是【(单词,类
型编号) 类型名】
源程序文件
字符的分离
单词的判断
查找相应的表
单词的类型的判断
调 用 不 同 类 型 的 单 词 处
理函数进行单词的处理
产生类型码
将中间单词和其类型码存入数组
处理完毕
词法分析程序如下:
bool lexcal()
{
int k=0;
char buf[16];
char ch;
while(1)
{
ins>>ch;
if(ins.fail())
break;
while(ch==' ')
ins>>ch;}
{
if(ch=='I')
{
{
}
{
ins>>buf;
if(strcmp(buf,"F")==0)
tokentable[total_len++].type=$IF;
}
else if(ch=='T')
ins>>buf;
if(strcmp(buf,"HEN")==0)
tokentable[total_len++].type=$THEN;
else if(ch=='E')
ins>>buf;
if(strcmp(buf,"LSE")==0)
tokentable[total_len++].type=$ELSE;
}
else if(ch=='>')
{
}
else if(ch=='<')
{
}
tokentable[total_len++].type=$greater;
tokentable[total_len++].type=$less;
else if(ch=='=')
{
{
tokentable[total_len++].type=$equal;
}
else if((ch>='A'&& ch<='Z' )|| (ch>='a' && ch<='z'))
{
tokentable[total_len].type=$id;
tokentable[total_len++].ch=ch;
}
else if(ch>='0' && ch<='9')
tokentable[total_len].type=$num;
tokentable[total_len++].ch =ch;
}
else
switch (ch)
{ case '+' :
tokentable[total_len].type=$add;
tokentable[total_len++].ch =ch;
break;
case '-' :
case '/' :
tokentable[total_len].type=$sub;
tokentable[total_len++].ch =ch;
break;
tokentable[total_len].type=$div;
tokentable[total_len++].ch =ch;
break;
case '*' :
tokentable[total_len].type=$mul;
tokentable[total_len++].ch =ch;
break;
case ';' :
case '(' :
case ')' :
tokentable[total_len].type=$fenhao;
tokentable[total_len++].ch =ch;
break;
tokentable[total_len].type=$left_paren;
tokentable[total_len++].ch =ch;
break;
tokentable[total_len].type=$right_paren;
tokentable[total_len++].ch =ch;
break;
default:cout<<"!"<'Z'){
if(X==a){
sp--;
front++;