⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 单词的词法分析程序设计.cpp

📁 单词的词法分析程序设计
💻 CPP
字号:
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;                                                                                                         
#define N 256//每行至多256个字符
#define n 20 //每个单词至多20个字符                                                       
char line[N];//存放每一行字符的数组   
char word[n];//存放一个单词的数组
int i;int j;//分别用于控制每个单词和每行字符数组时的计数 
char mark;char ch;//分别为单词种类标记和当前分析字符
int wordlen,linelen,count;//分别为单词长度,每行字符长度,以及行数
FILE *sp,*rp;//文件指针,分别指向源文件和目标文件

char *keyword[13]={"CONST","VAR","PROCEDURE","BEGIN","END","ODD","IF","THEN","CALL","WHILE","DO","READ","WRITE"};
char type[6]={'k','v','m','c','b'};//单词种类,k为关键字,v为标志符,m为运算符,c为常数,b为界限符

int IsKeyword(char *word)//判断是否为关键字
{
   int comkey=0;
   for(int i=0;i<13;i++)
   {if(strcmp(word,keyword[i])==0)//与关键字数组进行比较,有符合的则为关键字
    comkey=1;}
   return comkey;
}

void clear(char *array,int length)//清除数组中内容,以免出现因为单词(或每行)长短不一无法完全覆盖而造成的错误.
{
	
	for(int i=0;i<length;i++)
	{array[i]='\0';}//将数组清空(用于单词数组和每行字符数组的清空)
}

int IsMath()//判断当前字符是否为运算符
{
	if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='='||ch=='<'||ch=='>'||ch==':')
		return 1;
	
	else return 0;
}


int IsBound()//判断当前字符是否为界限符
{
    if(ch==','||ch=='.'||ch==';'||ch=='('||ch==')')
		return 1;
	else return 0;
}


void write(char *word,char mark,FILE *ofile)//设置输出格式为(单词,类别)
{
    fputc('(',ofile);
    fputs(word,ofile);//单词
	fputc(',',ofile); 
    fputc(mark,ofile);//类别
    fputc(')',ofile); 
}

int readline(FILE *fp)//读一行字符,存储在数组line[N]中
{
char str;
int len=0;//len为此行字符个数
str=fgetc(fp);//从文件中获取一个字符
while(!feof(fp) && str!='\n')//当遇到换行符或是文件结束时停止读入.
{
line[len]=str;
str=fgetc(fp);
len++;
}
linelen=len; 

if(feof(fp))//文件结束
return 0;
else 
return 1;
}

void error(int etype)//出现错误时,根据错误类型,显示相应出错信息,并作相应处理.
{
 if(etype==1)
 {
    if(!isspace(ch)&&ch!='\n'&&ch!='\t')
	{cout<<"第"<<count<<"行出现无效字符"<<ch<<endl;}
    j=j+1;ch=line[j];//跳过无效字符
 }
 else if(etype==2)
 cout<<"第"<<count<<"行指数形式错误"<<endl;
}


void Alpha()//单词开始字符为字母时
{       i=0;//每执行一次,则处理了一个单词,i置0,以下同上.
  	    while(isalpha(ch) || isdigit(ch))
			{
				word[i]=ch;
				i++;j++;
				ch=line[j];
			}
			
		if (IsKeyword(word))//为关键字时
		{mark=type[0];}
		else//为一般标志符时
		{mark=type[1];}
		write(word,mark,rp);
        wordlen=i;
        clear(word,wordlen);
	    	
}


void Digit()//当前字符为数字时
{
    i=0;int eyes;         
	do{
       word[i++]=ch;
       ch=line[++j];
	}while(isdigit(ch));
if(ch=='.')//小数时
{ 
  word[i++]=ch;
  ch=line[++j];
  if(!isdigit(ch)){eyes=1;}//前面已有小数点(.),则后面紧跟着的字符必须是数字,否则为错误形式.
  while(isdigit(ch))
  {  word[i++]=ch;
     ch=line[++j];  }
}

if(ch=='e'||ch=='E')//指数时
{  word[i++]=ch;
   ch=line[++j];
   if(ch=='-')
   {word[i++]=ch;ch=line[++j];}
   if(!isdigit(ch)){eyes=1;}//如果有E(e),说明是指数形式,E(e)后面必须为数字,否则为错误形式.
   while(isdigit(ch))
   {  word[i++]=ch;
        ch=line[++j];}
}
    if(eyes==1){error(2);}//如果有错误,则调用出错函数处理
    mark=type[3];
    write(word,mark,rp);
    wordlen=i;
    clear(word,wordlen);
	
}




void Math()//单词开始字符为运算符时
{       i=0;
	    word[i] =ch;
   	    if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='=')
		{   
			mark=type[2];wordlen=1;
		}	
		else if(ch=='>')//当为'>'时,可能为'>',也能为'>='
		{   j=j+1;
			ch=line[j];
			
			if(ch=='=')//为'>="时,单词长度为2,将'='和'>'合并为一个单词.
			{mark=type[2];word[1]=ch;wordlen=2;}
			else//为'>'时,单词长度为1,'>'后面的字符不属于该单词,属于后面单词,用j=j-1,退出,使后面的字符进入下一轮判断.
			{mark=type[2];wordlen=1;;}
		}
		else if( ch=='<')//有'<'和'<="两种情况,与'>'类似.

		{    j=j+1;
		     ch=line[j];
			
			if(ch=='=')
			{mark=type[2];word[1]=ch;wordlen=2;}
			else
			{mark=type[2];wordlen=1;j=j-1;}
		}
		else if(ch==':')
		{
             j=j+1;
		     ch=line[j];
			 if(ch=='=')//赋值符':='
			 {mark=type[2];word[1]=ch;wordlen=2;}
			 else//界限符':'
			 {mark=type[4];wordlen=1;j=j-1;}
		}

		j=j+1;
		ch=line[j];
        write(word,mark,rp);
        clear(word,wordlen);
}



void Bound()//单词开头为界限符时.
{
  i=0;
  word[i]=ch;
  mark=type[4];
  write(word,mark,rp);
  wordlen=1;
  clear(word,wordlen);
  j=j+1;
  ch=line[j];
  
}




void main()
{ 
 char sourcefile[20],resultfile[20];//存入输入,输出文件名

 cout<<"请输入需进行词法分析的文件名:";
 gets(sourcefile);
 cout<<"请输入词法分析后得到的输出文件名:";
 gets(resultfile);
 sp=fopen(sourcefile,"r");//以"读"形式打开源文件,以读入文件进行分析.
 rp=fopen(resultfile,"w");//以"写"形式打开目标文件,以将词性分析结果写入

 if(!sp)//源文件不存在
 {cout<<"对不起,你输入的源文件不存在!";
  exit(0);}
 else
 {
       while(readline(sp))//每执行一次循环,完成一行字符的处理操作,直到文件结束
	  {  
		 j=0;count++;//每完成一行,j置0,行数增加
         ch=line[0];//读入一行中第一个字符
	do{//对当前字符进行类别判断,进入不同的子程序分支.
		 if(isalpha(ch)) {Alpha();}//为字母时
		 else if(isdigit(ch)){ Digit();}//为数字时
		 else if(IsMath()) {Math();}//为运算符时
         else if(IsBound())  {Bound();}//为界限符时
	     else if(ch=='#') exit(0);//为结束符时,退出
		 else {error(1);}//其他时字符进行错误处理.
		 }while(j<linelen);//处理直到每行结束

        clear(line,linelen);//一行字符处理完成后,对此行字符数组进行清除处理.以免影响下一行字符.
        fputc('\n',rp);//每在目标文件中写完一行字符的分析结果,则进行换行,使目标文件与源文件行行对应.
	  }
}
fclose(sp);//分析完成,关闭文件
fclose(rp);
cout<<"词法分析成功!结果保存在:"<<resultfile<<endl;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -