编译原理课程实验.docx
- 文档编号:13104284
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:28
- 大小:60.18KB
编译原理课程实验.docx
《编译原理课程实验.docx》由会员分享,可在线阅读,更多相关《编译原理课程实验.docx(28页珍藏版)》请在冰点文库上搜索。
编译原理课程实验
学生学号
0121210680225
实验课成绩
武汉理工大学
学生实验报告书
实验课程名称《编译原理》
开课学院计算机科学与技术学院
指导老师姓名饶文碧
学生姓名李安福
学生专业班级软件sy1201
2014—2015学年第一学期
实验课程名称:
编译原理
实验项目名称
词法分析
实验成绩
实验者
李安福
专业班级
Sy1201
组别
同组者
郭烨华
实验日期
年月日
第一部分:
实验分析与设计(可加页)
一、实验内容描述(问题域描述)
实验目的:
根据PL/0语言的文法规范,编写PL/0语言的词法分析程序。
通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;加深对课堂教学的理解;提高词法分析方法的实践能力。
掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的法。
掌握词法分析的实现方法。
上机调试编出的词法分析程序。
二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或者算法描述)
分析:
对于单词符号我们将其分成四类:
保留字K、标识符I、常数C和界符P,每类单词符号均可使用一张表格表示.在词法分析过程中,保留字K和界符P这两个表格的内容是固定不变的(由语言确定),源程序字符串只能从其中选取,而标识符I、常数C这两表是在分析过程中不断形成的.
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是K、I、C或P中之一,那么就以单词的二元式形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串.
各类单词的二元式表述均具有相同的结构与长度,形式如下:
(单词种别t,单词自身的值i)
t是单词种别,而单词种别共分为K、I、C、P四类且每类对应一张表格.因此,t实际上就是一个指向这四类中某一类对应表格的指针.i则为指向该类表格中一个特定项目的指针.
所以整个的词法分析过程就是从源程序中获得一个个的单词符号,将这些符号分别填入四张类表中,并且有一个二元式序列构成一个索引,这个索引为以后的语法分析提供处理上的方便.
1
2
3
4
5
6
7
8
9
10
for
while
DO
ELSE
IF
STATIC
INT
SIZEOF
BREAK
CONTINUE
内部地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
界 符
+
-
*
/
<
<=
>
>=
!
=
==
=
(
)
,
:
;
{
}
单词符号
类别编码
标识符
1
常数
2
保留字
3
+
4
-
5
*
6
/
7
<
8
<=
9
>
10
>=
11
!
=
12
==
13
=
14
(
15
)
16
,
17
:
18
;
19
{
20
}
21
3.实验源代码如下:
#include
#include
#include
#include
#include
#defineLENGTH110//定义保留字的大小
FILE*fp=NULL;//输出流指针
FILE*fw=NULL;//输入流指针
charcharacter;//字符
chartoken[16];//字符数组,用来存放已读入的字符序列
//编码表
char*CODE[]={"identifier"/*标识符*/,"constant"/*常数*/,"keyword"/*保留字*/,"+","-",
"*","/","<","<=",">",">=","!
=","==","=","(",")",",",":
",";","{","}"};
//保留字表
char*k[]={"for","while","do","else","if","static","int","sizeof","break","continue"};
//标识符结构体
typedefstruct
{
char*I[256];//标识符数组
intlen;//标识符数量
}identifier;
//常量结构体
typedefstruct{
intcont[300];//存放常量的数组
intlen;//常量的数目
}constnumber;
//读入一个字符,从输入流中读入一个字符到变量character中。
voidgetNextChar(FILE*ifp)
{
if((character=getc(ifp))==EOF)
exit
(1);
}
//读入非空白字符,检查变量character中的字符是否为空白字符或回车或换行符。
若是,
//则调用getNextChar()读入下一个字符,直到character中的字符满足条件.
voidgetnbc(FILE*ifp)
{
while(character==''||character=='\n'||character==9)
{
getNextChar(ifp);
}
}
//连接字符串,把character中的字符连接到token数组的结尾。
voidconcat()
{
char*ct=&character;
strcat(token,ct);
}
//判断是否为字母。
intletter()
{
returnisalpha(character);
}
//判断是否为数字
intdigit()
{
returnisdigit(character);
}
//回退字符,将刚读入的character中的字符回退到输入流中。
并把character中的值置为空。
voidretract(FILE*ifp)
{
(ifp->_cnt)++;
(ifp->_ptr)--;
character='';
}
//处理保留字,对存放在token中的字符串查保留字,若查到,则返回该保留字的类别编码,否则返回0.
intreserve(char**k)
{
inti;
for(i=0;i if(strcmp(token,k[i])==0) returni+1; return0; } //处理标识符,对存放在token中的字符串查找符号表,若查到,则返回它在符号表的位置, //存入常数表中,并返回它在常数表中的位置编号。 intsymbol(identifier*id) { inti; for(i=0;i if(strcmp(token,id->I[i])==0) returni+1; if(id->len>256) assert(0); id->I[id->len]=token; id->len++; returnid->len; } //将数字字符串转化为整数。 intstrtonumber() { inti; intsum=0; for(i=0;i { sum=10*sum+(token[i]-'0'); } returnsum; } //常数存入常数表的函数,将token中的数字串(实际上是字符串),转化成标准的二进制值(整数值) //存入常数表中,并返回它在常数表中的位置编号。 intconstant(constnumber*con) { con->cont[con->len]=strtonumber(); con->len++; returncon->len; } //将整数值转化为字符串 char*numbertoString(intnum) { chars[3]; inti=num/10; while(i>0) { charc=i+'0'; strcat(s,&c); } returns; } //将结果写入到文件并且输出到屏幕。 voidreturntofile(intnum,intval,identifier*id,constnumber*con) { inti; int_num=num; charc; c='('; putc(c,fw); printf("%c",c); i=_num/10; while(i>0) { _num=_num-10*i; c=(i+'0'); printf("%c",c); putc(c,fw); i=_num/10; } c=_num+'0'; printf("%c",c); putc(c,fw); printf(","); putc(',',fw); //如果是标识符或常数则放入括号内。 if(num==1)//处理标识符 { printf("%s",id->I[val-1]); printf(")"); printf("\n"); fputs(id->I[val-1],fw); putc(')',fw); putc('\n',fw); } if(num==2)//处理常数 { _num=con->cont[val-1]; i=_num/10; while(i>0) { _num=_num-10*i; c=(i+'0'); printf("%c",c); putc(c,fw); i=_num/10; } c=_num+'0'; printf("%c",c); printf(")"); printf("\n"); putc(c,fw); putc(')',fw); putc('\n',fw); } if(num==3)//保留字 { printf("-"); printf(")"); printf(""); printf("#"); printf("%s",k[val-1]); printf("#"); printf("\n"); putc('-',fw); putc(')',fw); fputs("",fw); putc('#',fw); fputs(k[val-1],fw); putc('#',fw); putc('\n',fw); } if(num>3)//处理界符 { printf("-"); printf(")"); printf(""); printf("#"); printf("%s",CODE[num-1]); printf("#"); printf("\n"); putc('-',fw); putc(')',fw); fputs("",fw); putc('#',fw); fputs(CODE[num-1],fw); putc('#',fw); putc('\n',fw); } } //将错误写入到文件或输出到屏幕 voiderror() { printf("(ERROR,"); printf("%c",character); printf(")"); printf("\n"); fputs("(ERROR,",fw); putc(character,fw); putc(')',fw); putc('\n',fw); } //词法分析函数 voidLexAnalyze(char**k,char**CODE,identifier*id,constnumber*con,FILE*fp,FILE*fw) { intnum,val; strcpy(token,""); getNextChar(fp); getnbc(fp); switch(character) { case'a': case'b': case'c': case'd': case'e': case'f': case'g': case'h': case'i': case'j': case'k': case'l': case'm': case'n': case'o': case'p': case'q': case'r': case's': case't': case'u': case'v': case'w': case'x': case'y': case'z': case'A': case'B': case'C': case'D': case'E': case'F': case'G': case'H': case'I': case'J': case'K': case'L': case'M': case'N': case'O': case'P': case'Q': case'R': case'S': case'T': case'U': case'V': case'W': case'X': case'Y': case'Z': while(letter()||digit()) { concat(); getNextChar(fp); } retract(fp); num=reserve(k);//保留字 if(num! =0) returntofile(3,num,id,con); else { val=symbol(id); returntofile(1,val,id,con); } break; case'0': case'1': case'2': case'3': case'4': case'5': case'6': case'7': case'8': case'9': while(digit()) { concat(); getNextChar(fp); } retract(fp); val=constant(con); returntofile(2,val,id,con); break; case'<': getNextChar(fp); if(character=='=') returntofile(9,0,id,con); else { retract(fp); returntofile(8,0,id,con); } break; case'>': getNextChar(fp); if(character=='=') returntofile(11,0,id,con); else { retract(fp); returntofile(10,0,id,con); } break; case'=': getNextChar(fp); if(character=='=') returntofile(13,0,id,con); else { retract(fp); returntofile(14,0,id,con); } break; case'! ': getNextChar(fp); if(character=='=') returntofile(12,0,id,con); else error(); break; case'+': returntofile(4,0,id,con); break; case'-': returntofile(5,0,id,con); break; case'*': returntofile(6,0,id,con); break; case'/': returntofile(7,0,id,con); break; case'(': returntofile(15,0,id,con); break; case')': returntofile(16,0,id,con); break; case',': returntofile(17,0,id,con); break; case': ': returntofile(18,0,id,con); break; case';': returntofile(19,0,id,con); break; case'{': returntofile(20,0,id,con); break; case'}': returntofile(21,0,id,con); break; default: error(); } } main(intargc,char*argv[]) { //初始化标识符和常数结构体 identifier*id=(identifier*)malloc(sizeof(identifier)); constnumber*con=(constnumber*)malloc(sizeof(constnumber)); con->len=0; id->len=0; argc=3; argv[1]="A: \\file1.txt";//待分析的文件 argv[2]="A: \\file2.txt";//保存分析结果的文件 //从打开目标文件流 if((fp=fopen(argv[1],"r"))==NULL) { printf("cat: can'topen%s\n",*argv); return1; } //打开要写二元式的文件流 if((fw=fopen(argv[2],"w"))==NULL) { printf("cat: can'topen%s\n",argv[2]); return1; } while(! feof(fp)) { LexAnalyze(k,CODE,id,con,fp,fw);//执行词法分析 } //关闭流 fclose(fp); fclose(fw); return0; } 三、主要仪器设备及耗材 微机CPUP4以上,256M以上内存,安装好C语言,或C++,或VisualC++. 第二部分: 实验调试与结果分析(可加页) 一、调试过程(包括调试方法描述、实验数据记录,实验现象记录,实验过程发现的问题等) 按照要求编写完代码之后,首先检查一下有没有错误语法错误,然后编译连接运行,输入所给文法的源程序字符串,经此法分析之后,程序就会输出如下结果所示的二元组构成的序列: 二、实验结果及分析(包括结果描述、实验现象分析、影响因素讨论、综合分析和结论等) (1)输入程序段在A盘的file1.txt里面,经程序运行保存在file2.txt里, 其结果如下图所示 (2)输入第二段程序输出结果如下图所示: 三.实验小结、建议及体会 词法分析是编译的第一个阶段,它的主要任务是从左至右逐个字符地对源程序进行扫描,产生一个单词序列,用以语法分析,执行词法分析的程序成为词法分析程序或扫描程序。 本次实验就是要做一个这样的程序。 通过这次实验,我加深了对词法分析原理的理解。 实验课程名称: 编译原理 实验项目名称 语法分析 实验成绩 实验者 李安福 专业班级 Sy1201 组别 同组者 郭烨华 实验日期 年月日 第一部分: 实验分析与设计(可加页) 一、实验内容描述(问题域描述) (1)通过设计、编制、调试一个典型的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。 (2)选择最有代表性的语法分析方法,如递归子程序法;选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是表达式,作为分析对象。 二、实验基本原理与设计(包括实验方案设计,实验手段的确定,试验步骤等,用硬件逻辑或者算法描述) 代码如下: #include #include #include usingnamespacestd; intnum=-1; vector vector vector stringSTC; stringchangshengshi[8]={"","TA","+TA","FB","*FB","i","(E)","a=E"};//产生式 intsheet[6][7]={{7,-1,-1,-1,-1,-1,0}, {1,1,-1,-1,1,-1,-1},//预测表 {-1,-1,2,-1,-1,0,0}, {3,3,-1,-1,3,-1,-1}, {-1,-1,0,4,-1,0,0}, {5,5,-1,-1,6,-1,-1} }; //stringlin[10]={"t1","t2","t3","t4","t5","t6","t7","t8","t9","t0"}; boolIsLetter(charch) { if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) returntrue; returnfalse; } boolIsDigit(charch) { if(ch>='0'&&ch<='9') returntrue; returnfalse; } intFeichange(chara){ switch(a){ case'S': return0;break; case'E': r
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 课程 实验
![提示](https://static.bingdoc.com/images/bang_tan.gif)