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

📄 complier.cpp

📁 这是用VC++6.0编写的一个简单的c语言的词法分析器
💻 CPP
字号:
#include<iostream.h>
#include<fstream.h>
#include<string.h>
#define true 1
#define false 0
#define N 100  //确定缓冲区的最大容量
int IN=0; //I表计数器
int CN=0;  //C表计数器
int Len=0;//纪录待编译程序的行号

bool GetChar(char *c,char*buf,int *m);//从buffer中读取一个字符
bool IsLetter(char c);
bool IsDigit(char c);
void Concat(char *str,char ch);
int Change(char *str);//把从类型表(P,K,I,C)中读取的整数串转化成整数形式,并返回
int CheckK(char *str);
int CheckP(char *str);
int InsertI(char *str);
int InsertC(char *str);
void W_Answer(char *str,char value,int code);
//在Answer.txt中填写编译结果,包括单词符号及其所属属性,也包括错误处理信息

int main()
{
	char buffer[N];  //输入缓冲区
	int mark; //搜索指示器,指示下一次要读取的字符在buffer中的位置
	char ch;  //存放最新读进的字符
	char strToken[N]; //存放构成单词符号的字符串
	int code; //记录当前单词符号在所属表中的位置
	char value;//单词符号所属的种别,可取得值为:K,P,I,C,分别对应于四个表,值为E表示出错
	buffer[0]=strToken[0]='\0';
	
		
    ifstream inSP("SourPro.txt"); //打开源程序文件SourPro
    if(!inSP)
	{
		cout<<"Failed to open SourPro.txt"<<endl;
		return 0;
	}
	cout<<"***Scanning the file 'SourPro.txt'***"<<endl;
	inSP.getline(buffer,N);
	mark=0;  //mark复位
	while(!inSP.eof()||(buffer[mark]!='\0'))
	{
		while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
			         //读取字母,如果超过buffer的界限,则从文件中重新读取一行存入buffer
		{
			inSP.getline(buffer,N);
    		Len++;
		    mark=0;  
		}
		if(IsLetter(ch))//关键字或是标识符
		{
			while(IsLetter(ch) || IsDigit(ch)||ch=='_')
			{
				Concat(strToken,ch);//将ch连接到strToken之后 ???
				while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
				{
					inSP.getline(buffer,N);
					Len++;
			        mark=0;  //mark复位
				}
			}
			value='K';
			code=CheckK(strToken);//查K表,如该字符存在k表中,则返回表中的位置,否则返回0
			if(code==0)
			{
				code=InsertI(strToken); //不属于关键字,则插入到I表中
				value='I';
			}
			mark--;
			ch='\0';//回溯一个字符
		}
		else
			if(IsDigit(ch))  //常数串
			{
				while(IsDigit(ch))
				{
					Concat(strToken,ch);//将ch连接到strToken之后 ???
					while((GetChar(&ch,buffer,&mark)==0) && (!inSP.eof()))
					{
						inSP.getline(buffer,N);
						Len++;
						mark=0;  //mark复位
					}
				}
				if(ch=='.')
				{
					Concat(strToken,ch);//将ch连接到strToken之后 
					while((GetChar(&ch,buffer,&mark)==0) && (!inSP.eof()))
					{
						inSP.getline(buffer,N);
						Len++;
						mark=0;  //mark复位
					}
					if(!IsDigit(ch))
						value='E';//错误处理
					else
					{
						while(IsDigit(ch))
						{
							Concat(strToken,ch);//将ch连接到strToken之后 ???
							while((GetChar(&ch,buffer,&mark)==0) && (!inSP.eof()))
							{
								inSP.getline(buffer,N);
								Len++;
								mark=0;  //mark复位
							}
						}
						value='C';
						code=InsertC(strToken);
						mark--;
						ch='\0';
					}
				}
						
			}
			else//操作符或分隔符处理
			{
				switch(ch)
				{
				case'=':
						Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='=')//第二个等号
							Concat(strToken,ch);
						else
						{
							mark--;
							ch='\0';
						}			
						break;
				case'-':
						Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='>'||ch=='-')//第二个等号
							Concat(strToken,ch);
						else
						{
							mark--;
							ch='\0';
						}				
						break;
				case'>':
						Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='=')//第二个等号
							Concat(strToken,ch);
						else
						{
							mark--;
							ch='\0';
						}				
						break;
				case'<':				
						Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='=')//第二个等号
							Concat(strToken,ch);
						else
						{
							mark--;
							ch='\0';
						}				
						break;
				case'!':
						Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='=')//第二个等号
							Concat(strToken,ch);
						else
						{
							mark--;
							ch='\0';
						}				
						break;
				case'\"':Concat(strToken,ch);
						 code=CheckP(strToken);
						 value='P';
						 W_Answer(strToken,value,code);//将这个单词符号及属性写入answer文件中
						 strToken[0]='\0';
						 while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						 {
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						 }
						 while(ch!='\"')
						 {
							 Concat(strToken,ch);
							 while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
							{
								inSP.getline(buffer,N);
								Len++;
								mark=0;  //mark复位
							}
						 }
						 if(inSP.eof())
						 {
							 cout<<"error"<<endl;//双引号不匹配
							 break;
						 }
						 code=InsertC(strToken);
						 value='C';
						 W_Answer(strToken,value,code);//将这个单词符号及属性写入answer文件中
						 strToken[0]='\0';
						 Concat(strToken,ch);//处理最后一个引号
						 break;
				case'+':
						Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='+')
							Concat(strToken,ch);
						else
						{
							mark--;
							ch='\0';
						}				
						break;
				case'&':Concat(strToken,ch);
						while((GetChar(&ch,buffer,&mark)==0)&& (!inSP.eof()))
						{
							inSP.getline(buffer,N);
							Len++;
							mark=0;  //mark复位
						}
						if(ch=='&')
							Concat(strToken,ch);
						else
						{
							mark--; 
							ch='\0';
						}				
						break;
				case'{': case'}': case'(': case')': case'[': case']': 
				case'*': case'\'':	case'/': case';': case',': 	case'.':
				case'#':
						Concat(strToken,ch);						
						break;
				case' ':
				case'\n':
				case'\t':break;						
				default:if(ch=='\0')//处理文件结束时最后一个字符
						{
							inSP.close();
							cout<<"the complier results have been writen to 'Answer.txt'!"<<endl;
							cout<<"Please check the answer !"<<endl;
							return 0;
						}
						Concat(strToken,ch);
						value='E';
						break;
			}
			if(ch==' '||ch=='\t'||ch=='\n')
				continue;
			else
			{
				code=CheckP(strToken);
				value='P';
			}
		}
		W_Answer(strToken,value,code);//将这个单词符号及属性写入answer文件中
		strToken[0]='\0';
	}
	inSP.close();
	cout<<"the complier results have been writen to 'Answer.txt'!"<<endl;
	cout<<"Please check the answer !"<<endl;
	return 0;
}
///////////////////////////////////////////////////////////								         
//bool GetChar(char *c,char*buf,int *m)
//从buffer中读取一个字符,成功则返回true,否则返回false
//false表示buffer已空,需要再从SourPro.txt中再读取一行放到buffer中
bool GetChar(char *c,char*buf,int *m)
{
	*c=buf[*m];	
	if(*c=='\0')
		return false;
	else 
	{
		(*m)++;
		return true;
	}
}

bool IsLetter(char c)//若c为字母则返回true,否则返回false
{
	if( ((c>=65)&&(c<=90)) || ((c>=97)&&(c<=122)) )
		return true;
	return false;
}

bool IsDigit(char c)//若c为数字则返回true,否则返回false
{
	if((c>=48)&&(c<=57))
		return true;
	return false;
}
void Concat(char *str,char ch)  //将字符ch追加到串str后面
{
	int i=0;
	while(str[i]!='\0')
	{
		i++;
	}
	str[i]=ch;
	str[i+1]='\0';
	return;
}

int Change(char *str)//把从类型表(P,K,I,C)中读取的整数串转化成整数形式,并返回
{
	int i=0;
	int num=0;
	while(IsDigit(str[i]))
	{
		num=num*10+(int)str[i]-48;
		i=i+1;
	}
	return num;
}

int CheckK(char *str) //查K表,若str存在K表中,则返回它在表中的位置,若不存在则返回0
{
	int inte;
	char a[N],s[N];
	ifstream inK("K.txt"); //打开K文件
    if(!inK)
	{
		cout<<"Failed to open K.txt"<<endl;
		return 0;
	}
	while(!inK.eof())
	{
		inK.getline(a,N);
		inte=Change(a);
		inK.getline(s,N);
		if(!strcmp(s,str))
			break;
	}
	inK.close();
	if(!strcmp(s,str))
		return inte;
	return 0;	
}
int CheckP(char *str)//查P表,若str存在P表中,则返回它在表中的位置,若不存在则返回0
{
	int inte;
	char a[N],s[N];
	ifstream inP("P.txt"); //打开P标文件
    if(!inP)
	{
		cout<<"Failed to open P.txt"<<endl;
		return 0;
	}
	while(!inP.eof())
	{
		inP.getline(a,N);
		inte=Change(a);
		inP.getline(s,N);
		if(!strcmp(s,str))
			break;
	}
	inP.close();
	if(!strcmp(s,str))
		return inte;
	return 0;
}
	
int InsertI(char *str)//填I表并返回该单词在表中的位置
{
	int inte;
	char a[N],s[N];
	if(IN>0)
	{
		ifstream iI("I.txt"); //打开I文件,并作查询是否有str
		if(!iI)
		{
			cout<<"Failed to open I.txt"<<endl;
			return 0;
		}
		while(!iI.eof())
		{
			iI.getline(a,N);
			iI.getline(s,N);
			inte=Change(a);
			if(!strcmp(s,str))
				break;
		}
		iI.close();
		if(!strcmp(s,str))//表中已经存在str,则直接返回它在表中的位置
			return inte;		
	}
	IN++;
	ofstream oI("I.txt",ios::app); //str不存在表中,打开I文件将str填入表中
    if(!oI)
	{
		cout<<"Failed to open I.txt"<<endl;
		return 0;
	}
	oI<<IN<<":"<<endl<<str<<endl;
	oI.close();
	return IN;
}

int InsertC(char *str)//填C表并返回该单词在表中的位置
{
	int inte;
	char a[N],s[N];
	if(CN>0)
	{
		ifstream iC("C.txt"); //打开C表文件,并作查询是否有str
		if(!iC)
		{
			cout<<"Failed to open C.txt"<<endl;
			return 0;
		}
		while(!iC.eof())
		{
			iC.getline(a,N);
			iC.getline(s,N);
			inte=Change(a);
			if(!strcmp(s,str))
				break;
		}
		iC.close();
		if(!strcmp(s,str))//表中已经存在str,则直接返回它在表中的位置
			return inte;
	}	
	ofstream oC("C.txt",ios::app); ////str不存在表中,打开C文件将str填入表中
    if(!oC)
	{
		cout<<"Failed to open C.txt"<<endl;
		return 0;
	}
    CN++;
	oC<<CN<<":"<<endl<<str<<endl;
	oC.close();
	return CN;
}
/////////////////////////////////////////////////////////////////////
//以下子程序填写编译结果,将所得的单词符号及其所属属性写入Answer文件中
//也包括错误处理信息
void W_Answer(char *str,char value,int code)
{
	ofstream outAN("Answer.txt",ios::app); //打开I标文件
    if(!outAN)
	{
		cout<<"Failed to open Answer.txt"<<endl;
		return ;
	}
	if(value=='E')////////错误处理
	{
		outAN<<str<<"---at line "<<Len<<"--illegal ! :("<<endl;
		return;
	}
	outAN<<str<<" ----- [ "<<value<<" - "<<code<<" ]"<<endl;//输出单词信息
	outAN.close();
	return ;
}

⌨️ 快捷键说明

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