#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct test //关键字
{
char name[10];
int num;
};
struct oper//运算符与关系运算符
{
char name[4];
int num;
};
struct cut //分隔符
{
char name[2];
int num;
};
//定义全局变量
struct test test[10]={
{"main",3},{"if",4},{"int",5},{"for",6},{"while",7},{"do",8},{"retuen",9},{"break",10},{"continue",11},
};
struct oper oper[11]={
{"+",41},{"-",42},{"*",43},{"/",44},{"=",45},{">",46},{"<",47},{">=",48},{">=",49},{"==",50},{"!=",51}
};
struct cut cut[6]={
{",",61},{";",62},{"{",63},{"}",64},{"(",65},{")",66}
};
typedef struct sd
{int type;
int no;
char str[10];
}sdd;
sdd value[10];
//包含的函数
void menu();//菜单
void scansource();//查看源文件
void rule();//查看输出规则
void analyse();//分析结果显示
void getch(char ch); //读取为字母
void getnum(char ch); //读取为数字
void getspace(char ch); //读取制表符类
void getelse(char ch); //其他字符
int change(char str[10]);
char ch;
char str[10];
int k=0,i=0;
char sourcefile[20]; //源文件名
char objectfile[20]; //目标文件名
FILE *fp;
FILE *hp;
int count=-1;
int flag=-1;
int main(int argc,char *argv[])
{
int choice;
//显示菜单
menu();
printf("输入进行词法分析的源文件名:");
scanf("%s",sourcefile);
printf("\n输入分析结果存入的文件名:");
scanf("%s",objectfile);
printf("\n输入选项:");
scanf("%d",&choice);
for(; ;)
{
switch(choice)
{
case 1:
scansource();
break;
case 2:
rule();
break;
case 3:
analyse();
break;
case 4:
exit(1);
break;
}
printf("\n\n");
printf("请输入选项:");
scanf("%d",&choice);}
return 0;
}
void menu()
{
printf("/-----------------------------------------------/\n");
printf(" 词法分析器 \n");
printf(" 1.查看源文件: \n");
printf(" 2.符号种别码: \n");
printf(" 3.分析结果: \n");
printf(" 4.退出程序: \n");
printf("/------------------------------------------------/\n");
}
void scansource()
{
FILE *fp;
char ch;
if((fp=fopen(sourcefile,"r"))==NULL)
{
printf("文件打开错误或源文件不存在 !\n");
exit(1);
}
ch=fgetc(fp);
while(ch!=EOF)
{
putchar(ch);
ch=fgetc(fp);
}
fclose(fp);
printf("\n");
}
void rule()
{
int i;
printf("标识符及其对应种别码:\n");
printf("( 1,内部码 )\n");
printf("数字及其对应的种别码:\n");
printf("( 2,二进制码)\n");
printf("关键字及其对应种别码:\n");
for(i=0;i<9;i++)
{
printf("( %s,%d )\t",test[i].name,test[i].num);
}
printf("\n");
printf("运算符及其对应种别码:\n");
for(i=0;i<11;i++)
{
printf("( %s,%d )\t",oper[i].name,oper[i].num);
}
printf("\n");
printf("分隔符及其对应种别码:\n");
for(i=0;i<6;i++)
{
printf("( %s,%d )\t",cut[i].name,cut[i].num);
}
printf("\n");
}
void analyse()
{
if((fp=fopen(sourcefile,"r"))==NULL)
{
printf("文件打开错误 !\n");
exit(1);
}
if((hp=fopen(objectfile,"w"))==NULL)
{
printf("文件打开错误 !\n");
exit(1);
}
while(ch!=EOF)
{
ch=fgetc(fp);
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))
{
getch(ch);
}
else if((ch>='0')&&(ch<='9'))
{ //如果读取的是数字
getnum(ch);
}
else if((ch==' ')||(ch=='\r')||(ch=='\n')||(ch=='\t'))
{
getspace(ch);
}
else //其他情况
{
getelse(ch);
}
k=0;
str[k]='\0';
};
fclose(fp); //关闭文件
fclose(hp);
printf("\n");
}
void getch(char ch)
{
while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
{
str[k]=ch;
str[++k]='\0';
ch=fgetc(fp);
}
for(i=0;i<9;i++)
{ if(strcmp(str,test[i].name)==0) //测试是否为保留字{
{ printf("( -, )\n",test[i].num); fprintf(hp,"( -, )\n",test[i].num);
k=0;
flag=1;
int f;
f=count+1;
value[f].type=test[i].num;
break;
}
}
if(k!=0) //否则为标识
{ int m;
m=change(str);
printf("( 1,%d ) \n",m); fprintf(hp,"( 1,%d )\n",m);
k=0;
}
fseek(fp,-1L,1);
}
void getnum(char ch)
{
int s=0,i=0,a[20],j,m=0;
char b[20];
char *p;
while((ch>='0')&&(ch<='9'))
{
str[k]=ch;
str[++k]='\0';
ch=fgetc(fp);
}
for(p=str;(*p)!='\0';p++)
s=(*p-48)+s*10;
while(s>0)
{
a[i++]=s%2;
s=s/2;
}
for(j=i-1;j>=0;j--)
{
b[m]=a[j]+48;
m++;
}
b[m]='\0';
k=0;
fseek(fp,-1L,1);
printf("( 2,%s ) \n",b); fprintf(hp,"( 2,%s )\n",b);
}
void getspace(char ch)
{
for(; ;)
{
ch=fgetc(fp);
if(!((ch==' ')||(ch=='\n')||(ch=='\t')||(ch=='\r')))
{
fseek(fp,-1L,1);
break;
}
}
}
void getelse(char ch)
{
switch(ch)
{
case ',':
printf("( 61, )\n");
fprintf(hp,"( 61, )\n");
break;
case ';':
printf("( 62, )\n");
fprintf(hp,"( 62, )\n");
break;
case '{':
printf("( 63, )\n");
fprintf(hp,"( 63, )\n");
break;
case '}':
printf("( 64, )\n");
fprintf(hp,"( 64, )\n");
break;
case '(':
printf("( 65, )\n");
fprintf(hp,"( 65, )\n");
break;
case ')':
printf("( 66, )\n");
fprintf(hp,"( 66, )\n");
break;
case '+':
printf("( 41, )\n");
fprintf(hp,"( 41, )\n");
break;
case '-':
printf("( 42, )\n");
fprintf(hp,"( 42, )\n");
break;
case '*':
printf("( 43, )\n");
fprintf(hp,"( 43, )\n");
break;
case '/':
printf("( 44, )\n");
fprintf(hp,"( 44, )\n");
break;
case '=':
str[k]=ch;
str[++k]='\0';
ch=fgetc(fp);
if(ch!='=')
{
fseek(fp,-1L,1);
printf("( 45, )\n");
fprintf(hp,"( 45, )\n");
}
else if(ch=='=')
{
printf("( 50, )\n");
fprintf(hp,"( 50, )\n");
}
break;
case '>':
str[k]=ch;
str[++k]='\0';
if(ch!='=')
{
fseek(fp,-1L,1);
printf("( 46, )\n");
fprintf(hp,"( 46, )\n");
}
else if(ch=='=')
{
printf("( 48, )\n");
fprintf(hp,"( 48, )\n");
}
break;
case '<':
str[k]=ch;
str[++k]='\0';
if(ch!='=')
{
fseek(fp,-1L,1);
printf("( 47, )\n");
fprintf(hp,"( 47, )\n");
}
else if(ch=='=')
{
printf("( 49, )\n");
fprintf(hp,"( 49, )\n");
}
break;
case '!':
str[k]=ch;
str[++k]='\0';
if(ch!='=')
{
fseek(fp,-1L,1);
}
else if(ch=='=')
{
printf("( 51, )\n");
fprintf(hp,"( 51, )\n");
}
break;
}
}
int change(char str[10])
{
int j;
for(j=0;j<count+1;j++)
if(strcmp(str,value[j].str)==0)
break;
if(j<count+1)
return (value[j].type*100+value[j].no);
else
{
count++;
if(flag==-1)
value[count].type=1;
for(int i=0;i<9;i++)
value[count].str[i]=str[i];
value[count].no=count+1;
flag=-1;
return ((value[count].type)*100+value[count].no);
}
}