编译原理实验一.docx
《编译原理实验一.docx》由会员分享,可在线阅读,更多相关《编译原理实验一.docx(32页珍藏版)》请在冰豆网上搜索。
![编译原理实验一.docx](https://file1.bdocx.com/fileroot1/2023-1/23/fe4e769f-9a5d-4a26-8e0e-0f3db2ee37d4/fe4e769f-9a5d-4a26-8e0e-0f3db2ee37d41.gif)
编译原理实验一
实验内容:
实现标准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");