先用代码占个坑,等期末结束了再补详细解释。。。
/*
2020-06-20
by 软件工程172 202171139
TDM-GCC 4.9.2 64-bit
-std=C++11
*/
#include <bits/stdc++.h>
#define pcc pair<char, char>
#define fi first
#define sc second
#define mp(a, b) make_pair(a, b)
using namespace std;
string S;
map<char, vector<char> > fvt, lvt; //firstVT & LastVt
int table[130][130]; //1 2 3 => < = >
vector<char> K, T; //非终结符 终结符
map<char, bool> ist; //是否为终结符
map<char, vector<string> > rule; //文法规则
map<string, char> inc; //规约
void init_() {
int n;
cout << "请输入文法规则数:";
cin >> n;
cout << "请输入开始状态:";
cin >> S;
cout << "请输入文法规则:\n";
string line;
vector<string> x;
vector<char> y;
for (int i = 0; i <= n; ++i) {
if(i) cin >> line;
else line = "X->#" + S + "#";
ist[line[0]] = true;
for (int j = 3; j < line.length(); ++j) if (line[j] != '|') ist[line[j]];
for (int j = 3; j < line.length(); ++j) {
for (int k = 1; j + k <= line.length(); ++k)
if (j + k == line.length() || line[j + k] == '|') {
rule[line[0]].push_back(line.substr(j, k));
x.push_back(line.substr(j, k));
y.push_back(line[0]);
j = j + k;
break;
}
}
}
for (auto & e : ist) {
e.sc = !e.sc;
if (e.sc) T.push_back(e.fi);
else K.push_back(e.fi);
}
for(int i = 0; i < x.size(); i++) {
for(char & c : x[i]) if(!ist[c]) c = 'N';
inc[x[i]] = ist[y[i]] ? y[i] : 'N';
}
}
void getFirstVT() {
bool F[130][130];
memset(F, 0, sizeof(F));
stack<pcc> st; //序偶(P, a)
for (auto r : rule) for (auto s : r.sc) {
if (ist[s[0]]) {
F[r.fi][s[0]] = true;
st.push(mp(r.fi, s[0]));
} else if (ist[s[1]]) {
F[r.fi][s[1]] = true;
st.push(mp(r.fi, s[1]));
}
}
while (!st.empty()) {
pcc p = st.top();
st.pop();
for (auto r : rule) for (auto s : r.sc) {
if (s[0] == p.fi && !F[r.fi][p.sc]) {
F[r.fi][p.sc] = true;
st.push(mp(r.fi, p.sc));
}
}
}
for (char k : K) for (char t : T) {
if(F[k][t]) fvt[k].push_back(t);
}
}
void printFirstVT() {
cout << "-------------------------------\n";
cout << "FirstVT集为:\n";
for (auto e : fvt) {
cout << e.fi << ':';
for (char c : e.sc) cout << ' ' << c;
cout << '\n';
}
}
void getLastVT() {
bool F[130][130];
memset(F, 0, sizeof(F));
stack<pcc> st; //序偶(P, a)
for (auto r : rule) for (auto s : r.sc) {
reverse(s.begin(), s.end());
if (ist[s[0]]) {
F[r.fi][s[0]] = true;
st.push(mp(r.fi, s[0]));
} else if (ist[s[1]]) {
F[r.fi][s[1]] = true;
st.push(mp(r.fi, s[1]));
}
}
while (!st.empty()) {
pcc p = st.top();
st.pop();
for (auto r : rule) for (auto s : r.sc) {
reverse(s.begin(), s.end());
if (s[0] == p.fi && !F[r.fi][p.sc]) {
F[r.fi][p.sc] = true;
st.push(mp(r.fi, p.sc));
}
}
}
for (char k : K) for (char t : T) {
if (F[k][t]) lvt[k].push_back(t);
}
}
void printLastVT() {
cout << "-------------------------------\n";
cout << "LastVT集为:\n";
for (auto e : lvt) {
cout << e.fi << ':';
for (char c : e.sc) cout << ' ' << c;
cout << '\n';
}
}
void getTable() {
for (auto r : rule) for (auto s : r.sc) {
for (int i = 1; i < s.length(); ++i) {
if (i > 1 && ist[s[i - 2]] && !ist[s[i - 1]] && ist[s[i]]) {
table[s[i - 2]][s[i]] = 2;
}
if (ist[s[i - 1]] && !ist[s[i]]) {
for (char c : fvt[s[i]]) table[s[i - 1]][c] = 1;
}
if (!ist[s[i - 1]] && ist[s[i]]) {
for (char c : lvt[s[i - 1]]) table[c][s[i]] = 3;
}
}
}
}
#define putc(c) cout << c << " "
void printTable() {
cout << "-------------------------------\n";
cout << "算符优先分析表为:\n";
putc(' ');
for (char c : T) putc(c);
cout << '\n';
for (char i : T) {
putc(i);
for (char j : T) {
if(i == j && i == '#') putc(' ');
else if (table[i][j] == 1) putc('<');
else if (table[i][j] == 2) putc('=');
else if (table[i][j] == 3) putc('>');
else putc(' ');
}
cout << '\n';
}
}
void putstr(string & s) {
cout << s;
for(int i = 0; i < 10 - s.length(); ++i) {
putchar(' ');
}
}
void findl(string & s, int & a, int & len) {
//寻找最左质短语
vector<char> v;
vector<int> pos;
for (int i = 0; i < s.length(); ++i) if (ist[s[i]]) {
v.push_back(s[i]);
pos.push_back(i);
}
for(int i = 1; i < v.size(); i++) {
if(table[v[i - 1]][v[i]] == 3) continue;
int j = i;
while(j + 1 < v.size() && table[v[j]][v[j + 1]] == 2) ++j;
if(j == v.size() - 1 || table[v[j]][v[j + 1]] == 3) {
a = pos[i];
while(a - 1 >= 0 && !ist[s[a - 1]]) --a;
len = pos[j] - a + 1;
while(a + len < s.length() && !ist[s[a + len]]) ++len;
return;
}
}
}
void run() {
cout << "-------------------------------\n";
cout << "请输入以#结尾的符号串:\n";
string st = "#", que;
cin >> que;
cout << "栈 输入部分 操作 最左素短语\n";
while (que.length() >= 1) {
if(st == "#N" && que == "#") {
putstr(st), putstr(que);
cout << "结束\n";
cout << "输入串符合文法定义!\n";
return;
}
putstr(st);
putstr(que);
int p = st.length() - 1;
while(!ist[st[p]]) --p;
int x = table[st[p]][que[0]];
if(que[0] == '#' || x == 3) {
cout << "规约 ";
int a, len;
findl(st, a, len);
cout << st.substr(a, len) << '\n';
if(inc[st.substr(a, len)] == 0) break;
else {
st[a] = inc[st.substr(a, len)];
st.replace(a + 1, len - 1, "");
continue;
}
}
if(x == 1 || !ist[st[st.length() - 1]]) {
cout << "移进\n";
st += que.substr(0, 1);
que.erase(0, 1);
}
}
cout << "输入串不符合文法定义!\n";
}
int main () {
// freopen("in.txt", "r", stdin);
init_();
getFirstVT();
getLastVT();
getTable();
cout << "1.FirstVt\n2.LastVT\n3.算符优先分析表\n4.检测输入串\n5.退出\n";
while(true) {
cout << "请输入您所需要执行的功能:";
int op;
cin >> op;
if(op == 0) break;
if (op == 1) printFirstVT();
else if (op == 2) printLastVT();
else if (op == 3) printTable();
else run();
}
return 0;
}