直接上代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *KT[32]={"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"
};//关键字表
char PT[18]={';',',','.','{','}','[',']','+','-','*','/','%','(',')','=','>','<','#'};//单目界符
char *doublePT[11]={"++","--","<=","==",">=","+=","-=","*=","/=","<<",">>"};//双目界符
char IT[10][10],CT[10][10],ST[10][10];//分别储存标识符 常数 字符串
char cT[10];//储存字符
struct point
{
char*kind;//种类
char value[33];//名字
int num;//token值
};//用以储存词法分析的结果
int isLetter(char ch)//判断字符是否为字母
{
if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
return 1;
else return 0;
}
int isDigit(char ch)//判断字符是否为数字
{
if(ch>='0'&&ch<='9')return 1;
else return 0;
}
int Reserve(char strToken[33])//寻找关键字表
{
int i;
for(i=0;i<32;i++){
if(strcmp(KT[i],strToken)==0)return i+1;
}
return 0;
}
void Retract(FILE *fp)//缩进,当识别大于1个字符的单词时应用到
{
fseek(fp,-1L,1);
}
void Print(struct point a)//输出结果
{
printf("%s <%s,%d>\n",a.value,a.kind,a.num);
}
int isPartition(char ch)//判断是否是界符并返回序号
{
int i;
for(i=0;i<18;i++)if(PT[i]==ch)return i+1;
return 0;
}
int isSpecial(char ch)//判断是否为特殊符号
{
if(ch=='+'||ch=='-'||ch=='/'||ch=='<'||ch=='>'||ch=='*'||ch=='=')return 1;
else return 0;
}
void operate(struct point a)//将词法分析的结果输出到文件中
{
FILE *fp;
fp=fopen("result.txt","a+");
fprintf(fp,"%s <%s,%d>\n",a.value,a.kind,a.num);
fclose(fp);
}
int main()
{
int code,count1=0,count2=0,count3=0,count4=0,f=0,E=0;//辅助变量
struct point result;//保存结果
char strToken[33];//暂存每次识别的字符
char ch;
char *p;
FILE *fp;
fp=fopen("examplecode.txt","r");//打开示例代码的文本文件
if(fp==NULL)//当文件打开失败时
{
printf("file does not exist!");
return -1;
}
while(1)
{
p=strToken;
ch=fgetc(fp);//逐个读取字符
if(feof(fp))//当读到文件末尾
break;
if(ch==' '||ch=='\n')//遇到空格则跳过
continue;
if(isLetter(ch)){//判断是否是标识符或是关键字
while(isLetter(ch)||isDigit(ch))
{
*p=ch;
p++;
*p='\0';
ch=fgetc(fp);
if(feof(fp))return -1;
}
Retract(fp);
code=Reserve(strToken);
if(code!=0)
{
result.kind="KT";
strcpy(result.value,strToken);
result.num=code;
operate(result);
Print(result);
}
else
{
for(int i=0;i<20;i++)
if(strcmp(IT[i],strToken)==0){code=21;result.num=i+1;break;}
if(code!=21){strcpy(IT[count1],strToken);count1++; result.num=count1;}
result.kind="IT";
strcpy(result.value,strToken);
operate(result);
Print(result);
}
}
else if(isDigit(ch))//常数
{
while((isDigit(ch)||ch=='.'||ch=='e')&&(f==0||f==1)&&(E==0||E==1)){
if(ch=='.')f++;
if(ch=='e'){E++;*p=ch;
p++;
*p='\0';
ch=fgetc(fp);}
if(f>1||E>1)printf("Error occurs!at%c\n",ch);
*p=ch;
p++;
*p='\0';
ch=fgetc(fp);
if(feof(fp))return -1;
}
Retract(fp);
for(int i=0;i<20;i++)
if(strcmp(CT[i],strToken)==0){code=22;result.num=i+1;break;}
if(code!=22){strcpy(CT[count2],strToken);count2++;result.num=count2;}
strcpy(result.value,strToken);
result.kind="CT";//常数
operate(result);
Print(result);
}
else if(isPartition(ch))//界符
{
result.kind="PT";
result.num=isPartition(ch);
char ch2;
ch2=fgetc(fp);
*p=ch;
p++;
*p='\0';
if(isSpecial(ch2)&&isPartition(ch2))Retract(fp);
else if(!isSpecial(ch2))Retract(fp);
if(isSpecial(ch)&&ch2=='=')
{
code=1;
*p=ch2;
p++;
*p='\0';
ch=fgetc(fp);
}
if((ch=='>'||ch=='<'||ch=='+'||ch=='-')&&ch2==ch)
{
code=1;
*p=ch2;
p++;
*p='\0';
ch=fgetc(fp);
}
strcpy(result.value,strToken);
if(code==1)for(int i=0;i<11;i++)
if(strcmp(doublePT[i],strToken)==0){result.num=i+21;break;}
operate(result);
Print(result);
}
else if (ch=='\''){//字符
char ch2;
result.kind="cT";
printf("' <PT,19>\n");//前引号
ch2=fgetc(fp);
*p=ch2;
p++;
*p='\0';
for(int i=0;i<20;i++)
if(cT[i]==ch2){code=23;result.num=i+1;break;}
if(code!=23){cT[count3]=ch2;count3++;result.num=count3;}
strcpy(result.value,strToken);
operate(result);
Print(result);
printf("' <PT,19>\n");
ch2=fgetc(fp);
}
else if(ch=='"'){//字符串
result.kind="sT";
printf("\" <PT,20>\n");
ch=getc(fp);
while(isLetter(ch)||isDigit(ch)){
*p=ch;
p++;
*p='\0';
ch=fgetc(fp);
if(feof(fp))return -1;
}
Retract(fp);
for(int i=0;i<10;i++)
if(strcmp(IT[i],strToken)==0){code=24;result.num=i+1;break;}
if(code!=24){strcpy(ST[count4],strToken);count4++; result.num=count4;}
strcpy(result.value,strToken);
operate(result);
Print(result);
ch=getc(fp);
printf("\" <PT,20>\n");
}
else//其余情况为错误情况
{
if(ch=='\n')continue;
result.kind="Error!";
operate(result);
printf("Error occurs!at%c\n",ch);
}
}
return 1;
}