Description
已知文法G[S]的表达式求文法的LR(1)的项目集和Go函数.要求使用广度优先搜索,同时按照字典序进行转换,以保证项目集的序号正确.
Input
单组输入,当输入一个@时输入结束.
注意: 在输入中以@代表空.
规定:文法S的拓广文法为$->S
Output
输出文法的项目集和Go函数,参考示例中的格式
Samples
Sample #1
input
S->rD
D->Dai
D->i
@
output
Package: 0
$->.S
S->.rD
Package: 1
$->S.
Package: 2
S->r.D
D->.Dai
D->.i
Package: 3
S->rD.
D->D.ai
Package: 4
D->i.
Package: 5
D->Da.i
Package: 6
D->Dai.
0 1 S
0 2 r
2 3 D
2 4 i
3 5 a
5 6 i
解决代码
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<cstring>
#include<unordered_map>
#include<algorithm> // 用于排序
using namespace std;
vector< vector<char> > G; // 文法G[S]产生式
unordered_map<char, set<char>> ts; // 终结符及它的first集合
unordered_map<char, set<char>> nts; // 非终结符及它的first集合
map< map<string, char>, string> table; // LR分析表
struct C { // 闭包结构
vector< vector<char> > project; // 项目集
vector< set<char> > outlook; // 展望集
unordered_map<char, int> go; // GO函数
};
vector<C> c; // 闭包集
void show_Symbol() {
// 输出非终结符
for (unordered_map<char, set<char>>::iterator it = nts.begin(); it != nts.end(); it++) {
cout << it->first;
}
cout << endl;
// 输出终结符
for (unordered_map<char, set<char>>::iterator it = ts.begin(); it != ts.end(); it++) {
cout << it->first;
}
cout << endl << endl;
}
void show_Closure() {
// 打印项目集
for (unsigned int i = 0; i < c.size(); i++) {
cout << "Package: " << i << endl;
for (int j = 0; j < c[i].project.size(); j++) {
for (int k = 0; k < c[i].project[j].size(); k++) {
if (k == 1) cout << "->";
if (c[i].project[j][k] == ' ') cout << ".";
else cout << c[i].project[j][k];
}
cout << endl;
}
}
// 修正 Go 函数输出顺序
for (unsigned int i = 0; i < c.size(); i++) {
vector<pair<char, int>> goItems(c[i].go.begin(), c[i].go.end());
// 按照符号顺序进行排序,保证输出顺序正确
sort(goItems.begin(), goItems.end(), [](const pair<char, int>& a, const pair<char, int>& b) {
return a.first < b.first;
});
for (auto& it : goItems) {
cout << i << " " << it.second << " " << it.first << endl;
}
}
}
void read_G() { // 读取文法G[S]->G'[M],并区分终结符和非终结符
char ch;
int i = 0;
vector<char> v;
char X;
set<char> m;
nts['M'] = m;
while (ch = getchar()) {
if (ch == '@') break;
if (ch == '\n') {
if (!v.empty()) G.push_back(v);
v.clear();
i = 0;
continue;
}
if (ch != ' ' || ch != '\t') {
if (ch == '|') {
G.push_back(v);
v.clear();
i = 3;
v.push_back(X);
continue;
}
i++;
if (i == 1) {
X = ch;
nts[ch] = m;
}
else if (i != 2 && i != 3 && ch != '~') ts[ch] = m;
if (i != 2 && i != 3) v.push_back(ch);
}
}
if (G.empty()) exit(0);
v.clear();
v.push_back('$');
v.push_back(G[0][0]);
G.insert(G.begin(), v);
for (unordered_map<char, set<char>>::iterator it = nts.begin(); it != nts.end(); it++) {
unordered_map<char, set<char>>::iterator iter;
iter = ts.find(it->first);
if (iter != ts.end()) ts.erase(iter);
}
}
void get_First() {
for (auto& it : ts) it.second.insert(it.first); // 终结符的first集合是它自己
int r = 0;
int change = 1;
while (change) {
if (r == 20) break;
r++;
change = 0;
for (auto& it : nts) {
for (unsigned int i = 0; i < G.size(); i++) {
if (G[i][0] == it.first) {
unsigned int size = it.second.size();
unordered_map<char, set<char>>::iterator iter = ts.find(G[i][1]);
if (ts.find(G[i][1]) != ts.end() || G[i][1] == '~') {
it.second.insert(G[i][1]);
if (it.second.size() > size) change = 1;
}
else {
unsigned int col = 1;
while (1) {
int flag = 0;
unordered_map<char, set<char>>::iterator itt = nts.find(G[i][col]);
for (auto& iter : itt->second) {
if (iter == '~') flag = 1;
else it.second.insert(iter);
}
if (flag) {
col++;
if (G[i].size() <= col) {
it.second.insert('~');
break;
}
else if (ts.find(G[i][col]) != ts.end()) {
it.second.insert(G[i][col]);
break;
}
}
else break;
}
if (it.second.size() > size) change = 1;
}
}
}
}
}
}
void get_Closure() {
int i = 0;
C clo;
c.push_back(clo);
while (1) {
if (i == c.size()) break;
if (i == 0) {
vector<char> v(G[0]);
v.insert(v.begin() + 1, ' ');
c[i].project.push_back(v);
set<char> m;
m.insert('#');
c[i].outlook.push_back(m);
}
for (unsigned int j = 0; j < c[i].project.size(); j++) {
for (unsigned int k = 0; k < c[i].project[j].size(); k++) {
if (c[i].project[j][k] == ' ') {
if (k == c[i].project[j].size() - 1) break;
for (unsigned int x = 0; x < G.size(); x++) {
if (G[x][0] == c[i].project[j][k + 1]) {
vector<char> v(G[x]);
v.insert(v.begin() + 1, ' ');
int exist = 0;
for (unsigned int y = 0; y < c[i].project.size(); y++) {
if (c[i].project[y] == v) {
exist = y;
break;
}
}
if (exist == 0) c[i].project.push_back(v);
set<char> m;
bool kong = true;
int t = 0;
while (kong) {
kong = false;
if (k + t + 1 == c[i].project[j].size() - 1) {
for (auto it : c[i].outlook[j]) m.insert(it);
}
else if (ts.find(c[i].project[j][k + t + 2]) != ts.end()) {
m.insert(c[i].project[j][k + 2 + t]);
}
else {
set<char> m1((nts.find(c[i].project[j][k + 2 + t]))->second);
for (auto it : m1) {
if (it == '~') {
kong = true;
t++;
}
else {
m.insert(it);
}
}
}
}
if (exist) {
for (auto it : m) {
c[i].outlook[exist].insert(it);
}
}
else c[i].outlook.push_back(m);
}
}
break;
}
}
}
for (unsigned int j = 0; j < c[i].project.size(); j++) {
for (unsigned int k = 0; k < c[i].project[j].size(); k++) {
if (c[i].project[j][k] == ' ') {
if (k == c[i].project[j].size() - 1) break;
vector<char> new_closure_pro(c[i].project[j]);
new_closure_pro[k] = new_closure_pro[k + 1];
new_closure_pro[k + 1] = ' ';
set<char> new_closure_search(c[i].outlook[j]);
bool dif = false;
for (unsigned int x = 0; x < c.size(); x++) {
for (unsigned int y = 0; y < c[x].project.size(); y++) {
dif = false;
if (new_closure_pro == c[x].project[y]) {
if (c[x].outlook[0].size() != new_closure_search.size()) {
dif = true;
continue;
}
auto iter = c[x].outlook[0].begin();
for (auto it : new_closure_search) {
if (it != *iter) {
dif = true;
break;
}
iter++;
}
if (dif == false) {
c[i].go[new_closure_pro[k]] = x;
break;
}
}
else dif = true;
if (dif == false) break;
}
if (dif == false) break;
}
if (c[i].go.count(new_closure_pro[k]) != 0 && dif) {
c[c[i].go[new_closure_pro[k]]].project.push_back(new_closure_pro);
c[c[i].go[new_closure_pro[k]]].outlook.push_back(new_closure_search);
break;
}
if (dif) {
C new_closure;
new_closure.project.push_back(new_closure_pro);
new_closure.outlook.push_back(new_closure_search);
c.push_back(new_closure);
c[i].go[new_closure_pro[k]] = c.size() - 1;
}
}
}
}
i++;
}
}
int main() {
read_G();
cout << endl;
get_First();
get_Closure();
show_Closure();
return 0;
}