以S属性的语法制导定义为基础,实现语法制导的翻译过程

要求

1.以S属性的语法制导定义为基础,将下表的语义规则嵌套在语法分析的过程中,即实现语法制导的翻译过程。

     

       

  L -> E n

  print (E.val)

  E-> E1 + T 

  E.val := E1 .val + T.val 

  E ->T 

  E.val := T.val 

  T-> T1 * F 

  T.val := T1.val * F.val 

  T ->F 

  T.val := F.val 

  F->(E)

  F.val := E.val 

  F ->digit

  F.val := digit.lexval

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

3.输入:

5+3+8*2

输出:24

注:只能完成加法和乘法的运算,相对于之前上传的LR文法只是添加了把数字变成符号的过程(即把(2+5)*5变成(a+a)*a)再定义一个数字栈,与符号栈的动作对应,最后取出数据栈栈顶就是结果

#include <iostream>
#include <string.h>
#include<stack>
using namespace std;
/*
E->E+T
E->T
T->T*F
T->F
F->(E)
F->id
*/
/*初始化分析表*/
void Initial(string analysis[12][9]){
	/*移进规约*/
	analysis[0][0] = "s5"; analysis[0][3] = "s4"; analysis[0][6] = "1"; analysis[0][7] = "2"; analysis[0][8] = "3";
	analysis[1][1] = "s6"; analysis[1][5] = "acc";
	analysis[2][1] = "r2"; analysis[2][2] = "s7"; analysis[2][4] = "r2"; analysis[2][5] = "r2";
	analysis[3][1] = "r4"; analysis[3][2] = "r4"; analysis[3][4] = "r4"; analysis[3][5] = "r4";
	analysis[4][0] = "s5"; analysis[4][3] = "s4"; analysis[4][6] = "8"; analysis[4][7] = "2"; analysis[4][8] = "3";
	analysis[5][1] = "r6"; analysis[5][2] = "r6"; analysis[5][4] = "r6"; analysis[5][5] = "r6";
	analysis[6][0] = "s5"; analysis[6][3] = "s4"; analysis[6][7] = "9"; analysis[6][8] = "3";
	analysis[7][0] = "s5"; analysis[7][3] = "s4"; analysis[7][8] = "10";
	analysis[8][1] = "s6"; analysis[8][4] = "ss";//表示s11
	analysis[9][1] = "r1"; analysis[9][2] = "s7"; analysis[9][4] = "r1"; analysis[9][5] = "r1";
	analysis[10][1] = "r3"; analysis[10][2] = "r3"; analysis[10][4] = "r3"; analysis[10][5] = "r3";
	analysis[11][1] = "r5"; analysis[11][2] = "r5"; analysis[11][4] = "r5"; analysis[11][5] = "r5";
	/*出现错误*/
	analysis[0][1] = analysis[0][2] = analysis[0][5] = analysis[4][1] = analysis[4][2] = analysis[4][5] = "e1";
	analysis[6][1] = analysis[6][2] = analysis[6][5] = analysis[7][1] = analysis[7][2] = analysis[7][5] = "e1";
	analysis[0][4] = analysis[1][4] = analysis[4][4] = analysis[6][4] = analysis[7][4] = "e2";
	analysis[1][0] = analysis[1][2] = analysis[1][3] = analysis[8][0] = analysis[8][2] = analysis[8][3] = "e3";
	analysis[8][5] = "e4";
	analysis[2][0] = analysis[2][3] = "r2";
	analysis[3][2] = analysis[3][3] = "r4";
	analysis[5][0] = analysis[5][3] = "r6";
	analysis[9][0] = analysis[9][3] = "r1";
	analysis[10][0] = analysis[10][3] = "r3";
	analysis[11][0] = analysis[11][3] = "r5";

}
/*输出移进还是规约,规约的话输出用到的产生式*/
void print(int into)
{
	if (into == 0)
	{
		cout << "--移进--" << endl;
		return;
	}
	cout << "--按";
	switch (into)
	{
	case 1:cout << "E->E+T"; break;
	case 2:cout << "E->T"; break;
	case 3:cout << "T->T*F"; break;
	case 4:cout << "T->F"; break;
	case 5:cout << "F->(E)"; break;
	case 6:cout << "F->id"; break;
	}
	cout << "规约--" << endl;
}
/*为终结符合非终结符编号*/
int NumOfSymbols(char c){
	/*switch (c){
	case 'a':return 0;
	case '+':return 1;
	case '*':return 2;
	case '(':return 3;
	case ')':return 4;
	case '#':return 5;
	case 'E':return 6;
	case 'T':return 7;
	case 'F':return 8;
	}*/
	if (c == 'a'){ return 0; }
	if (c == '+'){ return 1; }
	if (c == '*'){ return 2; }
	if (c == '('){ return 3; }
	if (c == ')'){ return 4; }
	if (c == '$'){ return 5; }
	if (c == 'E'){ return 6; }
	if (c == 'T'){ return 7; }
	if (c == 'F'){ return 8; }
}
char GetSymbol(int num){
	if (num == 0){ return 'a'; }
	if (num == 1){ return '+'; }
	if (num == 2){ return '*'; }
	if (num == 3){ return '('; }
	if (num == 4){ return ')'; }
	if (num == 5){ return '$'; }
	if (num == 6){ return 'E'; }
	if (num == 7){ return 'T'; }
	if (num == 8){ return 'F'; }
}
int Num[10];//存储数
char *Change(char*a){
	int len = strlen(a);//字符串a的长度	
	char *b = new char[len];//存储字符
	int charnum = 0;//记录b中实际有多少字符串
	int cur1 = 0;//Num[]的角标
	int cur2 = 0;//b[]的角标
	for (int i = 0; i < len; i++){
		if (a[i] <= 59 && a[i] >= 48){
			int num_len = 1;//大于一位数的这个数的长度
			int num = 0;//最后记录这个数的大小
			b[cur1] = 'a';//遇见的数字,把a放进栈
			charnum++;
			cur1++;//b的角标向后挪
			int curr = i + 1;//curr指向当前处理字符的下一个字符,如果依然是数字那么就值个多位数
			/*记录这个多位数的位数*/
			while (a[curr] <= 59 && a[curr] >= 48){
				num_len++;
				curr++;
			}
			int acc = num_len;//记录循环次数,百位*10*10,千位*10*10*10
			for (int j = i; j < i + num_len; j++){
				int tempsum = 1;
				for (int k = 0; k < acc - 1; k++){
					tempsum *= 10;
				}
				acc--;
				num += (a[j] - 48)*tempsum;
			}
			Num[cur2] = num;//把得到的这个数(或多位数或一位数放入数组)
			cur2++;//Num角标后挪
			for (int l = 0; l < num_len - 1; l++){ i++; }//多位数有几位就向后挪几位,一位数不用挪
		}
		else{//不是数字的话直接放入b中
			b[cur1] = a[i];
			charnum++;
			cur1++;
		}
	}
	cout << "该式的原型为:" << endl;
	char *c = new char[charnum];//重新存储一下b,因为长度不准确
	for (int i = 0; i < charnum; i++){
		c[i] = b[i];
		cout << c[i] << " ";
	}
	cout << endl;
	cout << "---------------" << endl;
	return c;
}
void main(){
	string analysis[12][9];
	stack<int> s;//字符栈
	stack<int> val;//数字栈
	int curr = 0;//记录Num中还未放入数字栈的角标
	char* input = "(20+6)*5+8$";	
	cout << "输入表达式:" << input << endl;
	char* str = Change(input);
	/*cin >> str;*/
	int len = strlen(str);
	Initial(analysis);
	s.push(0);
	/*循环中i表示当前处理得输入串中的角标*/
	for (int i = 0; i < len;){
		int stack_top = s.top();//记录栈顶状态
		cout <<"此时栈定状态为:"<< stack_top;
		cout << "  此时输入字符为:"<< str[i] << endl;
		int lookahead = NumOfSymbols(str[i]);//记录当前输入串中,正在被处理的字符的标号
		    /*移进*/
			if (analysis[stack_top][lookahead][0] == 's'){
				if (analysis[stack_top][lookahead][1] == 's'){
					print(0);
					s.push(lookahead);
					s.push(11);
					cout << "将状态11移进栈。" << endl;
					i++;
				}
				else{
					print(0);
					s.push(lookahead);
					s.push(analysis[stack_top][lookahead][1] - '0');
					cout << "将状态" << analysis[stack_top][lookahead][1] - '0' << "移进栈。" << endl;
					i++;//移进了一个后,就可以看下一个字符了
				}
			}
			/*规约*/
			else if (analysis[stack_top][lookahead][0] == 'r'){
				int times;//如需规约,弹栈的次数
				int NumofNon_Terminal;//需要移进栈的终结符的编号
				print(analysis[stack_top][lookahead][1] - '0');//输出规约的式子
				switch (analysis[stack_top][lookahead][1] - '0'){
				case 1: times = 6; NumofNon_Terminal = NumOfSymbols('E'); break;
				case 2: times = 2; NumofNon_Terminal = NumOfSymbols('E'); break;
				case 3: times = 6; NumofNon_Terminal = NumOfSymbols('T'); break;
				case 4: times = 2; NumofNon_Terminal = NumOfSymbols('T'); break;
				case 5: times = 6; NumofNon_Terminal = NumOfSymbols('F'); break;
				case 6: times = 2; NumofNon_Terminal = NumOfSymbols('F'); break;
				}
				for (int j = 0; j < times; j++){
					s.pop();
				}				
				int pre_top=s.top();//记录此时的栈顶
				cout << "弹栈" << times << "次后,栈顶状态为"<< pre_top << endl;
				s.push(NumofNon_Terminal);
				char c = GetSymbol(NumofNon_Terminal);//为了输出字符,通过序号找到
				cout << "放入"<< c << endl;
				/*处理数字栈中的树*/
				if (analysis[pre_top][NumofNon_Terminal].size() == 1){
					s.push(analysis[pre_top][NumofNon_Terminal][0] - '0');
					cout << "将状态" << analysis[pre_top][NumofNon_Terminal][0] - '0' << "移进栈。" << endl;
				}
					
				else{
					s.push(10);
					cout << "将状态10移进栈。" << endl;
				}
				if (analysis[stack_top][lookahead][1] - '0' == 1){
					int temp1 = val.top();
					val.pop();
					int temp2 = val.top();
					val.pop();
					val.push(temp1 + temp2);
					cout << "弹出了" << temp1 << "  " << temp2 << ",放入" << val.top() << endl;
				}
				if (analysis[stack_top][lookahead][1] - '0' == 3){
					int temp1 = val.top();
					val.pop();
					int temp2 = val.top();
					val.pop();
					val.push(temp1 * temp2);
					cout << "弹出了" << temp1 << "  " << temp2 << ",放入" << val.top() << endl;
				}
				if (analysis[stack_top][lookahead][1] - '0' == 6){
					val.push(Num[curr]);
					curr++;
					cout << "放入" << val.top() << endl;
				}
			}
			/*错误恢复*/
			else if (analysis[stack_top][lookahead][0] == 'e'){
				cout << "出现错误" << endl;
				switch (analysis[stack_top][lookahead][1]){
				case '1':{   //期望遇到a,那就把a放进去
							 s.push(0);
							 s.push(5);
							 cout << "缺少运算符,加入a" << endl;
							 break;
				}
				case '2':{
							 //遇见右括号,没有左括号,说明右括号错误
							 i++;
							 cout << "不匹配的右括号,将忽略该字符" << endl;
							 break;
				}
				case '3':{
							 //期望遇见运算符,加进+
							 s.push(1);
							 s.push(6);
							 cout << "缺少运算符,加入a" << endl;
							 break;
				}
				case '4':{
							 //提前结束,但期望遇见右括号,那就加入有括号
							 s.push(4);
							 s.push(11);
							 cout << "缺少右括号" << endl;
							 break;
				}
				}
			}
			else{
				if (analysis[stack_top][lookahead][0] == 'a'){
					cout << "接受"<<endl;
					cout << "结果为:" << val.top() << endl;
					return;
				}
				else{	
					cout << "无法识别,完蛋了!" << endl;
					return;
				}
			}

			cout << "--------------------------------------" << endl;
	}
	
}


猜你喜欢

转载自blog.csdn.net/shl_shl/article/details/53535809
今日推荐