📄 cfmain.cpp
字号:
/*****************************************************
词法分析程序:以文件形式输入源程序,文件输出单词符号
******************************************************/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char *Key_Word[]={" ","auto","break","case","char","const","continue","default","do","double",
"else","enum","extern","float","for","goto","if","int","long","register",
"return","short","signed","sizeof","static","struct","switch","typedef",
"union","unsigned","void","volatile","while"}; /*C语言中全部的关键字,一共32个*/
char *Count_Boundary[]={" ","(",")","[","]","->",".","!","++","--","&","~",
"*","/","%","+","-","<<",">>","<","<=",">",">=","==","!=","&&","||",
"=","+=","-=","*=","/=",",",";","{","}","#","_","'"};/*运算符、界符*/
/*******************************************
函数名:Initial()
作用: 初始化函数
********************************************/
void Initial()
{
FILE *fp;
int i;
char c;
fp=fopen("关键字.txt","w");
for(i=1;i<=32;i++)
fprintf(fp,"%s\n",Key_Word[i]);
fclose(fp); /*初始化关键字表,并将关键字写入该表*/
fp=fopen("运算界符.txt","w");
for(i=1;i<=38;i++)
fprintf(fp,"%s\n",Count_Boundary[i]);
c='"';
fprintf(fp,"%c\n",c);
fclose(fp); /*初始化运算符、界符表,并将运算符、界符写入该表*/
fp=fopen("标识符.txt","w");
fclose(fp); /*初始化标识符表*/
fp=fopen("常数.txt","w");
fclose(fp); /*初始化常数表*/
fp=fopen("Word_Analyse_List.txt","w");
fclose(fp); /*初始化输出文件*/
}
/*******************************************
函数名:char *DecToBin(char *buf)
作用: 十进制转二进制函数
********************************************/
char *DecToBin(char *buf)
{
int temp[20];
char *binary;
int value=0,i=0,j;
for(i=0;buf[i]!='\0';i++)
value=value*10+(buf[i]-48); /*先将字符转化为十进制数*/
if(value==0)
{
binary=(char *)malloc(2*sizeof(char));
binary[0]='0';
binary[1]='\0';
return(binary);
}
i=0;
while(value!=0)
{
temp[i++]=value%2;
value/=2;
}
temp[i]='\0';
binary=(char *)malloc((i+1)*sizeof(char));
for(j=0;j<=i-1;j++)
binary[j]=(char)(temp[i-j-1]+48);
binary[i]='\0';
return(binary);
}
/*******************************************
函数名:int Word_Search(char *buf,int Type,int Command)
作用:根据不同命令查表或造表函数
********************************************/
int Word_Search(char *buf,int Type,int Command)
{
int number=0;
FILE *fp;
char c;
char temp[30];
int i=0;
switch(Type)
{
case 1: fp=fopen("关键字.txt","r");break;
case 2: fp=fopen("标识符.txt","r");break;
case 3: fp=fopen("常数.txt","r"); break;
case 4: fp=fopen("运算界符.txt","r");
}
c=fgetc(fp);
while(c!=EOF)
{
while(c!='\n')
{
temp[i++]=c;
c=fgetc(fp);
}
temp[i]='\0';
i=0;
number++;
if(strcmp(temp,buf)==0)
{
fclose(fp);
return(number); /*若找到,返回在相应表中的序号*/
}
else
c=fgetc(fp);
}
if(Command==1)
{
fclose(fp);
return(0); /*找不到,当只需查表,返回0,否则还需造表*/
}
switch(Type)
{
case 1: fp=fopen("关键字.txt","a");break;
case 2: fp=fopen("标识符.txt","a");break;
case 3: fp=fopen("常数.txt","a");break;
case 4: fp=fopen("运算界符.txt","a");
}
fprintf(fp,"%s\n",buf);
fclose(fp);
return(number+1); /*造表时,将字符串添加到表尾并返回序号值*/
}
/*******************************************
函数名:void Num_Dispose(char *buffer)
作用: 数字串处理函数
********************************************/
void Num_Dispose(char *buffer)
{
FILE *fp;
char *pointer;
int result;
pointer=DecToBin(buffer);
result=Word_Search(pointer,3,2); /*先查常数表,若找不到则造入常数表并返回序号值*/
fp=fopen("Word_Analyse_List.txt","a");
fprintf(fp,"%s\t\t\t\t\t\t43\n",buffer);
fclose(fp); /*写入输出文件*/
}
/*******************************************
函数名:void Char_Dispose(char *buffer)
作用: 字符串处理函数
********************************************/
void Char_Dispose(char *buffer)
{
FILE *fp;
int result;
result=Word_Search(buffer,1,1); /*先查关键字表*/
fp=fopen("Word_Analyse_List.txt","a");
if(result!=0)
fprintf(fp,"%s\t\t\t\t\t\t41\n",buffer); /*若找到,写入输出文件*/
else
{
result=Word_Search(buffer,2,2); /*若找不到,则非关键字,查标识符表,还找不到则造入标识符表*/
fprintf(fp,"%s\t\t\t\t\t\t42\n",buffer); /*若找到, 写入输出文件*/
}
fclose(fp);
}
/*******************************************
函数名:void Error_Dispose(char Error,int LineNum)
作用: 出错处理函数
********************************************/
void Error_Dispose(char Error,int LineNum)
{
printf("\nOneError: %cline %d",Error,LineNum); /*报告出错符号和所在行数*/
}
/*******************************************
函数名:void Word_Analyse()
作用: 逐个字符地扫描源程序
步骤:
1.打开需要进行词法分析的源程序"测试程序.txt"文本文件,如打开失败,显示错误信息.
2.先从源程序中读入一个字符进行判断.如果是字母或下划线则转向3,如果是数字则转向4,
如果是无用字符则转向5,如果是运算符或界符转向6,否则转向7.
3.继续读入字符,直到读到其它字符时调用字符串处理函数Char_Dispose.
4.继续读入字符,直到读到非数字时调用数字串处理函数Num_Dispose.
5.对如空格符,换行符,回车符,跳格符,注释中的内容等等剔除掉.
6.调用Word_Search函数在相应的表中查找该运算符或界符.
7.退出程序.
********************************************/
void Word_Analyse()
{
FILE *fpin,*fpout;
char ch;
int i=0,line=1;
int count,result,Error_Num=0;
char array[32];
char *word;
if((fpin=fopen("测试程序.txt","r"))==NULL)
{
printf("Cannot open file");
return;
}
ch=fgetc(fpin);
while(ch!=EOF) /*按字符依次扫描源程序,直至结束*/
{
i=0;
if(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch=='_')) /*以字母开头*/
{
while(((ch>='A')&&(ch<='Z'))||((ch>='a')&&(ch<='z'))||(ch=='_')||((ch>='0')&&(ch<='9')))
{
array[i++]=ch;
ch=fgetc(fpin);
}
word=(char *)malloc((i+1)*sizeof(char));
memcpy(word,array,i);
word[i]='\0';
Char_Dispose(word);
if(ch!=EOF)
fseek(fpin,-1L,SEEK_CUR);
}
else if(ch>='0'&&ch<='9') /*以数字开头*/
{
while(ch>='0'&&ch<='9')
{
array[i++]=ch;
ch=fgetc(fpin);
}
word=(char *)malloc((i+1)*sizeof(char));
memcpy(word,array,i);
word[i]='\0';
Num_Dispose(word);
if(ch!=EOF)
fseek(fpin,-1L,SEEK_CUR);
}
/*进行预处理,跳过无用的字符*/
else if((ch==' ')||(ch=='\t'))
; /*消除空格符和水平制表符*/
else if(ch=='\n')
line++; /*消除回车并记录行数*/
else if(ch=='/')
{ /*消除注释*/
ch=fgetc(fpin);
if(ch=='=')
{ /*判断是否为‘/=’符号*/
fpout=fopen("Word_Analyse_List.txt","a");
fprintf(fpout,"/=\t\t\t\t\t\t32\n");
fclose(fpout);
}
else if(ch!='*')
{ /*若为除号写入输出文件*/
fpout=fopen("Word_Analyse_List.txt","a");
fprintf(fpout,"/\t\t\t\t\t\t13\n");
fclose(fpout);
fseek(fpin,-1L,SEEK_CUR);
}
else if(ch=='*')
{ /*若为注释的开始,消除包含在里面的所有字符*/
count=0;
ch=fgetc(fpin);
while(count!=2)
{ /*当扫描到‘*’且紧接着下一个字符为‘/’才是注释的结束*/
count=0;
while(ch!='*')
ch=fgetc(fpin);
count++;
ch=fgetc(fpin);
if(ch=='/')
count++;
else
ch=fgetc(fpin);
}
}
}
else if(ch=='"') /*消除包含在双引号中的字符串常量*/
{
fpout=fopen("Word_Analyse_List.txt","a");
fprintf(fpout,"%c\t\t\t\t\t\t37\n",ch);
ch=fgetc(fpin);
while(ch!='"')
ch=fgetc(fpin);
fprintf(fpout,"%c\t\t\t\t\t\t37\n",ch);
fclose(fpout);
}
else
{ /*首字符为其它字符,即运算符、界符或非法字符*/
array[0]=ch;
ch=fgetc(fpin); /*再读入下一个字符,判断是否为双字符运算符、界符*/
if(ch!=EOF)
{ /*若该字符非文件结束符*/
array[1]=ch;
word=(char *)malloc(3*sizeof(char));
memcpy(word,array,2);
word[2]='\0';
result=Word_Search(word,4,1); /*先检索是否为双字符运算符、界符*/
if(result==0)
{ /*若不是*/
word=(char *)malloc(2*sizeof(char));
memcpy(word,array,1);
word[1]='\0';
result=Word_Search(word,4,1); /*检索是否为单字符运算符、界符*/
if(result==0)
{ /*若还不是,则为非法字符*/
Error_Dispose(array[0],line);
Error_Num++;
fseek(fpin,-1L,SEEK_CUR);
}
else
{ /*若为单字符运算符、界符,写入输出文件并将扫描文件指针回退一个字符*/
fpout=fopen("Word_Analyse_List.txt","a");
fprintf(fpout,"%s\t\t\t\t\t\t%d\t\n",word,result);
fclose(fpout);
fseek(fpin,-1L,SEEK_CUR);
}
}
else
{ /*若为双字符运算符、界符,写入输出文件*/
fpout=fopen("Word_Analyse_List.txt","a");
fprintf(fpout,"%s\t\t\t\t\t\t%d\n",word,result);
fclose(fpout);
}
}
else
{ /*若读入的下一个字符为文件结束符*/
word=(char *)malloc(2*sizeof(char));
memcpy(word,array,1);
word[1]='\0';
result=Word_Search(word,4,1); /*只考虑是否为单字符运算符、界符*/
if(result==0) /*若不是,转出错处理*/
Error_Dispose(array[0],line);
else
{ /*若是,写输出文件*/
fpout=fopen("Word_Analyse_List.txt","a");
fprintf(fpout,"%s\t\t\t\t\t\t%d\n",word,result);
fclose(fpout);
}
}
}
ch=fgetc(fpin);
}
fclose(fpin);
printf("There are %d Error(s).\n",Error_Num); /*报告错误字符个数*/
}
/*******************************************
main函数
********************************************/
int main()
{
FILE *fp;
Initial(); /*初始化*/
fp=fopen("Word_Analyse_List.txt","w");
fprintf(fp,"单词符号串\t\t\t\t 种别编码值\n");
fclose(fp);
Word_Analyse(); /*扫描源程序*/
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -