编译原理——LR(0)分析器

        直接输入根据己知文法构造的LR(0)分析表,对于输入的文法和符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子,并要求输出分析过程。


#include<bits/stdc++.h>
using namespace std;
const string ERROR="出错,该句子不被当前文法识别!";
const int MAX=100;	
int gone=0;	//步骤
int state[MAX];	//状态栈
int statetop=-1; //状态栈指针 
char sign[MAX]; //符号栈
int signtop=-1;	//符号栈指针
string s;	//输入串
queue<char> sq;	//存放输入串的队列 
string ACTION[MAX][MAX];	//ACTION表 
int GOTO[MAX][MAX];		//GOTO表 
int sta;	//状态数 
int vt;		//终结符数
int vn;		//非终结符数  
char c;		//暂存字符变量 
map<char,int> mpvt;	//映射ACTION表中终结符的列号 
map<char,int>::iterator vtit;	//遍历vt列号的迭代器 
map<char,int> mpvn;	//映射GOTO表中非终结符的列号 
map<char,int>::iterator vnit;	//遍历vn列号的迭代器 
int ms_num;	//产生式数 
string ms_str; //暂存产生式  
map<int,string> ms;	//保存产生式 
map<int,string>::iterator msit;	//访问产生式映射  
int Action;		//保存从 Si中解析出的要移进的状态
int whichms;	//保存从 ri中解析出的产生式编号 
int Goto;		//保存从 GOTO表中读取的要转向的状态 
string thems;	//保存当前次归约使用的产生式  

int FindSr(string s); 	//将 Si/ri中对应的状态/产生式编号解析出来    
void inputx();	//输入函数 
void outputx();	//输出函数  
void terror();	//出错处理 
void anysit();	//总控程序  
 
int main(){
	inputx();
	anysit();
	return 0;
}
int FindSr(string s){
	int num=0;
	int k;
	int L=s.length();
	for(int i=1;i<L;i++){
		k=s[i]-'0';
		for(int j=i;j<L-1;j++){
			k*=10;
		}
		num+=k;
	}
	if(s[0]=='S'){
		Action=num;
		return Action;
	}
	else{
		whichms=num;
		return whichms;
	}
	
}
void inputx(){
	cout<<"输入文法的产生式的个数:";
	cin>>ms_num;
	cout<<"输入文法的产生式:"<<endl;
	for(int i=1;i<=ms_num;i++){
		cin>>ms_str;
		ms[i]=ms_str;
	} 
	cout<<"输入状态数:";
	cin>>sta;
	cout<<"输入终结符数:";
	cin>>vt;
	cout<<"依次输入终结符:";
	for(int i=0;i<vt;i++){
		cin>>c;
		mpvt[c]=i;
	}
	cout<<"输入ACTION表(以 <> 表示空):"<<endl;
	for(int i=0;i<sta;i++){
		for(int j=0;j<vt;j++){
			cin>>ACTION[i][j];
		}
	}
	cout<<"输入非终结符数:";
	cin>>vn;
	cout<<"依次输入非终结符:"; 
	for(int i=0;i<vn;i++){
		cin>>c;
		mpvn[c]=i;
	}
	cout<<"输入GOTO表(以 -1 表示空):"<<endl;
	for(int i=0;i<sta;i++){
		for(int j=0;j<vn;j++){
			cin>>GOTO[i][j];
		}
	}
	cout<<"输入要进行LR(0)分析的句子:";
	cin>>s;
	for(int i=0;i<s.length();i++){
		sq.push(s[i]);
	}
}
void outputx(){
	cout<<++gone<<"		";
	for(int i=0;i<=statetop;i++){
		cout<<state[i];
	}cout<<"		";
	for(int i=0;i<=signtop;i++){
		cout<<sign[i];
	}cout<<"		";
	int p=0;
	char x;
	while(p<sq.size()){
		x=sq.front();
		cout<<x;
		sq.pop();
		sq.push(x);
		p++;
	}
	cout<<"		";
}
void terror(){
	cout<<ERROR;
}
void anysit(){
	cout<<"对输入串 "<<s<<" 的LR(0)分析过程:"<<endl; 
	cout<<"步骤		"<<"状态栈		"<<"符号栈		"<<"输入串		"<<"ACTION		"<<"GOTO		"<<"归约使用的产生式"<<endl;
	state[++statetop]=0;
	sign[++signtop]='#';
	int x,y;char cc;string now;
	do{
		outputx();
		x=state[statetop];
		cc=sq.front();
		for(vtit=mpvt.begin();vtit!=mpvt.end();vtit++){
			if(vtit->first==cc){
				y=vtit->second;
				break;
			}
		}
		now=ACTION[x][y];
		if(now=="<>"){
			terror();
			cout<<"(ACTION表出错)"<<endl; 
			break;
		}
		else if(now[0]=='S'){
			FindSr(now);
			cout<<now<<endl;
			state[++statetop]=Action;
			sign[++signtop]=cc;
			sq.pop(); 
		} 
		else if(now[0]=='r'){
			int p=FindSr(now);
			for(msit=ms.begin();msit!=ms.end();msit++){
				if(msit->first==p){
					thems=msit->second;
					break;
				}
			}
			for(int k=thems.length()-1;k>2;k--){
				if(sign[signtop]==thems[k]){
					signtop--;
					statetop--;
				}
			}
			sign[++signtop]=thems[0];
			x=state[statetop];
			cc=sign[signtop];
			for(vnit=mpvn.begin();vnit!=mpvn.end();vnit++){
				if(vnit->first==cc){
					y=vnit->second;
					break;
				}
			}
			Goto=GOTO[x][y];
			if(Goto==-1){
				terror();
				cout<<"(GOTO表出错)"<<endl; 
				break;
			}
			cout<<now<<"		"<<Goto<<"		"<<thems<<endl;
			state[++statetop]=Goto;
		}
	}while(now!="acc");
	if(now=="acc"){
		cout<<now<<endl;
		cout<<"该句子被成功识别!"<<endl; 
	}
}

输入:

输出:

希望能帮到你哦。


看完点波关注哦~

  • 9
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
在规范规约的过程中,一方面记住已移进和规约出的整个符号串,即记住“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来进行“展望”。当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据记载的“历史”和“展望”以及“现实”的输入符号等三个方面的材料,来确定栈顶的符号串是否构成相对某一产生式的句柄。 2.LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机。 3.LR分析器的每一步工作是由栈顶状态和现行输入符号所唯一决定的。 4.为清晰说明LR分析器实现原理和模型: LR分析器的核心部分是一张分析表。这张分析表包括两个部分,一是“动作”(ACTION)表,另一是“状态转换”(GOTO)表。他们都是二维数组。ACTION(s,a)规定了当状态s面临输入符号a时应采取什么动作。GOTO(s,X)规定了状态s面对文法符号X(终结符或非终结符)时下一状态是什么。显然,GOTO(s,X)定义了一个以文法符号为字母表的DFA。 每一项ACTION(s,a)所规定的动作不外是下述四种可能之一: (1)移进 把(s,a)的下一个转态s’ = GOTO(s,X)和输入符号a推进栈,下一输入符号变成现行输入符号。 (2)规约 指用某一产生式A→β 进行规约。假若β的长度为r,规约的动作是A,去除栈顶的r个项,使状态Sm-r 变成栈顶状态,然后把(Sm-r,A)的下一状态s’ = GOTO(Sm-r,A)和文法符号A推进栈。规约动作不改变现行输入符号。执行规约动作意味着β(= Xm-r+1…Xm)已呈现于栈顶而且是一个相对于A的句柄。 (3)接受 宣布分析成功,停止分析器的工作。 (4)报错 发现源程序含有错误,调用出错处理程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白马无缰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值