大连理工大学编译原理第5次上机—语法分析2

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

要求

1. 使用如下文法:

  1. E->  E+T | T
  2. T -> T*F | F
  3. 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)对应的元素继续分析。

 

扩展:

1.利用P94页的表3.13的方式将错误进行分类提示,即给出具体的出错信息。

错误处理:

cpp实现:

#include<iostream>
#include<cstring>
#include<map>
#include<stack>
#include<queue>
#include<iomanip> 
#include<stdio.h>
using namespace std;
struct item;                   //表项,状态和终结符 
stack<string> sta;             //栈  
queue<string> input;           //用于存放输入串 

map<item,string> Action;       //map类型的Action表。。因为太长了用函数写太麻烦了 
map<item,string> :: iterator it;

map<item,string> Error;       //map类型的错误分析表 
map<item,string> :: iterator itError;

string Goto(string state,string nonter){         //Goto函数 
	if(state=="0"){
		if(nonter == "E")
			return "1";
		if(nonter == "T")
			return "2";
		if(nonter == "F")
			return "3";
	}
	else if(state == "4"){
		if(nonter == "E")
			return "8";
		if(nonter == "T")
			return "2";
		if(nonter == "F")
			return "3";
	}
	else if(state == "6"){
		if(nonter == "T")
			return "9";
		if(nonter == "F")
			return "3";
	}
	else if(state == "7"&& nonter == "F")
		return "10";
	else 
	return "false";
}

struct item{                   //有state和nonterminal(非终结符) 
	string state;
	string nonter;
	item(string s,string n){
		this->state = s;
		this->nonter = n;
	}
	bool operator < (const struct item &i) const{       
		return (this->state<i.state||(this->state==i.state&&this->nonter<i.nonter));
	}
	bool operator == (const struct item &i) const{
		return (i.state==this->state&&i.nonter==this->nonter);
	}
};

/*重载一下运算符就不需要这个函数了啊! 
string find(map<item,string> m,item i){
	map<item,string> :: iterator it;
	for(it = m.begin();it!=m.end();it++)
		if(it->first==i)
			return it->second;
	return "mo";
}*/ 

void handle(string in){        //把读入的串放到队列里 
	string cut;
	while(!in.empty()){
		if(in[0]=='i'){        //遇到id,应该截两个字符 
			cut = in.substr(0,2);
			in = in.substr(2);
			input.push(cut);
		} 
		else if(in[0]==' ')    //空格,丢掉 
			in = in.substr(1); 
		else{                  //其他的,截一个字符 
			cut = in.substr(0,1);
			in = in.substr(1);
			input.push(cut);
		}
		cut.clear();	
	}
	input.push("$");	
}

void show(){
	int i,sizeOfQueue,sizeOfStack;
	string temp1,temp;
	int kongge = 0;
	stack<string> newStack;
	//输出栈中的元素
	kongge += sta.size();
	sizeOfStack = sta.size();
	for(i=0;i<sizeOfStack;i++){
		temp = sta.top();
		sta.pop();
		newStack.push(temp);	
	}
	for(i=0;i<sizeOfStack;i++){
		temp = newStack.top();
		cout <<temp << " ";
		kongge+=temp.size();
		newStack.pop();
		sta.push(temp);
	}
	for(int j=0;j<20-kongge;j++)
			cout <<" ";
	//输出队列中的元素 
	kongge = 0;
	sizeOfQueue = input.size();
	for(i=0;i<sizeOfQueue;i++){
		temp1 = input.front();
		input.pop();
		kongge+=temp1.size();
		cout << temp1;  
		input.push(temp1);
	}
	for(int x=0;x<15-kongge;x++)
		cout << " ";
} 

void analyse_error(string state,string next){
	string error_type; 
	itError = Error.find(item(state,next));
	if(itError==Error.end()){
		cout << "未知符号,扔了扔了" << endl;
		input.pop();
		return ;
	}
	error_type = itError->second;
	if(error_type=="e1"){
		cout << "缺少运算对象" << endl; 
		sta.push("id");
		sta.push("5");
	}
	else if(error_type=="e2"){
		cout << "不匹配的右边括号" << endl;
		input.pop();
	}
	else if(error_type=="e3"){
		cout << "缺少右括号" << endl;
		sta.push(")");
		sta.push("11");
	}
	else if(error_type=="e4"){
		cout << "缺少运算符+" << endl;
		sta.push("+");
		sta.push("6");
	}
	else if(error_type=="e5"){
		cout << "缺少运算符*" << endl;
		sta.push("*");
		sta.push("7");
	}
	return ;
}

void analyse(){
	string state;
	string next;
	string res;
	string left;
	while(true){
		//先看看栈顶的状态 
		state = sta.top();                 //cout << "state = " << state << endl;
		//取下一个输入 
		next = input.front();              //cout << "next = "  << next << endl;
		//查找相应的动作 
		it = Action.end();
		it = Action.find(item(state,next));   
		while(it==Action.end()){//如果出错,就扔了这个符号,接着看下一个 
			cout << "error" << endl;
			show();
			//进入错误处理过程
			analyse_error(state,next); 
			//input.pop();
			if(input.empty()){
				cout << "结束" << endl; 
				return ;
			}
			next = input.front();              //cout << "next = "  << next << endl;
			state = sta.top();
			it = Action.find(item(state,next));		
		}
		res = it->second;   //好,现在我们已经找到了相应的动作 
		//移进
		if(res.size()<=2){
			show();
			cout << "移进" << endl;	
			state=it->second;     //得到移进后的状态 
			sta.push(next);        
			sta.push(state);
			input.pop(); 
			
		}
		//规约
		else if(res.size()>2&&res!="acc"){
			show();
			cout << "按" << res << "规约" << endl; 
			//得到规约后的非终结符,即生成式的左部
			string left; 
			left = res.substr(0,1);
			//首先弹出生成式右部(右部长度*2)
			int length; 
			if(res.size()!=5)//不含id 
				length = 2*(res.size()-3);
			else if(res.size()==5) // 含id 
				length = 2;
			for(int i=0;i<length;i++)
				sta.pop();
				
			//看看栈顶状态 
			state = sta.top();
			//得到规约后的状态(用栈顶的状态和用于规约的生成式的左部)
			state = Goto(state,left);
			sta.push(left);
			sta.push(state); 
			
		}
		//接受
		else if(res=="acc"){
			show();
			cout << "接受" << endl;
			return ; 
		}
	}
} 


int main(){
Action[item("0","id")] = "5";
Action[item("0","(")] = "4";
Action[item("1","$")] = "acc";
Action[item("1","+")] = "6";
Action[item("2","+")] = "E->T";
Action[item("2","*")] = "7";
Action[item("2",")")] = "E->T"; 
Action[item("2","$")] = "E->T";
Action[item("3","+")] = "T->F";
Action[item("3","*")] = "T->F";
Action[item("3",")")] = "T->F";
Action[item("3","$")] = "T->F";
Action[item("4","id")] = "5";
Action[item("4","(")] = "4";
Action[item("5","+")] = "F->id";
Action[item("5","*")] = "F->id";
Action[item("5",")")] = "F->id";
Action[item("5","$")] = "F->id";
Action[item("6","id")] = "5";
Action[item("6","(")] = "4";
Action[item("7","id")] = "5";
Action[item("7","(")] = "4";
Action[item("8","+")] = "6";
Action[item("8",")")] = "11";
Action[item("9","+")] = "E->E+T";
Action[item("9","*")] = "7";
Action[item("9",")")] = "E->E+T";
Action[item("9","$")] = "E->E+T";
Action[item("10","+")] = "T->T*F";
Action[item("10","*")] = "T->T*F";
Action[item("10",")")] = "T->T*F";
Action[item("10","$")] = "T->T*F";
Action[item("11","+")] = "F->(E)";
Action[item("11","*")] = "F->(E)";
Action[item("11",")")] = "F->(E)";
Action[item("11","$")] = "F->(E)";

Action[item("3","id")] = "T->F";
Action[item("3","(")] = "T->F";
Action[item("5","id")] = "F->id";
Action[item("5","(")] = "F->id";
Action[item("10","id")] = "T->T*F";
Action[item("10","(")] = "T->T*F";
Action[item("11","id")] = "F->(E)";
Action[item("11","(")] = "F->(E)";





Error[item("0","+")] = "e1";
Error[item("0","id")]= "e1";
Error[item("4","+")] = "e1";
Error[item("4","id")]= "e1";
Error[item("6","+")] = "e1";
Error[item("6","id")]= "e1";
Error[item("0",")")] = "e2";
Error[item("1",")")] = "e2";
Error[item("4",")")] = "e2";
Error[item("6",")")] = "e2";
Error[item("7",")")] = "e2";
Error[item("8","$")] = "e3";
Error[item("1","id")]= "e4";
Error[item("1","(")] = "e4";
Error[item("8","id")]= "e4";
Error[item("8","(")] = "e4";
Error[item("2","id")]= "e5";
Error[item("2","(")] = "e5";
Error[item("9","id")]= "e5";
Error[item("9","(")] = "e5";




sta.push("0");


char in[100];
cin.getline(in,100);
string in1 = in;
handle(in1);
analyse();

return 0;
}

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值