编译原理 简单编译器课程设计报告.docx

上传人:b****3 文档编号:3652660 上传时间:2022-11-24 格式:DOCX 页数:30 大小:116.16KB
下载 相关 举报
编译原理 简单编译器课程设计报告.docx_第1页
第1页 / 共30页
编译原理 简单编译器课程设计报告.docx_第2页
第2页 / 共30页
编译原理 简单编译器课程设计报告.docx_第3页
第3页 / 共30页
编译原理 简单编译器课程设计报告.docx_第4页
第4页 / 共30页
编译原理 简单编译器课程设计报告.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

编译原理 简单编译器课程设计报告.docx

《编译原理 简单编译器课程设计报告.docx》由会员分享,可在线阅读,更多相关《编译原理 简单编译器课程设计报告.docx(30页珍藏版)》请在冰豆网上搜索。

编译原理 简单编译器课程设计报告.docx

编译原理简单编译器课程设计报告

信息科学与工程学院课程设计任务书

 

题目:

一个简单编译器的设计与分析

 

姓名:

学号:

专业班级:

课程:

编译原理

指导教师:

职称:

讲师

完成时间:

2011年12月----2011年12月

枣庄学院信息科学与工程学院制

2011年12月20日

课程设计任务书及成绩评定

课程设计的任务和具体要求

在理解编译原理相关理论的基础上,要求用C或C++语言描述及上机调试,实现一个小编译器(包括符号表的构造,词法分析,语法分析,语义分析,目标代码生成等重要子程序,其中词法分析、语法分析及语义分析功能必须完成),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。

 

指导教师签字:

_______日期:

指导教师评语

 

成绩:

____________指导教师签字:

日期:

课程设计所需软件、硬件等

硬件环境:

WindowsXP/Win7操作系统

软件环境:

MicrosoftvisualC++6.0

课程设计进度计划

起至日期

工作内容

备注

2011-12-01—05

2011-12-06—10

2011-12-11—16

查找资料

理清思路,编写程序

完善程序,编辑文档

参考文献、资料索引

序号

文献、资料名称

编著者

出版单位

【1】

程序设计语言编译原理陈火旺李春林国防工业出版社

【2】数据结构严蔚敏清华大学出版社

【3】C++程序设计吴乃林况迎辉高等教育出版社

【4】C语言程序设计谭浩强清华大学出版社

【5】程序设计语言编译原理陈火旺、刘春林等国防工业出版社

 

一、摘要

编译程序的工作过程一般可以分为五个阶段:

词法分析、语法分析、语义分析与中间代码产生、优化、目标代码生成。

每一个阶段在功能上是相对独立的,它一方面从上一个阶段获取分析的结果来进行分析,另一方面由将结果传递给下一个阶段。

由编译程序的五个阶段就对应了编译系统的结构。

其中词法分析器利用超前搜索、状态转换等方法,将源程序转化成为一个一个的单词符号二元式。

一般程序语言的单词符号包括关键字、运算符、常数、标识符和界符。

语法分析器将这些单词符号作为输入,对它进行语法分析。

语法分析分为两种方法:

自上而下分析法和自下而上分析法。

针对不同程序语言的语法规则可以采取不同的分析方法,当然两种方法也可以同时使用。

语法分析器把语法单元作为输入供语义分析器使用。

一般的语义分析器主要采用的是语法制导方法,即在语法分析的同时进行语法分析,并产生一定的语义动作,来生成中间代码。

上面三个过程可以与硬件无关,而接下来的优化器和目标代码生成器是针对某一种处理器而言的。

代码优化是将语义分析生成的中间代码进行优化,产生执行效率更高的代码。

目标代码生成器最终生成可以在某种机器上运行的机器语言或者汇编语言。

在整个编译过程中还包括对表格的操作和对错误的处理,这些也都是非常重要的环节。

 

下图给出了编译系统的结构框图

 

二、总体设计方案及主要设计原理

2.1、单词符号及种别表示

单词符号

种别编码

单词值

main

1

 

int

2

 

float

3

 

double

4

 

char

5

 

if

6

 

else

7

 

do

8

 

while

9

 

l(l|d)*

10

内部字符串

(+|-|ε)d*(.dd*|ε)(e(+|-|ε)dd*|ε)

20

二进制数值表示

=

21

 

+

22

-

23

 

*

24

 

/

25

 

26

 

27

 

{

28

 

}

29

 

30

 

;

31

 

>

32

 

>=

33

 

<

34

 

<=

35

 

==

36

 

!

=

37

 

 

2.2、语法结构定义

<程序>:

:

=main()<语句块>

<语句块>:

:

=‘{‘<语句串>’}’//程序用括号括起来

<语句串>:

:

=<语句>{;<语句>};

<语句>:

:

=<赋值语句>|<条件语句>|<循环语句>

<赋值语句>:

:

=ID=<表达式>//赋值语句用”=”号

<条件语句>:

:

=if<条件><语句块>//条件怎么没有括号,囧(自己加1个)

<循环语句>:

:

=do<语句块>while<条件>

<条件>:

:

=<表达式><关系运算符><表达式>

<表达式>:

:

=<项>{+<项>|-<项>}

<项>:

:

=<因子>{*<因子>|/<因子>}

<因子>:

:

=ID|num|(<表达式>)

num:

:

=(+|-|ε)数字*(.数字数字*|ε)(e(+|-|ε)数字数字*|ε)

ID:

:

=字母(字母|d数字)*

字母:

:

=a|b|c…|z|A|B|C…|Z

数字:

:

=0|1|2…|9

<关系运算符>:

:

=<|<=|>|>=|==|!

=

2.3、主要算法

2.3.1、词法分析主要算法

这部分对源文件进行分析,允许/**/注释。

从源文件依次读取字符,对字符进行分析,组成字符串、数字、关系符等固定含义的token符,并把它们添加到token链中,如果遇到非法字符报错并退出程序。

2.3.2、语法分析主要思想

这部分对Token链进行分析,利用自底向上的分析方法,构建SLR

(1)分析表的过程是手工完成的。

语法分析的同时构建语法树,移进时创建叶子,规约时创建节点。

2.3.3、语义分析主要分析

这部分对语法树从左到右进行遍历,节点记录了规约式的编号,遍历到节点时就进行相应处理。

语义分析主要检查变量、函数是否被定义或重定义,同时产生四元式。

三、源程序代码

 

#include

#include

#include

#include

charprog[80];//存放所有输入字符

chartoken[8];//存放词组

charch;//单个字符

intsyn,p,m,n,i;//syn:

种别编码

doublesum;

intcount;

intisSignal;//是否带正负号(0不带,1负号,2正号)

intisError;

intisDecimal;//是否是小数

doubledecimal;//小数

intisExp;//是否是指数

intindex;//指数幂

intisNegative;//是否带负号

doubletemp;

inttemp2;

intrepeat;//是否连续出现+,-

intnextq;

intkk;//临时变量的标号

intntc,nfc,nnc,nnb,nna;

char*rwtab[9]={"main","int","float","double","char","if","else","do","while"};

struct{

charresult[10];//字符串(字符数组)

chararg1[10];

charopera[10];

chararg2[10];

}fourCom[20];//结构体数组

voidscanner();//扫描

voidlrparser();

voidstaBlock(int*nChain);//语句块

voidstaString(int*nChain);//语句串

voidsta(int*nChain);//语句

voidfuzhi();//赋值语句

voidtiaojian(int*nChain);//条件语句

voidxunhuan();//循环语句

char*E();//Expresiion表达式

char*T();//Term项

char*F();//Factor因子

char*newTemp();//自动生成临时变量

voidbackpatch(intp,intt);//回填

intmerge(intp1,intp2);//合并p1和p2

voidemit(char*res,char*num1,char*op,char*num2);//生成四元式

voidmain()

{

p=0;

count=0;

isDecimal=0;

index=0;

repeat=0;

kk=0;

printf("\nPleaseinputyoursourcestring:

\n");

do{

ch=getchar();

prog[p++]=ch;

}while(ch!

='#');

p=0;

isError=0;

scanner();

lrparser();

for(i=1;i

{

printf("\n%d\t",i);

printf("(%5s%5s%5s\t%5s)\n",fourCom[i].arg1,fourCom[i].opera,fourCom[i].arg2,fourCom[i].result);

}

}

voidlrparser()

{

intnChain;

nfc=ntc=1;

nextq=1;

if(syn==1)//main

{

scanner();

if(syn==26)//(

{

scanner();

if(syn==27)//)

{

scanner();

staBlock(&nChain);

}

else

printf("缺少右括号\n");

}

else

printf("缺少左括号\n");

}

else

printf("缺少main\n");

}

//<语句块>:

:

='{'<语句串>'}'

voidstaBlock(int*nChain)//语句块

{

if(syn==28)//{

{

scanner();

staString(nChain);

//backpatch(*nChain,nextq);

if(syn==29)//}

scanner();//读下一个

else

printf("缺少}号\n");

}

else

printf("缺少{号\n");

}

//<语句串>:

:

=<语句>{;<语句>};

voidstaString(int*nChain)//语句串

{

sta(nChain);

backpatch(*nChain,nextq);

while(syn==31)//;

{

scanner();

sta(nChain);

}

//backpatch(*nChain,nextq-1);

}

voidsta(int*nChain)//语句

{

if(syn==10)

{

fuzhi();

//*nChain=0;

}

elseif(syn==6)//if

{

tiaojian(nChain);

}

elseif(syn==8)//do

xunhuan();

}

//<条件语句>->if(<条件>)<语句块>

voidtiaojian(int*nChain)

{

charres[10],num1[10],num2[10],op[10];

intnChainTemp;

//<条件>-><表达式><关系运算符><表达式>

if(syn==6)//if

{

scanner();

//strcpy(num1,E());

if(syn==26)//(

{

scanner();

strcpy(num1,E());

if((syn<=37)&&(syn>=32))

{

switch(syn)

{

case32:

strcpy(op,">");

break;

case33:

strcpy(op,">=");

break;

case34:

strcpy(op,"<");

break;

case35:

strcpy(op,"<=");

break;

case36:

strcpy(op,"==");

break;

case37:

strcpy(op,"!

=");

break;

default:

printf("error");

}

}

scanner();

strcpy(num2,E());

strcat(num1,op);

strcat(num1,num2);

//nfc=nextq+1;

ntc=nextq;//记住if语句位置

emit("0","if",num1,"goto");

nfc=nextq;//if中表达式为假

emit("0","","","goto");

//第一个0已回填

backpatch(ntc,nextq);//ntc链接的所有四元式都回填nextq

}

if(syn==27)//)

scanner();

staBlock(&nChainTemp);//语句块

*nChain=merge(nChainTemp,nfc);

}

}

//<循环语句>:

:

=do<语句块>while<条件>

voidxunhuan()

{

charres[10],num1[10],num2[10],op[10];

intnChainTemp;

if(syn==8)//do

{

nnc=nextq;//记住if语句位置,emit之后nextq就变了

//emit("0","if",num1,"goto");

scanner();

staBlock(&nChainTemp);//语句块

if(syn==9)//while

{

scanner();

if(syn==26)//(

{

scanner();

strcpy(num1,E());

if((syn<=37)&&(syn>=32))

{

switch(syn)

{

case32:

strcpy(op,">");

break;

case33:

strcpy(op,">=");

break;

case34:

strcpy(op,"<");

break;

case35:

strcpy(op,"<=");

break;

case36:

strcpy(op,"==");

break;

case37:

strcpy(op,"!

=");

break;

default:

printf("error");

}

}

scanner();

strcpy(num2,E());

strcat(num1,op);

strcat(num1,num2);

nnb=nextq;

emit("0","if",num1,"goto");

backpatch(nnb,nnc);

nna=nextq;

emit("0","","","goto");

backpatch(nna,nextq);

}

if(syn==27)//)

scanner();

}

}

}

voidfuzhi()//赋值语句只有1个操作数

{

charres[10],num[10];//num操作数

if(syn==10)//字符串

{

strcpy(res,token);//结果

scanner();

if(syn==21)//=

{

scanner();

strcpy(num,E());

emit(res,num,"=","");

}

else

{

printf("缺少=号\n");

}

}

}

char*E()//Expression表达式

{

char*res,*num1,*op,*num2;

res=(char*)malloc(10);

num1=(char*)malloc(10);

op=(char*)malloc(10);

num2=(char*)malloc(10);

strcpy(num1,T());

while((syn==22)||(syn==23))//+-

{

if(syn==22)//+

strcpy(op,"+");

else

strcpy(op,"-");

scanner();

strcpy(num2,T());

strcpy(res,newTemp());

emit(res,num1,op,num2);

strcpy(num1,res);

}

returnnum1;

}

char*T()//Term项

{

char*res,*num1,*op,*num2;

res=(char*)malloc(10);

num1=(char*)malloc(10);

op=(char*)malloc(10);

num2=(char*)malloc(10);

strcpy(num1,F());

while((syn==24)||(syn==25))//*/

{

if(syn==24)

strcpy(op,"*");

else

strcpy(op,"/");

scanner();

strcpy(num2,F());

strcpy(res,newTemp());

emit(res,num1,op,num2);

strcpy(num1,res);

}

returnnum1;

}

char*F()//Factor因子

{

char*res;

res=(char*)malloc(10);

if(syn==10)//字符串

{

strcpy(res,token);

scanner();

}

elseif(syn==20)//二进制数

{

itoa((int)sum,res,10);//整数转换为字符串

scanner();

}

elseif(syn==26)//(

{

scanner();

res=E();

if(syn==27)//)

{

scanner();

}

elseisError=1;

}

else

isError=1;

returnres;

}

char*newTemp()

{

char*p;

charvarTemp[10];

p=(char*)malloc(10);

kk++;

itoa(kk,varTemp,10);

strcpy(p+1,varTemp);

p[0]='T';

returnp;

}

//将p所链接的每个四元式的第四个分量都回填t

voidbackpatch(intp,intt)

{

intw,circle=p;

while(circle)//circle不为0的时候

{

w=atoi(fourCom[circle].result);//四元式circle第四分量内容

//strcpy(fourCom[circle].result,t);//把t填进四元式circle的第四分量

sprintf(fourCom[circle].result,"%d",t);

circle=w;//w记录的是链条上下一个四元式,移动!

}

return;

}

intmerge(intp1,intp2)//合并p1和p2

{

charcircle,nResult;

if(p2==0)

nResult=p1;

else

{

nResult=circle=p2;

while(atoi(fourCom[circle].result))//四元式第四个分量不为0

{

circle=atoi(fourCom[circle].result);

//strcpy(fourCom[circle].result,p1);

sprintf(fourCom[circle].result,"%s",p1);

}

//目的是用p1的值覆盖0

}

returnnResult;//p2是头,p1覆盖0,接在p2后边

}

voidemit(char*res,char*num1,char*op,char*num2)

{

strcpy(fourCom[nextq].result,res);

strcpy(fourCom[nextq].arg1,num1);

strcpy(fourCom[nextq].opera,op);

strcpy(fourCom[nextq].arg2,num2);

nextq++;

}

voidscanner()

{

sum=0;

decimal=0;

m=0;

for(n=0;n<8;n++)

token[n]=NULL;

ch=prog[p++];//从prog中读出一个字符到ch中

while(ch==''||ch=='\n')//跳过空字符(无效输入)

ch=prog[p++];

if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))//ch是字母字符

{

whi

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1