#编译原理实验一.docx
- 文档编号:23933519
- 上传时间:2023-05-22
- 格式:DOCX
- 页数:28
- 大小:173.23KB
#编译原理实验一.docx
《#编译原理实验一.docx》由会员分享,可在线阅读,更多相关《#编译原理实验一.docx(28页珍藏版)》请在冰豆网上搜索。
#编译原理实验一
实验内容:
实现标准C语言词法分析器
实验目的:
1.掌握程序设计语言词法分析的设计方法;
2.掌握DFA的设计与使用方法;
3.掌握正规式到有限自动机的构造方法;
实验要求:
1.单词种别编码要求
基本字<关键字)、运算符、界符:
一符一种;
标识符<变量名):
统一为一种;
常量<):
按类型编码;
2.词法分析工作过程中建立符号表、常量表,并以文本文件形式输出;
3.词法分析的最后结果以文本文件形式输出;
4.完成对所设计词法分析器的功能测试,并给出测试数据和实验结果;
5.为增加程序可读性,请在程序中进行适当注释说明;
6.整理上机步骤,总结经验和体会;
7.认真完成并按时提交实验报告。
二、设计方案:
这个词法分析器分析的主要关键字有:
main,int,float,char,if,else,for,while,do,switch,case,break。
default……。
选择要分析的c文件,首先对其去掉注释和与空格处理,再根据字符的不同类型分析。
1、全局数据结构:
*key[]:
关键字表
全局文件指针*fr,*fw,*temp1,*temp2用于文件的读写。
2、以层次图模块的组成及调用关系
3、主要函数的设计要求<功能、参数、返回值):
isKey:
判断ch中的字符是否为关键字;
isLer和isNum:
布尔函数过程,分别判断ch中的字符是否为字母和数字;
isBoudany<):
布尔函数过程,分别判断ch组成的字符否为边界符号;
check:
词法分析;
clock:
时间函数,计算程序运行所需的时间
main:
主函数。
4、状态转换图:
字母或数字
字母非字母或数字
数字数字
非数字
字符a
字符a
字符b
‘=’
字符c
字符a包括:
=,&,|,+,--
字符b包括:
--,<,>,|,*
字符c包括:
,:
(,>,{,},[,],!
#,%,”,/,*,+,--,>,<,.
#include
#include
#include
#include
#include
FILE*fr,*fw,*temp1,*temp2。
char*key0[]={"main","printf","scanf","else","if","auto","double",
"int","struct","break","long","switch","case","enum","register","typedef",
"char","extern","return","union","const","float","short","unsigned","continue","for",
"signed","void","default","goto","sizeof","volatile","do","while","static"}。
/*关键字表*/
char*key1[]={"\"","\\","(",">","[","]","{","}",",","。
","'"}。
/*边界符表*/
intisLet(charc>//判断是否是字母
{
if(c>='a'&&c<='z'||c>='A'&&c<='Z'>
return1。
else
return0。
}
intisNum(charc>//判断是否是数字
{
if(c>='0'&&c<='9'>
return1。
else
return0。
}
intisKey(char*word>
{
intm,i。
for(i=0。
i<36。
i++>
{
if((m=strcmp(word,key0[i]>>==0>
{
if(i==0>
return2。
else
return1。
}
}
return0。
}
intisBoudany(charc>
{
if(c=='\\'>
return2。
else
if(c=='('||c=='>'||c=='{'||c=='}'||c=='['||c==']'||c==','||c=='。
'||c=='\''||c=='\"'||c=='\"'>
return1。
else
return0。
}
voidcheck(FILE*fr>
{
charword[30]。
while(!
feof(fr>>
{
memset(word,0,sizeof(word>>。
charch,temp。
ch=fgetc(fr>。
//获取字符,指针fr并自动指向下一个字符
inti,c。
if(ch=='#'>//预处理
{
//temp=fgetc(fr>。
while(ch!
='>'>
ch=fgetc(fr>。
ch=fgetc(fr>。
fprintf(fw,"*****************************************跳过头文件和文件宏定义\n">。
}
else
if(ch=='/'>//跳过注释/**/类型
{
ch=fgetc(fr>。
if(ch=='/'>//跳过注释//类型
{
while(ch!
='\n'>
ch=fgetc(fr>。
fprintf(fw,"*********************************************************跳过注释\n">。
}
else
if(ch=='*'>
{
ch=fgetc(fr>。
temp=fgetc(fr>。
do
{
ch=fgetc(fr>。
temp=fgetc(fr>。
}
while(ch!
='*'||temp!
='/'>。
fprintf(fw,"******************************************************跳过注释\n">。
ch=fgetc(fr>。
}
}
else
if(isLet(ch>>
{
word[0]=ch。
ch=fgetc(fr>。
i=1。
while(isNum(ch>||isLet(ch>>//判断该字符是否是字母或数字
{
word[i]=ch。
i++。
ch=fgetc(fr>。
}
word[i]='\0'。
//'\0'代表字符结束(空格>
fseek(fr,-1,1>。
c=isKey(word>。
//判断是否是关键字
if(c==0>//不是关键字
{
fprintf(temp1,"%s",word>。
fprintf(fw,"字符%s是:
标识符,种别编码为:
%d\n",word,2>。
}
else
{
if(ch!
='"'>//判断是否是定义的字符
{
if(c==2>
fprintf(fw,"字符%s是:
***************************************************主函数,种别编码为:
%d\n",word,0>。
//主函数
else
fprintf(fw,"字符%s是:
关键字,种别编码为:
%d\n",word,1>。
//关键字
}
else
{
fprintf(fw,"字符%s是:
定义的字符常量,种别编码为:
%d\n\n",word,32>。
}
}
}
else//开始判断的字符不是字母
if(isNum(ch>>
{//判断是否是数字
word[0]=ch。
ch=fgetc(fr>。
i=1。
while(isNum(ch>>
{
word[i]=ch。
i++。
ch=fgetc(fr>。
}
word[i]='\0'。
fseek(fr,-1,1>。
//回退
fprintf(fw,"字符%s是:
常量,种别编码为:
%d\n",word,3>。
}
else
{
c=isBoudany(ch>。
//开始判断的字符不是字母也不是数字
//边界符
if(c>
{
if(c==2>//判断是否是转义字符
{
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
word[2]='\0'。
fprintf(fw,"字符%s是:
转义字符,种别编码为:
%d\n",word,4>。
}
else
if(c==1>
{
fprintf(fw,"字符%c是:
界符,种别编码为:
%d\n",ch,5>。
fprintf(temp2,"%c",ch>。
}
}
else
switch(ch>
{
case'+':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='='>{
word[2]='\0'。
fprintf(fw,"字符%s是:
运算符,种别编码为:
%d\n",word,6>。
//运算符"+="
}
else
if(ch=='+'>
{
word[2]='\0'。
fprintf(fw,"字符%s是运算符,种别编码为:
%d\n",word,7>。
//判断结果为"++"
}
else{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c是运算符,种别编码为:
%d\n",ch,8>。
//判断结果为"+"
}
break。
case'-':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='='>{
word[2]='\0'。
fprintf(fw,"字符%s是:
运算符,种别编码为:
%d\n",word,9>。
}
else
if(ch=='-'>{
word[2]='\0'。
fprintf(fw,"字符%s是运算符,种别编码为:
%d\n",word,10>。
//判断结果为"--"
}
else{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c是运算符,种别编码为:
%d\n",ch,11>。
//判断结果为"-"
}
break。
case'*':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch!
='='>
{
if(isNum(ch>>
{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c:
是运算符,种别编码为:
%d\n",ch,12>。
//判断结果为"*"
}
else
{//判断是否是指针
i=2。
ch=fgetc(fr>。
while(isLet(ch>>
{
word[i]=ch。
ch=fgetc(fr>。
i++。
}
fprintf(fw,"字符%s:
是指针定义运算符,种别编码为:
%d\n",word,13>。
}
}
else
{
word[2]='\0'。
fprintf(fw,"字符%s:
是运算符,种别编码为:
%d\n",word,14>。
//判断结果为"*="
}
break。
case'/':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch!
='='>
{
if(isNum(ch>>
{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c:
是运算符,种别编码为:
%d\n",ch,15>。
//判断结果为"/"
}
}
else{
word[2]='\0'。
fprintf(fw,"字符%s:
是运算符,,种别编码为:
%d\n",word,16>。
//判断结果为"/="
}
break。
case'!
':
case'?
':
case':
':
case'.':
case'=':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch!
='='>{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c:
是运算符,种别编码为:
%d\n",ch,17>。
}
else{word[2]='\0'。
fprintf(fw,"字符%s:
是运算符,种别编码为:
%d\n",word,18>。
}
break。
case'|':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='|'>{
word[2]='\0'。
fprintf(fw,"字符%c是运算符,种别编码为:
%d\n",ch,19>。
//判断结果为运算符"||"
}
else{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c是运算符,种别编码为:
%d\n",ch,20>。
//判断结果为"|"
}
break。
case'%':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='='>
{
word[2]='\0'。
fprintf(fw,"字符%s是运算符,种别编码为:
%d\n",word,21>。
}
else
if(isLet(ch>>
{
word[2]='\0'。
fprintf(fw,"字符%s是输出类型标识符,种别编码为:
%d\n",word,22>。
}
else
{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c是取余运算符,种别编码为:
%d\n",ch,23>。
}
break。
case'&':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='&'>{
word[2]='\0'。
fprintf(fw,"字符%s是:
运算符,种别编码为:
%d\n",word,24>。
//判断结果为运算符"&&"
}
else{
fseek(fr,-2,1>。
ch=getc(fr>。
fprintf(fw,"字符%c是:
运算符,种别编码为:
%d\n",ch,25>。
//判断结果为"&"
}
break。
case'<':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='='>{
word[2]='\0'。
fprintf(fw,"字符%s是:
运算符,种别编码为:
%d\n",word,26>。
//判断结果为运算符"<="
}
else
if(ch=='<'>{
word[2]='\0'。
fprintf(fw,"字符%s是:
运算符,种别编码为:
%d\n",word,27>。
//判断结果为运算符"<<"
}
else
{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c是:
运算符,种别编码为:
%d\n",ch,28>。
//判断结果为"<"
}
break。
case'>':
word[0]=ch。
ch=fgetc(fr>。
word[1]=ch。
if(ch=='='>{
word[2]='\0'。
fprintf(fw,"字符%s是运算符,种别编码为:
%d\n",word,29>。
}
else
if(ch=='>'>{
word[2]='\0'。
fprintf(fw,"字符%s是运算符,种别编码为:
%d\n",word,30>。
}
else{
fseek(fr,-2,1>。
ch=fgetc(fr>。
fprintf(fw,"字符%c是运算符,种别编码为:
%d\n",ch,31>。
}
break。
default:
break。
}
}
fprintf(fw,"\n">。
}
}
intmain(>
{
clock_tstart,end。
charcr。
charstr_in[25],str_out[25],str_out1[25],str_out2[25]。
doubleduration。
start=clock(>。
printf("请输入文件的读取路径<包含文件的后缀名):
\n">。
scanf("%s",str_in>。
fr=fopen(str_in,"r">。
while(fr==NULL>
{
printf("文件路径输入错误!
请重新输入:
\n">。
scanf("%s",str_in>。
fr=fopen(str_in,"r">。
}
printf("文件读入成功!
内容显示如下:
\n">。
printf("**************************************************\n">。
cr=fgetc(fr>。
while(cr!
=EOF>{
putchar(cr>。
cr=fgetc(fr>。
}
printf("\n">。
printf("**************************************************\n">。
printf("请输入文件的最终结果的写入路径<包含文件的后缀名):
\n">。
scanf("%s",str_out>。
printf("请输入文件的常量表的写入路径<包含文件的后缀名):
\n">。
scanf("%s",str_out1>。
printf("请输入文件的符号表的写入路径<包含文件的后缀名):
\n">。
scanf("%s",str_out2>。
while(str_in==str_out||str_in==str_out1||str_in==str_out2>
{
if(str_out==str_in>{printf("请输入文件的最终结果的写入路径<包含文件的后缀名):
\n">。
scanf("%s",str_out>。
}else
if(str_in==str_out1>{
printf("请输入文件的常量表的写入路径<包含文件的后缀名):
\n">。
scanf("%s",str_out1>。
}else
if(str_in==str_out2>{
printf("请输入文件的符号表的写入路径<包含文件的后缀名):
\n">。
scanf("%s",str_out2>。
}
}
fw=fopen(str_out,"w">。
temp1=fopen(str_out1,"w">。
temp2=fopen(str_out2,"w">。
while(fw==NULL||temp1==NULL||temp2==NULL>
{
printf("文件写入路径错误,请重新输入:
\n">。
if(fw==NULL>
{
scanf("%s",str_out>。
fw=fopen(str_out,"w">。
}
else
if(temp1=NULL>
{
scanf("%s",str_out1>。
temp1=fopen(str_out1,"w">。
}
else
if(temp2=NULL>{
scanf("%s",str_out2>。
temp2=fopen(str_out2,"w">。
}
}
fprintf(temp1,"文件中依次出现的标识符\n">。
fprintf(temp2,"文件中依次出现的符号\n">。
fr=fopen(str_in,"r">。
check(fr>。
printf("文件写入成功!
编译结果已写入指定文件区域!
请注意查看...........\n\n">。
fclose(fw>。
fclose(temp1>。
fclose(temp2>。
fclose(fr>。
printf("\n">。
end=clock(>。
duration=(double>(end-start>/CLOCKS_PER_SEC*1000。
printf("该词法分析程序共运行约%lfms\n",duration>。
return0。
}
测试结果:
这个程序主要参考书上关于词法分析器的假设,完成了关于c语言词法分
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 实验