预头文件
/*----Head file for analysis programs in....----*/
#include <stdio.h>
#include <string.h>
#include <ctype.h> //使用到的字符分类函数定义在的头文件
/**
*TEST编译器:词法分析头文件
*@author mohui
*@date 2015/04/12
***/
//--------预定义常量--------
#define keywordSum 8 //关键字个数
#define compileOK 0 //词法分析成功完成代码
#define inputERROR 1 //词法分析源文件输入出错代码
#define outputERROR 2 //词法分析输出文件出错代码
#define unusualChr 3 //词法分析非法字符代码
//--------变量、结果类型--------
char *keyword[keywordSum]={"if","else","for","while","do","int","read","write"};
char singleword[20]="+-*(){};,:"; //纯单分界符
char doubleword[20]="><=!"; //双分界符的首字符
char inFile[50],outFile[50]; //源文件名与输出报告文件名(含路径)
FILE *fin,*fout;
//--------analysis.c---------
int TESTscan(); //词法分析函数
int IOinfo(); //文件流输入输出监管
void String(char *ch); //检查标识符(包括关键字)并记录
void Number(char *ch); //检查数字并记录
void sDelimiter(char *ch); //纯单分界符
void dDelimiter(char *ch); //分离双分界符与单分界符
void comments(char *ch); //注释符内容处理
int illegalChr(char *ch); //词法分析过程非法字符处理
C源程序
#include "analysis.h"
/**
*TEST编译器:词法分析
*@author mohui
*@date 2015/04/12
***/
//---------主 程 序--------
int main(){
int ecode=compileOK;
ecode=TESTscan();
if(ecode>0)
{
printf("==================================\n");
printf("ERROR : 词法分析存在错误,编译中断!\n错误代码 : %d\n",ecode);
printf("==================================\n");
}
else
printf("词法分析成功!\n");
return 0;
}
//--------集成函数主模块--------
int TESTscan(){
char ch;
int ecode;
ecode=IOinfo();
ch=getc(fin);
do{
while(isspace(ch)) //检查是否是空格符和跳格符(控制字符)或换行符
ch=getc(fin);
if(isalpha(ch)) //判断是否是字母
{
String(&ch); //记录标识符[关键字]
}
else if(isdigit(ch)) //检查是否是数字
{
Number(&ch); //记录数字
}
else if(strchr(singleword,ch)>0) //判断singleword中有没有ch,有返回值为1,没有返回值为0
{
sDelimiter(&ch); //记录纯单分界符
}
else if(strchr(doubleword,ch)>0)
{
dDelimiter(&ch); //分离双分界符与单分界符
}
else if(ch=='/')
{
comments(&ch); //分离注释处理
}
else
{
ecode=illegalChr(&ch); //分析过程异常符号处理
}
}while(!feof(fin));
fclose(fin);
fclose(fout);
return ecode;
}
//--------文件流情况的监管--------
int IOinfo(){
printf("请输入源文件文件名[包括路径]:\n");
fscanf(stdin,"%s",inFile);
printf("请输入词法分析输出文件名[包括路径]:\n");
fscanf(stdin,"%s",outFile);
if((fin=fopen(inFile,"r"))==NULL)
{
printf("打开词法分析源文件出错!\n");
return (inputERROR);
}
if((fout=fopen(outFile,"w"))==NULL)
{
printf("创建词法分析输出文件出错!\n");
return (outputERROR);
}
return compileOK;
}
//--------检查&记录标识符(包括关键字)--------
void String(char *ch){
char checked[50];
int j,n;
checked[0]=*ch;
j=1;
*ch=getc(fin); //读入下一个字符
while(isalnum(*ch)) //检查是否是数字或字母
{
checked[j++]=*ch;
*ch=getc(fin);
}
checked[j]='\0'; //标识符组合结束
n=0;
while((n<keywordSum)&&strcmp(checked,keyword[n]))
n++;
if(n>=keywordSum)
fprintf(fout,"%s\t%s\n","ID",checked); //输出标识符符号
else
fprintf(fout,"%s\t%s\n",checked,checked); //输出保留字符号
}
//--------检 查&记 录 数 字--------
void Number(char *ch){
char checked[100];
int j;
checked[0]=*ch;
j=1;
*ch=getc(fin); //读入下一个字符
while(isdigit(*ch))
{
checked[j++]=*ch;
*ch=getc(fin);
}
checked[j]='\0'; //数字组合结束
fprintf(fout,"%s\t%s\n","NUM",checked); //输出整数符号
}
//--------单分界符--------
void sDelimiter(char *ch){
char checked[2];
checked[0]=*ch;
checked[1]='\0';
*ch=getc(fin);
fprintf(fout,"%s\t%s\n",checked,checked); //输出单分界符
}
//--------双分界符--------
void dDelimiter(char *ch){
char checked[5];
checked[0]=*ch;
*ch=getc(fin);
if(*ch=='=')
{
checked[1]=*ch;
checked[2]='\0';
*ch=getc(fin);
}
else
checked[1]='\0';
fprintf(fout,"%s\t%s\n",checked,checked); //输出双分界符或单分界符
}
//--------注释符处理--------
void comments(char *ch){ //程序顺序执行到这里,已经过单分界符的判断,so可以不必再记录ch
char checked[2];
*ch=getc(fin);
if (*ch=='*')
{
char ch1;
ch1=getc(fin);
do{
*ch=ch1;
ch1=getc(fin);
}while((*ch!='*'||ch1!='/')&&!feof(fin));
*ch=getc(fin);
}
else
{
checked[0]='/';
checked[1]='\0';
fprintf(fout,"%s\t%s\n",checked,checked); //输出单分界符
}
}
//--------异常(非法)字符处理--------
int illegalChr(char *ch){
char checked[2];
checked[0]=*ch;
checked[1]='\0';
*ch=getc(fin);
fprintf(fout,"%s\t%s\n",checked,checked); //输出异常(非法)符号
return (unusualChr);
}
测试用的两个TEST源码:
test.txt内容:
illegal.txt内容:
运行结果: