您的位置:首页 > Web前端

编译原理简单词法分析

2011-04-15 19:33 309 查看
/*
编译原理简单词法分析

@	关键字识别
@	标识符判断
@	常数(包括小数的识别(暂不支持负数))
@	界符的识别

&		将源文件扫描一遍						&
&		将所有编码结果输出到编码文件当中		&
&		常数和标识符分别单独再存到一个表中		&
&		便于查找和识别							&
&		避免二次写入							&

*/
#include<stdio.h>
#include<string.h>

FILE *in,*out,*changshu,*biaozhifu;		/*源文件		编码文件	常数表		标识符表*/

char key[][20]={"int","long","short","float","double","char","signed","undighed","static","const",
"void","if","else","do","while","switch","case","default","for","break","continue","goto",
"include","return","main"};

int keynum=25;				/*关键字的数量*/

int NUMBER(char ch)			/*数字*/
{
if(ch>='0'&&ch<='9')
return 1;
else
return 0;
}

int OPERATOR(char ch)				/*运算符*/
{
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='='||ch=='^'||ch=='~'||ch=='&'||ch=='%'||ch=='<'||ch=='>'||ch=='.'||ch=='!')
return 1;
else
return 0;
}

int BOUNCE(char ch)			/*界符*/
{
if(ch=='//'||ch==','||ch==';'||ch=='#'||ch=='{'||ch=='}'||ch=='('||ch==')'||ch=='"')
return 1;
else
return 0;
}

char buffer[50];				/*定义一个缓冲区存放字符串*/
int cflag=0;					/*代表缓冲区中存放字符的个数*/
int nflag=0;					/*代表缓冲区存放数字的个数*/
int nth=0;						/*表示在常数表中存储的位置*/
int bth=0;						/*表示在标识符表中存储的位置*/
int numflag=0;					/*标志是否处于读书状态  1读数  0没读数*/
char num[50];					/*存放数字*/
char Biaozhifu[100][20];		/*存储已经定义的标识符*/
char Changshu[100][100];		/*存储已经出现过的常数*/

void analysis()
{
int i;
char ch;
while(!feof(in))
{
ch=fgetc(in);
if(NUMBER(ch))			/*如果是数字*/
{
if(cflag)			/*有可能在定义标识符	避免遗漏 a1等情况*/
{
buffer[cflag++]=ch;
}
else
{
numflag=1;
num[nflag++]=ch;
}
}
else if(BOUNCE(ch))		/*如果是界符*/
{
if(cflag)		/*如果缓冲区中已存在字符*/
{
buffer[cflag]='/0';
for(i=0;i<keynum;i++)
{
if(strcmp(key[i],buffer)==0)
break;
}
if(i<keynum)
{
fprintf(out,"%s/t/t%d/t/t%s/n",buffer,3,"关键字");
}
else
{
for(i=0;i<bth;i++)						/*判断此标识符是否在之前定义过*/
{
if(strcmp(Biaozhifu[i],buffer)==0)
break;
}
if(i==bth)
{
strcpy(Biaozhifu[bth],buffer);		/*如果没有出现过  就将此标识符保存在Bianzhifu字符数组中  并写入标识符表中*/
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",buffer,1,"标识符",bth);
fprintf(biaozhifu,"%s/t%d/n",buffer,bth++);
}
else					/*如果已经出现过则*/
{
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",buffer,1,"标识符",i);
}
}
cflag=0;		/*解除读字符状态*/
}
else if(numflag)
{
num[nflag]='/0';
for(i=0;i<nth;i++)
{
if(strcmp(Changshu[i],num)==0)
break;
}
if(i==nth)		/*如果该数字在之前没有出现过   就将这个数字写入Changshu字符数组中  并相应写入常数表中*/
{

strcpy(Changshu[nth],num);
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",num,2,"常数",nth);
fprintf(changshu,"%s/t%d/n",num,nth++);
}
else		/*如果已经出现过*/
{
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",num,2,"常数",i);
}

nflag=0;
numflag=0;		/*解除读数状态*/
}
fprintf(out,"%c/t/t%d/t/t%s/n",ch,5,"界符");
}
else if(OPERATOR(ch))	/*如果是运算符*/

{
if(cflag)		/*如果缓冲区中已存在字符*/
{
buffer[cflag]='/0';
for(i=0;i<keynum;i++)
{
if(strcmp(key[i],buffer)==0)
break;
}
if(i<keynum)
{
fprintf(out,"%s/t/t%d/t/t%s/n",buffer,3,"关键字");
}
else
{
for(i=0;i<bth;i++)						/*判断此标识符是否在之前定义过*/
{
if(strcmp(Biaozhifu[i],buffer)==0)
break;
}
if(i==bth)
{
strcpy(Biaozhifu[bth],buffer);		/*如果没有出现过  就将此标识符保存在Bianzhifu字符数组中  并写入标识符表中*/
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",buffer,1,"标识符",bth);
fprintf(biaozhifu,"%s/t%d/n",buffer,bth++);
}
else					/*如果已经出现过则*/
{
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",buffer,1,"标识符",i);
}
}

cflag=0;		/*解除读字符状态*/
}
else if(numflag&&ch=='.')
{
num[nflag++]=ch;
}

if((ch=='.'&&!numflag)||ch!='.')//如果当前读入的为" ."并且之前没有数字则.为运算符
{
fprintf(out,"%c/t/t%d/t/t%s/n",ch,4,"运算符");
}

}
else					/*其它字符*/
{
if(ch==' '||ch=='/t'||ch=='/n')
{
if(cflag)		/*如果缓冲区中已存在字符*/
{
buffer[cflag]='/0';
for(i=0;i<keynum;i++)
{
if(strcmp(key[i],buffer)==0)
break;
}
if(i<keynum)
{
fprintf(out,"%s/t/t%d/t/t%s/n",buffer,3,"关键字");
}
else
{
for(i=0;i<bth;i++)						/*判断此标识符是否在之前定义过*/
{
if(strcmp(Biaozhifu[i],buffer)==0)
break;
}
if(i==bth)
{
strcpy(Biaozhifu[bth],buffer);		/*如果没有出现过  就将此标识符保存在Bianzhifu字符数组中  并写入标识符表中*/
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",buffer,1,"标识符",bth);
fprintf(biaozhifu,"%s/t%d/n",buffer,bth++);
}
else					/*如果已经出现过则*/
{
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",buffer,1,"标识符",i);
}
}
cflag=0;		/*解除读字符状态*/
}
else if(numflag)
{
num[nflag]='/0';
for(i=0;i<nth;i++)
{
if(strcmp(Changshu[i],num)==0)
break;
}
if(i==nth)		/*如果该数字在之前没有出现过   就将这个数字写入Changshu字符数组中  并相应写入常数表中*/
{
strcpy(Changshu[nth],num);
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",num,2,"常数",nth);
fprintf(changshu,"%s/t%d/n",num,nth++);
}
else		/*如果已经出现过*/
{
fprintf(out,"%s/t/t%d/t/t%s/t/t%d/n",num,2,"常数",i);
}
numflag=0;		/*解除读数状态*/
nflag=0;
}

}
else
{
if(ch=='e'&&numflag)
{
num[nflag++]=ch;
}
else
buffer[cflag++]=ch;
}
}
}

}

void main()
{
in=fopen("源文件.c","r");
out=fopen("编码文件.txt","w");
changshu=fopen("常数.txt","w");
biaozhifu=fopen("标识符.txt","w");

fprintf(out,"%s/t/t%s/t%s    /t%s/n","名称","属性标号","属性","对应表中序号");
fprintf(biaozhifu,"%s/t%s/n","名称","序号");
fprintf(changshu,"%s/t%s/n","名称","序号");

analysis();

fclose(in);
fclose(out);
fclose(changshu);
fclose(biaozhifu);

}

/*

@	2011.4.15
@ Zhang Bing.

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息