编译技术第五次上机作业

目的:熟练掌握自下而上的语法分析方法,并能用程序实现。

要求

1. 使用如下文法:

E ® E+T | T

      T ® T*F | F

      F ® (E) | id

2. 对于任意给定的输入串(词法记号流)进行语法分析,要求采用LR分析器来完成。手工构造LR分析表,利用移进-归约分析算法(P71 图3.12)输出(P72 表3.8)对应的动作部分。如:

输入:id*+id/(id+id)#

输出:移进

按 F->id归约

      移进

      error

      ……

3. 要有一定的错误处理功能。即对错误能提示,并且能在一定程度上忽略尽量少的记号来进行接下来的分析。

例如:

从状态0开始的记号流为:bm

将b移进之后,栈里的情况应该为: 0 b 2

此时查表发现 action[2,m]=error

输出打印:error

把A和状态1相继压入栈,用户指针后移到FOLLOW(A)对应的元素继续分析。

把LR分析表画出来之后,代码写出来应该不难。我使用map和vector的组合来储存LR分析表的信息,这样代码可能短一些。对于输入串,自定义push函数可以将输入串倒置(注意是将终结符的顺序倒置,而不是字符的简单倒置),这样便于使用栈。

代码量100行出头相对小巧些,所以如果代码中有什么问题,欢迎大家留言!

#include<iostream>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
vector<string> zhan;
static string getT(string s1,string s2){//LR分析表
	map<string,map<string,string>> m;
	map<string,string>n0={{"id","s5"},{"(","s4"},{"E","1"},{"T","2"},{"F","3"}},
	n1={{"+","s6"},{"#","acc"}},
	n2={{"*","s7"},{"+","r3"},{"#","r3"},{")","r3"}},
	n3={{"+","r5"},{"*","r5"},{"#","r5"},{")","r5"}} ,
	n4={{"(","s4"},{"id","s5"},{"E","8"},{"T","2"},{"F","3"}},
	n5={{"+","r7"},{"*","r7"},{"#","r7"},{")","r7"}},
	n6={{"(","s4"},{"id","s5"},{"T","9"},{"F","3"}},
	n7={{"(","s4"},{"id","s5"},{"F","10"}},
	n8={{"+","s6"},{")","s11"}},
	n9={{"+","r2"},{"#","r2"},{")","r2"}},
	n10={{"+","r4"},{"*","r4"},{"#","r4"},{")","r4"}},
	n11={{"+","r6"},{"*","r6"},{"#","r6"},{")","r6"}};
	m["0"]=n0;
	m["1"]=n1;
	m["2"]=n2;
	m["3"]=n3;
	m["4"]=n4;
	m["5"]=n5;
	m["6"]=n6;
	m["7"]=n7;
	m["8"]=n8;
	m["9"]=n9;
	m["10"]=n10;
	m["11"]=n11;
	string s=m[s1][s2];
	if(s.length()==0){
		cout<<"error"<<endl;
		return "error";
	}else
	return m[s1][s2];
}
static vector<string> getL(string num){//归约的依据
	map<string,vector<string>> m;
	vector<string>v2={"E","E","+","T"};
	vector<string>v3={"E","T"};
	vector<string>v4={"T","T","*","F"};
	vector<string>v5={"T","F"};
	vector<string>v6={"F","(","E",")"};
	vector<string>v7={"F","id"};
	m["2"]=v2;
	m["3"]=v3;
	m["4"]=v4;
	m["5"]=v5;
	m["6"]=v6;
	m["7"]=v7;
	return m[num];
}

vector<string> push(string a){
	vector<string> v;
	string s="";
	v.push_back("#");
	for(int i=a.length()-1;i>=0;i--){
		char w=a.at(i);
		s+=w;
		if(s==" "||s=="#"){
			s="";
			continue;	
		}
		else if(s=="*"||s=="("||s==")"||s=="+"){
			v.push_back(s);
		}else if(s=="d"){
			v.push_back("id");
			i--;
		}
		s="";
	}
	return v;	
}
int main(){
	int count=0; 
	vector<string>v=push("id * * id + id#");
	zhan.push_back("#");
	zhan.push_back("0");
	while(count<20){
		count++;
		string get=getT(zhan.back(),v.back());
		string state="";
		state+=get.at(0);
		string num=get.substr(1);
		if(state=="s")
		{
			cout<<"移进"<<endl; 
			zhan.push_back(v.back());
			zhan.push_back(num);
			v.pop_back();
		}else if(state=="r"){
			vector<string>list=getL(num);
			cout<<"按照"<<list[0]<<"->";
			for(int i=1;i<list.size();i++) {
				cout<<list[i];
			}
			cout<<"进行归约"<<endl;
			while(list.size()>1){
				zhan.pop_back();//抛掉数字 
				zhan.pop_back();
				list.pop_back(); 
		}
			string pre=zhan.back();
			zhan.push_back(list.back());
			string go=getT(pre,zhan.back());
			zhan.push_back(go) ;
		}
		else if(state=="a"){
			cout<<"接受"<<endl;
			break;
		}else if(state=="e"){
			zhan.pop_back();
			zhan.pop_back();
		}
		state="";
		
	}
}

如果不好理解的话,下面有注释版本的,运行一下,可以把我个人的思路和代码逻辑都可以清晰地打印出来。

#include<iostream>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
vector<string> zhan;
static string getT(string s1,string s2){
	map<string,map<string,string>> m;
	map<string,string>n0={{"id","s5"},{"(","s4"},{"E","1"},{"T","2"},{"F","3"}},
	n1={{"+","s6"},{"#","acc"}},
	n2={{"*","s7"},{"+","r3"},{"#","r3"},{")","r3"}},
	n3={{"+","r5"},{"*","r5"},{"#","r5"},{")","r5"}} ,
	n4={{"(","s4"},{"id","s5"},{"E","8"},{"T","2"},{"F","3"}},
	n5={{"+","r7"},{"*","r7"},{"#","r7"},{")","r7"}},
	n6={{"(","s4"},{"id","s5"},{"T","9"},{"F","3"}},
	n7={{"(","s4"},{"id","s5"},{"F","10"}},
	n8={{"+","s6"},{")","s11"}},
	n9={{"+","r2"},{"#","r2"},{")","r2"}},
	n10={{"+","r4"},{"*","r4"},{"#","r4"},{")","r4"}},
	n11={{"+","r6"},{"*","r6"},{"#","r6"},{")","r6"}};
	m["0"]=n0;
	m["1"]=n1;
	m["2"]=n2;
	m["3"]=n3;
	m["4"]=n4;
	m["5"]=n5;
	m["6"]=n6;
	m["7"]=n7;
	m["8"]=n8;
	m["9"]=n9;
	m["10"]=n10;
	m["11"]=n11;
	string s=m[s1][s2];
	if(s.length()==0){
		return "error";
	}else
	return m[s1][s2];
}
static vector<string> getL(string num){
	map<string,vector<string>> m;
	vector<string>v2={"E","E","+","T"};
	vector<string>v3={"E","T"};
	vector<string>v4={"T","T","*","F"};
	vector<string>v5={"T","F"};
	vector<string>v6={"F","(","E",")"};
	vector<string>v7={"F","id"};
	m["2"]=v2;
	m["3"]=v3;
	m["4"]=v4;
	m["5"]=v5;
	m["6"]=v6;
	m["7"]=v7;
	return m[num];
}
void dis(vector<string> &v);
vector<string> push(string a){
	vector<string> v;
	string s="";
	v.push_back("#");
	for(int i=a.length()-1;i>=0;i--){
		char w=a.at(i);
		s+=w;
		if(s==" "||s=="#"){
			s="";
			continue;	
		}
		else if(s=="*"||s=="("||s==")"||s=="+"){
			v.push_back(s);
		}else if(s=="d"){
			v.push_back("id");
			i--;
		}
		s="";
	}
	dis(v);
	return v;	
}
void dis(vector<string> &v){
	cout<<"此时:"<<endl;
	for(int i=0;i<v.size();i++){
		cout<<v[i]<<" ";
	}
	cout<<endl;
}
int main(){
	int count=0; 
	vector<string>v=push("id * * id + id#");
	zhan.push_back("#");
	zhan.push_back("0");
	while(count<20){
		count++;
		cout<<"使用两个key:"<<zhan.back()<<"和"<<v.back()<<endl;
		string get=getT(zhan.back(),v.back());
		cout<<"查表得到"<<get<<endl;
		string state="";
		state+=get.at(0);
		string num=get.substr(1);
		cout<<"分解为"<<state<<"和"<<num<<endl;
		if(state=="s")
		{
			cout<<"移进"<<endl; 
			zhan.push_back(v.back());
			zhan.push_back(num);
			cout<<"装入"<<v.back()<<"和"<<num<<endl;
			v.pop_back();
			dis(zhan);
		}else if(state=="r"){
			vector<string>list=getL(num);
			cout<<"按照"<<list[0]<<"->";
			for(int i=1;i<list.size();i++) {
				cout<<list[i];
			}
			cout<<"进行归约"<<endl;
			while(list.size()>1){
				zhan.pop_back();//抛掉数字 
				cout<<"约去"<<zhan.back()<<"和"<<list.back()<<endl;
				zhan.pop_back();
				list.pop_back(); 
			}
			cout<<"装入"<<list.back()<<endl;
			string pre=zhan.back();
			zhan.push_back(list.back());
			string go=getT(pre,zhan.back());
			cout<<"再次查表得到goto表项,并装入"<<go<<endl;
			zhan.push_back(go) ;
			dis(zhan);
		}
		else if(state=="a"){
			dis(zhan);
			cout<<"接受"<<endl;
			break;
		}else if(state=="e"){
			zhan.pop_back();
			zhan.pop_back();
			dis(zhan);
		}
		state="";
		
	}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值