编译原理实验一.docx
《编译原理实验一.docx》由会员分享,可在线阅读,更多相关《编译原理实验一.docx(30页珍藏版)》请在冰豆网上搜索。
![编译原理实验一.docx](https://file1.bdocx.com/fileroot1/2022-10/12/b6771240-ef11-4b11-85b6-07231dfb60f3/b6771240-ef11-4b11-85b6-07231dfb60f31.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'