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

📄 grama.cpp

📁 产生的DFA在屏幕上显示,分析表写到文件里面.
💻 CPP
字号:
#include <fstream.h>
#include <stdlib.h>
#include <fstream.h>
#include "GRAMA.h"

CGRAMA::CGRAMA():start_symbol(-5)				//构造函数
{
	char *buf,ch;
	List<char> buflist;							
	int i=0;
	ifstream fin("grama.txt",ios::nocreate);	//打开文件
	if(!fin){
		cout<<"file not found!\n";
		exit(0);
	}
	fin>>vnnum>>vtnum>>gncount;
	vnstring=new char[vnnum];
	vtstring=new char[vtnum];
	vn=new int[vnnum];
	vt=new int[vtnum];
	for(i=0;i<vnnum;i++){						//对非终结符进行编码
		fin>>vnstring[i];
		vn[i]=-10-5*i;
	}
	for(i=0;i<vtnum;i++){						//对终结符进行编码
		fin>>vtstring[i];
		vt[i]=10+5*i;
	}
	Gener first_gener;							//对文法进行拓广		
	first_gener.vn=start_symbol;				//-5是文法开始符号				
	first_gener.sentence=new int[2];
	first_gener.sentence[0]=vn[0];				
	first_gener.sentence[1]=END;
	gn_list.Insert(first_gener);
	fin.get(ch);
	for(i=0;i<gncount;i++){
		while(1){	
			fin.get(ch);
			if(ch=='\n')	break;
			buflist.Insert(ch);
		}
		buflist.PutToArray(buf);
		buflist.MakeEmpty();
		Encode(buf);
	}
	fin.close();
}

CGRAMA::~CGRAMA()								//析构函数
{
	gn_list.MakeEmpty();
	item_list.MakeEmpty();
	convert_list.MakeEmpty();
	delete[]vt;
	delete[]vn;
	delete[]vtstring;
	delete[]vnstring;
}

void CGRAMA::Encode(char *&buf)
{
	char *pS=buf;								//搜索buf字符串的指针
	int temp,flag(0);							//temp是中转变量,
	Gener gener,g1,g2;
	List<Gener> temp_list;
	gener.vn=EncodeVn(*pS);						//产生式左部的编码
	pS=pS+3;									//跳过"->"
	int length=::GetStrLen(buf)-3;				//length为产生式右部的最大长度
	gener.sentence=new int[length+1];			//堆内存分配		
	for(int i=0;i<length;i++){
		if((temp=EncodeVt(*pS))==-1) 			//若在终结符中找不到就到非终结符中找
			temp=EncodeVn(*pS);
		gener.sentence[i]=temp;					//存入编码值
		pS++;
	}
	gener.sentence[length]=END;
	temp_list.Insert(gener);
	for(ListNode<Gener> *p=temp_list.first;p;p=p->link)
	{
		length=p->data.GetRightLength();
		flag=0;
		for(i=0;i<length;i++)
		{
			if(p->data.sentence[i]==-1)
			{
				flag=1;
				break;
			}
		}
		g1.vn=p->data.vn;
		if(flag==1)		g1.sentence=new int[i+1];
		else g1.sentence=new int[length];
		for(int j=0;j<i;j++)
			g1.sentence[j]=p->data.sentence[j];
		g1.sentence[i]=END;
		gn_list.Insert(g1);
		if(flag==1){
			g2.vn=p->data.vn;
			g2.sentence=new int[length-i];
			for(j=0;j<length-i-1;j++)
				g2.sentence[j]=p->data.sentence[j+i+1];
			g2.sentence[length-i-1]=END;
			temp_list.Insert(g2);
		}
	}
}


int CGRAMA::EncodeVn(char ch)							//查找非终结符号表
{
	for(int i=0;i<vnnum;i++)
		if(ch==vnstring[i])
			return vn[i];
	return -1;
}

int CGRAMA::EncodeVt(char ch)							//查找终结符号表
{
	for(int i=0;i<vtnum;i++)
		if(ch==vtstring[i])
			return vt[i];
	if(ch=='$') return 0;
	return -1;
}

char CGRAMA::Decode(int num)
{
	char c;int i;
	for(i=0;i<vnnum;i++)
		if(num==vn[i])
			return vnstring[i];
	for(i=0;i<vtnum;i++)
		if(num==vt[i])
			return vtstring[i];
	if(num==-5)	c='X';
	if(num==1)	c='.';
	if(num==5)	c='#';
	if(num==0)	c='$';
	return c;
}

void CGRAMA::ToItemSet()								//产生式转化为项目并插入链表
{
	int gener_len;
	for(ListNode<Gener> *p=gn_list.first;p;p=p->link)
	{
		gener_len=p->data.GetRightLength();
		p->data.GenToItem(item_list,gener_len);
	}	
}

void CGRAMA::Closure(List<CItem> &kernel)				//CLOSURE(I)函数
{
	Queue<CItem> queue,item_q;
	ListNode<CItem> *p,*q;
	CItem item,mid_item;
	int code,pos;
	List<int> f_set;
	for(p=kernel.first;p;p=p->link)
	{
		if(p->data.vn==-5)
		{
			p->data.string.MakeEmpty();
			p->data.string.Insert(5);
		}
		queue.QInsert(p->data);
		item_q.QInsert(p->data);
	}
	kernel.MakeEmpty();	
	while(!queue.QueueEmpty())											
	{
		item.string.MakeEmpty();
		item=queue.QDelete();
		if(item.IsForReduce())
		{
			pos=item.GetDotPos();
			f_set.MakeEmpty();                   
			FirstX(item.sentence+pos+2,f_set);
			for(q=item_list.first;q;q=q->link)
			{
				if(q->data.vn==item.sentence[pos+1]&&q->data.sentence[0]==1)
				{
					mid_item=q->data;
					if(f_set.IsEmpty()) mid_item.string.Add(item.string);
					else mid_item.string.Add(f_set);
					item.string.MakeEmpty();
					code=item_q.GetCode(mid_item);
					if(code==0){
						queue.QInsert(mid_item);				
						item_q.QInsert(mid_item);
					}
					else if(!(mid_item.string==item_q.queue[code].string))
						item_q.queue[code].Merge(mid_item);
				}
			}//end for
		}//end if
	}
	for(int i=1;i<=item_q.rear;i++)	kernel.Insert(item_q.queue[i]);
	
}

void CGRAMA::FromItoJ(CItem &item,List<CItem> &J)		//由A->a.Br找出
{														//形如A->aB.r的式子
	int pos=item.GetDotPos();
	int temp=item.sentence[pos+1];
	for(ListNode<CItem> *p=item_list.first;p;p=p->link)
	{		
		if(p->data.vn==item.vn)
		{
			int pos1=p->data.GetDotPos();
			if(p->data.sentence[pos1-1]==temp&&pos1-pos==1){
				if(!p->data.string.IsEmpty())
					p->data.string.MakeEmpty();
				p->data.string.Add(item.string);
				J.Insert(p->data);
			}
		}
	}
}

int CGRAMA::GO(const List<CItem> &I,int X,List<CItem> &J)		//GO(I,X)函数
{
	int pos;
	for(ListNode<CItem> *p=I.first;p;p=p->link)
	{
		pos=p->data.GetDotPos();
		if(p->data.sentence[pos+1]==X)
			FromItoJ(p->data,J);
	}
	Closure(J);
	if(J.IsEmpty()) return 0;
	return 1;
}

void CGRAMA::GetSymbol(List<CItem> &item_set,List<int> &symbol_list)
{
	int pos,temp;
	symbol_list.MakeEmpty();
	for(ListNode<CItem> *q=item_set.first;q;q=q->link)
	{
		pos=q->data.GetDotPos();
		temp=q->data.sentence[pos+1];
		if(temp!=END) symbol_list.Insert(temp);
	}
	symbol_list.DelRepeated();							//必须放到For的外面!
}

void CGRAMA::OutPut(List<CItem> &list)
{
	List<char> char_list;
	char ch;
	for(ListNode<CItem> *p=list.first;p;p=p->link)
	{
		char_list.MakeEmpty();
		ch=Decode(p->data.vn);
		char_list.Insert(ch);
		char_list.Insert('-');
		char_list.Insert('>');
		if(p->data.sentence!=NULL){
		for(int i=0;p->data.sentence[i]!=END;i++)
		{
			ch=Decode(p->data.sentence[i]);
			char_list.Insert(ch);
		}
		}
		char_list.Print();
		cout<<"    \t";
		for(ListNode<int> *q=p->data.string.first;q;q=q->link)
			cout<<Decode(q->data)<<" ";
		cout<<endl;
	}
}

void CGRAMA::PrintDFA()									//输出DFA
{
	Queue<List<CItem> > q;								//q1是分析中用										
	List<CItem> start_set;								
	start_set.Insert(item_list.first->data);
	Closure(start_set);
	q.QInsert(start_set);
	state_queue.QInsert(start_set);
	List<int> sym_list;
	List<CItem> go_list;
	List<CItem> temp_list;
	CItem item;	
	cout<<"********* LALR(1)文法分析程序 *********:\n";
	List<int> change_list;
	while(!q.QueueEmpty())								//用队列来实现			
	{
		temp_list.MakeEmpty();	
		temp_list=q.QDelete();
		GetSymbol(temp_list,sym_list);					//把求的的 X 存入链表
		for(ListNode<int> *p=sym_list.first;p;p=p->link)//对项目集中各个文法符号X用GO(I,X)
		{
			if(GO(temp_list,p->data,go_list))			
			{	
				int code=state_queue.GetCode(go_list);
				if(code==0)
				{
					q.QInsert(go_list);					//如果Ix还未出现过则进队列
					state_queue.QInsert(go_list);
				}
				else{
					state_queue.queue[code].MergeString(go_list);
					change_list.Insert(code);
				}
				item.vn=state_queue.GetCode(temp_list);
				item.sentence=new int[2];
				item.sentence[0]=p->data;
				item.sentence[1]=state_queue.GetCode(go_list);
				convert_list.Insert(item);				//convert_list记录转换关系
				go_list.MakeEmpty();
			}
		}
	}
	for(int k=1;k<state_queue.rear;k++)
	{
		if(change_list.Contains(k))
		{
			sym_list.MakeEmpty();
			GetSymbol(state_queue.queue[k],sym_list);					
			for(ListNode<int> *p=sym_list.first;p;p=p->link)//对项目集中各个文法符号X用GO(I,X)
			{
				go_list.MakeEmpty();
				if(GO(state_queue.queue[k],p->data,go_list))			
				{	
					int code=state_queue.GetCode(go_list);
					state_queue.queue[code].MergeString(go_list);
				}
			}
		}
	}
	cout<<"\nDFA中所有状态列表:\n[X代表拓广文法开始符号]\n";
	for(int i=1;i<=state_queue.rear;i++)				//把DFA中所有状态输出
	{
		cout<<"STATE "<<i<<":\n";
		OutPut(state_queue.queue[i]);
		cout<<endl;
	}
	ListNode<CItem> *p;
	int newline=0;
	cout<<"\n状态间转换关系:\n";
	for(p=convert_list.first;p;p=p->link)				//打印转换关系
	{
		cout<<"I"<<p->data.vn<<"--- "<<Decode(p->data.sentence[0])
			<<" --> "<<"I"<<p->data.sentence[1]<<"    "<<"\t";
		newline++;
		if(newline%2==0)
			cout<<endl;
	}
	if(newline%2!=0) cout<<endl;
	cout<<endl;
}

void CGRAMA::PrintRuleTable()							//把规则列表写到文件中
{
	List<char> char_list;
	char ch;
	int count=0;
	for(ListNode<CItem> *p=item_list.first;p;p=p->link)
	{
		if(p->data.IsReduce())
			rule_list.Insert(p->data);
	}
	ofstream ofstr("rule.txt");
	ofstr<<"规则列表:"<<endl;
	for(p=rule_list.first;p;p=p->link,count++)
	{
		char_list.MakeEmpty();
		ch=Decode(p->data.vn);
		char_list.Insert(ch);
		char_list.Insert('-');
		char_list.Insert('>');
		for(int i=0;p->data.sentence[i]!=END;i++)
		{
			ch=Decode(p->data.sentence[i]);
			char_list.Insert(ch);
		}
		ofstr<<count<<":\t";
		for(ListNode<char> *q=char_list.first;q;q=q->link)
			ofstr<<q->data;
		ofstr<<endl;
	}
	ofstr.close();
}

void CGRAMA::First(int symbol,List<int> &first_set)		//递归求FIRST集合
{
	if(symbol>0){										//symbol为终结符的情况
		first_set.Insert(symbol);
		return;
	}
	List<int> temp,mid;
	for(ListNode<Gener> *p=gn_list.first;p;p=p->link)	//先不考虑A->A…的情况
		if(p->data.vn==symbol&&p->data.sentence[0]!=symbol)							//找到形如A->…的产生式
		{
			if(p->data.sentence[0]>=0){					//A->a…的情况
				first_set.Insert(p->data.sentence[0]);
				continue;
			}//end if
			else{										//A->X1…Xn的情况
				for(int i=0;p->data.sentence[i]!=END;i++)
				{
					temp.MakeEmpty();
					First(p->data.sentence[i],temp);
					mid=temp;
					if(p->data.sentence[i+1]!=END)	mid.Remove(0);
					first_set.Add(mid);					//First(Xi)=>First(symbol)
					mid.MakeEmpty();
					if(temp.Contains(0)) continue;		//First(Xi)包含ε则继续求	
					else break;					
				}
			}//end else
		}
	for(p=gn_list.first;p;p=p->link)
	{
		if(p->data.vn==symbol&&p->data.sentence[0]==symbol){
			if(first_set.Contains(0)){
				FirstX(p->data.sentence+1,mid);
				first_set.Add(mid);
				mid.MakeEmpty();
			}
		}
	}
	first_set.DelRepeated();
}

void CGRAMA::FirstX(int *array,List<int> &first_set)	//First(X1…Xn)
{
	first_set.MakeEmpty();
	if(*array==END) return;
	List<int> temp;
	First(*array,temp);
	if(!temp.Contains(0)){
		first_set.Add(temp);
		return;
	}
	temp.Remove(0);
	first_set.Add(temp);
	FirstX(array+1,first_set);
	first_set.DelRepeated();
}

void CGRAMA::PrintTable()								//打印分析表
{
	int i;
	ListNode<CItem> *p;
	ofstream ofstr("table.txt");
  	ofstr<<"LALR(1)分析表:\n";
	for(i=0;i<(vtnum+vnnum+1);i++)	ofstr<<"________";
	ofstr<<"__"<<endl;
	for(i=0;i<vtnum;i++)	ofstr<<"\t"<<Decode(vt[i]);
	ofstr<<"\t#";
	for(i=0;i<vnnum;i++)	ofstr<<"\t"<<Decode(vn[i]);
	ofstr<<endl;
	for(i=0;i<(vtnum+vnnum+1);i++)	ofstr<<"________";
	ofstr<<"__"<<endl;
	ListNode<CItem> *pItem;
	for(i=1;i<=state_queue.count;i++)
	{
		ofstr<<"I"<<i<<"\t";
		pItem=state_queue.queue[i].first;

		/***********ACTION部分************/

		for(int j=0;j<vtnum;j++)					
		{
			if(pItem->data.IsReduce()&&pItem->data.string.Contains(vt[j]))
				ofstr<<"r"<<rule_list.GetCode(pItem->data);
			for(p=convert_list.first;p;p=p->link)
				if(p->data.sentence[0]==vt[j]&&p->data.vn==i)					
					ofstr<<"s"<<p->data.sentence[1];
			ofstr<<"  \t";
		}
		if(pItem->data.IsReduce()&&pItem->data.string.Contains(5))
		{
			if(pItem->data.IsAccept())	ofstr<<"acc";
			else ofstr<<"r"<<rule_list.GetCode(pItem->data);
		}
		ofstr<<"\t";

		/************GOTO部分************/

		for(j=0;j<vnnum;j++)						
		{
			for(p=convert_list.first;p;p=p->link)
				if(p->data.sentence[0]==vn[j]&&p->data.vn==i)					
					ofstr<<p->data.sentence[1];//<<"\t";
			ofstr<<"\t";
		}
		ofstr<<endl;
	}//end for
	for(i=0;i<(vtnum+vnnum+1);i++)	ofstr<<"________";
	ofstr<<"__"<<endl;
	ofstr<<"\n规则列表已经写入文件rule.txt中"<<endl;
	ofstr.close();
}

⌨️ 快捷键说明

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