大连理工大学编译原理第6次上机——算术表达式的扩充

1. 实验目的

充分理解语义分析的方法及相关语义计算的执行时机。

掌握LR分析表的设计方法和语义加工程序的扩充。

2. 实验要求

参照算术表达式LR分析表的设计方法,设计扩充后的算术表达式LR分析表,并对原语义加工程序进行修改,加入新添加的内容。写一段程序,打印出计算结果E。

3. 实验内容

假设有以下文法:

  1. L->En
  2. E->E+T
  3. E->E-T
  4. E->T
  5. T->T*F
  6. T->T/F
  7. T->F
  8. F->(E)
  9. F->id

设该文法进行自下而上计算时,打印出四则运算的计算结果。

E、T、F这些非终结符需要综合属性。以L属性的翻译方案为基础,将下表的语义规则嵌套在语法分析的过程中,即实现语法制导的翻译过程。

 

产  生  式 

语  义  规  则 

L->En

 

{print(E.val)}

E->E+T

{ E.val=E1.val+T.val}

E->E-T

{ E.val=E1.val-T.val}

E->T

{ E.val= T.val}

T->T*F

{ T.val=T1.val*F.val}

T->T/F

{ T.val=T1.val/F.val}

T->F

{ T.val= F.val}

F->(E)

{ F.val=E.val}

F->id

{ F.val=id.lexval}

 

 

 

2.以词法分析和语法分析部分的上机结果为基础,添加语义分析部分。即以LR文法为基础。当进行产生式归约时执行对应的语义动作。

 

3.输入:

5+3+8*2

输出:24

 

输入10-6/2

 

输出:7

4. 若输入有误,如:3++2

则应提示:重新输入!

 

5. 由于输入串是具体的数值,因此应调用相应的词法分析的功能。

(照着上一次的改的,将错就错改的更麻烦了。。先这样吧,错误分析部分还没来得及载改一下)

LR分析表:

#include<iostream>
#include<cstring>
#include<map>
#include<stack>
#include<queue>
#include<iomanip> 
#include<stdio.h>
#include<cmath>
using namespace std;
struct item;                   //表项,状态和终结符 
stack<string> sta;             //栈  
queue<string> input;           //用于存放输入串 
map<item,string> Action;       //map类型的Action表。。因为太长了用函数写太麻烦了 
map<item,string> :: iterator it;


queue<double> NUM; 
stack<double> T;
stack<double> F;
stack<double> E; 
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 "10";
		if(nonter == "T")
			return "2";
		if(nonter == "F")
			return "3";
	}
	else if(state == "6"){
		if(nonter == "T")
			return "11";
		if(nonter == "F")
			return "3";
	}
	else if(state == "7"){
		if(nonter == "T")
			return "12";
		if(nonter == "F")
			return "3";
	}
	else if(state == "8"&& nonter == "F")
		return "13";
	else if(state == "9"&& nonter == "F")
		return "14";
	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]>='0'&&in[0]<='9'){
			int i=1;
			while(in[i]>='0'&&in[0]<='9')
				i++;
			string Stringnum=in.substr(0,i);
			in = in.substr(i);
			int num=0;
			for(int j=0;j<Stringnum.size();j++){
				num+=(Stringnum[j]-48)*pow(10,Stringnum.size()-j-1);
			}
			NUM.push(num);
			cut = "id";
			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<40-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<25-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);
			//下面是计算
			if(res=="F->id"){	
				F.push(NUM.front());
				NUM.pop();
			}
			if(res=="F->(E)"){
				F.push(E.top());
				E.pop();
			}
			if(res=="T->F"){
				T.push(F.top());
				F.pop();
			}
			if(res=="E->T"){
				E.push(T.top());
				T.pop();
			}
			if(res=="E->E+T"){
				int num1 = E.top();
				E.pop();
				int num2 = T.top();
				T.pop();
				E.push(num2+num1);
			}
			if(res=="T->T*F"){
				double num1 = T.top();
				T.pop();
				double num2 = F.top();
				F.pop();
				T.push(num2*num1);
			}
			if(res=="E->E-T"){
				double num1 = E.top();
				E.pop();
				double num2 = T.top();
				T.pop();
				E.push(num1-num2);}
			if(res=="T->T/F"){
				double num1 = T.top();
				T.pop();
				double num2 = F.top();
				F.pop();
				T.push(num1/num2);}
			//首先弹出生成式右部(右部长度*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("1","-")] = "7";

Action[item("2","*")] = "8";
Action[item("2","/")] = "9";
Action[item("2","+")] = "E->T";
Action[item("2","-")] = "E->T";
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("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("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","id")] = "5";
Action[item("8","(")] = "4";

Action[item("9","id")] = "5";
Action[item("9","(")] = "4";

Action[item("10","+")] = "6";
Action[item("10","-")] = "7";
Action[item("10",")")] = "15";

Action[item("11","*")] = "8";
Action[item("11","/")] = "9";
Action[item("11","+")] = "E->E+T";
Action[item("11","-")] = "E->E+T";
Action[item("11",")")] = "E->E+T";
Action[item("11","$")] = "E->E+T";

Action[item("12","*")] = "8";
Action[item("12","/")] = "9";
Action[item("12","+")] = "E->E-T";
Action[item("12","-")] = "E->E-T";
Action[item("12",")")] = "E->E-T";
Action[item("12","$")] = "E->E-T";

Action[item("13","+")] = "T->T*F";
Action[item("13","-")] = "T->T*F";
Action[item("13","*")] = "T->T*F";
Action[item("13","/")] = "T->T*F";
Action[item("13",")")] = "T->T*F";
Action[item("13","$")] = "T->T*F";

Action[item("14","+")] = "T->T/F";
Action[item("14","-")] = "T->T/F";
Action[item("14","*")] = "T->T/F";
Action[item("14","/")] = "T->T/F";
Action[item("14",")")] = "T->T/F";
Action[item("14","$")] = "T->T/F";

Action[item("15","+")] = "F->(E)";
Action[item("15","-")] = "F->(E)";
Action[item("15","*")] = "F->(E)";
Action[item("15","/")] = "F->(E)";
Action[item("15",")")] = "F->(E)";
Action[item("15","$")] = "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();
cout << "结果为:" << E.top();
return 0;
}

 


 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值