/* 编译原理简单词法分析 @ 关键字识别 @ 标识符判断 @ 常数(包括小数的识别(暂不支持负数)) @ 界符的识别 & 将源文件扫描一遍 & & 将所有编码结果输出到编码文件当中 & & 常数和标识符分别单独再存到一个表中 & & 便于查找和识别 & & 避免二次写入 & */ #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. */