SDUT:M - LR(1)文法

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值