編譯原理實驗:語法分析(LR分析)

LR分析(NCWU慎用)

1.實驗要求
⑴ 選擇LR分析方法;
⑵ 選擇對各種常見程序語言都用的語法結構,如賦值語句或表達式或控制流語句等作爲分析對象,並且與所選語法分析方法要比較貼切。
⑶ 實驗時間爲6學時。
2.實驗內容及要求
(1)根據給定文法,先對文法進行解析,構造識別活前綴的DFA並輸出;
(2)根據DFA構造LR分析表並輸出;
(3)分析給定表達式是否是該文法識別的正確的算術表達式(要求輸出歸約過程)
(4)假如給定表達式文法爲:
G(E’): E’→#E#
E→E+T | T
T→T*F |F
F→(E)|i
分析的句子可爲:
(i+i)*i和i+i)*i
3.運行結果:
在這裏插入圖片描述
在這裏插入圖片描述
4.源代碼:

// Exper3.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

static string AftSource[50][50];//處理後的產生式
static int Len_Source = 0;//產生式的個數
static int num[50];//產生式對應句子的個數
static char Vn[50];//非終結符數組
static int len_vn = 0;//非終結符的個數
static char Vt[50];//記錄終結符
static int len_vt = 0;//終結符的個數
static char V[50];//將終結符和非終結符合並後的數組
static int len_v = 0;
static int arr[50][50];//DFA
static string Proj[50][50];//記錄文法的項目
static int len_pro[50];
static string ProFam[50][50];//記錄項目集規範族
static int Data[50][50];//記錄當前產生是否被判斷
static int Len_ProFam = 0;//記錄項目集的個數
static int num_P[50];//每個項目集中項目的個數
static string First[50][50];//記錄first集
static int len_first = 0;
static int num_Fi[50];
//static int num_Fo[50];
//static int len_follow = 0;
//static string Follow[50][50];//記錄follow集
static string Gen[50][50];//記錄消除左遞歸後的產生式
static int len_Gen = 0;//消除左遞歸後的產生式的個數
static int Gen_num[50];//消除左遞歸後每個產生式中句子的個數
static int arrx[50];//follow集中包含的元素
static char ch[50];//LR分析表表頭元素
static string arry[50][50];//LR分析表

bool IsVn(char c) {//判斷是否爲非終結符
	for (int i = 0; i < len_vn; i++) {
		if (c == Vn[i]) {
			return true;
		}
	}
	return false;
}
bool IsVt(char c) {//判斷是否爲終結符/e(空集)
	for (int i = 0; i < len_vt; i++) {
		if (c == Vt[i] || c == 'e') {
			return true;
		}
	}
	return false;
}
void Pretreatment(string arr[], int n) {//預處理,將產生重新存儲,並且將終結符和非終結符分開存放
	for (int i = 0; i < n; i++) {
		Vn[len_vn++] = arr[i][0];
		AftSource[i][num[i]++] = arr[i].substr(0, 1);//將第一個字符存入處理後的數組
		int npc = 3;
		for (int j = 3; j < arr[0].length(); j++) {
			if (arr[i][j] == '|' || arr[i][j] == ';') {
				AftSource[i][num[i]++] = arr[i].substr(npc, j - npc);
				npc = j + 1;
			}
		}
	}
	for (int i = 0; i < Len_Source; i++) {
		for (int j = 1; j < num[i]; j++) {
			for (int k = 0; k < AftSource[i][j].length(); k++) {
				if (!IsVn(AftSource[i][j][k])) {
					Vt[len_vt++] = AftSource[i][j][k];
				}
			}
		}
	}
}

void BuPro() {//構造文法的項目
	Proj[0][0] = "S";
	Vn[len_vn++] = 'S';
	Proj[0][1] = ".";
	Proj[0][2] = AftSource[0][0];
	Proj[0][1] += AftSource[0][0];
	Proj[0][2] +=".";
	len_pro[0] = 3;
	//cout << Proj[0][0] << " " << Proj[0][1] << " " << Proj[0][2] << endl;
	for (int i = 0; i < Len_Source; i++) {//第i條產生式
		Proj[i + 1][len_pro[i + 1]++] = AftSource[i][0];
		for (int j = 1; j < num[i]; j++) {//第i條產生式中的第j個句子
			int len = AftSource[i][j].length();
			for (int k = 0; k <= len; k++) {//.在第k字符
				string a = AftSource[i][j].substr(0, k);
				string b = AftSource[i][j].substr(k, len - k);
				Proj[i + 1][len_pro[i + 1]++] = a + "." + b;
			}
		}
	}
	cout << "\n============該文法的項目爲:===============" << endl << endl;
	for (int i = 0; i < Len_Source + 1; i++) {
		for (int j = 0; j < len_pro[i]; j++) {
			cout << Proj[i][j] << "\t";
		}
		cout << endl;
	}
}
void Extend(int n) {//擴展當前項目集
	for (int i = 0; i < num_P[n]; i++) {
		int len = ProFam[n][i].length();
		int flag = 0;
		string ch="";
		for (int j = 0; j < len; j++) {
			if (ProFam[n][i][j] == '.' && IsVn(ProFam[n][i][j + 1])) {//.後是非終結符
				flag = 1;
				ch = ProFam[n][i][j + 1];
				break;
			}
		}
		if (flag == 1) {
			for (int j = 0; j < Len_Source + 1; j++) {//在項目裏面找尋該非終結符開頭的
				if (ch._Equal(Proj[j][0])) {
					for (int k = 0; k < len_pro[j]; k++) {
						if (Proj[j][k][0] == '.') {
							int npc = 0;
							string temp;
							for (int p = 0; p < num_P[n]; p++) {//判斷是否存在
								temp = Proj[j][0] + "->";
								temp += Proj[j][k];
								if (temp._Equal(ProFam[n][p])) {
									npc = 1;
									break;
								}
							}
							if (npc == 0) {//不存在
								ProFam[n][num_P[n]++] = temp;
							}
						}
					}
					break;
				}
			}
		}
	}
}

void Merge() {//終結符和非終結符合並
	len_v = len_vn + len_vt;
	int i = 0;
	for (int j = 0; j < len_vn; j++) {
		V[i++] = Vn[j];
	}
	for (int j = 0; j < len_vt; j++) {
		V[i++] = Vt[j];
	}
}
int Findsub(int m, char c) {//尋找下標
	int t;
	for (int i = 0; i < len_v; i++) {
		if (V[i] == c) {
			t = i;
			break;
		}
	}
	return arr[m][t];
}
int Findsub(char c) {//找下標
	for (int i = 0; i < len_v; i++) {
		if (V[i] == c) {
			return i;
		}
	}
	//return -1;
}
//=============構建DFA
void PrintDFA() {//輸出DFA
	cout << "\n===================識別活前綴的DFA:=============\n\n";
	for (int i = 0; i < Len_ProFam; i++) {
		for (int j = 0; j < len_v; j++) {
			if (arr[i][j] != 0)
				cout << "(I" << i << "," << V[j] << ")=I" << arr[i][j] << endl;
		}
	}
}
void Build() {//構建DFA
	Merge();//將終結符和非終結符合併爲一個數組
	ProFam[Len_ProFam][num_P[Len_ProFam]++] = "S->"+Proj[0][1];
	Extend(Len_ProFam);
	Len_ProFam++;
	int pwd = 1;
	for (int i = 0; i < Len_ProFam; i++) {
		for (int j = 0; j < num_P[i]; j++) {
			int len = ProFam[i][j].length();
			if (Data[i][j] == 0 && ProFam[i][j][len - 1] != '.') {//當前產生式沒有判斷,且.不在末尾
				string str = ProFam[i][j];//後面用於記錄. 和其後的元素交換後的字符串
				int sub,m;//sub表示在DFA表中的某個值
				for (int k = 0; k < len; k++) {
					if (ProFam[i][j][k] == '.') {
						sub = Findsub(i, ProFam[i][j][k + 1]);//返回DFA表中第i行第ProFam[i][j][k + 1]的值,判斷是否已經加入某個項目集
						m = Findsub(ProFam[i][j][k + 1]);//返回ProFam[i][j][k + 1]對應DFA的第幾列
						//if(sub==0)
						char ch = str[k];
						str[k] = str[k + 1];
						str[k + 1] = ch;
						break;
					}
				}
				if (sub == 0) {
					int pw = 1;//用於判斷是否已經生成了一個新的項目集
					int suv = -1;//若生成了,則suv爲應該加入的行下標
					for (int w = 0; w < Len_ProFam; w++) {
						int flag = 0;
						for (int e = 0; e < num_P[w]; e++) {
							if (str._Equal(ProFam[w][e])) {
								pw = 0;
								suv = w;
								flag = 1;
								break;
							}
						}
						if (flag == 1) {
							break;
						}
					}
					if (pw == 1) {//該前件還沒有生成一個新的項目集
						ProFam[Len_ProFam][num_P[Len_ProFam]++] = str;
						arr[i][m] = Len_ProFam;
						Len_ProFam++;
					}
					else {
						arr[i][m] = suv;
					}
				}
				else {
					ProFam[sub][num_P[sub]++] = str;
				}
				
			}
		}

		for (int j = pwd; j < Len_ProFam; j++) {
			Extend(j);
		}
		pwd = Len_ProFam;
		//Extend(i + 1);//有問題
	}
	/*for (int i = 1; i < Len_ProFam; i++) {
		Extend(i);
	}*/
	cout << "\n===================項目集規範族:=============\n\n";
	for (int j = 0; j < Len_ProFam; j++) {
		cout << "I" << j << ":\t";
		for (int i = 0; i < num_P[j]; i++) {
			cout << ProFam[j][i] << "\t\t";
		}
		cout << endl;
	}
	cout << "\n===================識別活前綴的DFA:=============\n\n";
	cout << "  \t";
	for (int i = 0; i < len_v; i++) {
		cout << V[i] << "   ";
	}
	cout << endl;
	for (int i = 0; i < Len_ProFam; i++) {
		cout << "I" << i << ":\t";
		for (int j = 0; j < len_v; j++) {
			if (arr[i][j] == 0) {
				cout <<  "*   ";
			}
			else {
				cout << arr[i][j] << "   ";
			}
		}
		cout << endl;
	}
	PrintDFA();
}
//=============消除左遞歸
void Eli_Left() {//消除左遞歸
	for (int i = 0; i < Len_Source; i++) {
		Gen[len_Gen][Gen_num[len_Gen]++] = AftSource[i][0];
		int flag = 0;
		int npc = 0;
		for (int j = 1; j < num[i]; j++) {//判斷當前產生式是否存在左遞歸
			if (AftSource[i][j][0] == AftSource[i][0][0]) {
				npc = 1;
				break;
			}
		}
		for (int j = 1; j < num[i]; j++) {
			if (npc == 1) {//存在左遞歸
				if (AftSource[i][j][0] == AftSource[i][0][0]) {
					if (flag == 0) {//用於生成一個新的前件  例如  E'   若已經生成就flag=1;
						Gen[len_Gen + 1][Gen_num[len_Gen + 1]++] = AftSource[i][0] + "'";
						Gen[len_Gen + 1][Gen_num[len_Gen + 1]++] = AftSource[i][j].substr(1, AftSource[i][j].length() - 1) + AftSource[i][0][0] + "'";
						flag = 1;
					}
					else {
						Gen[len_Gen + 1][Gen_num[len_Gen + 1]++] = AftSource[i][j].substr(1, AftSource[i][j].length() - 1) + AftSource[i][0][0] + "'";
					}
				}
				else {
					Gen[len_Gen][Gen_num[len_Gen]++] = AftSource[i][j] + AftSource[i][0][0] + "'";
				}
			}
			else {//不存在左遞歸
				Gen[len_Gen][Gen_num[len_Gen]++] = AftSource[i][j];
			}
		}
		if (flag == 0) {
			len_Gen++;
		}
		else {
			Gen[len_Gen + 1][Gen_num[len_Gen + 1]++] = "e";
			len_Gen += 2;
		}
	}
	cout << "\n==========消除左遞歸後的產生式:============\n" << endl;
	for (int i = 0; i < len_Gen; i++) {
		cout << Gen[i][0] << "->";
		for (int j = 1; j < Gen_num[i]-1; j++) {
			cout << Gen[i][j] << "|";
		}
		cout << Gen[i][Gen_num[i] - 1] << ";" << endl;
	}
}
//=============求解first集用到
bool Is(char c,int n) {
	for (int i = 0; i < num_Fi[n]; i++) {
		if (First[n][i][0] == c) {
			return true;
		}
	}
	return false;
}
void Cre_First() {//構建first集
	Eli_Left();
	for (int i = 0; i < len_Gen; i++) {
		First[len_first][num_Fi[len_first]++] = Gen[i][0];
		for (int j = 1; j < Gen_num[i]; j++) {
			if (Gen[i][j][0] != Gen[i][0][0] && !Is(Gen[i][j][0],i)) {//P->Q.. && Q不在P的first集中
				First[len_first][num_Fi[len_first]++] += Gen[i][j][0];
			}
		}
		len_first++;
	}
	int flag = 1;
	while (flag) {
		flag = 0;
		for (int i = 0; i < len_first; i++) {
			string arr[50];
			int len = 0;
			for (int j = 1; j < num_Fi[i]; j++) {
				if (IsVt(First[i][j][0])) {
					arr[len++] = First[i][j];
				}
				else{
					string str = First[i][j];
					for (int k = 0; k < len_first; k++) {
						if (str._Equal(First[k][0])) {
							for (int p = 1; p < num_Fi[k]; p++) {
								arr[len++] = First[k][p];
							}
							break;
						}
					}
				}
			}
			num_Fi[i] = 1;
			for (int j = 0; j < len; j++) {
				First[i][num_Fi[i]++] = arr[j];
			}
		}
		for (int i = 0; i < len_first; i++) {
			int npc = 0;
			for (int j = 1; j < num_Fi[i]; j++) {
				if (!IsVt(First[i][j][0])) {
					flag = 1;
					npc = 1;
					break;
				}
			}
			if (npc == 1) {
				break;
			}
		}
	}
	cout << "\n==========first集合:============\n" << endl;
	for (int i = 0; i < len_first; i++) {
		cout << "FIRST(" << First[i][0] << "):";
		for (int j = 1; j < num_Fi[i]; j++) {
			cout << First[i][j] << " ";
		}
		cout << endl;
	}
}
//=============求解follow用到
int FindSub(string c) {//follow中對應的下標
	for (int i = 0; i < len_Gen; i++) {
		if (c._Equal(Gen[i][0])) {
			return i;
		}
	}
	return -1;
}
int FindSub_Vt(char c) {
	if (c == '#') {
		return len_vt;
	}
	for (int i = 0; i < len_vt; i++) {
		if (c == Vt[i])
			return i;
	}
	return -1;
}
void PrintFollow(bool arry[][50]) {
	cout << "\n==========follow集合:============\n" << endl;
	for (int i = 0; i < len_Gen; i++) {
		cout << "follow(" << Gen[i][0] << "): ";
		for (int j = 0; j < len_vt+1; j++) {
			if (j == len_vt) {
				cout << "#" << " ";
			}
			else if (arry[i][j] == true) {
				cout << Vt[j] << " ";
			}
		}
		cout << endl;
	}
	for (int i = 0; i < len_Gen; i++) {
		for (int j = 0; j < len_vt + 1; j++) {
			if (arry[i][j] == true) {
				arrx[j]=1;
			}
		}
	}
}
void Cre_Follow() {//2020-5-27 終於寫出來了,
	bool arry[50][50];
	for (int i = 0; i < len_Gen; i++) {
		for (int j = 0; j < len_vt + 1; j++) {
			arry[i][j] = false;
		}
	}
	arry[0][len_vt] = true;
	for (int i = 0; i < len_Gen; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			for (int k = 1; k < len; k++) {
				if (IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k - 1])) {   //p->Qa   a加入follow(Q)
					string str="";
					if (len > 2 && Gen[i][j][k - 1] == '\'') {
						str = Gen[i][j].substr(k - 2, 2);
					}
					else {
						str += Gen[i][j][k - 1];
					}
					int x = FindSub(str);
					int y = FindSub_Vt(Gen[i][j][k]);
					arry[x][y] = true;
				}
			}
		}
	}
	for (int i = 0; i < len_Gen; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			for (int k = 0; k < len - 1; k++) {
				if (!IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k + 1]) && Gen[i][j][k + 1] != '\'') {//P->..QW   first(W)-"e"  --->follow(Q)
					string str = "";
					if (k < len - 2 && Gen[i][j][k + 2] == '\'') {
						str = Gen[i][j].substr(k + 1, 2);
					}
					else {
						str += Gen[i][j][k + 1];
					}
					int y = FindSub(str);//  W  在消除左遞歸後的數組中所在的行下標
					str = "";
					if (k > 0 && Gen[i][j][k] == '\'') {
						str = Gen[i][j].substr(k - 1, 2);
					}
					else {
						str += Gen[i][j][k];
					}
					int x = FindSub(str);//  Q  在消除左遞歸後的數組中所在的行下標 
					for (int w = 1; w < num_Fi[y]; w++) {
						if (!First[y][w]._Equal("e")) {
							int m = FindSub_Vt(First[y][w][0]);
							arry[x][m] = true;
						}
					}
				}
			}
		}
	}
	for (int i = 0; i < len_Gen; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			for (int k = 0; k < len; k++) {
				if (k == len - 1 && !IsVt(Gen[i][j][k])) {//最後一個元素   P->....Q||P->....Q'   follow(P)入follow(Q)
					string str = "";
					if (Gen[i][j][k] == '\'') {
						str = Gen[i][j].substr(k - 1, 2);
					}
					else {
						str += Gen[i][j][k];
					}
					int x = FindSub(str);//Q所在行
					int y = FindSub(Gen[i][0]);//P所在行
					for (int p = 0; p < len_vt + 1; p++) {
						if (arry[y][p]) {
							arry[x][p] = true;
						}
					}
				}
				else if (k < len - 1) {
					if (!IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k + 1])) {
						string str = "";
						if (k < len - 2 && Gen[i][j][k + 2] == '\'') {
							str = Gen[i][j].substr(k + 1, 2);
						}
						else {
							str += Gen[i][j][k];
						}
						int t = FindSub(str);
						int flag = 0;
						for (int w = 1; w < num_Fi[t]; w++) {//判斷是否包含空集
							if (First[t][w]._Equal("e")) {
								flag = 1;
								break;
							}
						}
						if (flag) {//包含空集
							str = "";
							if (Gen[i][j][k] == '\'') {
								str = Gen[i][j].substr(k - 1, 2);
							}
							else {
								str += Gen[i][j][k];
							}
							int x = FindSub(str);//Q所在行
							int y = FindSub(Gen[i][0]);//P所在行
							for (int p = 0; p < len_vt + 1; p++) {
								if (arry[y][p]) {
									arry[x][p] = true;
								}
							}
						}
						
					}
				}
			}
		}
	}
	PrintFollow(arry);
	//for (int i = 0; i < len_Gen; i++) {
	//	for (int j = 0; j < len_vt + 1; j++) {
	//		cout << arry[i][j] << " ";
	//	}
	//	cout << endl;
	//}
}

/*void Cre_Follow() {
	for (int i = 0; i < len_Gen; i++) {
		Follow[len_follow++][num_Fo[len_follow]++] = Gen[i][0];
	}
	for (int i = 0; i < len_Gen; i++) {
		if (i == 0) {
			Follow[i][num_Fo[i]++] = "#";
		}
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			if (len == 1 || (len == 2 && Gen[i][j][1] == '\'')) {//長度爲1 P->Q ||  P->E'
				if (!IsVt(Gen[i][j][0])) {   //P->Q   follow(P)--->follow(Q)
					int x = FindSub(Gen[i][0][0]);//P所在的行
					int y = FindSub(Gen[i][j][0]);//Q所在的行
					for (int k = 1; k < num_Fo[x]; k++) {
						Follow[y][num_Fo[y]++] = Follow[x][k];
					}
				}
			}
			else if (len == 2){
				
			}
			if (Gen[i][j][len - 1] != '\'') {//最後一個字符不是'
				for (int k = 0; k < len - 1; k++) {
					if (!IsVt(Gen[i][j][k]) && IsVt(Gen[i][j][k + 1])) {//當前字符不是終結符P->..Qa  a加入Q
						int sub = FindSub(Gen[i][j][k]);
						Follow[sub][num_Fo[sub]++] += Gen[i][j][k + 1];
					}
					else if (!IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k + 1])) {//  p->...QB    將first(B)中除e外其他字符加入follow(Q)
						int sub = FindSub(Gen[i][j][k]);
						int sub1 = FindSub(Gen[i][j][k + 1]);
						int flag = 1;
						for (int p = 0; p < num_Fi[sub1]; p++) {
							if (!First[sub1][p]._Equal("e")) {
								Follow[sub][num_Fo[sub]++] += First[sub1][p];
							}
							else {
								flag = 0;
							}
						}
						if (flag == 0) {
							Follow[sub][num_Fo[sub]++] = Gen[i][0];
						}
					}
				}
			}
		}
	}
	cout << endl;
	for (int i = 0; i < len_Gen; i++) {
		for (int j = 0; j < num_Fo[i]; j++) {
			cout << Follow[i][j] << " ";
		}
		cout << endl;
	}
}*/

//=============構造LR分析表用到
int Judge(string str) {
	int t = 1;
	for (int i = 0; i < Len_Source; i++) {
		for (int j = 1; j < num[i]; j++) {
			if (AftSource[i][j]._Equal(str)) {
				return t;
			}
			t++;
		}
	}
}
void Cre_LR() {
	int len = 0;
	for (int i = len_vn; i < len_v; i++) {
		ch[len++] = V[i];
	}
	ch[len++] = '#';
	for (int i = 0; i < len_vn - 1; i++) {
		ch[len++] = V[i];
	}
	for (int i = 0; i < Len_ProFam; i++) {
		int t = 0;
		for (int j = len_vn; j < len_v; j++) {
			if (arr[i][j] != 0) {
				arry[i][t++] = to_string(arr[i][j]);
			}
			else {
				arry[i][t++] = "-";
			}
			
		}
		arry[i][t++] = "-";
		for (int j = 0; j < len_vn - 1; j++) {
			if (arr[i][j] != 0) {
				arry[i][t++] = to_string(arr[i][j]);
			}
			else {
				arry[i][t++] = "-";
			}
		}
	}
	for (int i = 0; i < Len_ProFam; i++) {
		for (int j = 0; j < len_vt; j++) {
			if (!arry[i][j]._Equal("-")) {
				string str = arry[i][j];
				arry[i][j] = "S" + str;
			}
		}
	}
	for (int i = 0; i < Len_ProFam; i++) {
		int flag = -1;
		string str="";
		for (int j = 0; j < num_P[i]; j++) {
			int len = ProFam[i][j].length();
			if (ProFam[i][j][len - 1] == '.') {
				flag = 0;
				if (ProFam[i][j][0] == 'S') {
					flag = 1;
				}
				else {
					str = ProFam[i][j].substr(3, len - 4);
				}
				break;
			}
		}
		if (flag == 1) {
			arry[i][len_vt] = "acc";
		}
		else if (flag == 0) {
			int a = Judge(str);
			string s = "R" + to_string(a);
			for (int j = 0; j < len_vt + 1; j++) {
				if (arrx[j] == 1 && arry[i][j]._Equal("-")) {
					arry[i][j] = s;
				}
			}
		}
	}
	cout << "\n===================LR分析表:=============\n\n";
	cout << "狀態\t\t\tACTION\t\t\t\t\tGOTO" << endl << endl;
	cout << "\t";
	for (int i = 0; i < len; i++) {
		cout << ch[i] << "\t";
	}
	cout << endl;
	for (int i = 0; i < Len_ProFam; i++) {
		cout << "I" << i << "\t";
		for (int j = 0; j < len; j++) {
			cout << arry[i][j] << "\t";
		}
		cout << endl;
	}
}

//=============分析句子用到
int FindSub1(char c) {
	for (int i = 0; i < len_vt + len_vn; i++) {
		if (ch[i] == c) {
			return i;
		}
	}
}
void Analysis(string str) {
	string stack = "#";
	string no[50];
	int len_no = 0;
	no[len_no++] = "0";
	int npc = -1;
	int qw = 1;
	cout << "\n==========分析過程:==========\n" << endl;
	cout << "序號\t\t" << "狀態\t\t" << "符號\t\t" << "輸入串\t\t"<<"操作\n";
	cout << qw++ << "\t\t";
	for (int e = 0; e < len_no; e++) {
		cout << no[e];
	}
	cout << "\t\t" << stack << "\t\t" << str << "\t\t" << "預備" << endl;
	for (int i = 0; i < str.length(); i++) {
		int y = FindSub1(str[i]);
		int x = atoi(no[len_no - 1].c_str());//將轉換爲int型
		if (arry[x][y]._Equal("acc")) {//接受
			cout << qw++ << "\t\t";
			for (int e = 0; e < len_no; e++) {
				cout << no[e];
			}
			cout << "\t\t" << stack << "\t\t" << str.substr(i, str.length() - i) << "\t\t" << "接受" << endl;
			break;
		}
		else if (arry[x][y][0] == 'S') {//移進
			stack += str[i];
			no[len_no++] = arry[x][y].substr(1, arry[x][y].length() - 1);
			cout << qw++ << "\t\t";
			for (int e = 0; e < len_no; e++) {
				cout << no[e];
			}
			cout << "\t\t" << stack << "\t\t" << str.substr(i + 1, str.length() - i) << "\t\t" << "移進"<< endl;
		}
		else if (arry[x][y][0] == 'R') {//歸約
			int a = arry[x][y][1] - '0';
			int t = 1;
			int m, n;//第m行的第n個產生式
			for (int j = 0; j < Len_Source; j++) {
				int flag = 0;
				for (int k = 1; k < num[j]; k++) {
					if (t == a) {
						m = j;
						n = k;
						flag = 1;
						break;
					}
					t++;
				}
				if (flag == 1) {
					break;
				}
			}
			int leng = AftSource[m][n].length();
			stack = stack.substr(0, stack.length() - leng);
			len_no -= leng;
			stack += AftSource[m][0];
			int c = atoi(no[len_no - 1].c_str());
			int d = FindSub1(AftSource[m][0][0]);
			no[len_no++] = arry[c][d];
			i--;
			cout << qw++ << "\t\t";
			for (int e = 0; e < len_no; e++) {
				cout << no[e];
			}
			cout << "\t\t" << stack << "\t\t" << str.substr(i + 1, str.length() - i) << "\t\t" << "歸約" << endl;
		}
		else {
			cout << "error" << endl;
			break;
		}
	}
}
int main()
{
	static string BefSource[100];
	ifstream infile("Source.txt");
	if (!infile)
		cout << "error" << endl;
	int Len = 0;
	while (infile.good()) {
		getline(infile, BefSource[Len++]);
	}
	cout << "==========從文件中讀取到的產生式==========\n" << endl;
	for (int i = 0; i < Len; i++) {
		cout << BefSource[i] << endl;
	}
	Len_Source = Len;
	Pretreatment(BefSource, Len);
	BuPro();
	Build();
	Cre_First();
	Cre_Follow();
	Cre_LR();
	string str;
	cout << "\n==========請輸入需要分析的句子:==========" << endl;
	cin >> str;
	Analysis(str);
}

5.附件
文件中的產生式:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章