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

📄 1020310725.cpp

📁 一个很一般的编译程序有词法分析
💻 CPP
字号:
#include<iostream.h>
#include<stdio.h>
#include <fstream>
#define  BMaxlen  10000    //定义缓冲区的最大长度
#define  WMaxlen  10      //用来定义取出的标识符的最大长度
#define  KEY_No    32       //定义要比较的关键字的个数
#define  Maxtype  '5'     //单词的总类型共有5种
char *KEY[KEY_No]={{"include"},{"main"},{"if"},{"else"},{"int"},
{"char"},{"for"},{"while"},{"do"},{"return"},{"break"},{"printf"},
{"scanf"},{","},{";"},{"{"},{"}"},{"("},{")"},{"+"},{"-"},{"*"},
{"/"},{"#"},{"%"},{"="},{"<"},{">"},{">="},{"<="},{"!="},{"=="}
};
char Symbolk[100][10];//作为一个缓冲区,用来存放将要写入symbolk文件中的字符编号
int Inr=0;
int flag1;
char Str[BMaxlen];//建立缓冲区
char Word[WMaxlen];//用来标识标识取出的单词,且其长度不超过单词的最大长度
int  pStr=-1;     //用来表示从缓冲区取字母时的指针
char ch;        //用来表示从缓冲区中取出的一个字母
int  Flag=1;//标志缓冲区中是否还有字母,如果没有则为-1;如果还有则其为1
char CType;//用来标识得到的单词的类型
int CNum;//用来标识得到的字符的编号
char Lasttype;//用来标识是其前面的单词的类型
void insource()//用来把文件中的内容放到缓冲区中,以'@'作为标识符
{
     FILE *fp;
     char c;
	 int i=0;
     if((fp=fopen("t.txt","r"))==NULL)
     printf("Not found!");
     else
	 {
       while((c=fgetc(fp))!=EOF)
       Str[i++]=c;
	 }
     Str[i]='@'; //以'@'作为标识符
	 fclose(fp);
}
void scanner()//用来从缓冲区中取一个字符,如果成功,则返回1,否则为-1
{ 
    
	ch=Str[++pStr];

	if (ch=='@') 
		Flag=-1;//当取出的字符是'@',则表明缓冲区中已无字符,返回值为-1
	else Flag=1;
}
void Insymbolk()//来把字符写入文件a.txt中
{
    FILE *fp1;
	int q=-1;
	flag1=0;
    for (int p=-1;p<Inr;p++)//判断取出的当前单词是不是已经写入文件中了
    if (strcmp(Word,Symbolk[p])==0)
	{
		flag1=1;break;
	}
    if(flag1==0)
	{
		 cout<<"写入"<<endl;
         fp1=fopen("a.txt","a+");
         fprintf(fp1,"%s",Word);
		 for(int j=0;j<5;j++)
		   fputc('-',fp1);
	     fprintf(fp1,"%d",CNum);
		 fputc('\n',fp1);
		 fclose(fp1);
	     strcat(Symbolk[Inr++],Word);//把该字符加入到数组中,以供以后的操作进行判断是否应该写入文件中
	 }
	else cout<<"已写入"<<endl;
}
void Work()//从缓冲区中取一个单词进行词法分析
{
	bool flag=false;//用来表示取出的单词是否为关键词,如果是则flag的值为true,否则为false
	int k=-1;       //表示取出的字符放在单词数组的指针
	CType='0';      //预先定义的取出的单词的类型
	Lasttype='0';   //初始化先前的类型,此变量为判断正负数用
    scanner();//首先取出一个字符
    if (ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z')//取出标识符或者是关键词
	{
		while(true)//取出的单词长度不超过WMaxlen,如果超过,则其后的字符无效
		{  
			if((++k)<WMaxlen)//(++k)为了使取出的单词最长为WMaxlen
			{
				Word[k]=ch;
				scanner();//处理完一个后,紧接着再取出一个字符供一次判断
			   if  (!(ch>='a'&& ch<='z'|| ch>='A'&& ch<='Z'||ch>='0' && ch<='9'||ch=='.'))
		   	break; //如果后继取出的字符不是字母或是数字,则此次取单词结束
			}
		}
		Word[++k]='\0';//以'\0'标识取出单词的结束,这样便把单词各自分离开来
		for (int i=0;i<13;i++)//判断取出的当前单词是不是关键词
			if (strcmp(Word,KEY[i])==0)
			{ 
				flag=true;
				break;
			}
			if (flag){  
				CType='1';//如果是关键词,则把此单词的类型定义为k型
			   
			}
			else 	CType='2'; 
			{     //否则是标识符,其类型为2
			pStr--;//原理和把pStr初始化为-1一样。
			CNum=33;//因为符号表的数目为33个,所以标识符的编号34
			}
	}
    else if (ch>='0' && ch<='9')//判断是不是为整数
	{  
		Word[++k]=ch;
		scanner();
		while(true)//如果是数字,则一直接受,且定义它的类型为3
		{    
			if(ch>='0' && ch<='9')
			{
				Word[++k]=ch;
				scanner();//完成操作后立即取出下一个字符
			}
			else  
			    CType='3';
			    Word[++k]='\0';	
			    CNum=34;
            break;
			//不是数字则跳出循环
            }
	}
    else if (ch=='+'||ch=='-'||ch=='*'||ch=='/')//取出是运算符号的单词
	{   
	   Word[++k]=ch;
	   if (ch=='+' || ch=='-')//如果是+号或者是-号,则还要判断是不是正负数
		{
			if (Lasttype=='6')//判断其取出的当前字母的前一个单词是6号类型的,
				//即是<、>、<=、>=、==、=时则可判断现在取出的是整数
			{	
			    while(ch>='0' && ch<='9')//如果是整数 ,则说明是正负号
				{
					scanner();
					Word[++k]=ch;
				}
				CType='3';//如果正负整数,则直接返回类型为3,则表示此单词为整数
			}
		}
		else 
			Word[++k]='\0';
			CType='4';//如果不是整数,则定义当前取出的单词是运算符,定义此类型为4
	}
	else if (ch=='>'||ch=='<'||ch=='='||ch=='!')//取出运算符的另几类,即<、<=、>、>=、==、=、!=
	{    
		Word[++k]=ch;
		scanner();
		if( ch=='=')//判断是不是<=、>=、==、!=
		Word[++k]=ch;
		else pStr--;//如果不是=则后退一位 ,以便下次取用
	    Word[++k]='\0';
        CType='4';
		Lasttype='6';//当下一个字符的开头为“+”或“-”时,可以据些来判断是不是正负数
	} 
	else if (ch==','||ch==';'||ch=='{'||ch=='}'||ch=='('||ch==')'||ch=='#')
		//判断当前取出的单词是不是界符,如果是界符,则定义其类型为5
	{     
		CType='5';
		Word[++k]=ch;
		Word[++k]='\0';
	}
	for (int j=0;j<KEY_No;j++)//判断取出的当前单词是不是关键词
	 if (strcmp(Word,KEY[j])==0)
	{ 
		 CNum=j;
		 break;
	}//查出其编号
   if(CType==0){}//用来处理空格,即如果是空格,则不执行任何操作。
    else if(CType=='1') 
   {
	    cout<<Word<<"-------"<<CNum;
	    cout<<"---------关健字"<<endl;
	    Insymbolk();//把字符写进符号表symbolk.txt中。
   } 
   else if(CType=='2')
   { 
	    cout<<Word<<"-------"<<CNum;
	    cout<<"----------标识符"<<endl;
	    Insymbolk();//把字符写进符号表symbolk.txt中。
   }
   else if(CType=='3') 
   {  
        cout<<Word<<"-------"<<CNum;
	    cout<<"----------整数"<<endl;
	    Insymbolk();//把字符写进符号表symbolk.txt中。
   }
   else if(CType=='4')
   {
       cout<<Word<<"-------"<<CNum;
	   cout<<"---------运算符"<<endl;
	   Insymbolk();//把字符写进符号表symbolk.txt中。
   }
   else if(CType=='5')

   {
	  cout<<Word<<"-------"<<CNum;
	  cout<<"--------分割符"<<endl;
      Insymbolk();//把字符写进符号表symbolk.txt中。
   }
}
int main()
{
	int j=0;
	insource();//把文件中的内容放入缓冲区
	Flag=1;//初始化定义,认为缓冲区中还有字母
	cout<<"word-----cnum------TYPE"<<endl<<endl;
	while(Flag!=-1)
	Work();
    return  0;
}

⌨️ 快捷键说明

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