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

📄 词法分析器.cpp

📁 Pascal源程序的词法分析器 Pascal有35个关键字
💻 CPP
字号:
#include "iostream.h"
#include "fstream.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#define AND		   1
#define ARRAY      2
#define BEGIN      3
#define CASE       4
#define CONST      5
#define DIV        6
#define DO         7
#define DOWNTO     8
#define ELSE       9
#define END        10
#define FILE       11
#define FOR        12
#define FUNCTION   13
#define GOTO       14
#define IF         15
#define IN         16
#define LABEL      17
#define MOD        18
#define NIL        19
#define NOT        20
#define OF         21
#define OR         22
#define PACKED     23
#define PROCEDURE  24
#define PROGRAM    25
#define RECODE     26
#define REPEAT     27
#define SET        28
#define THEN       29
#define TO         30
#define TYPE       31
#define UNTIL      32
#define VAR        33
#define WHILE      34
#define WITH       35	//35个关键字
#define IDENTIFIER 36	//标识符
#define UNSIGNINT  63	//整型
#define UNSIGNREAL 64	//实型
#define CHAR       65	//字符型
#define STRING     66	//字符串型
#define TAB	9

void Analysis(fstream &file)
{	
	char ch;		//搜索字符
    char word[121];	//单词数组
	int i;			//单词下标
	int length;		//单词长度
	int type;		//单词类型
    bool tag,flag;		//单词分析循环控制变量,过程控制变量
    char KEYWORD[10],keyword[10];	//准关键字和关键字
    int INT;				//无符号整型数的值
	float REAL,weight;		//无符号实型数的值,权
	int exp;				//指数
	
	
	fstream finalfile,keyword_file;
    finalfile.open("final.txt",ios::out|ios::app);
	if(finalfile.fail())
	{
		cout<<"输出文件打开失败!"<<endl;
		exit(0);
	}
	
	tag=true;		//没有语法错误
	length=0;		//初始化单词长度
	
	while(!file.eof() && tag)
	{						
		file.get(ch);
		if(!file.eof())
		{
			if((ch>='A' && ch<='Z') ||(ch>='a' && ch<='z') )	//标识符或关键字识别开始
			{
				i=0;
				while( (ch>='A' && ch<='Z') || (ch>='a'&& ch<='z') || (ch>='0' && ch<='9') )
				{
					if(i<120)	//截断
					{
						word[i]=ch;
						file.get(ch);
						i++;
					}
				}
				file.seekg(-1L,ios::cur);	//文件指针回退一步 
				word[i]='\0';
				length=i;
				flag=true;				//flag为true表示word是准关键字,false表示word为标识符	
				for(i=0;i<length;i++)	//把标识符转换成大写字符串,以便判断是不是关键字
				{
					if(word[i]>='a' && word[i]<='z')
						KEYWORD[i]=word[i]-32;
					else if(word[i]>='A' && word[i]<='Z' )
						KEYWORD[i]=word[i];
					else
					{
						flag=false;
						type=IDENTIFIER;	//word为标识符
						break;
					}
				}                       //大写转换完毕
				if(flag)
				{
					KEYWORD[i]='\0';	//字符串结束符
					keyword_file.open("keyword.txt",ios::in);	//打开关键字表
					if(keyword_file.fail())
					{
						cout<<"找不到keyword_file!"<<endl;
						exit(0);
					}					
					keyword_file>>keyword;
					type=1;						
					while(!keyword_file.eof())	//匹配关键字表
					{
						if(strcmp(keyword,KEYWORD)==0)
							break;
						else
						{
							keyword_file>>keyword;
							type++;
						}
					}
					keyword_file.close();
				}	//1-35为关键字,36为标识符,所以若关键字表找不到,type为36,刚好是标识符
				finalfile<<type<<" "<<word<<endl;	//存放到文件finalfile中去
				break;								//退出词法分析循环
			}										//标识符或关键字识别完毕
			else if(ch>='0' && ch<='9')				//无符号数识别开始
			{
				i=0;
				while(ch>='0' && ch<='9')
				{
					word[i]=ch;
					file.get(ch);
					i++;
				}
				if(ch!='.' && ch!='E')
				{
					word[i]='\0';
					length=i;
					file.seekg(-1L,ios::cur);	//文件指针回退一步
					INT=0;
					for(i=0;i<length;i++)
						INT=INT*10+word[i]-'0';
					finalfile<<UNSIGNINT<<" "<<INT<<endl;
					break;
				}		//无符号整型数识别
				else	//无符号实型数识别开始
				{
					if(ch=='.')					//开始处理小数点
					{
						word[i]=ch;				//保存小数点
						file.get(ch);	//读取下一个字符
						i++;					//下标前移
						if(ch>='0' && ch<='9')	//读取小数点后的数开始
						{
							while(ch>='0' && ch<='9')
							{
								word[i]=ch;
								i++;
								file.get(ch);
							}				//小数部分读取
							if(ch!='E')		//无符号实数xxx.xxx转换开始
							{
								word[i]='\0';
								length=i;
								file.seekg(-1L,ios::cur);	
								REAL=0.0;
								for(i=0;word[i]!='.';i++)	//整数部分
								{
									REAL=REAL*10+word[i]-'0';
								}
								weight=10.0;
								for(i++;i<length;i++)			//小数部分
								{
									REAL=REAL+(word[i]-'0')/weight;
									weight*=10;
								}
								finalfile<<UNSIGNREAL<<" "<<REAL<<endl;
							}		//无符号实数xxx.xxx识别
							else	//继续识别无符号实数XXX.XXXEXXX
							{
								word[i]=ch;				//保存E
								i++;					//下标前移
								file.get(ch);	//读取下一个字符
								if(ch=='+' || ch=='-')	//读进一个正号或负号,如果没有则略过
								{
									word[i]=ch;
									i++;
									file.get(ch);
								}
								if(ch>='0' && ch<='9')
								{
									while(ch>='0' && ch<='9')	//读取阶码
									{
										word[i]=ch;
										i++;
										file.get(ch);
									}
									word[i]='\0';
									length=i;
									file.seekg(-1L,ios::cur);
									REAL=0.0;
									for(i=0;word[i]!='.';i++)		//整数部分
									{
										REAL=REAL*10+word[i]-'0';
									}
									weight=0.1f;
									for(i++;word[i]!='E';i++)		//小数部分
									{
										REAL=REAL+(word[i]-'0')*weight;
										weight/=10.0;
									}								//E前的尾数
									i++;
									weight=10.0;					//如果没有正负号,默认阶码为正
									if(word[i]=='+')				//判断阶码正负号
									{
										weight=10.0;
										i++;
									}
									else if(word[i]=='-')
									{
										weight=0.1f;
										i++;
									}
									exp=0;				//阶码
									for(;i<length;i++)
									{
										exp=exp*10+word[i]-'0';
									}
									while(exp>0)
									{
										REAL=REAL*weight;
										exp--;
									}
									finalfile<<UNSIGNREAL<<" "<<REAL<<endl;
								}		//无符号实数XXX.XXXEXXX识别
								else
								{
									tag=false;
									break;
								}
							}			//无符号实数XXX.XXXEXXX识别
						}	//读取小数点后的数结束
						else
						{
							tag=false;
							break;
						}
					}	//小数点处理结束
					else if(ch=='E')			//开始处理E
					{
						word[i]=ch;				//读进一个E
						i++;					//下标前移
						file.get(ch);	//读取下一个字符
						if(ch=='+' || ch=='-')	//读进一个正号或负号,如果没有就跳过
						{
							word[i]=ch;
							i++;
							file.get(ch);
						}
						if(ch>='0' && ch<='9')
						{
							while(ch>='0' && ch<='9')		//读取阶码
							{
								word[i]=ch;
								i++;
								file.get(ch);
							}
							word[i]='\0';
							length=i;
							file.seekg(-1L,ios::cur);
							REAL=0.0;
							for(i=0;word[i]!='E';i++)		//整数部分
							{
								REAL=REAL*10+word[i]-'0';
							}								//E前的尾数
							i++;							//略过E
							weight=10.0;					//如果没有正负号,默认阶码为正
							if(word[i]=='+')				//判断阶码正负号
							{
								weight=10.0;
								i++;
							}
							else if(word[i]=='-')
							{
								weight=0.1f;
								i++;
							}
							exp=0;				
							for(;i<length;i++)	//阶码
							{
								exp=exp*10+word[i]-'0';
							}
							while(exp>0)
							{
								REAL=REAL*weight;
								exp--;
							}
							finalfile<<UNSIGNREAL<<" "<<REAL<<endl;	//保存到文件finalfile
						}
						else
						{
							tag=false;
							break;
						}
					}	//E处理完毕
				}		//无符号实型数处理完毕
				break;	//退出词法分析循环
			}			//无符号数识别完毕
			else if(ch=='\'')	//字符或字符串常数识别开始
			{
				i=0;
				file.get(ch);		
				flag=true;		//flag为true表示字符或字符串处理还没结束,为false表示处理结束
				while(flag)
				{
					if(ch=='\'')
					{
						file.get(ch);
						if(ch=='\'')	//读到字符串中的“''”,即“'”号
						{
							word[i]=ch;
							i++;
							file.get(ch);
						}
						else			//字符或字符串识别完毕
						{
							file.seekg(-1L,ios::cur);
							flag=false;
						}
					}
					else
					{
						if(i<120)		//截断
						{
							word[i]=ch;
							i++;
							file.get(ch);
						}
					}
					if(file.eof())
					{
						tag=false;
						break;
					}
				}
				word[i]='\0';
				length=i;
				if(tag==false)
					break;
				if(length==0)
					tag=false;
				else if(length==1)
					finalfile<<CHAR<<" "<<word<<endl;
				else if(length>1)
					finalfile<<STRING<<" "<<word<<endl;
				break;
			}	//字符或字符串常数识别完毕
			else if((ch>=40 && ch<=45) || ch=='/' || ch==';' || ch=='=')				
			{	//ASCII字符从40-47, ‘/’ , ‘;’ , ‘=’ 都是可唯一确定的界符,且编号等于它们的ASCII码
				finalfile<<int(ch)<<" "<<ch<<endl; 
				break;
			}
			else 
			{
				flag=false;		//flag 为true 表示已寻找到界符,为false表示没有寻找到界符
				switch(ch)
				{
				case'[':
					finalfile<<54<<" "<<ch<<endl;
					flag=true;
					break;
				case']':
					finalfile<<55<<" "<<ch<<endl;
					flag=true;
					break;
				case'^':
					finalfile<<53<<" "<<ch<<endl;
					flag=true;
					break;
				case'<':
					file.get(ch);
					if(ch=='=')					
						finalfile<<48<<" "<<'<'<<ch<<endl;					
					else if(ch=='>')				
						finalfile<<49<<" "<<'<'<<ch<<endl;						
					else
					{
						file.seekg(-1L,ios::cur);
						finalfile<<int('<')<<" "<<'<'<<endl;									
					}
					flag=true;
					break;
				case'>':
					file.get(ch);
					if(ch=='=')				
						finalfile<<50<<" "<<'>'<<ch<<endl;					
					else
					{
						file.seekg(-1L,ios::cur);
						finalfile<<int('>')<<" "<<'>'<<endl;						
					}
					flag=true;
					break;
				case':':
					file.get(ch);
					if(ch=='=')				
						finalfile<<51<<" "<<':'<<ch<<endl;					
					else
					{
						file.seekg(-1L,ios::cur);
						finalfile<<int(':')<<" "<<':'<<endl;						
					}
					flag=true;
					break;
				case'.':
					file.get(ch);
					if(ch=='.')
						finalfile<<52<<" "<<'.'<<ch<<endl;
					else
					{
						file.seekg(-1L,ios::cur);
						finalfile<<int('.')<<" "<<'.'<<endl;
					}
					flag=true;
					break;
				case '\n':
				case TAB:
				case ' ':
					while(ch==' '|| ch==TAB || ch=='\n')	//略过空格					
						file.get(ch);
					if(file.eof())
					{
						tag=false;
						break;
					}					
					file.seekg(-1L,ios::cur);	//文件指针后移一步
					break;
				case '{':			//清除注释	
					while(ch!='}')	
					{
						file.get(ch);
						if(file.eof())
						{
							tag=false;
							break;
						}
					}
					break;
				}
				if(flag)
					break;
			}			
		}
	}
	finalfile.close();
}




void main()
{
    fstream file;
    file.open("source.txt",ios::in|ios::nocreate);
    if(file.fail())
	{
		cout<<"文件打开失败,请确认文件时候存在!"<<endl;
	       exit(0);
	}
	while(!file.eof())
		Analysis(file);
    cout<<"结果已保存到了文件final.txt中"<<endl;
}

⌨️ 快捷键说明

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