ZZU编译原理实验8——语法分析器实验:LR(1)分析表的构造

  • 实验目的

理解LR(1)语法分析方法的原理,掌握LR(1)分析表的构造,设计相关数据结构和程序结构,加深对自下而上语法分析方法的理解。

  • 实验内容

需要实现的功能:

1)使用LR(1)分析方法构造识别活前缀的DFA;

2)构造文法的分析表(Action表和Goto表);

3)输入文法:文法描述存储在文本文件中,文件名作为命令行参数输入;

4)输出文法的项目集簇(标准输出设备);

5)输出识别活前缀的DFA(标准输出设备);

6)输出文法的Action表和Goto表(输出到创建的指定LR分析表文件,文件名与文法描述文件同名,扩展名为lrtbl);

7)输出文法是否是LR(1)文法的判断结果(标准输出设备)。

  •         代码实现
#include<iostream>
#include<stack>
#include<map>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include <fstream>
using namespace std;
typedef char* symbol;

symbol empty = (symbol)"0";
symbol ed = (symbol)"#";
symbol dot = (symbol)".";
symbol acc = (symbol)"acc";
symbol shift = (symbol)"s";
symbol reduction = (symbol)"r";

int vnNum;
int vtNum;
int productionNum;

//非终结符
typedef struct vnSymbol{
    symbol VnSymbol;
    int idx;
    vector<symbol> first;
    vector<symbol> follow;
    vnSymbol(): idx(0) {
        VnSymbol = new char;
        first.clear();
        follow.clear();
    }
    ~vnSymbol()
    {
        delete VnSymbol;
        VnSymbol = nullptr;
    }
}VnSymbol;

//终结符
typedef struct vtSymbol{
    symbol VtSymbol;
    int idx;
    vtSymbol() :idx(0) {
        VtSymbol = new char;
    }
    ~vtSymbol()
    {
        delete VtSymbol;
        VtSymbol = nullptr;
    }
}VtSymbol;

typedef struct production{
    symbol left;    //产生式左部
    vector<symbol> right;   //产生式右部
    vector<symbol> select;
    vector<symbol> first;
    int idx;
    production() :idx(0) {
        right.clear();
        select.clear();
        first.clear();
        left = new char;
    }
    ~production()
    {
        delete left;
        left = nullptr;
    }
}Production;

//文法四元组
typedef struct cfg{
    vector<VnSymbol*> VNSet;   //非终结符集
    vector<VtSymbol*> VTSet;   //终结符集
    symbol S;           //开始符号
    vector<Production*> ProductionSet;   //产生式集
    cfg(){
        VNSet.clear();
        VTSet.clear();
        ProductionSet.clear();
        S = new char;
    }
    ~cfg()
    {
        delete S;
        S = nullptr;
    }
} CFG;

CFG *cfg = new CFG();


void print_cfg(CFG *cfg);   //打印文法相关信息
void create_first1(CFG *cfg);   //构造每个非终结符的first集
void create_first2(CFG *cfg);   //构造每个候选式的first集
void create_follow(CFG *cfg);   //构造每个非终结符的follow集
void create_select(CFG *cfg);   //构造每个产生式的select集
int isVnSymbol(CFG *cfg, symbol x); //判断x是否是非终结符,若是,是第几个
int isVtSymbol(CFG *cfg, symbol x); //判断x是否是终结符,若是,是第几个
bool haveEpsilon(CFG *cfg, int x); //判断空串ε是否在第x个非终结符的first集合中
bool haveEpsilon1(CFG *cfg, int x); //判断空串是否在第x个产生式右部的first集里面


void print_cfg(CFG *cfg)
{
    cout << "CFG=(VN,VT,P,S)" << endl;
    cout << "VN : " ;
    for(int i = 0; i < vnNum; i++)
    {
        cout << cfg->VNSet[i]->VnSymbol << ' ';
    }
    cout << endl;
    cout << "VT : ";
    for(int i = 0; i < vtNum; i ++)
    {
        cout << cfg->VTSet[i]->VtSymbol << ' ';
    }
    cout << endl;
    cout << "Production : " << endl;
    for(int i = 0; i < productionNum; i++)
    {
        cout << '\t' << cfg->ProductionSet[i]->idx << " : " << cfg->ProductionSet[i]->left
        << " -> ";
        for(int j = 0; j < cfg->ProductionSet[i]->right.size(); j ++)
        {
            cout << cfg->ProductionSet[i]->right[j] << ' ';
        }
        cout << endl;
    }
    cout << "StartSymbol : " << cfg->S << endl;
    cout << endl;

}


void create_first1(CFG *cfg)
{
    bool flag = true;
    while(true)
    {
        if(!flag) break;
        flag = false;
        for(int i = 0; i < productionNum; i++)
        {
            symbol x = cfg->ProductionSet[i]->left;
            // cout << "第" << i << "个产生式的左部是: " << x << endl;
            int j = isVnSymbol(cfg, x);
            // cout << "产生式左部" << x << "在非终结符集中是第" << j << "个" << endl;
            if(j != -1)
            {
                symbol y = cfg->ProductionSet[i]->right[0];
                // cout << "第" << i << "个产生式的右部第一个符号串是: " << y << endl;
                if(!strcmp(y, empty)) {
                    vector<symbol>::iterator it;
                    it = find(cfg->VNSet[j]->first.begin(), cfg->VNSet[j]->first.end(), empty);
                    if(it == cfg->VNSet[j]->first.end())
                    {
                        cfg->VNSet[j]->first.push_back(y);
                        // cout << "右部是空串,添加成功" << endl;
                        flag = true;
                    }
                }
                else
                {
                    int k = isVtSymbol(cfg, y);
                    //第一个符号串是终结符,直接加入到first集合里面去
                    if(k != -1) {
                        vector<symbol>::iterator it;
                        it = find(cfg->VNSet[j]->first.begin(), cfg->VNSet[j]->first.end(),y);
                        if(it == cfg->VNSet[j]->first.end())
                        {
                            cfg->VNSet[j]->first.push_back(y);
                            // cout << "右部第一个符号串是终结符,添加成功" << endl;
                            flag = true;
                        }
                    }
                    //第一个字符是非终结符
                    else
                    {
                        //从产生式右部的第一个元素开始遍历
                        int n;
                        for(n = 0; n < cfg->ProductionSet[i]->right.size(); n++)
                        {
                            y = cfg->ProductionSet[i]->right[n];
                            // m 表示非终结符y(如果是非终结符的话)在非终结符集中是第几个
                            int m = isVnSymbol(cfg, y);
                            //y是非终结符且y中含有空串
                            if(m != -1 && haveEpsilon(cfg, m))
                            {
                                for(int n = 0; n < cfg->VNSet[m]->first.size(); n++)
                                {
                                    vector<symbol>::iterator it;
                                    it = find(cfg->VNSet[j]->first.begin(), cfg->VNSet[j]->first.end(),cfg->VNSet[m]->first[n]);
                                    if(strcmp(cfg->VNSet[m]->first[n],empty) && it ==cfg->VNSet[j]->first.end()){
                                        cfg->VNSet[j]->first.push_back(cfg->VNSet[m]->first[n]);
                                        // cout << "右部是Y1Y2...Yn类型, 添加成功" << endl;
                                        flag = true;
                                    }
                                }
                            }
                            if(m == -1) {
                                //说明y是终结符
                                vector<symbol>::iterator it;
                                it = find(cfg->VNSet[j]->first.begin(), cfg->VNSet[j]->first.end(),y);
                                if(it == cfg->VNSet[j]->first.end())
                                {
                                    cfg->VNSet[j]->first.push_back(y);
                                    // cout << "中间碰上终结符,添加成功" << endl;
                                    flag = true;
                                }
                                break;
                            }
                            if(!haveEpsilon(cfg, m)) {
                                //说明y之前的串的first集都含有空串
                                for(int q = 0; q < cfg->VNSet[m]->first.size(); q++)
                                {
                                    vector<symbol>::iterator it;
                                    it = find(cfg->VNSet[j]->first.begin(), cfg->VNSet[j]->first.end(),cfg->VNSet[m]->first[q]);
                                    if(it == cfg->VNSet[j]->first.end()){
                                        cfg->VNSet[j]->first.push_back(cfg->VNSet[m]->first[q]);
                                        // cout << "这一个非终结符的first集合里面没有空串, 添加成功" << endl;
                                        flag = true;
                                    }
                                }
                                break;
                            }
                        }
                        if(n == cfg->ProductionSet[i]->right.size())
                        {
                            vector<symbol>::iterator it;
                            it = find(cfg->VNSet[j]->first.begin(), cfg->VNSet[j]->first.end(),empty);
                            if(it == cfg->VNSet[j]->first.end())
                            {
                                cfg->VNSet[j]->first.push_back(empty);
                                // cout << "产生式右部能够推出空串,添加成功" << endl;
                            }
                        }
                    }
                }
            }
        }
    }
}

//文法任意候选式的首符集
void create_first2(CFG *cfg)
{
    for(int i = 0; i < productionNum; i++)
    {
        //该产生式右部的第一个符号
        symbol x = cfg->ProductionSet[i]->right[0];
        if(!strcmp(x, empty)) cfg->ProductionSet[i]->first.push_back(empty);
        else {
            int k = isVtSymbol(cfg, x);
            //这个候选式的第一个符号是终结符
            if(k != -1) cfg->ProductionSet[i]->first.push_back(x);
            //第一个符号是非终结符
            else
            {
                int j;
                for(j = 0; j < cfg->ProductionSet[i]->right.size(); j ++)
                {
                    symbol y = cfg->ProductionSet[i]->right[j];
                    int m = isVnSymbol(cfg, y);
                    if(m != -1 && haveEpsilon(cfg, m))
                    {
                        for(int n = 0; n < cfg->VNSet[m]->first.size(); n ++)
                        {
                            vector<symbol>::iterator it;
                            it = find(cfg->ProductionSet[i]->first.begin(), cfg->ProductionSet[i]->first.end(), cfg->VNSet[m]->first[n]);
                            if(strcmp(cfg->VNSet[m]->first[n],empty) && it == cfg->ProductionSet[i]->first.end())
                            {
                                cfg->ProductionSet[i]->first.push_back(cfg->VNSet[m]->first[n]);
                            }
                        }
                    }
                    if(m==-1)
                    {
                        vector<symbol>::iterator it;
                        it = find(cfg->ProductionSet[i]->first.begin(), cfg->ProductionSet[i]->first.end(),y);
                        if(it == cfg->ProductionSet[i]->first.end())
                        {
                            cfg->ProductionSet[i]->first.push_back(y);
                        }
                        break;
                    }
                    if(!haveEpsilon(cfg, m))
                    {
                        for(int q = 0; q < cfg->VNSet[m]->first.size(); q++)
                        {
                            vector<symbol>::iterator it;
                            it = find(cfg->ProductionSet[i]->first.begin(), cfg->ProductionSet[i]->first.end(),cfg->VNSet[m]->first[q]);
                            if(it == cfg->ProductionSet[i]->first.end()){
                                cfg->ProductionSet[i]->first.push_back(cfg->VNSet[m]->first[q]);
                            }
                        }
                        break;
                    }
                }
                if(j == cfg->ProductionSet[i]->right.size())
                {
                    vector<symbol>::iterator it;
                    it = find(cfg->ProductionSet[i]->first.begin(), cfg->ProductionSet[i]->first.end(),empty);
                    if(it == cfg->ProductionSet[i]->first.end())
                    {
                        cfg->ProductionSet[i]->first.push_back(empty);
                    }
                }
            }
        }
    }
}

void create_follow(CFG *cfg)
{
    int x = isVnSymbol(cfg, cfg->S);
    cfg->VNSet[x]->follow.push_back(ed);
    // cout << "将结束符号" << ed << "加入到开始符号" << cfg->S << "的follow集中,添加成功" << endl;
    bool flag = true;
    while(true){
        if(!flag) break;
        flag = false;
        for(int i = 0; i < productionNum; i ++)
        {
            for(int j = 0; j < cfg->ProductionSet[i]->right.size(); j ++)
            {
                symbol y = cfg->ProductionSet[i]->right[j];
                // cout << "第" << i << "个产生式的右部的第" << j << "个符号是" << y << endl;
                int m = isVnSymbol(cfg, y);
                //是非终结符
                if(m != -1) {
                    // cout << y << "是一个非终结符" << endl;
                    int k;
                    for(k = j + 1; k < cfg->ProductionSet[i]->right.size(); k++)
                    {
                        //是终结符
                        int n = isVtSymbol(cfg, cfg->ProductionSet[i]->right[k]);
                        if( n != -1)
                        {
                            // cout << y << "后面的符号" << cfg->ProductionSet[i]->right[k] << "是一个终结符" << endl;
                            vector<symbol>::iterator it;
                            it = find(cfg->VNSet[m]->follow.begin(),cfg->VNSet[m]->follow.end(),cfg->ProductionSet[i]->right[k]);
                            if(strcmp(cfg->ProductionSet[i]->right[k], empty) && it == cfg->VNSet[m]->follow.end()){
                                cfg->VNSet[m]->follow.push_back(cfg->ProductionSet[i]->right[k]);
                                // cout << "终结符" << cfg->ProductionSet[i]->right[k] << "要加到" << y << "的follow集中去,添加成功" << endl;
                                flag = true;
                            }
                            break;
                        }
                        //是非终结符
                        else
                        {
                            // cout << y << "后面的符号是非终结符" << cfg->ProductionSet[i]->right[k] << endl;
                            n = isVnSymbol(cfg, cfg->ProductionSet[i]->right[k]);
                            for(int p = 0; p < cfg->VNSet[n]->first.size(); p++)
                            {
                                vector<symbol>::iterator it;
                                it = find(cfg->VNSet[m]->follow.begin(), cfg->VNSet[m]->follow.end(),cfg->VNSet[n]->first[p]);
                                if(strcmp(cfg->VNSet[n]->first[p], empty) && it == cfg->VNSet[m]->follow.end())
                                {
                                    cfg->VNSet[m]->follow.push_back(cfg->VNSet[n]->first[p]);
                                    // cout << "把非终结符" <<  cfg->ProductionSet[i]->right[k] << " first集里的符号" << cfg->VNSet[n]->first[p] << "加入到" << y << "的follow集合中去,添加成功"<< endl;
                                    flag = true;
                                }
                            }
                            if(!haveEpsilon(cfg, n)) {
                                // cout << "符号" << cfg->ProductionSet[i]->right[k] << "的first集中没有空串,要结束此次循环" << endl;
                                break;
                            }

                        }
                    }
                    // A -> αBβ first(β) 里面有 ε
                    if( k == cfg->ProductionSet[i]->right.size())
                    {
                        int n = isVnSymbol(cfg, cfg->ProductionSet[i]->left);
                        for(int p = 0; p < cfg->VNSet[n]->follow.size(); p ++)
                        {
                            vector<symbol>::iterator it;
                            it = find(cfg->VNSet[m]->follow.begin(), cfg->VNSet[m]->follow.end(), cfg->VNSet[n]->follow[p]);
                            if(it == cfg->VNSet[m]->follow.end())
                            {
                                cfg->VNSet[m]->follow.push_back(cfg->VNSet[n]->follow[p]);
                                // cout << cfg->ProductionSet[i]->left << "的follow集添加到符号" << y << "的follow集中,添加成功" << endl;
                                flag = true;
                            }
                        }
                    }
                }
                //A -> αB
                if(j == cfg->ProductionSet[i]->right.size() - 1)
                {
                    //最后一个字符是非终结符
                    if(m != -1)
                    {
                        int n = isVnSymbol(cfg, cfg->ProductionSet[i]->left);
                        for(int p = 0; p < cfg->VNSet[n]->follow.size(); p ++)
                        {
                            vector<symbol>::iterator it;
                            it = find(cfg->VNSet[m]->follow.begin(), cfg->VNSet[m]->follow.end(), cfg->VNSet[n]->follow[p]);
                            if(it == cfg->VNSet[m]->follow.end())
                            {
                                cfg->VNSet[m]->follow.push_back(cfg->VNSet[n]->follow[p]);
                                // cout << cfg->ProductionSet[i]->left << "的follow集添加到" << y << "的follow集中" << endl;
                                flag = true;
                            }
                        }
                    }
                }
            }
        }
    }
}

void create_select(CFG *cfg)
{
    for(int i = 0; i < productionNum; i ++)
    {
        if(!haveEpsilon1(cfg, i))
        {
            for(int j = 0; j < cfg->ProductionSet[i]->first.size(); j++)
            {
                cfg->ProductionSet[i]->select.push_back(cfg->ProductionSet[i]->first[j]);
            }
        }
        else {
            for(int j = 0; j < cfg->ProductionSet[i]->first.size(); j++)
            {
                if(strcmp(cfg->ProductionSet[i]->first[j], empty))
                {
                    cfg->ProductionSet[i]->select.push_back(cfg->ProductionSet[i]->first[j]);
                }
            }
            int x = isVnSymbol(cfg, cfg->ProductionSet[i]->left);
            for(int j = 0; j < cfg->VNSet[x]->follow.size(); j ++)
            {
                vector<symbol>::iterator it;
                it = find(cfg->ProductionSet[i]->select.begin(), cfg->ProductionSet[i]->select.end(), cfg->VNSet[x]->follow[j]);
                if(it == cfg->ProductionSet[i]->select.end())
                {
                    cfg->ProductionSet[i]->select.push_back(cfg->VNSet[x]->follow[j]);
                }
            }
        }
    }
}

//判断某符号串在非终结符里面是第几个
int isVnSymbol(CFG *cfg, symbol x)
{
    for(int i = 0; i < vnNum; i++)
    {
        if(!strcmp(x, cfg->VNSet[i]->VnSymbol)) return i;
    }
    return -1;
}

//判断某符号串在终结符集里面是第几个
int isVtSymbol(CFG *cfg, symbol x)
{
    for(int i = 0; i < vtNum; i ++)
    {
        if(!strcmp(x, cfg->VTSet[i]->VtSymbol)) return i;
    }
    return -1;
}

//判断空串ε是否在第x个非终结符的first集合中
bool haveEpsilon(CFG * cfg, int x)
{
    for(int i = 0; i < cfg->VNSet[x]->first.size(); i++)
    {
        if(!strcmp(cfg->VNSet[x]->first[i],empty)) return true;
    }
    return false;
}

//判断空串是否在第x个产生式右部的first集里面
bool haveEpsilon1(CFG *cfg, int x)
{
    for(int i = 0; i < cfg->ProductionSet[x]->first.size(); i ++)
    {
        if(!strcmp(cfg->ProductionSet[x]->first[i], empty)) return true;
    }
    return false;
}


//项目
typedef struct item{
    Production *p;
    int position;
    //展望串
    vector<symbol> look_ahead;
    //这个项目dot后面部分的first集合
    vector<symbol> first;
    item()
    {
        p = new Production;
        look_ahead.clear();
        first.clear();
    }
    ~item()
    {
        delete p;
        p = nullptr;
    }
}Item;

typedef pair<int,symbol> PII;
typedef map<PII,int> DFA;
typedef pair<char *, int> PII2;
typedef map<PII, PII2> ACTION;
typedef map<PII,int> GOTO;

vector<symbol> symbols; //文法符号集
vector<vector<Item *> > itemSets; //项目集簇

int inIset(Item *I, vector<Item *> &itemSet);    //判断某一个项目是否已经存在于项目集中
void create_first(Item *I, CFG *cfg);   //构造dot后面串的first集合
void create_closure(CFG *cfg, vector<Item *> &itemSet);   //构造项目集的闭包
int inISets(vector<item*> &itemSet);    //判断某一个项目集是否已经存在于项目集簇(项目集簇是全局变量)
void create_dfa(CFG *cfg, DFA &dfa);    //构造项目集簇和识别或前缀的DFA
void create_tables(DFA &dfa, ACTION &action, GOTO &go2);    //构造action表和goto表

int main(int argc, char *argv[])
{
    /*
    * 处理文法
    */
    if(!freopen(argv[1], "r", stdin))
    {
        printf("文件打开失败\n");
        return 0;
    }
    //读入非终结符
    scanf("%d",&vnNum);
    for(int i = 0; i < vnNum; i ++)
    {
        VnSymbol *vn = new VnSymbol;
        scanf("%s",vn->VnSymbol);
        vn->idx = i;
        cfg->VNSet.push_back(vn);
    }
    //读入终结符
    scanf("%d",&vtNum);
    for(int i = 0; i < vtNum; i ++)
    {
        VtSymbol *vt = new VtSymbol;
        vt->idx = i;
        scanf("%s",vt->VtSymbol);
        cfg->VTSet.push_back(vt);
    }

    //读入产生式
    scanf("%d",&productionNum);
    for(int i = 0; i < productionNum; i++)
    {
        Production *p = new Production;
        char *r = new char;
        p->idx = i;
        scanf("%s -> %s",p->left, r);
        if(!strcmp(r,empty)) p->right.push_back(empty);
        else p->right.push_back(r);
        while(getchar() != '\n')
        {
            char *r1 = new char;
            scanf("%s",r1);
            if(!strcmp(r1,empty)) p->right.push_back(empty);
            else p->right.push_back(r1);
        }
        cfg->ProductionSet.push_back(p);
    }
    scanf("%s",cfg->S);
    fclose(stdin);

    //输出文法相关信息
    print_cfg(cfg);

    //把文法符号拿出来存储
    symbols.push_back(ed);
    for(int i = 0; i < vtNum; i ++)
    {
        symbols.push_back(cfg->VTSet[i]->VtSymbol);
    }
    for(int i = 0; i < vnNum; i ++)
    {
        symbols.push_back(cfg->VNSet[i]->VnSymbol);
    }

    DFA dfa;
    create_dfa(cfg, dfa);
    //输出项目集簇
    cout << "[LR(1) item set cluster]" << endl;
    for(int i = 0; i < itemSets.size(); i++)
    {
        cout << "I" << i << ":" << endl;
        for(int j = 0; j < itemSets[i].size(); j++)
        {
            int d = itemSets[i][j]->position;
            cout << "    " << itemSets[i][j]->p->left << "->" ;
            for(int k = 0; k < itemSets[i][j]->p->right.size(); k++)
            {
                if(k == d) cout << ". ";
                cout << itemSets[i][j]->p->right[k] << ' ';
            }
            if(d == itemSets[i][j]->p->right.size())  cout << "." ;
            cout << ", ";
            for(int k = 0; k < itemSets[i][j]->look_ahead.size(); k++)
            {
                cout << itemSets[i][j]->look_ahead[k] << ' ';
            }
            cout << endl;
        }
        cout << endl;
    }

    //输出识别活前缀的DFA
    cout << "[LR(1) state tran function]" << endl;
    for(auto it : dfa)
    {
        cout << it.first.first << " , " << it.first.second << " -> " << it.second << endl;
    }
    cout << "文法是LR(1)文法!" << endl;

    ACTION action;
    GOTO go2;
    create_tables(dfa, action, go2);

    //分析表文件输出
    //freopen("tables.lrtbl", "w", stdout);
    std::string fn(argv[1]);
    fn.erase(fn.find("txt") , strlen("txt"));
    fn.append("lrtbl");
    //std::ifstream inputFile(fileName);
	std::ofstream outputFile(fn);
    outputFile<< "Action:\n"<< action.size() << endl;
    for(auto it : action)
    {
       outputFile<< it.first.first << ' ' << it.first.second << ' ' << it.second.first << it.second.second << endl;
    }
    outputFile<< endl;
    outputFile<< "Goto: " << go2.size() << endl;
    for(auto it : go2)
    {
        outputFile<< it.first.first << ' ' << it.first.second << ' ' << it.second << endl;
    }
    fclose(stdout);

    return 0;
}

//构造项目集簇和识别或前缀的DFA
void create_dfa(CFG *cfg, DFA &dfa)
{
    Item *I = new Item;
    vector<Item *> itemSet;
    I->p = cfg->ProductionSet[0];
    I->position = 0;
    I->look_ahead.push_back(ed);
    create_first(I, cfg);
    itemSet.push_back(I);
    create_closure(cfg, itemSet);
    int idx = 0;    //项目集的编号
    itemSets.push_back(itemSet), idx ++;

    for(int i = 0; i < itemSets.size(); i++)
    {
        for(int j = 0; j < symbols.size(); j ++)
        {
            // cout << endl;
            // cout << "当文法符号是" << symbols[j] << "的时候" << endl;
            vector<Item *> itemSet;
            for(int k = 0; k < itemSets[i].size(); k ++)
            {
                int d = itemSets[i][k]->position;
                // cout << "第" << i << "个项目集的第" << k << "项目, 点的位置在" << d <<  endl;
                // cout << "项目右部的长度是 " << itemSets[i][k]->p->right.size() << endl;
                if(d < itemSets[i][k]->p->right.size())
                {
                    // cout << "点右边的文法符号是" << itemSets[i][k]->p->right[d] << endl;
                    if(!strcmp(symbols[j], itemSets[i][k]->p->right[d]))
                    {
                        item *I = new item;
                        I->p = itemSets[i][k]->p;
                        I->position = itemSets[i][k]->position + 1;
                        I->look_ahead = itemSets[i][k]->look_ahead;
                        create_first(I, cfg);
                        itemSet.push_back(I);
                        // cout << "-------将项目添加到项目集中-----------" << endl;
                    }
                }
            }
            if(!itemSet.empty())
            {
                // cout << "构造项目集itemSet的项目集闭包" << endl;
                create_closure(cfg, itemSet);
                // cout << "构造成功" << endl;
                PII p;
                p.first = i, p.second = symbols[j];
                int m = inISets(itemSet);
                if(m == -1)
                {
                    itemSets.push_back(itemSet);
                    // cout << "添加到项目集簇成功" << endl;
                    dfa.insert(pair<PII,int>(p, idx++));
                    // cout << "添加到DFA成功"<< endl;
                }
                else
                {
                    dfa.insert(pair<PII,int>(p, m));
                    // cout << "添加到DFA成功"<< endl;
                }
            }
        }
    }

}


//判断某一个项目集是否已经存在于项目集簇(项目集簇是全局变量)
int inISets(vector<item*> &itemSet)
{
    for(int i = 0 ; i < itemSets.size(); i ++)
    {
        if(itemSet.  size() != itemSets[i].size()) continue;
        //判断项目集和项目集簇中的第i个项目集是否相等
        int j;
        for(j = 0; j < itemSet.size(); j ++)
        {
            Production *p = itemSet[j]->p;
            int d = itemSet[j]->position;
            //判断两个项目是否相同
            int k;
            for(k = 0; k < itemSets[i].size(); k++)
            {
                bool flag = false;
                if(itemSets[i][k]->p == p && itemSets[i][k]->position == d && itemSet[j]->look_ahead.size() == itemSets[i][k]->look_ahead.size())
                {
                    int m;
                    for(m = 0; m < itemSet[j]->look_ahead.size(); m++)
                    {
                        auto it = find(itemSets[i][k]->look_ahead.begin(), itemSets[i][k]->look_ahead.end(), itemSet[j]->look_ahead[m]);
                        if(it == itemSets[i][k]->look_ahead.end())
                        {
                            break;
                        }
                    }
                    if(m == itemSet[j]->look_ahead.size())
                    {
                        flag = true;
                    }
                }
                if(flag) break;
            }
            if(k >= itemSets[i].size())
            {
                break;
            }
        }
        //说明找着了
        if(j >= itemSet.size())
        {
            return i;
        }
    }
    return -1;
}

//构造项目集的闭包
void create_closure(CFG *cfg, vector<Item *> &itemSet)
{
    for(int i = 0; i < itemSet.size(); i++)
    {
        int d = itemSet[i]->position;
        if(d >= itemSet[i]->p->right.size()) return;
        if(isVnSymbol(cfg, itemSet[i]->p->right[d]) != -1)
        {
            symbol vn = itemSet[i]->p->right[d];
            for(int j = 0; j < productionNum; j++)
            {
                if(!strcmp(vn, cfg->ProductionSet[j]->left))
                {
                    Item *I = new Item;
                    I->p = cfg->ProductionSet[j];
                    I->position = 0;
                    int m = inIset(I, itemSet);
                    //该项目在这个项目集中是否出现过
                    if(m != -1)
                    {
                        for(int k = 0; k < itemSet[i]->first.size(); k++)
                        {
                            symbol x = itemSet[i]->first[k];
                            for(int n = 0; n < itemSet[m]->look_ahead.size(); n ++)
                            {
                                if(strcmp(x, itemSet[m]->look_ahead[n]) != 0)
                                {
                                    itemSet[m]->look_ahead.push_back(x);
                                }
                            }
                        }
                        create_first(itemSet[m], cfg);
                    }
                    else
                    {
                        for(int k = 0; k < itemSet[i]->first.size(); k++)
                        {
                            I->look_ahead.push_back(itemSet[i]->first[k]);
                        }
                        create_first(I, cfg);
                        itemSet.push_back(I);
                    }
                }
            }
        }
    }
}

//判断某一个项目是否已经存在于项目集中
int inIset(Item *I, vector<Item *> &itemSet)
{
    for(int i = 0; i < itemSet.size(); i ++)
    {
        //同一个产生式并且dot的位置相同
        if(I->p == itemSet[i]->p && I->position == itemSet[i]->position) return i;
    }
    return -1;
}

//构造dot后面串的first集合
void create_first(Item *I, CFG *cfg)
{
    int d = I->position;
    if(d < I->p->right.size())
    {
        if(isVtSymbol(cfg, I->p->right[d]) != -1) return;
    }
    if(d + 1 >= I->p->right.size())
    {
        for(int i = 0; i < I->look_ahead.size(); i ++)
        {
            auto it = find(I->first.begin(), I->first.end(), I->look_ahead[i]);
            if(it == I->first.end())
            {
                I->first.push_back(I->look_ahead[i]);
            }
        }
    }
    else
    {
        symbol x = I->p->right[d+1];
        int k = isVtSymbol(cfg, x);
        if(k != -1)
        {
            auto it = find(I->first.begin(), I->first.end(), x);
            if(it == I->first.end())
            {
                I->first.push_back(x);
            }
        }
        else
        {
            int i;
            for(i = d + 1; i < I->p->right.size(); i++)
            {
                symbol y = I->p->right[i];
                int m = isVnSymbol(cfg, y);
                if(m != -1 && haveEpsilon(cfg, m))
                {
                    for(int j = 0; j < cfg->VNSet[m]->first.size(); j++)
                    {
                        auto it = find(I->first.begin(), I->first.end(), cfg->VNSet[m]->first[j]);
                        if(it == I->first.end())
                        {
                            if(strcmp(empty, cfg->VNSet[m]->first[j]))
                            {
                                I->first.push_back(cfg->VNSet[m]->first[j]);
                            }
                        }
                    }
                }
                if(m == -1)
                {
                    auto it = find(I->first.begin(), I->first.end(), y);
                    if(it == I->first.end())
                    {
                        I->first.push_back(y);
                    }
                    break;
                }
                if(!haveEpsilon(cfg, m))
                {
                    for(int n = 0; n < cfg->VNSet[m]->first.size(); n ++)
                    {
                        auto it = find(I->first.begin(), I->first.end(), cfg->VNSet[m]->first[n]);
                        if(it == I->first.end())
                        {
                            I->first.push_back(cfg->VNSet[m]->first[n]);
                        }
                    }
                    break;
                }
            }
            if( i == I->p->right.size())
            {
                for(int j = 0; j < I->look_ahead.size(); j++)
                {
                    auto it = find(I->first.begin(), I->first.end(), I->look_ahead[j]);
                    if(it == I->first.end())
                    {
                        I->first.push_back(I->look_ahead[j]);
                    }
                }
            }
        }
    }
}

//构造action表和goto表
void create_tables(DFA &dfa, ACTION &action, GOTO &go2)
{
    for(int i = 0; i < itemSets.size(); i ++)
    {
        //移入处理
        for(int j = 0; j < symbols.size(); j ++)
        {
            if(isVtSymbol(cfg, symbols[j]) != -1)
            {
                PII p1(i,symbols[j]);
                if(dfa.find(p1) != dfa.end())
                {
                    PII2 p2;
                    p2.first = (char *)"s";
                    p2.second = dfa[p1];
                    action.insert(pair<PII,PII2>(p1,p2));
                }
            }
            else
            {
                PII p1(i, symbols[j]);
                if(dfa.find(p1) != dfa.end())
                {
                    int status = dfa[p1];
                    go2.insert(pair<PII,int>(p1,status));
                }
            }
        }
        //接收和归约处理
        for(int j = 0; j < itemSets[i].size(); j ++)
        {
            if(!strcmp(itemSets[i][j]->p->left, cfg->S) && itemSets[i][j]->position == 1)
            {
                PII p1(i,ed);
                PII2 p2;
                p2.first = (char *)"acc";
                p2.second = 0;
                action.insert(pair<PII,PII2>(p1,p2));
            }
            if(itemSets[i][j]->position == itemSets[i][j]->p->right.size() && strcmp(itemSets[i][j]->p->left, cfg->S) != 0)
            {
                for(int k = 0; k < itemSets[i][j]->look_ahead.size(); k++)
                {
                    PII p1(i, itemSets[i][j]->look_ahead[k]);
                    PII2 p2;
                    p2.first = (char *)"r";
                    p2.second = itemSets[i][j]->p->idx;
                    action.insert(pair<PII,PII2>(p1,p2));
                }
            }
        }
    }
}

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小毛驴lv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值