編譯原理:LL1(1)文法的語法分析器(通過文法構造分析表)

參考了大佬的代碼,思路以後補上,先把代碼貼在這裏:
(使用了一些c++11的特性)

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1005;

struct node {
	char left;
	string right;
};

map <char , int>mp , mp1; //記錄非終結符和非終結符 
vector <node> input;
vector <char> non_c , ter_c , sta , vs;
set <char> first[maxn];
set <char> follow[maxn];
int f[maxn] , f1[maxn];
int tableMap[maxn][maxn];
int n;

void getFirst(char t) {
	if(!f[mp[t]]) return; 
	for(int i = 0 ; i < n ; i++) {
		if(input[i].left == t) {
			if(!mp.count(input[i].right[0])) {
				first[mp[t]].insert(input[i].right[0]);
			}
			else {	
				int num = 0;
				for(int j = 0 ; j < input[i].right.length() ; j++) {
					if(!mp.count(input[i].right[j])) {
						first[mp[t]].insert(input[i].right[j]);
						break;
					}
					getFirst(input[i].right[j]);
					bool flag = 0;
					for(auto it = first[mp[input[i].right[j]]].begin() ; it != first[mp[input[i].right[j]]].end() ; it++) {
						if(*it == '$')flag = 1;
						else first[mp[t]].insert(*it);
					}
					if(!flag) break;
					else {
						num += flag; flag = 0;
					}
				}
				//cout << "num = " << num << "\n";
				if(num == input[i].right.length()) {
					first[mp[t]].insert('$');
				}
			}
		}
	}
	f[mp[t]] = 0;
}

void getFollow(char tmp) {
	if(!f1[mp[tmp]])return;
	for(int i = 0 ; i < n ; i++) {
		int index = -1;
		for(int j = 0 ; j < input[i].right.length() ; j++) {
			if(input[i].right[j] == tmp) {
					index = j; break;
			}
		}
		if(index > -1 && index < input[i].right.length() - 1) {
			char nxt = input[i].right[index + 1];
			if(!mp.count(nxt)) {
				follow[mp[tmp]].insert(nxt);
			}
			else {
				int flag = 0 , j;
				for(j = index + 1; j < input[i].right.length() ; j++) {
					nxt = input[i].right[j];
					if(!mp.count(nxt)) {
						follow[mp[tmp]].insert(nxt);
						break;
					}
					for(auto it = first[mp[nxt]].begin() ; it != first[mp[nxt]].end() ; it++) {
						if(*it == '$')flag = 1;
						else follow[mp[tmp]].insert(*it);
					}
					if(!flag)break;
				}
				if(j == input[i].right.length() && flag) {
					getFollow(input[i].left);
					for(auto it = follow[mp[input[i].left]].begin() ; it != follow[mp[input[i].left]].end() ; it++) {
						follow[mp[tmp]].insert(*it);
					}		
				}
			}
		}
		else if(index == input[i].right.length() - 1 && input[i].left != input[i].right[index]) {
			getFollow(input[i].left);
			for(auto it = follow[mp[input[i].left]].begin() ; it != follow[mp[input[i].left]].end() ; it++) {
				follow[mp[tmp]].insert(*it);
			}
		}
	}
	f1[mp[tmp]] = 0;
}

void getTable() {
	for(int i = 0 ; i < n ; i++) {
		char tmp = input[i].right[0];
		if(!mp.count(tmp)) {
			if(tmp != '$')tableMap[mp[input[i].left]][mp1[tmp]] = i;
			else {
				for(auto it = follow[mp[input[i].left]].begin() ; it != follow[mp[input[i].left]].end() ; it++) {
					tableMap[mp[input[i].left]][mp1[*it]] = i;
				}
			}
		}
		else {
			int j;
			bool flag = 0;
			for(j = 0; j < input[i].right.length() ; j++) {
				tmp = input[i].right[j];
				if(mp1.count(tmp)) {
					tableMap[mp[input[i].left]][mp1[tmp]] = i;
					break;
				}
				for(auto it = first[mp[tmp]].begin() ; it != first[mp[tmp]].end() ; it++) {
					if(*it == '$')flag = 1;
					else tableMap[mp[input[i].left]][mp1[*it]] = i;
				}
				if(!flag)break;
			}
			if(j == input[i].right.length() && flag) {
				for(auto it = follow[mp[input[i].left]].begin() ; it != follow[mp[input[i].left]].end() ; it++) {
					tableMap[mp[input[i].left]][mp1[*it]] = i;
				}		
			}
		} 
	}
}

void analyExp(string s) {
	for(int i = s.length() - 1 ; i >= 0 ; i--) {
		vs.push_back(s[i]);
	}
	sta.push_back('#');
	sta.push_back(non_c[0]);
	while(vs.size() > 0) {
		string outs , outs1; 
		//輸出分析棧
		 for(int i = 0 ; i < sta.size() ; i++) {
		 	outs += sta[i];
		 }
		  for(int i = vs.size() - 1 ; i >= 0 ; i--) {
		 	outs1 += vs[i];
		 }
		 cout << setw(16) << outs << setw(16)<<outs1;
		 
		 
		 char c1 = sta[sta.size() - 1] , c2 = vs[vs.size() - 1];
		 if(c1 == c2) {
		 	if(c1 == '#') {
		 		cout << setw(16)<<"Accepted!\n";
		 		break;	
			}
			else {
				sta.pop_back(); vs.pop_back();
				cout << setw(16)<<c1 << "\n";
			}
		 } 
		 else if(tableMap[mp[c1]][mp1[c2]] != -1) {
		 	int t = tableMap[mp[c1]][mp1[c2]];
		 	sta.pop_back();
		 	if(input[t].right != "$") {
		 		for(int i = input[t].right.length() - 1 ; i >= 0 ; i--)sta.push_back(input[t].right[i]);	
			}
			cout << setw(16) <<input[t].right << "\n";
		 } 
		 else {
		 	cout <<setw(16) <<"error\n";
		 	break;
		 }
	}
}

void showFirst() {
	cout << "first集合\n";
	for(int i = 0 ; i < non_c.size() ; i++) {
		cout << non_c[i] << ":";
		for(auto it = first[mp[non_c[i]]].begin() ; it != first[mp[non_c[i]]].end() ; it++) {
			cout << *it << " ";
		}
		cout << "\n";
	}	
}

void showFollow() {
	cout << "follow集合\n";
	for(int i = 0 ; i < non_c.size() ; i++) {
		cout << non_c[i] << ":";
		for(auto it = follow[mp[non_c[i]]].begin() ; it != follow[mp[non_c[i]]].end() ; it++) {
			cout << *it << " ";
		}
		cout << "\n";
	}
}

void showTable() {
	for(int i = 0 ; i < ter_c.size() ; i++) {
		cout <<setw(6)<< ter_c[i] ;
	}
	cout << "\n";
	for(int i = 0 ; i < non_c.size() ; i++) {
		cout << non_c[i] << ":";
		for(int j = 0 ; j < ter_c.size() ; j++) {
			if(tableMap[i][j] == -1) {
				cout << setw(6)<< "error";
			}
			else cout << setw(6)<< input[tableMap[i][j]].right;
		}
		cout << "\n";
	}
}


int main() {
	cout << "請輸入文法的行數\n";
	ios::sync_with_stdio(0);
	cin >> n;
	int flag = 0;
	cin.get();
	int tag;
	memset(tableMap , -1 ,sizeof(tableMap));
	for(int i = 0 ; i < n ; i++) {
		string s;
		node t;
		getline(cin , s);
		t.left = s[0];
		if(!mp.count(s[0])) {
			mp[s[0]] = non_c.size();
			f[non_c.size()] = f1[non_c.size()] = 1;
			non_c.push_back(s[0]);
		}
		tag = 0;
		for(int j = 1 ; j < s.length() ; j++) {
			if(!tag && s[j] == '-')tag = 1;
			else if(tag == 1 && s[j] == '>')tag = 2;
			else if(tag == 2) {
				if(!isupper(s[j]) && !mp1.count(s[j])){
					mp1[s[j]] = ter_c.size();
					if(s[j] != '$')ter_c.push_back(s[j]);
				}
				t.right += s[j]; 
			}
			else {
				cout << "讀入出錯,程序自動關閉,請重新啓動\n";
				return 0;
			}
		}
		input.push_back(t); 
	}
	ter_c.push_back('#');
	mp1['#'] = ter_c.size() - 1;
	for(int i = 0 ; i < non_c.size() ; i++) {
		getFirst(non_c[i]);
	}
	showFirst();
	for(int i = 0 ; i < non_c.size() ; i++) {
		if(i == 0)follow[i].insert('#');
		getFollow(non_c[i]);
	}	
	showFollow();
	getTable();
	showTable();
	cout << "請輸入要分析的字符串\n";
	string s;
	getline(cin , s);
	cout << setw(16) << "分析棧" << setw(16) << "剩餘輸入串" << setw(16) << "推導式" << endl;
	analyExp(s);
	return 0;
}

運行結果:
在這裏插入圖片描述
在這裏插入圖片描述

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