编译实验词法分析报告郑章孝.docx
《编译实验词法分析报告郑章孝.docx》由会员分享,可在线阅读,更多相关《编译实验词法分析报告郑章孝.docx(17页珍藏版)》请在冰豆网上搜索。
编译实验词法分析报告郑章孝
词法分析实验报告
姓名:
郑章孝班级:
计算机0201班学号:
012002013324
一.设计内容及思想
编写一个C语言的子集的词法分析程序,对C语言源代码程序进行扫描,识别简单语言的基本字、标识符、无符号整数、运算符和界符等
单词符号,产生的单词转换成特别码
表示,形成word文件(单词序列)保存。
给出C语言单词符号子集的种别编码(如下所示),保存于key.txt文件中:
break1
case2主程序算法思想
char3
const4
continue5
default6
do7
double8
else9
enum10
float11
for12
if13
int14
long15
main16
printf17
return18
scanf19程序模块结构图
Scanner
sizeof20
static21
struct22
switch23
typedef24
IsOther
IsChar
IsNumber
IsAnotation
IsAlpha
void25
while26
标识符27
整常数28
实常数29
字符串常量30
(31
Error
OutPut
)32
/33
*34(各模块功能见程序源代码中的注释)
+35
-36
37
{38
}39
=40
==41
;42
<43
<=44
二.调试结果。
/*程序调试环境vc++6.0*/
/*test.c*/
voidmain()
{
char_ad='A';@
for(intBB=22;BB<=30;BB=BB+1)printf("Ihatecprogram!
");
}/*sb拉连注释都忘了!
输出结果保存于word.txt文件内容:
void25
main16
(31
)32
{38
char3
_ad27
=40
A30
;42
for12
(31
int14
BB27
=40
2228
;42
BB27
<=44
3028
;42
BB27
=40
BB27
+35
128
)32
printf17
(31
Ihatecprogram!
30
)32
;42
}39
三.源代码
#include
#include
#include
#defineLENGTH61
#defineN100
typedefstructKeyWord//单词编码表结构
{
charname[30];//单词
intcode;//编码
}KeyWord;
charch;
interror_count;//错误个数
intLine;//代码行数
charfilename[30];//保存输入的源代码文件名
FILE*KeyFin;//单词集文件输入流
FILE*SourceFin;//源代码文件输入流
FILE*WordFout;//词法分析结果输出流
KeyWordkey[LENGTH];//单词编码表保存单词集
KeyWordCurrentWord;//保存当前单词
voidScanner();//主程序扫描模块
voidScannerInit();//进行初始化:
key[]和CurrenWord
voidIsAlpha();//识别保留字和标识符
voidIsNumber();//识别整数和实数
voidIsAnotation();//处理除号和注释
voidIsChar();//识别字符串
voidIsOther();//识别其他单词
voidOutPut();//输出识别出的单词
voidError(inta);//出错处理
/**********************************/
voidmain()
{
Line=1;
Scanner();
}
/*******************主程序******************/
voidScanner()
{
inti=0;
error_count=0;
ScannerInit();
printf("C语言词法分析器\n");
printf("输入源文件名:
");
scanf("%s",filename);
printf("单词****************编码\n");
if((SourceFin=fopen(filename,"r"))==NULL){
printf("can'topenthefile!
\n");
exit
(1);
}
if((WordFout=fopen("word.txt","wt+"))==NULL){//word.txt用于保存分析结果
printf("can'topenword.txt!
\n");
exit
(1);
}
ch=fgetc(SourceFin);//读取第一个字符
while(ch!
=EOF){/*循环处理字符*/
for(i=0;i<30;i++)CurrentWord.name[i]='\0';
if((ch>47)&&(ch<58))IsNumber();//字符==数字时
else{
if(((ch>64)&&(ch<90))||((ch>96)&&(ch<123))||ch=='_')
IsAlpha();//字符==字母或字符==’_’时
else{
if(ch=='/')IsAnotation();//调用处理注释模块
elseif(ch=='"'||ch=='\'')IsChar();//处理字符串常数模块
elseIsOther();
}
}
}
fclose(SourceFin);
fclose(WordFout);
printf("分析完毕!
\n");
}
/****************初始化**************************/
voidScannerInit()
{//打开单词编码文件,并将单词编码读到编码表中
inti=1;
intk=0;
if((KeyFin=fopen("key.txt","rt"))==NULL){
printf("can'topenni.txt!
\n");
exit
(1);
}
for(i=0;i<60;i++)
for(k=0;k<30;k++)key[i].name[k]='\0';
for(i=1;i<60;i++)fscanf(KeyFin,"%s%d",key[i].name,&key[i].code);
fclose(KeyFin);
}
/*************数字处理*****************************/
voidIsNumber()
{
intk=0;
intflag=0;
charch1;
while(((ch>47)&&(ch<58)))
{
CurrentWord.name[k++]=ch;//记录当前字符
ch=fgetc(SourceFin);//读取下一个字符
if(ch=='.'){flag=1;break;}//==’.’时为实数
}
CurrentWord.code=28;
if(flag){//为实数时
ch1=fgetc(SourceFin);
if((ch1>47)&&(ch1<58))CurrentWord.name[k++]=ch;
elseError
(2);
ch=ch1;
while((ch>47)&&(ch<58))
{
CurrentWord.name[k++]=ch;
ch=fgetc(SourceFin);
}
CurrentWord.code=29;//记单词编码为实数的编码
if(ch=='.'){//实数中出现两个小数点,出错处理
Error
(2);
ch=fgetc(SourceFin);//过虑掉余下的数字
while((ch>47)&&(ch<58))ch=fgetc(SourceFin);
}
}
if(((ch>64)&&(ch<90))||((ch>96)&&(ch<123)))
{//当前字符为字母时,出错处理并过虑掉尾部
Error
(2);
while(((ch>64)&&(ch<90))||((ch>96)&&(ch<123)))
{
ch=fgetc(SourceFin);
while((ch>47)&&(ch<58))ch=fgetc(SourceFin);
}
}
OutPut();
}
/**********************字母处理****************************/
voidIsAlpha()
{
inti,h;
h=0;i=0;
while(((ch>64)&&(ch<90))||((ch>96)&&(ch<123))||ch=='_')
{//ch为字母或数字或’_’时
CurrentWord.name[i++]=ch;
ch=fgetc(SourceFin);
}
for(i=1;i{//判断字符串是否为保留字并置标志符h(h=1为保留字)
h=strcmp(CurrentWord.name,key[i].name);
if(!
h)break;
}
if(!
h)CurrentWord.code=key[i].code;
elseCurrentWord.code=27;
OutPut();//调用输出保留字或标识符
}
/**********************注释处理**************************/
voidIsAnotation()
{
charch1;
ch1=ch;
ch=fgetc(SourceFin);
if(ch=='*')for(;;){
ch=fgetc(SourceFin);
if(ch==EOF){//没有注释结束标志时,出错输出
Error(3);break;
}
if(ch=='*'){
ch1=ch;
ch=fgetc(SourceFin);
if(ch=='/'){ch=fgetc(SourceFin);break;}
}
}
else{//当前符!
=*时,为除号并输出
CurrentWord.name[0]='/';
CurrentWord.code=33;
OutPut();
}
}
/***************字符串处理***************************/
voidIsChar()
{
inti=0;
for(;;){
ch=fgetc(SourceFin);
CurrentWord.code=30;
if(ch!
='"'&&ch!
='\'')CurrentWord.name[i++]=ch;
elsebreak;
if(i>30){printf("ERROR!
请检查你是否漏掉串的结束字符\"出错于%3d行\n",Line);
exit(-1);}
}
OutPut();
ch=fgetc(SourceFin);
}
/********************其他情况的处理**************************/
voidIsOther()
{//处理其他单界符或双界符或非法符号,对非法符号将其删除并报错
charch1;
inti;
for(i=0;i<30;i++)CurrentWord.name[i]='\0';
switch(ch){
case'(':
CurrentWord.name[0]='(';
CurrentWord.code=31;OutPut();
ch=fgetc(SourceFin);break;
case')':
CurrentWord.name[0]=')';
CurrentWord.code=32;OutPut();
ch=fgetc(SourceFin);break;
case'*':
CurrentWord.name[0]='*';
CurrentWord.code=34;OutPut();
ch=fgetc(SourceFin);break;
case'+':
CurrentWord.name[0]='+';
CurrentWord.code=35;OutPut();
ch=fgetc(SourceFin);break;
case',':
CurrentWord.name[0]=',';
CurrentWord.code=37;OutPut();
ch=fgetc(SourceFin);break;
case'-':
CurrentWord.name[0]='-';
CurrentWord.code=36;OutPut();
ch=fgetc(SourceFin);break;
case'{':
CurrentWord.name[0]='{';
CurrentWord.code=38;OutPut();
ch=fgetc(SourceFin);break;
case'}':
CurrentWord.name[0]='}';
CurrentWord.code=39;OutPut();
ch=fgetc(SourceFin);break;
case'=':
ch1=fgetc(SourceFin);
if(ch1=='='){
CurrentWord.name[0]='=';
CurrentWord.name[1]='=';
CurrentWord.code=41;OutPut();
ch1=fgetc(SourceFin);
}
else{
CurrentWord.name[0]='=';
CurrentWord.code=40;OutPut();
}ch=ch1;break;
case';':
CurrentWord.name[0]=';';
CurrentWord.code=42;OutPut();
ch=fgetc(SourceFin);break;
case'<':
ch1=fgetc(SourceFin);
if(ch1=='='){
CurrentWord.name[0]='<';
CurrentWord.name[1]='=';
CurrentWord.code=44;OutPut();
ch1=fgetc(SourceFin);
}
else{
CurrentWord.name[0]='<';
CurrentWord.code=43;OutPut();
}ch=ch1;break;
case10:
Line++;
ch=fgetc(SourceFin);break;
case13:
Line++;
ch=fgetc(SourceFin);break;
case'':
ch=fgetc(SourceFin);break;
caseEOF:
Error(4);break;
default:
Error
(1);
ch=fgetc(SourceFin);break;
}
}
/***************输出模块**************/
voidOutPut()
{
inti=0;/*输出到word表文件*/
for(;;)if(CurrentWord.name[i++]=='\0')break;
fprintf(WordFout,"%-20s",CurrentWord.name);//写入到word.txt文件中
printf("%-20s",CurrentWord.name);//屏幕显示
fprintf(WordFout,"%3d\n",CurrentWord.code);
printf("%3d\n",CurrentWord.code);
}
voidError(inta)
{error_count++;
switch(a){
case1:
printf("error%2d非法字符于%3d行。
\n",error_count,Line);break;
case2:
printf("error%2d实常数出错于%3d行。
\n",error_count,Line);break;
case3:
printf("error%2d没有匹配的注释符'*/'出错于%3d行。
\n",error_count,Line);break;
case4:
printf("error%2d非正常结束!
\n",error_count);break;
default:
break;
}
return;
}