编译原理 SLR文法(算法原理和C++实现)

编译原理 SLR文法(算法原理和C++实现)

设计目标

给定一个上下文无关文法,编程完成以下功能:

  1. 计算非终结符的FOLLOW集✔️
  2. LR(0)项目集规范族✔️
  3. 构造SLR分析表✔️
  4. 判断该文法是否为SLR文法✔️
  5. 输入字符串,按照SLR文法分析法判断该字符串的语法是否正确,并给出确定过程✔️

测试结果截图

测试样例一

// 输入样例一
E::=E + T
E::=T
T::=T * F
T::=F
F::=( E )
F::=id

首先,输入文法。
在这里插入图片描述

增广文法:如果G 是一个以S为开始符号的文法,则G的增广文法 G’ 就是在G中加上新开始符号S’ 和产生式S’ → S而得到的文法

增广文法,编号并输出产生式集合。
在这里插入图片描述

LR(0)项目:右部某位置标有圆点的产生式称为相应文法的一个LR(0)项目(简称为项目)
如图:在这里插入图片描述
Tips:产生式A→ε 只生成一个项目A→ ·

输出LR(0)项目表。
在这里插入图片描述
打印FIRST集合、FOLLOW集合计算结果。
在这里插入图片描述
输出项目集规范族。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DFA状态转换关系
在这里插入图片描述
打印SLR(1)分析表
在这里插入图片描述

SLR文法判断结果
在这里插入图片描述

输入字串进行SLR文法分析。
在这里插入图片描述

测试样例二

// 输入样例二
S::=A S
S::=b
A::=S A
A::=a

输入文法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

变量声明与定义

头文件引用

#include "iostream"
#include "string"
#include "vector"
#include "set"
#include "algorithm"
#include "iomanip"
#include "stack"
using namespace std;

宏定义

#define MOVEIN 1        // 移进项目
#define REDUCE 2        // 归约项目
#define TOBEREDUCE 3    // 待约项目
#define ACCEPTION 4     // 接受项目
#define MRCONFLICT 0    // 移进-归约冲突
#define RRCONFLICT 1    // 归约归约冲突
#define NONECONFLICT 2  // 无冲突

类定义

// 一个产生式
class Pro
{
    public:
        string left;          // 产生式左部
        vector<string> right; // 产生式右部
        int index;            // 产生式编号
        Pro(const string &str);
        void push(const string &str);
        void print();
        bool operator==(const Pro &p);
        void printWithPoint(int i);
};

// 一个非终结符的FIRST & FOLLOW集合
class f_vn
{
    public:
        string vn;               // 非终结符
        set<string> vfirst;      // FIRST集合
        set<string> vfollow;     // FOLLOW集合
        f_vn(const string &str); // 构造函数
        void insert1(string t);  // FIRST集合插入
        void insert2(string t);  // FOLLOW集合插入
        void print();            // 输出FIRST、FOLLOW集合
};

// 一个项目
class Project
{
    public:
        int pro_index;   // 产生式的标号
        int point_index; // 产生式右部 ·的位置
        int project_num; // 项目编号
        int p_type;      // 项目类型
        string leftstr;     // 产生式左部非终结符
        string pointright;      // ·右边的第一个符号
        Project(int pro_index, int point_index, int project_num);
        Project(int pro_index, int point_index, int project_num, int p_type);
        void print();// 打印当前项目
};

// 一个项目闭包Ik
class Closure
{
    public:
        vector<int> project_nums;   // 项目编号集合
        int closureIk;              // 状态Ik的编号k (k=0,1,2,...)
        Closure(int i);
        void print();
        bool operator==(const Closure &a);
};

// Action[vt, k] = val
class ActionVT
{
public:
    string vt;  // 终结符
    int stateK; // 状态k
    string val; // <vt, stateK> 处的值
    ActionVT(const string & vt, int k);
};

// Goto[vnt, k] = k2
class GotoVNT
{
public:
    string vnt;  // 非终结符
    int stateK; // 状态k
    int toK2;   // <vnt, stateK> 处的值
    GotoVNT(const string & vnt, int k);
    GotoVNT(const string & vnt, int k, int k2);
};

全局变量定义与声明

/***
 * 全局变量定义
 * 对象定义与方法声明
 ***/
set<string> VN;            // 非终结符集合
set<string> VT;            // 终结符集合
string istr;               // 输入的待分析的字串
string G_start;            // 文法开始符
vector<Pro> productions;   // 产生式集合
vector<f_vn> fcollections; // 非终结符的FIRST集合和FOLLOW集合
vector<Project> projects;  // 项目集
vector<Closure> normfamily;      // 项目规范族
vector<GotoVNT> gotoTables;      // Goto表
vector<ActionVT> actionTables;   // Action表
stack<string> GAnalasis;         // 语法分析栈
stack<int> stack_Ik;             // 状态栈

功能函数定义

// 函数声明
void inputG();           // 文法输入处理函数
void broadenG();         // 增广文法
int getProI(int i);      // 找到产生式编号为i的对应数组下标
void printProductions(); // 测试,打印存储的产生式集合
void printVNT();         // 测试,打印所有的非终结符,终结符
void calVN();            // 记录所有非终结符
void calVT();            // 记录所有终结符
bool isVN(string str);   // 是否为非终结符
void calProjectSet();    // 记录项目集
void printProjectSet();  // 打印项目集
int getProjectArrayIndex(int project_i);   // 找到编号为i的项目 返回所在项目集数组的下标
void initFcollections();        // 初始化FIRST FOLLOW集合(将所有非终结符加入进去)
void calFIRST();                // 计算FIRST集合
void calFOLLOW();               // 计算FOLLOW集合
void printFirstFollow();        // 打印FIRST FOLLOW集合
int getSuccessorProject(int project_i);  // 找到编号为i的项目的后继项目 返回所在项目集数组的下标 返回-1表示没有后继项目
void calProjectsNormFamily();    // 求LR(0)项目集规范族
void printProjectsNormFamily();  // 输出LR(0)项目集规范族
int judgeConflict(int k);         // 判断项目集Ik是否存在冲突
void printConflict();            // 打印LR(0)项目集规范族存在的冲突
void printGotoTable();           // 打印Goto表
void calActionTable();           // 求Action表
void printLine(int num);         // 打印num个——
void printSLRtable();            // 打印SLR分析表
bool isSLR();                    // 判断是否为SLR文法
void inputIstr();                // 输入待分析的字符串
string getStackStr(int choose);  // 获得栈中的所有内容
void AnalysisSLR();              // SLR文法分析输入的字符串
void WholeBeautifulProcess();    // 梳理一下函数调用,美化终端输入

↓↓↓主要功能点介绍↓↓↓

FOLLOW集合计算

直接参照实验三

在这里插入图片描述

求LR(0)项目集规范族

后继项目在这里插入图片描述

把拓广文法的第一个项目{S’->*S}作为初态集的核,通过求核的闭包和转换函数,求出LR(0)项目集规范族,在由转换函数建立状态之间的连接关系。
确定完I0后,以I0为起点,确定DFA转换关系,Ik --->(a) Ik+1,a指Ik的项目集中所有可以接受的符号,对于新建立的状态Ik+1,要与已建立的I0~Ik状态比对查重,确定是否是新的项目集。
下面是这部分代码实现,实际求闭包的过程也是比较混乱,没写明白。

void calProjectsNormFamily()
{
    // 求closure-I0
    Closure ce(0);
    set<string> cur_left;    // 记录 E' -> . E 中的E'
    set<string> rights;
    cur_left.insert(projects[0].leftstr);
    rights.insert(projects[0].pointright);
    bool is_change_ce=true;
    // E'->.E先加入 项目集规范族
    ce.project_nums.push_back(projects[0].project_num);
    while(is_change_ce)
    {
        is_change_ce = false;
        vector<string> tmp_right;
        for(auto r: rights)
        {
            // 左部项目集还未出现过,加入
            if(cur_left.count(r) < 1)
            {
                // cout<<r<<" 在左部项目集还未出现过"<<endl;
                for(int i=0; i<projects.size(); i++)
                {
                    if((projects[i].leftstr == r)&&(projects[i].point_index == 0))
                    {
                        // cout<<"添加项目 :"<<projects[i].project_num<<endl;
                        ce.project_nums.push_back(projects[i].project_num);
                        is_change_ce = true;
                        if((rights.count(projects[i].pointright)<1)&&(cur_left.count(projects[i].pointright) < 1)&&(isVN(projects[i].pointright)))
                        {
                            tmp_right.push_back(projects[i].pointright);
                        }
                    }
                }
                cur_left.insert(r);
                break;
            }
        }
        //更新右部
        for(int j=0;j<tmp_right.size();j++)
        {
            // cout<<"新增右部非终结符 :"<<tmp_right[j]<<endl;
            rights.insert(tmp_right[j]);
        }
        tmp_right.clear();

    }
    normfamily.push_back(ce);
    // cout<<"I0求解完毕"<<endl;
    // 求I1, I2, ...
    int cur_I=0;            // 当前分析到的 I0
    bool is_add_closure=true;
    // 每轮大循环分析当前I[cur_I],对每个move分析 直到没有新增项目集,退出循环
    while(is_add_closure)
    {
        is_add_closure = false;
        // cout<<"打印当前分析的I[cur_I] = I"<<cur_I<<endl;
        // normfamily[cur_I].print();
        vector<string> moveSets;   // E'->.E  E->.T  T->() 记录E,T,(,...
        moveSets.clear();
        // 求moveSets
        for(int i=0; i<normfamily[cur_I].project_nums.size(); i++)
        {
            int tmp = getProjectArrayIndex(normfamily[cur_I].project_nums[i]);
            if(projects[tmp].p_type == REDUCE || projects[tmp].p_type == ACCEPTION)
            {
                continue;
            }
            // 避免重复插入
            for(int j=0;j<moveSets.size();j++)
            {
                if(moveSets[j] == projects[tmp].pointright)
                {
                    tmp = -1;
                    break;
                }
            }
            if(tmp >= 0)
            {
                moveSets.push_back(projects[tmp].pointright);
            } 
        }
        //打印moveSets
        // cout<<"当前moveSets: ";
        // for(int m=0; m<moveSets.size(); m++)
        // {
        //     cout<<moveSets[m]<<" ";
        // }
        // cout<<endl;
        //遍历moves
        for(int moveme=0; moveme<moveSets.size(); moveme++)
        {
            //计算move后的一个新状态Ik
            int kkk = normfamily.size();
            Closure ck(kkk);
            for(int h=0; h<normfamily[cur_I].project_nums.size(); h++)
            {
                int tmp1 = getProjectArrayIndex(normfamily[cur_I].project_nums[h]);
                // cout<<"projects["<<tmp1<<"].pointright: "<<projects[tmp1].pointright<<endl;
                // cout<<"moveSets["<<moveme<<"]: "<<moveSets[moveme]<<endl;
                if(projects[tmp1].pointright == moveSets[moveme])
                {
                    // cout<<"寻找项目编号"<<projects[tmp1].project_num<<"的后继项目。。。"<<endl;
                    // 找到匹配的项目的后继项目
                    int backPnum = getSuccessorProject(projects[tmp1].project_num);
                    if(backPnum == -1)
                    {
                        cout<<"后继项目匹配失败!"<<endl;
                    }
                    else
                    {
                        ck.project_nums.push_back(backPnum);
                    }
                    
                }
            }
            // cout<<"move后的新状态I"<<kkk<<endl;
            // ck.print();
            bool is_add_project = true;
            // 每轮循环直到CLOSURE(I)不再增大为止
            int cur_pp = 0;
            // 避免循环添加新项目,这个set集合作用就是记录左部已经出现的形式如S->.E中的S
            set<string> left_vns;
            for(int i=0;i<ck.project_nums.size(); i++)
            {
                int iindex=getProjectArrayIndex(ck.project_nums[i]);
                if(projects[iindex].point_index == 0)
                {
                    left_vns.insert(projects[iindex].leftstr);
                }
            }
            
            while(is_add_project)
            {
                is_add_project = false;
                // 扫描右部形如 A->.Bc 记录B
                set<string> rightB;
                int cur_size = ck.project_nums.size();
                // cout<<"start_p : "<<start_p<<endl;
                for(int luffy=cur_pp; luffy < ck.project_nums.size(); luffy++)
                {
                    int tmp1 = getProjectArrayIndex(ck.project_nums[luffy]);
                    // if((leftA.count(projects[tmp1].pointright) < 1) && (isVN(projects[tmp1].pointright)))
                    // if((projects[tmp1].leftstr != projects[tmp1].pointright) && (isVN(projects[tmp1].pointright)))
                    if(isVN(projects[tmp1].pointright))
                    {
                        // A->.Abc的情况可以直接排除,不用再添加A的项目
                        if((projects[tmp1].leftstr == projects[tmp1].pointright) && (projects[tmp1].point_index == 0))
                        {
                            continue;
                        }
                        // 避免 S->.A S->a A->.S  又添加S的项目,循环往复,此时通过set集合判断已经有过S即可避免此情况
                        if(left_vns.count(projects[tmp1].pointright) > 0)
                        {
                            continue;
                        }
                        // 否则更新set集合
                        else
                        {
                            left_vns.insert(projects[tmp1].pointright);
                        }
                        
                        //添加右部中出现的非终结符
                        rightB.insert(projects[tmp1].pointright);
                    }
                }
                // cout<<"rightB: ";
                // for(auto r:rightB)
                // {
                //     cout<<r<<"  ";
                // }
                // cout<<endl;
                for(auto r:rightB)
                {
                    // 找到每个B->.abc 加入项目集
                    for(int g=0;g<projects.size();g++)
                    {
                        if((r == projects[g].leftstr) && (projects[g].point_index==0))
                        {
                            ck.project_nums.push_back(projects[g].project_num);
                            is_add_project = true;
                        }
                    }
                }
                cur_pp = cur_size;
                rightB.clear();
            }
            
            //判断新状态是否与已创建过的状态有重合
            bool flag_tmp=false;
            for(int h=0; h<normfamily.size(); h++)
            {
                if(ck == normfamily[h])
                {
                    //Ik 与 Ih相等
                    flag_tmp=true;
                    // 更新Goto表
                    // I[cur_I] --->(VN) I[h]
                    GotoVNT go1(moveSets[moveme], cur_I, normfamily[h].closureIk);
                    gotoTables.push_back(go1);
                    // if(isVN(moveSets[moveme]))
                    // {
                    //     // 更新Goto表
                    //     // I[cur_I] --->(VN) I[h]
                    //     GotoVNT go1(moveSets[moveme], cur_I, normfamily[h].closureIk);
                    //     gotoTables.push_back(go1);
                    // }
                    break;
                }
            }        
            if(!flag_tmp)
            {
                //添加新状态
                normfamily.push_back(ck);
                // 更新Goto表
                // I[cur_I] --->(VN) I[k]
                GotoVNT go1(moveSets[moveme], cur_I, ck.closureIk);
                gotoTables.push_back(go1);
                // if(isVN(moveSets[moveme]))
                // {
                //     // I[cur_I] --->(VN) I[k]
                //     GotoVNT go1(moveSets[moveme], cur_I, ck.closureIk);
                //     gotoTables.push_back(go1);
                // }
                
                // cout<<"新加状态: Ik"<<endl;
                // ck.print();
                is_add_closure=true;
            }
        }
        cur_I ++;
        if(cur_I >= normfamily.size())
        {
            break;
        }
        else{
            is_add_closure = true;
        }
    }
    
    // cout<<"项目族求解完毕!"<<endl;
}

构造SLR分析表

首先搞明白LR(0)分析表的构建。
在这里插入图片描述
参考博客

注:GOTO表在求项目集规范族中已实现。


void calActionTable()
{
    for(int i=0; i<normfamily.size(); i++)
    {
        //遍历项目Ik的项目
        for(int j=0; j<normfamily[i].project_nums.size(); j++)
        {
            int project_j = getProjectArrayIndex(normfamily[i].project_nums[j]);
            // A->B.aC, 且Go(Ik, a) = Ij, a ∈ VT 则Action[k, a] = Sj
            if((projects[project_j].p_type == MOVEIN) && (!isVN(projects[project_j].pointright)))
            {
                int go_j=0;
                for(;go_j < gotoTables.size(); go_j++)
                {
                    if((gotoTables[go_j].vnt == projects[project_j].pointright) && 
                    (gotoTables[go_j].stateK == normfamily[i].closureIk))
                    {
                        break;
                    }
                }
                string tmps = "S" + to_string(gotoTables[go_j].toK2);
                ActionVT avt(projects[project_j].pointright, normfamily[i].closureIk);
                avt.val = tmps;
                actionTables.push_back(avt);
            }
            // S'->S. 接受项目,属于Ik, Action[k, $] = acc
            else if(projects[project_j].p_type == ACCEPTION)
            {
                ActionVT avt("$", normfamily[i].closureIk);
                avt.val = "acc";
                actionTables.push_back(avt);
            }
            // A->a. 归约项目,for all a ∈ FOLLOW(A) do Action[k, a] = rj (j是产生式A->a的编号)
            else if(projects[project_j].p_type == REDUCE)
            {
                int follow_vn_index=0;
                int num_proA = projects[project_j].pro_index;
                for(;follow_vn_index<fcollections.size(); follow_vn_index++)
                {
                    if(fcollections[follow_vn_index].vn == projects[project_j].leftstr)
                    {
                        break;
                    }
                }
                for(auto f: fcollections[follow_vn_index].vfollow)
                {
                    ActionVT avt(f, normfamily[i].closureIk);
                    avt.val = "r" + to_string(num_proA);
                    actionTables.push_back(avt);
                }
            }
        }
    }
    return;
}


void printSLRtable()
{
    cout<<"     ᕙ▐° ◯ °▐ᕗ 构建的SLR分析表如下 ᕙ▐° ◯ °▐ᕗ     "<<endl;
    //表头状态编号9个宽度(+2个竖线) + (终结符个数) * 10个宽度(加一个竖线) + (非终结符-开始符)个数 * 8个宽度(加一个竖线)
    printLine(11, 1, false);
    printLine(11, VT.size(), false);
    printLine(9 , VN.size() - 1, false);
    cout<<endl;

    cout<<"|";
    cout<<setw(11)<<left<<" 状态";
    cout<<"|";
    // action居中ᕙ▐° ◯ °▐ᕗ显示
    string tmp111="";
    for(int jj=0; jj<5 * VT.size(); jj++)
    {
        tmp111+=" ";
    }
    tmp111 += "ACTION";
    cout<<setw(11 * VT.size() - 1)<<left<<tmp111;
    cout<<"|";
    // goto居中ᕙ▐° ◯ °▐ᕗ显示
    tmp111 = "";
    for(int jj=0; jj<4 * (VN.size()-1); jj++)
    {
        tmp111+=" ";
    }
    tmp111+="GOTO";
    cout<<setw(9 *(VN.size()-1) - 1)<<left<<tmp111;
    cout<<"|"<<endl;

    cout<<"|   💻    |";
    printLine(10, VT.size(), true);
    printLine(8 , VN.size() - 1, true);
    cout<<endl;

    cout<<"|         |";
    for(auto tt : VT)
    {
        string tmp = "  " + tt;
        cout<<setw(10)<<left<<tmp;
        cout<<"|";
    }
    for(auto nn: VN)
    {
        if(nn != G_start)
        {
            string tmp = "  " + nn;
            cout<<setw(8)<<left<<tmp;
            cout<<"|";
        }
    }
    cout<<endl;

    printLine(9+1,1,true);
    printLine(10, VT.size(), true);
    printLine(8 , VN.size() - 1, true);
    cout<<endl;
    for(int i=0; i<normfamily.size(); i++)
    {
        cout<<"|";
        string tmp = " I" + to_string(normfamily[i].closureIk);
        cout<<setw(9)<<left<<tmp;
        cout<<"|";
        
        // Action 输出
        for(auto tt: VT)
        {
            int jjj=0;
            for(; jjj<actionTables.size(); jjj++)
            {
                if(actionTables[jjj].vt == tt && actionTables[jjj].stateK == normfamily[i].closureIk)
                {
                    string tmp = " " + actionTables[jjj].val;
                    cout<<setw(10)<<left<<tmp;
                    cout<<"|";
                    break;
                }
            }
            if(jjj >= actionTables.size())
            {
                cout<<setw(10)<<left<<"   ";
                cout<<"|";
            }
            
        }
        
        // Goto 输出
        for(auto nn: VN)
        {
            if(nn != G_start)
            {
                int j=0;
                for(; j<gotoTables.size(); j++)
                {
                    if(gotoTables[j].vnt == nn && gotoTables[j].stateK == normfamily[i].closureIk)
                    {
                        string tmp = " I" + to_string(gotoTables[j].toK2);
                        cout<<setw(8)<<left<<tmp;
                        cout<<"|";
                        break;
                    }
                }
                if(j>=gotoTables.size())
                {
                    cout<<setw(8)<<left<<"   ";
                    cout<<"|";
                }
            }
        }
        cout<<endl;

        printLine(9+1,1,true);
        printLine(10, VT.size(), true);
        printLine(8 , VN.size() - 1, true);
        cout<<endl;
    }

}


是否为SLR文法

在这里插入图片描述


bool isSLR()
{
    printConflict();
    cout<<"分析中ing~~~"<<endl;
    bool judge_res = true;
    // 遍历项目集规范族
    for(int i=0; i<normfamily.size(); i++)
    {
        int res = judgeConflict(normfamily[i].closureIk);
        if(res == MRCONFLICT)
        {
            cout<<"对于 I"<<normfamily[i].closureIk<<" 中的 移进——归约冲突"<<endl;
            // 定位冲突双方 A->B.cD  B->E.
            // 判断{c} ∩ FOLLOW(B) = ∅ ?
            vector<string> tmp_move;    //存放移进项目中的c
            vector<string> vn_reduce;   //存放归约项目中的B
            for(int j=0; j<normfamily[i].project_nums.size(); j++)
            {
                int tmp_index = getProjectArrayIndex(normfamily[i].project_nums[j]);
                if(projects[tmp_index].p_type == MOVEIN)
                {
                    tmp_move.push_back(projects[tmp_index].pointright);
                }
                else if(projects[tmp_index].p_type == REDUCE)
                {
                    vn_reduce.push_back(projects[tmp_index].leftstr);
                    // 调试用
                    // cout<<"I"<<normfamily[i].closureIk<<" 归约项 B: "<< projects[tmp_index].leftstr<<endl;
                }
            }

            // 逐个获取FOLLOW(B)
            for(int kk=0; kk<vn_reduce.size(); kk++)
            {
                int followb_index = 0;
                for(;followb_index < fcollections.size(); followb_index ++)
                {
                    if(vn_reduce[kk] == fcollections[followb_index].vn)
                    {
                        break;
                    }
                }
                // 遍历移进项目终结符
                for(auto tm: tmp_move)
                {
                    //遍历 FOLLOW(B)
                    for(auto fb: fcollections[followb_index].vfollow)
                    {
                        if(tm == fb)
                        {
                            // 交集非空
                            cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ {"<<tm<<"} != ∅"<<endl;
                            judge_res = false;
                            break;
                        }
                    }
                    if(judge_res == false)
                    {
                        break;
                    }
                    else
                    {
                        cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ {"<<tm<<"} = ∅"<<endl;
                    }
                }
                if(judge_res == false)
                {
                    break;
                }
            }
            if(judge_res == false)
            {
                cout<<" 🤖 🤖 🤖 经过竭尽全力的抢救,👩🏻‍⚕️ 🧑‍⚕️ 👩🏼‍⚕️我们很遗憾的通知您,文法中存在的 🥷🏽 移进——归约 🥷🏽 冲突无法消除, 该文法不是SLR文法。😦 😦 😦"<<endl;
                break;
            }
        }
        else if(res == RRCONFLICT)
        {
            cout<<"对于 I"<<normfamily[i].closureIk<<" 中的 归约——归约冲突"<<endl;
            // 定位冲突双方 B->E.  C->T.
            // 判断FOLLOW(B) ∩ FOLLOW(C) = ∅ ?
            vector<string> vn_reduce;   //存放归约项目中的B,C,...
            for(int j=0; j<normfamily[i].project_nums.size(); j++)
            {
                int tmp_index = getProjectArrayIndex(normfamily[i].project_nums[j]);
                if(projects[tmp_index].p_type == REDUCE)
                {
                    vn_reduce.push_back(projects[tmp_index].leftstr);
                    // 调试用
                    // cout<<"I"<<normfamily[i].closureIk<<" 归约项 B: "<< projects[tmp_index].leftstr<<endl;
                }
            }

            // 逐个获取FOLLOW(B)
            for(int kk=0; kk<vn_reduce.size(); kk++)
            {
                int followb_index = 0;
                for(;followb_index < fcollections.size(); followb_index ++)
                {
                    if(vn_reduce[kk] == fcollections[followb_index].vn)
                    {
                        break;
                    }
                }
                // 逐个获取FOLLOW(C)
                int ll;
                for(ll=kk+1; ll<vn_reduce.size(); ll++)
                {
                    int followc_index = 0;
                    for(;followc_index < fcollections.size(); followc_index ++)
                    {
                        if(vn_reduce[ll] == fcollections[followc_index].vn)
                        {
                            break;
                        }
                    }
                    //判断FOLLOW(B) 和 FOLLOW(C)交集是否为空
                    for(auto fb: fcollections[followb_index].vfollow)
                    {
                        for(auto fc: fcollections[followc_index].vfollow)
                        {
                            if(fb == fc)
                            {
                                // 交集非空
                                cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ FOLLOW["<<vn_reduce[ll]<<"] = {"<<fb<<"} 非空!!!"<<endl;
                                judge_res = false;
                                break;
                            }
                        }
                        if(judge_res == false)
                        {
                            break;
                        }
                    }
                    if(judge_res == false)
                    {
                        break;
                    }
                }
                if(judge_res == false)
                {
                    break;
                }
                else
                {
                    cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ FOLLOW["<<vn_reduce[ll]<<"] = ∅"<<endl;
                }
            }
            if(judge_res == false)
            {
                cout<<" 🤖 🤖 🤖 经过竭尽全力的抢救,👩🏻‍⚕️ 🧑‍⚕️ 👩🏼‍⚕️我们很遗憾的通知您,文法中存在的 🥷🏽 归约——归约 🥷🏽 冲突无法消除, 该文法不是SLR文法。😦 😦 😦"<<endl;
                break;
            }
        }
    }
    if(judge_res)
    {
        cout<<" 👨🏻‍💻 🧑🏻‍💻 📺 📱 📑 🔧 🛠️ 🐣经过我缜密的逻辑推理分析,🐼下面我宣布,该文法是SLR文法。 真的!!! 🤩 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 "<<endl;
    }
    return judge_res;
}

SLR文法分析输入字串

维护两个栈:状态栈和符号栈
在这里插入图片描述
查ACTION表,对于s4这种移进操作,把剩余字串栈顶元素压入符号栈,状态栈压入I4状态。
对于r3这种归约操作,找到3号产生式T->T * F,右部三个符号,则符号栈出栈3个元素,压入左部非终结符;状态栈出栈3个元素,然后对于当前栈顶状态I4,查表Goto[I4, T(产生式左部非终结符)] = Ik, 状态Ik入栈。

void inputIstr(){
    cout<<"请输入待分析的字串($代表结束符): ";
    cin>>istr;
    if(istr[istr.size()-1] != '$')
    {
        istr.push_back('$');
    }
    cout<<"开始进行SLR文法分析……"<<endl;
}

string getStackStr(int choose){
    vector<string> ss1;
    string res="◀||";
    if(choose == 1)
    {
        stack<string> s1;
        s1 = GAnalasis;

        while(!s1.empty()){
            ss1.push_back(s1.top());
            s1.pop();
        }
        for(int i=ss1.size()-1; i>=0; i--){
            res += ss1[i];
            res += " ";
        }
    }
    else if(choose == 2)
    {
        stack<int> s1;
        s1 = stack_Ik;

        while(!s1.empty()){
            int tmp_num = s1.top();
            string tmp_str = "I" + to_string(tmp_num);
            ss1.push_back(tmp_str);
            s1.pop();
        }
        for(int i=ss1.size()-1; i>=0; i--){
            res += ss1[i];
            res += " ";
        }
    }
    
    return res;
}

void AnalysisSLR()
{
    inputIstr();
    //压入终止符号
    GAnalasis.push("$");
    //初始状态0压入栈
    stack_Ik.push(0);
    int i=0, steps=0;
    cout<<"输入串 '"<<istr<<"' 的分析过程如下:"<<endl;
    for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
    cout<<endl;
    cout<<setw(16)<<left<<"过程计数";
    cout<<setw(36)<<left<<"状态栈";
    cout<<setw(36)<<left<<"语法分析栈";
    cout<<setw(30)<<left<<"剩余未匹配的字串";

    cout<<setw(20)<<left<<"操作";
    cout<<setw(15)<<left<<"ACTION";
    cout<<setw(15)<<left<<"GOTO"<<endl;
    for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
    cout<<endl;

    while(i<istr.length())
    {
        steps++;
        cout<<setw(16)<<left<<steps;
        string tmp = getStackStr(2);
        // cout<<"状态栈:"<<tmp<<endl;
        cout<<setw(36)<<left<<tmp;
        tmp = getStackStr(1);
        // cout<<"语法分析栈:"<<tmp<<endl;
        cout<<setw(36)<<left<<tmp;
        string tmp2="";
        for(int j=i;j<istr.length();j++){
            tmp2+=istr[j];
        }
        cout<<setw(15)<<left<<tmp2;
        char cur_c = istr[i];   //当前指示字符
        //取栈顶元素
        if(GAnalasis.empty()){
            cout<<"栈为空!!!"<<endl;
            return;
        }
        //判断是否为id类型
        int new_i=-1;
        string str_id = "";
        if((VT.count("id")>0)&&(cur_c >= 'a' && cur_c <= 'z'))
        {
            str_id += cur_c;
            new_i = i+1;
            while(true)
            {
                if((istr[new_i] >= 'a' && istr[new_i] <= 'z')||(istr[new_i] >= '0' && istr[new_i] <= '9'))
                {
                    str_id += istr[new_i];
                }
                else{
                    break;
                }
                new_i ++;
            }
        }
        string str_vt="";
        if(new_i > -1)
        {
            // id类型
            str_vt = str_id;
            // i = new_i;            
        }
        else
        {
            // 其他终结符类型
           str_vt += cur_c;
            //    i++;
        }
        
        //查表 Action[状态栈顶Ik, str_vt]
        int topIk = stack_Ik.top();
        int ac=0;
        for(; ac<actionTables.size(); ac++)
        {
            if(topIk == actionTables[ac].stateK)
            {
                if((new_i > 0) && (actionTables[ac].vt == "id"))
                {
                    break;
                }
                if(actionTables[ac].vt == str_vt)
                {
                    break;
                }
            }
        }
        if(ac >= actionTables.size())
        {
            cout<<endl;
            cout<<"✖️ ✖️ ✖️ ERROR ✖️ ✖️ ✖️"<<endl;
            for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
            cout<<endl;
            return;
        }
        if(actionTables[ac].val == "error")
        {
            cout<<endl;
            cout<<"✖️ ✖️ ✖️ ERROR ✖️ ✖️ ✖️"<<endl;
            for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
            cout<<endl;
            return;
        }
        else
        {
            if(actionTables[ac].val[0] == 'S')
            {
                //移进 操作
                if(new_i > -1)
                {
                    i = new_i;
                }
                else
                {
                    i++;
                }
                cout<<setw(20)<<left<<"移进";
                cout<<setw(15)<<left<<actionTables[ac].val;
                cout<<setw(15)<<left<<"        "<<endl;
                int snum = stoi(actionTables[ac].val.substr(1));
                // 状态栈压栈
                stack_Ik.push(snum);
                // 语法分析栈压入str_vt
                GAnalasis.push(str_vt);

            }
            else if(actionTables[ac].val[0] == 'r')
            {
                //归约
                int rnum = stoi(actionTables[ac].val.substr(1));
                // 找到产生式编号为rnum
                int pro_index = getProI(rnum);
                string pro_str = "归约:";
                pro_str += productions[pro_index].left;
                pro_str += "->";
                for(int ps=0; ps<productions[pro_index].right.size(); ps++)
                {
                    pro_str += productions[pro_index].right[ps];
                    pro_str += " ";
                }
                cout<<setw(20)<<left<<pro_str;
                cout<<setw(15)<<left<<actionTables[ac].val;
                
                // 更新语法分析栈
                // cout<<"归约使用产生式:";
                // productions[pro_index].print();
                // 出栈 数量等同 产生式右部 符号个数
                for(int pnum=0; pnum<productions[pro_index].right.size(); pnum++)
                {
                    GAnalasis.pop();
                    stack_Ik.pop();
                }
                int top_back_num = stack_Ik.top();
                // 产生式左部入栈
                GAnalasis.push(productions[pro_index].left);
                // 找Goto[top_back_num, productions[pro_index].left]
                int goto_index=0;
                for(;goto_index<gotoTables.size();goto_index++)
                {
                    if((gotoTables[goto_index].vnt == productions[pro_index].left) 
                    && (gotoTables[goto_index].stateK == top_back_num))
                    {
                        // 新状态压入栈
                        // cout<<"新状态"<<gotoTables[goto_index].toK2<<"入栈"<<endl;
                        stack_Ik.push(gotoTables[goto_index].toK2);
                        string tmpgo = "I" + to_string(gotoTables[goto_index].toK2);
                        cout<<setw(15)<<left<<tmpgo<<endl;
                        break;
                    }
                }
            }
            else if(actionTables[ac].val == "acc")
            {
                //接受,完美结束
                cout<<setw(20)<<left<<"接受!😍!";
                cout<<setw(15)<<left<<"    ";
                cout<<setw(15)<<left<<"    "<<endl;
                for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
                cout<<endl;
                return;
            }
        }
        
        // cout<<"step:"<<steps<<" done!"<<endl;
        // cout<<"cur_i:"<<i<<endl;
    }
}

完整源代码

#include "iostream"
#include "string"
#include "vector"
#include "set"
#include "algorithm"
#include "map"
#include "iomanip"
#include "stack"
using namespace std;

#define MOVEIN 1        // 移进项目
#define REDUCE 2        // 归约项目
#define TOBEREDUCE 3    // 待约项目
#define ACCEPTION 4     // 接受项目
#define MRCONFLICT 0    // 移进-归约冲突
#define RRCONFLICT 1    // 归约归约冲突
#define NONECONFLICT 2  // 无冲突
// 一个产生式
class Pro
{
    public:
        string left;          // 产生式左部
        vector<string> right; // 产生式右部
        int index;            // 产生式编号
        Pro(const string &str);
        void push(const string &str);
        void print();
        bool operator==(const Pro &p);
        void printWithPoint(int i);
};

// 一个非终结符的FIRST & FOLLOW集合
class f_vn
{
    public:
        string vn;               // 非终结符
        set<string> vfirst;      // FIRST集合
        set<string> vfollow;     // FOLLOW集合
        f_vn(const string &str); // 构造函数
        void insert1(string t);  // FIRST集合插入
        void insert2(string t);  // FOLLOW集合插入
        void print();            // 输出FIRST、FOLLOW集合
};

// 一个项目
class Project
{
    public:
        int pro_index;   // 产生式的标号
        int point_index; // 产生式右部 ·的位置
        int project_num; // 项目编号
        int p_type;      // 项目类型
        string leftstr;     // 产生式左部非终结符
        string pointright;      // ·右边的第一个符号
        Project(int pro_index, int point_index, int project_num);
        Project(int pro_index, int point_index, int project_num, int p_type);
        void print();// 打印当前项目
};

// 一个项目闭包Ik
class Closure
{
    public:
        vector<int> project_nums;   // 项目编号集合
        int closureIk;              // 状态Ik的编号k (k=0,1,2,...)
        Closure(int i);
        void print();
        bool operator==(const Closure &a);
};

// Action[vt, k] = val
class ActionVT
{
public:
    string vt;  // 终结符
    int stateK; // 状态k
    string val; // <vt, stateK> 处的值
    ActionVT(const string & vt, int k);
};

// Goto[vnt, k] = k2
class GotoVNT
{
public:
    string vnt;  // 非终结符
    int stateK; // 状态k
    int toK2;   // <vnt, stateK> 处的值
    GotoVNT(const string & vnt, int k);
    GotoVNT(const string & vnt, int k, int k2);
};

/***
 * 全局变量定义
 * 对象定义与方法声明
 ***/
set<string> VN;            // 非终结符集合
set<string> VT;            // 终结符集合
string istr;               // 输入的待分析的字串
string G_start;            // 文法开始符
vector<Pro> productions;   // 产生式集合
vector<f_vn> fcollections; // 非终结符的FIRST集合和FOLLOW集合
vector<Project> projects;  // 项目集
vector<Closure> normfamily;      // 项目规范族
vector<GotoVNT> gotoTables;      // Goto表
vector<ActionVT> actionTables;   // Action表
stack<string> GAnalasis;         // 语法分析栈
stack<int> stack_Ik;             // 状态栈

// 函数声明
void inputG();           // 文法输入处理函数
void broadenG();         // 增广文法
int getProI(int i);      // 找到产生式编号为i的对应数组下标
void printProductions(); // 测试,打印存储的产生式集合
void printVNT();         // 测试,打印所有的非终结符,终结符
void calVN();            // 记录所有非终结符
void calVT();            // 记录所有终结符
bool isVN(string str);   // 是否为非终结符
void calProjectSet();    // 记录项目集
void printProjectSet();  // 打印项目集
int getProjectArrayIndex(int project_i);   // 找到编号为i的项目 返回所在项目集数组的下标
void initFcollections();        // 初始化FIRST FOLLOW集合(将所有非终结符加入进去)
void calFIRST();                // 计算FIRST集合
void calFOLLOW();               // 计算FOLLOW集合
void printFirstFollow();        // 打印FIRST FOLLOW集合
int getSuccessorProject(int project_i);  // 找到编号为i的项目的后继项目 返回所在项目集数组的下标 返回-1表示没有后继项目
void calProjectsNormFamily();    // 求LR(0)项目集规范族
void printProjectsNormFamily();  // 输出LR(0)项目集规范族
int judgeConflict(int k);         // 判断项目集Ik是否存在冲突
void printConflict();            // 打印LR(0)项目集规范族存在的冲突
void printGotoTable();           // 打印Goto表
void calActionTable();           // 求Action表
void printLine(int num);         // 打印num个——
void printSLRtable();            // 打印SLR分析表
bool isSLR();                    // 判断是否为SLR文法
void inputIstr();                // 输入待分析的字符串
string getStackStr(int choose);  // 获得栈中的所有内容
void AnalysisSLR();              // SLR文法分析输入的字符串
void WholeBeautifulProcess();    // 梳理一下函数调用,美化终端输入

int main()
{
    WholeBeautifulProcess();
    return 0;
}

Pro::Pro(const string &str)
{
    left = str;
    right.clear();
    index = 0;
}
void Pro::push(const string &str)
{
    right.push_back(str);
}
void Pro::print()
{
    cout << left << "::=";
    vector<string>::iterator it = right.begin();
    for (; it != right.end(); it++)
    {
        cout << (*it) << " ";
    }
    cout << endl;
}
void Pro::printWithPoint(int i)
{
    cout << left << "::=";
    for (int j = 0; j < right.size(); j++)
    {
        if (j == i)
        {
            cout << "· ";
        }
        cout << right[j] << " ";
    }
    if(i == right.size())
    {
        cout << "·";
    }
    cout << endl;
}
bool Pro::operator==(const Pro &p)
{
    if ((left == p.left) && (right.size() == p.right.size()))
    {
        int i = 0;
        for (; i < right.size(); i++)
        {
            if (right[i] != p.right[i])
            {
                break;
            }
        }
        if (i >= right.size())
        {
            return true;
        }
    }
    return false;
}

Closure::Closure(int i)
{
    closureIk = i;
}
void Closure::print()
{
    cout<<"\t   Closure-I"<<closureIk<<endl;
    cout<<"项目编号\t项目类型\t项目内容"<<endl;
    for (int i = 0; i < project_nums.size(); i++)
    {
        int index0 = getProjectArrayIndex(project_nums[i]);
        projects[index0].print();
    }
    cout<<endl;
}
bool Closure::operator==(const Closure &a)
{
    set<int> s1,s2;
    for(int i=0;i<a.project_nums.size(); i++)
    {
        s1.insert(a.project_nums[i]);
    }
    for(int i=0;i<project_nums.size(); i++)
    {
        s2.insert(project_nums[i]);
    }
    if(s1 == s2)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Project::Project(int pro_index, int point_index, int project_num)
{
    Project::pro_index = pro_index;
    Project::point_index = point_index;
    Project::project_num = project_num;
    Project::pointright = "NONE";
}
Project::Project(int pro_index, int point_index, int project_num, int p_type)
{
    Project::pro_index = pro_index;
    Project::point_index = point_index;
    Project::project_num = project_num;
    Project::p_type = p_type;
    Project::pointright = "NONE";
}
void Project::print() // 打印当前项目
{   
    int pii = getProI(pro_index);
    cout<<project_num<<"\t\t";
    if(p_type == MOVEIN)
    {
        cout<<"移进项目\t";
    }
    else if(p_type == REDUCE)
    {
        cout<<"归约项目\t";
    }
    else if(p_type == TOBEREDUCE)
    {
        cout<<"待约项目\t";
    }
    else if(p_type == ACCEPTION)
    {
        cout<<"接受项目\t";
    }
    productions[pii].printWithPoint(point_index);
}

f_vn::f_vn(const string &str)
{
    vn = str;
    vfirst.clear();
    vfollow.clear();
}
void f_vn::insert1(string t)
{
    if (vfirst.empty() == true || vfirst.count(t) < 1)
    {
        vfirst.insert(t);
    }
}
void f_vn::insert2(string t)
{
    if (vfollow.empty() == true || vfollow.count(t) < 1)
    {
        vfollow.insert(t);
    }
}
void f_vn::print()
{
    if (vfirst.empty())
    {
        cout << "FIRST:NULL" << endl;
    }
    else
    {
        cout << "FIRST[" << vn << "] = { ";
        set<string>::iterator it1 = vfirst.begin();
        cout << (*it1);
        it1++;
        for (; it1 != vfirst.end(); it1++)
        {
            cout << ", " << (*it1);
        }
        cout << " }\t\t\t";
    }

    if (vfollow.empty())
    {
        cout << "FOLLOW:NULL" << endl;
    }
    else
    {
        cout << "FOLLOW[" << vn << "] = {  ";
        set<string>::iterator it2 = vfollow.begin();
        cout << (*it2);
        it2++;
        for (; it2 != vfollow.end(); it2++)
        {
            cout << ",  " << (*it2);
        }
        cout << "}" << endl;
    }
}

ActionVT::ActionVT(const string & vt, int k)
{
    ActionVT::vt = vt;
    ActionVT::stateK = k;
    ActionVT::val = "error";
}

GotoVNT::GotoVNT(const string & vnt, int k)
{
    GotoVNT::vnt = vnt;
    GotoVNT::stateK = k;
    GotoVNT::toK2 = -1;
}
GotoVNT::GotoVNT(const string & vnt, int k, int k2)
{
    GotoVNT::vnt = vnt;
    GotoVNT::stateK = k;
    GotoVNT::toK2 = k2;
}

void inputG()
{
    string input_str;
    // int xixi=0;
    cout<<"🖨️   🖨️   🖨️   🖨️   🖨️   🖨️   🖨️   请 输 入 文 法   🖨️   🖨️   🖨️   🖨️   🖨️   🖨️   🖨️ "<<endl<<endl;
    cout<<"💯 输 入 范 例:E::=F * T 💯"<<endl<<endl;
    cout<<"🤳   🤳   🤳[Tips]: 输 入 我 看 不 懂 的 即 默 认 结 束 输 入"<<endl;
    while (getline(cin, input_str))
    {
        if (!(input_str[0] >= 'A' && input_str[0] <= 'Z'))
        {
            break;
        }
        // if(xixi==0){
        //     //输入的第一个非终结符标记为文法的开始符
        //     G_start = input_str[0];
        //     xixi=1;
        // }
        int i = 0;
        string tmp1 = "";
        while (input_str[i] != ':')
        {
            tmp1 += input_str[i++];
        }
        i += 3;
        Pro pro1(tmp1);
        // cout<<"input_str.length(): "<<input_str.length()<<endl;
        while (true)
        {
            string tmp2 = "";
            while (input_str[i] != ' ')
            {
                tmp2 += input_str[i];
                i++;
                if (i >= input_str.length())
                {
                    break;
                }
            }
            pro1.push(tmp2);
            if (i < input_str.size())
            {
                i++;
            }
            else
            {
                break;
            }
        }
        productions.push_back(pro1);
    }
}

void broadenG()
{
    cout<<"🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊构造增广文法完毕🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊 🔊"<<endl;
    if (!productions.empty())
    {
        G_start = productions[0].left + "'";
        vector<string> tmp;
        tmp.push_back(productions[0].left);
        Pro p0(G_start);
        p0.right = tmp;
        productions.insert(productions.begin(), p0);
        // 产生式编号
        for (int i = 0; i < productions.size(); i++)
        {
            productions[i].index = i;
        }
    }
    cout<<endl;
}

int getProI(int i)
{
    for (int j = 0; j < productions.size(); j++)
    {
        if (productions[j].index == i)
        {
            return j;
        }
    }
    cout << "✖️ ✖️ ✖️ ✖️ 查询的产生式编号不存在!✖️ ✖️ ✖️ ✖️ ✖️" << endl;
    return -1;
}

void printProductions()
{
    cout<<"📑 📑 📑 📑 📑 📑 📑  产生式集合如下所示  📑 📑 📑 📑 📑 📑 📑 📑 "<<endl;
    for (auto t : productions)
    {
        cout<<"© 产生式("<<t.index<<") : ";
        t.print();
    }
    cout<<"📑 📑 📑 📑 📑 📑 📑  📑 📑 📑 📑 📑  📑 📑 📑 📑 📑 📑 📑 📑 "<<endl;
    cout<<endl;
}

void calVN()
{
    vector<Pro>::iterator it = productions.begin();
    for (; it != productions.end(); it++)
    {
        if (VN.count((*it).left) <= 1)
        {
            VN.insert((*it).left);
        }
        for (int i = 0; i < (*it).right.size(); i++)
        {
            if ((*it).right[i][0] >= 'A' && (*it).right[i][0] <= 'Z')
            {
                if (VN.count((*it).right[i]) < 1)
                {
                    VN.insert((*it).right[i]);
                }
            }
        }
    }
}

void calVT()
{
    vector<Pro>::iterator it = productions.begin();
    for (; it != productions.end(); it++)
    {
        for (int i = 0; i < (*it).right.size(); i++)
        {
            if (VN.count((*it).right[i]) < 1 && VT.count((*it).right[i]) < 1)
            {
                VT.insert((*it).right[i]);
            }
        }
    }
    VT.insert("$");
}

bool isVN(string str)
{
    if(str[0] >= 'A' && str[0] <= 'Z')
    {
        return true;
    }
    else
    {
        return false;
    }
}

void calProjectSet()
{
    int pnum=0;
    for (auto t : productions)
    {
        //产生式`A→ε `只生成一个项目`A→ ·`
        if(t.right[0] == "ε")
        {
            Project pj(t.index, 0, pnum);
            pnum++;
            pj.p_type = REDUCE;
            pj.pointright = "ε";
            continue;
        }
        for (int i = 0; i <= t.right.size(); i++)
        {
            Project pj(t.index, i, pnum);
            if(t.index == 0 && i == t.right.size())
            {
                pj.p_type = ACCEPTION;
            }
            else if(i == t.right.size())
            {
                pj.p_type = REDUCE;
            }
            else if(isVN(t.right[i]))
            {
                pj.p_type = TOBEREDUCE;
            }
            else
            {
                pj.p_type = MOVEIN;
            }
            pj.leftstr = t.left;
            if(i==t.right.size())
            {
                pj.pointright = "NONE";
            }
            else
            {
                pj.pointright = t.right[i];
            }
            projects.push_back(pj);
            pnum ++;
        }
    }
}

void printProjectSet()
{
    cout<<"项目编号\t项目类型\t项目内容"<<endl;
    for(auto p : projects)
    {
        p.print();
    }
}

int getProjectArrayIndex(int project_i)
{
    for(int j=0; j<projects.size(); j++)
    {
        if(project_i == projects[j].project_num)
        {
            return j;
        }
    }
    cout<<"未找到该项目!!!"<<endl;
    return -1;
}

void printVNT()
{
    cout << "文法中出现的非终结符:";
    for (auto it : VN)
    {
        cout << it << " ";
    }
    cout << endl;
    cout << "文法中出现的终结符:";
    for (auto it : VT)
    {
        if (it != "$")
        {
            cout << it << " ";
        }
    }
    cout << endl <<endl;
}

void initFcollections()
{
    for (auto it : VN)
    {
        f_vn f1(it);
        if (it == G_start)
        {
            // 文法开始符 $插入FOLLOW集
            f1.insert2("$");
        }
        fcollections.push_back(f1);
    }
}

void calFIRST()
{
    bool is_change = true; // 标记每轮扫瞄准是否更新FIRST集合
    while (is_change)
    {
        is_change = false;
        for (int i = 0; i < productions.size(); i++)
        {
            int k = 0;
            // 定出fcollections[k].vn = productions[i].left 即为当前分析的非终结符
            for (k = 0; k < fcollections.size(); k++)
            {
                if (fcollections[k].vn == productions[i].left)
                {
                    break;
                }
            }

            bool have_e = false; // 标记能否一直推出ε
            for (int ri = 0; ri < productions[i].right.size(); ri++)
            {
                // 遍历该候选式的右部
                have_e = false;
                // 是非终结符  E->A类型 FIRST[E] += ( FIRST[A] - {ε} );
                if (productions[i].right[ri][0] >= 'A' && productions[i].right[ri][0] <= 'Z')
                {
                    // 定fcollections[h].vn = productions[i].right[ri] 即右部要分析的非终结符 A
                    int h = 0;
                    for (; h < fcollections.size(); h++)
                    {
                        if (fcollections[h].vn == productions[i].right[ri])
                        {
                            break;
                        }
                    }

                    // 判断FIRST[A]非空
                    if (!(fcollections[h].vfirst.empty()))
                    {
                        // 判断FIRST[A]中是否有相对FIRST[E]的新元素
                        for (auto it : fcollections[h].vfirst)
                        {
                            if (it != "ε")
                            {
                                // 更新FIRST[E]集合
                                if (fcollections[k].vfirst.count(it) < 1)
                                {
                                    is_change = true;
                                }
                                fcollections[k].insert1(it);
                            }
                        }
                    }
                    else
                    {
                        // FIRST[A]为空
                        // 跳过本轮
                        break;
                    }

                    if (fcollections[h].vfirst.count("ε"))
                    {
                        // ε 属于 FIRST[A] 继续遍历右部
                        have_e = true;
                    }
                    else
                    {
                        // 否则,跳出循环
                        break;
                    }
                }
                // 是终结符 或 ε
                else
                {
                    // E->a类型 FIRST[E] += {a};
                    if (fcollections[k].vfirst.count(productions[i].right[ri]) < 1)
                    {
                        is_change = true;
                    }
                    fcollections[k].insert1(productions[i].right[ri]); // 更新FIRST集合
                    // 终结符 跳出循环
                    break;
                }
            }

            if (have_e)
            {
                // 能一直推出ε
                //  FIRST[E] += {ε}
                fcollections[k].insert1("ε");
            }
        }
    }
}

void calFOLLOW()
{
    bool is_change = true; // 标记每轮扫瞄中是否更新FOLLOW集合
    while (is_change)
    {
        is_change = false;
        for (int i = 0; i < productions.size(); i++)
        {
            for (int j = 0; j < productions[i].right.size(); j++)
            {
                // 判断是否为非终结符
                if (productions[i].right[j][0] >= 'A' && productions[i].right[j][0] <= 'Z')
                {
                    // 1.形式为 A->aF  follow(A)加入到follow(F)
                    if (j + 1 == productions[i].right.size())
                    {

                        int k = 0, m = 0, fg = 0;
                        // 定出fcollections[k].vn=A
                        //    fcollections[m].vn=F
                        for (int nn = 0; nn < fcollections.size(); nn++)
                        {
                            if (fcollections[nn].vn == productions[i].left)
                            {
                                k = nn;
                                fg++;
                            }
                            if (fcollections[nn].vn == productions[i].right[j])
                            {
                                m = nn;
                                fg++;
                            }
                            if (fg == 2)
                            {
                                break;
                            }
                        }

                        // 判断FOLLOW[A]是否为空
                        if (!(fcollections[k].vfollow.empty()))
                        {
                            // 判断FOLLOW[A]中是否有新元素
                            for (auto it : fcollections[k].vfollow)
                            {
                                if (fcollections[m].vfollow.count(it) < 1)
                                {
                                    fcollections[m].insert2(it); // 更新FOLLOW集合
                                    is_change = true;
                                }
                            }
                        }
                    }

                    // 2.形式为 A->aFB FIRST(B)-ε 加入到follow(F)
                    else if (productions[i].right[j + 1][0] >= 'A' && productions[i].right[j + 1][0] <= 'Z')
                    {
                        int k = 0, m = 0, fg = 0;
                        // 定出fcollections[k].vn=F
                        //    fcollections[m].vn=B
                        for (int nn = 0; nn < fcollections.size(); nn++)
                        {
                            if (fcollections[nn].vn == productions[i].right[j])
                            {
                                k = nn;
                                fg++;
                            }
                            if (fcollections[nn].vn == productions[i].right[j + 1])
                            {
                                m = nn;
                                fg++;
                            }
                            if (fg == 2)
                            {
                                break;
                            }
                        }

                        int flag_e = 0;
                        for (auto it : fcollections[m].vfirst)
                        {
                            if (it == "ε")
                            {
                                flag_e = 1;
                            }
                            if (it != "ε") // 除去ε
                            {
                                if (fcollections[k].vfollow.count(it) < 1)
                                {
                                    fcollections[k].insert2(it); // 更新FOLLOW集合
                                    is_change = true;
                                }
                            }
                        }

                        // 2.2 B->...->ε follow(A)加入到follow(F)
                        if (flag_e)
                        {
                            // fcollections[k].vn=F
                            // 定出fcollections[m].vn=A
                            for (m = 0; m < fcollections.size(); m++)
                            {
                                if (fcollections[m].vn == productions[i].left)
                                {
                                    break;
                                }
                            }
                            // 判断FOLLOW[A]是否为空
                            if (!(fcollections[m].vfollow.empty()))
                            {
                                // 判断FOLLOW[A]中是否有新元素
                                for (auto it : fcollections[m].vfollow)
                                {
                                    if (fcollections[k].vfollow.count(it) < 1)
                                    {
                                        fcollections[k].insert2(it); // 更新FOLLOW集合
                                        is_change = true;
                                    }
                                }
                            }
                        }
                    }

                    // 3.形式为 A->aFb {b}加入到follow(F)
                    else
                    {
                        int k = 0;
                        // 定出fcollections[k].vn=F
                        for (k = 0; k < fcollections.size(); k++)
                        {
                            if (fcollections[k].vn == productions[i].right[j])
                            {
                                break;
                            }
                        }
                        // 判断是否要更新follow集合
                        if (fcollections[k].vfollow.count(productions[i].right[j + 1]) < 1)
                        {
                            fcollections[k].insert2(productions[i].right[j + 1]); // 更新FOLLOW集合
                            is_change = true;
                        }
                    }
                }
            }
        }
    }
}

void printFirstFollow()
{
    for (int i = 0; i < fcollections.size(); i++)
    {
        fcollections[i].print();
    }
}

int getSuccessorProject(int project_i)
{
    // 寻找项目编号为i的后继项目 编号j
    int project_j = -1;
    int pi_location = getProjectArrayIndex(project_i);
    if((projects[pi_location].p_type == TOBEREDUCE) || (projects[pi_location].p_type == MOVEIN))
    {
        for(int jk=0; jk<projects.size(); jk++)
        {
            if((projects[pi_location].pro_index == projects[jk].pro_index) && 
            (projects[jk].point_index == projects[pi_location].point_index + 1))
            {
                project_j = projects[jk].project_num;
                break;
            }
        }
    }
    else
    {
        //归约项目和接受项目没有后继项目
        cout<<"归约项目和接受项目没有后继项目"<<endl;
    }
    return project_j;
}

void calProjectsNormFamily()
{
    // 求closure-I0
    Closure ce(0);
    set<string> cur_left;    // 记录 E' -> . E 中的E'
    set<string> rights;
    cur_left.insert(projects[0].leftstr);
    rights.insert(projects[0].pointright);
    bool is_change_ce=true;
    // E'->.E先加入 项目集规范族
    ce.project_nums.push_back(projects[0].project_num);
    while(is_change_ce)
    {
        is_change_ce = false;
        vector<string> tmp_right;
        for(auto r: rights)
        {
            // 左部项目集还未出现过,加入
            if(cur_left.count(r) < 1)
            {
                // cout<<r<<" 在左部项目集还未出现过"<<endl;
                for(int i=0; i<projects.size(); i++)
                {
                    if((projects[i].leftstr == r)&&(projects[i].point_index == 0))
                    {
                        // cout<<"添加项目 :"<<projects[i].project_num<<endl;
                        ce.project_nums.push_back(projects[i].project_num);
                        is_change_ce = true;
                        if((rights.count(projects[i].pointright)<1)&&(cur_left.count(projects[i].pointright) < 1)&&(isVN(projects[i].pointright)))
                        {
                            tmp_right.push_back(projects[i].pointright);
                        }
                    }
                }
                cur_left.insert(r);
                break;
            }
        }
        //更新右部
        for(int j=0;j<tmp_right.size();j++)
        {
            // cout<<"新增右部非终结符 :"<<tmp_right[j]<<endl;
            rights.insert(tmp_right[j]);
        }
        tmp_right.clear();

    }
    normfamily.push_back(ce);
    // cout<<"I0求解完毕"<<endl;
    // 求I1, I2, ...
    int cur_I=0;            // 当前分析到的 I0
    bool is_add_closure=true;
    // 每轮大循环分析当前I[cur_I],对每个move分析 直到没有新增项目集,退出循环
    while(is_add_closure)
    {
        is_add_closure = false;
        // cout<<"打印当前分析的I[cur_I] = I"<<cur_I<<endl;
        // normfamily[cur_I].print();
        vector<string> moveSets;   // E'->.E  E->.T  T->() 记录E,T,(,...
        moveSets.clear();
        // 求moveSets
        for(int i=0; i<normfamily[cur_I].project_nums.size(); i++)
        {
            int tmp = getProjectArrayIndex(normfamily[cur_I].project_nums[i]);
            if(projects[tmp].p_type == REDUCE || projects[tmp].p_type == ACCEPTION)
            {
                continue;
            }
            // 避免重复插入
            for(int j=0;j<moveSets.size();j++)
            {
                if(moveSets[j] == projects[tmp].pointright)
                {
                    tmp = -1;
                    break;
                }
            }
            if(tmp >= 0)
            {
                moveSets.push_back(projects[tmp].pointright);
            } 
        }
        //打印moveSets
        // cout<<"当前moveSets: ";
        // for(int m=0; m<moveSets.size(); m++)
        // {
        //     cout<<moveSets[m]<<" ";
        // }
        // cout<<endl;
        //遍历moves
        for(int moveme=0; moveme<moveSets.size(); moveme++)
        {
            //计算move后的一个新状态Ik
            int kkk = normfamily.size();
            Closure ck(kkk);
            for(int h=0; h<normfamily[cur_I].project_nums.size(); h++)
            {
                int tmp1 = getProjectArrayIndex(normfamily[cur_I].project_nums[h]);
                // cout<<"projects["<<tmp1<<"].pointright: "<<projects[tmp1].pointright<<endl;
                // cout<<"moveSets["<<moveme<<"]: "<<moveSets[moveme]<<endl;
                if(projects[tmp1].pointright == moveSets[moveme])
                {
                    // cout<<"寻找项目编号"<<projects[tmp1].project_num<<"的后继项目。。。"<<endl;
                    // 找到匹配的项目的后继项目
                    int backPnum = getSuccessorProject(projects[tmp1].project_num);
                    if(backPnum == -1)
                    {
                        cout<<"后继项目匹配失败!"<<endl;
                    }
                    else
                    {
                        ck.project_nums.push_back(backPnum);
                    }
                    
                }
            }
            // cout<<"move后的新状态I"<<kkk<<endl;
            // ck.print();
            bool is_add_project = true;
            // 每轮循环直到CLOSURE(I)不再增大为止
            int cur_pp = 0;
            // 避免循环添加新项目,这个set集合作用就是记录左部已经出现的形式如S->.E中的S
            set<string> left_vns;
            for(int i=0;i<ck.project_nums.size(); i++)
            {
                int iindex=getProjectArrayIndex(ck.project_nums[i]);
                if(projects[iindex].point_index == 0)
                {
                    left_vns.insert(projects[iindex].leftstr);
                }
            }
            
            while(is_add_project)
            {
                is_add_project = false;
                // 扫描右部形如 A->.Bc 记录B
                set<string> rightB;
                int cur_size = ck.project_nums.size();
                // cout<<"start_p : "<<start_p<<endl;
                for(int luffy=cur_pp; luffy < ck.project_nums.size(); luffy++)
                {
                    int tmp1 = getProjectArrayIndex(ck.project_nums[luffy]);
                    // if((leftA.count(projects[tmp1].pointright) < 1) && (isVN(projects[tmp1].pointright)))
                    // if((projects[tmp1].leftstr != projects[tmp1].pointright) && (isVN(projects[tmp1].pointright)))
                    if(isVN(projects[tmp1].pointright))
                    {
                        // A->.Abc的情况可以直接排除,不用再添加A的项目
                        if((projects[tmp1].leftstr == projects[tmp1].pointright) && (projects[tmp1].point_index == 0))
                        {
                            continue;
                        }
                        // 避免 S->.A S->a A->.S  又添加S的项目,循环往复,此时通过set集合判断已经有过S即可避免此情况
                        if(left_vns.count(projects[tmp1].pointright) > 0)
                        {
                            continue;
                        }
                        // 否则更新set集合
                        else
                        {
                            left_vns.insert(projects[tmp1].pointright);
                        }
                        
                        //添加右部中出现的非终结符
                        rightB.insert(projects[tmp1].pointright);
                    }
                }
                // cout<<"rightB: ";
                // for(auto r:rightB)
                // {
                //     cout<<r<<"  ";
                // }
                // cout<<endl;
                for(auto r:rightB)
                {
                    // 找到每个B->.abc 加入项目集
                    for(int g=0;g<projects.size();g++)
                    {
                        if((r == projects[g].leftstr) && (projects[g].point_index==0))
                        {
                            ck.project_nums.push_back(projects[g].project_num);
                            is_add_project = true;
                        }
                    }
                }
                cur_pp = cur_size;
                rightB.clear();
            }
            
            //判断新状态是否与已创建过的状态有重合
            bool flag_tmp=false;
            for(int h=0; h<normfamily.size(); h++)
            {
                if(ck == normfamily[h])
                {
                    //Ik 与 Ih相等
                    flag_tmp=true;
                    // 更新Goto表
                    // I[cur_I] --->(VN) I[h]
                    GotoVNT go1(moveSets[moveme], cur_I, normfamily[h].closureIk);
                    gotoTables.push_back(go1);
                    // if(isVN(moveSets[moveme]))
                    // {
                    //     // 更新Goto表
                    //     // I[cur_I] --->(VN) I[h]
                    //     GotoVNT go1(moveSets[moveme], cur_I, normfamily[h].closureIk);
                    //     gotoTables.push_back(go1);
                    // }
                    break;
                }
            }        
            if(!flag_tmp)
            {
                //添加新状态
                normfamily.push_back(ck);
                // 更新Goto表
                // I[cur_I] --->(VN) I[k]
                GotoVNT go1(moveSets[moveme], cur_I, ck.closureIk);
                gotoTables.push_back(go1);
                // if(isVN(moveSets[moveme]))
                // {
                //     // I[cur_I] --->(VN) I[k]
                //     GotoVNT go1(moveSets[moveme], cur_I, ck.closureIk);
                //     gotoTables.push_back(go1);
                // }
                
                // cout<<"新加状态: Ik"<<endl;
                // ck.print();
                is_add_closure=true;
            }
        }
        cur_I ++;
        if(cur_I >= normfamily.size())
        {
            break;
        }
        else{
            is_add_closure = true;
        }
    }
    
    // cout<<"项目族求解完毕!"<<endl;
}

void printProjectsNormFamily()
{
    for(int i=0; i<normfamily.size(); i++)
    {
        normfamily[i].print();
    }
}

int judgeConflict(int k)
{
    int cnt_move=0;
    int cnt_reduce=0;
    int kk=0;
    for(;kk<normfamily.size();kk++)
    {
        if(normfamily[kk].closureIk == k)
        {
            break;
        }
    }
    for(int i=0; i<normfamily[kk].project_nums.size(); i++)
    {
        int index0 = getProjectArrayIndex(normfamily[kk].project_nums[i]);
        if(projects[index0].p_type == REDUCE)
        {
            cnt_reduce ++;
        }
        else if(projects[index0].p_type == MOVEIN)
        {
            cnt_move ++;
        }
    }
    if(cnt_move > 0 && cnt_reduce > 0)
    {
        return MRCONFLICT;
    }
    else if(cnt_reduce > 1)
    {
        return RRCONFLICT;
    }
    else
    {
        return NONECONFLICT;
    }
}

void printConflict()
{
    for(int i=0; i<normfamily.size(); i++)
    {
        int res = judgeConflict(normfamily[i].closureIk);
        if(res == MRCONFLICT)
        {
            cout<<"I"<<normfamily[i].closureIk<<" 存在 移进——归约冲突"<<endl;
        }
        else if(res == RRCONFLICT)
        {
            cout<<"I"<<normfamily[i].closureIk<<" 存在 归约——归约冲突"<<endl;
        }
    }
}

void printGotoTable()
{
    cout<<"GOTO表:"<<endl;
    for(int i=0; i<gotoTables.size(); i++)
    {
        cout<<"Goto[I"<<gotoTables[i].stateK<<", "<<gotoTables[i].vnt<<" ] = I"<<gotoTables[i].toK2<<endl;
    }
}

void calActionTable()
{
    for(int i=0; i<normfamily.size(); i++)
    {
        //遍历项目Ik的项目
        for(int j=0; j<normfamily[i].project_nums.size(); j++)
        {
            int project_j = getProjectArrayIndex(normfamily[i].project_nums[j]);
            // A->B.aC, 且Go(Ik, a) = Ij, a ∈ VT 则Action[k, a] = Sj
            if((projects[project_j].p_type == MOVEIN) && (!isVN(projects[project_j].pointright)))
            {
                int go_j=0;
                for(;go_j < gotoTables.size(); go_j++)
                {
                    if((gotoTables[go_j].vnt == projects[project_j].pointright) && 
                    (gotoTables[go_j].stateK == normfamily[i].closureIk))
                    {
                        break;
                    }
                }
                string tmps = "S" + to_string(gotoTables[go_j].toK2);
                ActionVT avt(projects[project_j].pointright, normfamily[i].closureIk);
                avt.val = tmps;
                actionTables.push_back(avt);
            }
            // S'->S. 接受项目,属于Ik, Action[k, $] = acc
            else if(projects[project_j].p_type == ACCEPTION)
            {
                ActionVT avt("$", normfamily[i].closureIk);
                avt.val = "acc";
                actionTables.push_back(avt);
            }
            // A->a. 归约项目,for all a ∈ FOLLOW(A) do Action[k, a] = rj (j是产生式A->a的编号)
            else if(projects[project_j].p_type == REDUCE)
            {
                int follow_vn_index=0;
                int num_proA = projects[project_j].pro_index;
                for(;follow_vn_index<fcollections.size(); follow_vn_index++)
                {
                    if(fcollections[follow_vn_index].vn == projects[project_j].leftstr)
                    {
                        break;
                    }
                }
                for(auto f: fcollections[follow_vn_index].vfollow)
                {
                    ActionVT avt(f, normfamily[i].closureIk);
                    avt.val = "r" + to_string(num_proA);
                    actionTables.push_back(avt);
                }
            }
        }
    }
    return;
}

void printLine(int num, int cols, bool isI)
{
    for(int i=0; i<cols; i++)
    {
        for(int j=0; j<num; j++)
        {
            cout<<"-";
        }
        if(isI)
        {
            cout<<"|";
        }
    }
}

void printSLRtable()
{
    cout<<"     ᕙ▐° ◯ °▐ᕗ 构建的SLR分析表如下 ᕙ▐° ◯ °▐ᕗ     "<<endl;
    //表头状态编号9个宽度(+2个竖线) + (终结符个数) * 10个宽度(加一个竖线) + (非终结符-开始符)个数 * 8个宽度(加一个竖线)
    printLine(11, 1, false);
    printLine(11, VT.size(), false);
    printLine(9 , VN.size() - 1, false);
    cout<<endl;

    cout<<"|";
    cout<<setw(11)<<left<<" 状态";
    cout<<"|";
    // action居中ᕙ▐° ◯ °▐ᕗ显示
    string tmp111="";
    for(int jj=0; jj<5 * VT.size(); jj++)
    {
        tmp111+=" ";
    }
    tmp111 += "ACTION";
    cout<<setw(11 * VT.size() - 1)<<left<<tmp111;
    cout<<"|";
    // goto居中ᕙ▐° ◯ °▐ᕗ显示
    tmp111 = "";
    for(int jj=0; jj<4 * (VN.size()-1); jj++)
    {
        tmp111+=" ";
    }
    tmp111+="GOTO";
    cout<<setw(9 *(VN.size()-1) - 1)<<left<<tmp111;
    cout<<"|"<<endl;

    cout<<"|   💻    |";
    printLine(10, VT.size(), true);
    printLine(8 , VN.size() - 1, true);
    cout<<endl;

    cout<<"|         |";
    for(auto tt : VT)
    {
        string tmp = "  " + tt;
        cout<<setw(10)<<left<<tmp;
        cout<<"|";
    }
    for(auto nn: VN)
    {
        if(nn != G_start)
        {
            string tmp = "  " + nn;
            cout<<setw(8)<<left<<tmp;
            cout<<"|";
        }
    }
    cout<<endl;

    printLine(9+1,1,true);
    printLine(10, VT.size(), true);
    printLine(8 , VN.size() - 1, true);
    cout<<endl;
    for(int i=0; i<normfamily.size(); i++)
    {
        cout<<"|";
        string tmp = " I" + to_string(normfamily[i].closureIk);
        cout<<setw(9)<<left<<tmp;
        cout<<"|";
        
        // Action 输出
        for(auto tt: VT)
        {
            int jjj=0;
            for(; jjj<actionTables.size(); jjj++)
            {
                if(actionTables[jjj].vt == tt && actionTables[jjj].stateK == normfamily[i].closureIk)
                {
                    string tmp = " " + actionTables[jjj].val;
                    cout<<setw(10)<<left<<tmp;
                    cout<<"|";
                    break;
                }
            }
            if(jjj >= actionTables.size())
            {
                cout<<setw(10)<<left<<"   ";
                cout<<"|";
            }
            
        }
        
        // Goto 输出
        for(auto nn: VN)
        {
            if(nn != G_start)
            {
                int j=0;
                for(; j<gotoTables.size(); j++)
                {
                    if(gotoTables[j].vnt == nn && gotoTables[j].stateK == normfamily[i].closureIk)
                    {
                        string tmp = " I" + to_string(gotoTables[j].toK2);
                        cout<<setw(8)<<left<<tmp;
                        cout<<"|";
                        break;
                    }
                }
                if(j>=gotoTables.size())
                {
                    cout<<setw(8)<<left<<"   ";
                    cout<<"|";
                }
            }
        }
        cout<<endl;

        printLine(9+1,1,true);
        printLine(10, VT.size(), true);
        printLine(8 , VN.size() - 1, true);
        cout<<endl;
    }

}

bool isSLR()
{
    printConflict();
    cout<<"分析中ing~~~"<<endl;
    bool judge_res = true;
    // 遍历项目集规范族
    for(int i=0; i<normfamily.size(); i++)
    {
        int res = judgeConflict(normfamily[i].closureIk);
        if(res == MRCONFLICT)
        {
            cout<<"对于 I"<<normfamily[i].closureIk<<" 中的 移进——归约冲突"<<endl;
            // 定位冲突双方 A->B.cD  B->E.
            // 判断{c} ∩ FOLLOW(B) = ∅ ?
            vector<string> tmp_move;    //存放移进项目中的c
            vector<string> vn_reduce;   //存放归约项目中的B
            for(int j=0; j<normfamily[i].project_nums.size(); j++)
            {
                int tmp_index = getProjectArrayIndex(normfamily[i].project_nums[j]);
                if(projects[tmp_index].p_type == MOVEIN)
                {
                    tmp_move.push_back(projects[tmp_index].pointright);
                }
                else if(projects[tmp_index].p_type == REDUCE)
                {
                    vn_reduce.push_back(projects[tmp_index].leftstr);
                    // 调试用
                    // cout<<"I"<<normfamily[i].closureIk<<" 归约项 B: "<< projects[tmp_index].leftstr<<endl;
                }
            }

            // 逐个获取FOLLOW(B)
            for(int kk=0; kk<vn_reduce.size(); kk++)
            {
                int followb_index = 0;
                for(;followb_index < fcollections.size(); followb_index ++)
                {
                    if(vn_reduce[kk] == fcollections[followb_index].vn)
                    {
                        break;
                    }
                }
                // 遍历移进项目终结符
                for(auto tm: tmp_move)
                {
                    //遍历 FOLLOW(B)
                    for(auto fb: fcollections[followb_index].vfollow)
                    {
                        if(tm == fb)
                        {
                            // 交集非空
                            cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ {"<<tm<<"} != ∅"<<endl;
                            judge_res = false;
                            break;
                        }
                    }
                    if(judge_res == false)
                    {
                        break;
                    }
                    else
                    {
                        cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ {"<<tm<<"} = ∅"<<endl;
                    }
                }
                if(judge_res == false)
                {
                    break;
                }
            }
            if(judge_res == false)
            {
                cout<<" 🤖 🤖 🤖 经过竭尽全力的抢救,👩🏻‍⚕️ 🧑‍⚕️ 👩🏼‍⚕️我们很遗憾的通知您,文法中存在的 🥷🏽 移进——归约 🥷🏽 冲突无法消除, 该文法不是SLR文法。😦 😦 😦"<<endl;
                break;
            }
        }
        else if(res == RRCONFLICT)
        {
            cout<<"对于 I"<<normfamily[i].closureIk<<" 中的 归约——归约冲突"<<endl;
            // 定位冲突双方 B->E.  C->T.
            // 判断FOLLOW(B) ∩ FOLLOW(C) = ∅ ?
            vector<string> vn_reduce;   //存放归约项目中的B,C,...
            for(int j=0; j<normfamily[i].project_nums.size(); j++)
            {
                int tmp_index = getProjectArrayIndex(normfamily[i].project_nums[j]);
                if(projects[tmp_index].p_type == REDUCE)
                {
                    vn_reduce.push_back(projects[tmp_index].leftstr);
                    // 调试用
                    // cout<<"I"<<normfamily[i].closureIk<<" 归约项 B: "<< projects[tmp_index].leftstr<<endl;
                }
            }

            // 逐个获取FOLLOW(B)
            for(int kk=0; kk<vn_reduce.size(); kk++)
            {
                int followb_index = 0;
                for(;followb_index < fcollections.size(); followb_index ++)
                {
                    if(vn_reduce[kk] == fcollections[followb_index].vn)
                    {
                        break;
                    }
                }
                // 逐个获取FOLLOW(C)
                int ll;
                for(ll=kk+1; ll<vn_reduce.size(); ll++)
                {
                    int followc_index = 0;
                    for(;followc_index < fcollections.size(); followc_index ++)
                    {
                        if(vn_reduce[ll] == fcollections[followc_index].vn)
                        {
                            break;
                        }
                    }
                    //判断FOLLOW(B) 和 FOLLOW(C)交集是否为空
                    for(auto fb: fcollections[followb_index].vfollow)
                    {
                        for(auto fc: fcollections[followc_index].vfollow)
                        {
                            if(fb == fc)
                            {
                                // 交集非空
                                cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ FOLLOW["<<vn_reduce[ll]<<"] = {"<<fb<<"} 非空!!!"<<endl;
                                judge_res = false;
                                break;
                            }
                        }
                        if(judge_res == false)
                        {
                            break;
                        }
                    }
                    if(judge_res == false)
                    {
                        break;
                    }
                }
                if(judge_res == false)
                {
                    break;
                }
                else
                {
                    cout<<"FOLLOW["<<vn_reduce[kk]<<"] ∩ FOLLOW["<<vn_reduce[ll]<<"] = ∅"<<endl;
                }
            }
            if(judge_res == false)
            {
                cout<<" 🤖 🤖 🤖 经过竭尽全力的抢救,👩🏻‍⚕️ 🧑‍⚕️ 👩🏼‍⚕️我们很遗憾的通知您,文法中存在的 🥷🏽 归约——归约 🥷🏽 冲突无法消除, 该文法不是SLR文法。😦 😦 😦"<<endl;
                break;
            }
        }
    }
    if(judge_res)
    {
        cout<<" 👨🏻‍💻 🧑🏻‍💻 📺 📱 📑 🔧 🛠️ 🐣经过我缜密的逻辑推理分析,🐼下面我宣布,该文法是SLR文法。 真的!!! 🤩 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 🎉 "<<endl;
    }
    return judge_res;
}

void inputIstr(){
    cout<<"请输入待分析的字串($代表结束符): ";
    cin>>istr;
    if(istr[istr.size()-1] != '$')
    {
        istr.push_back('$');
    }
    cout<<"开始进行SLR文法分析……"<<endl;
}

string getStackStr(int choose){
    vector<string> ss1;
    string res="◀||";
    if(choose == 1)
    {
        stack<string> s1;
        s1 = GAnalasis;

        while(!s1.empty()){
            ss1.push_back(s1.top());
            s1.pop();
        }
        for(int i=ss1.size()-1; i>=0; i--){
            res += ss1[i];
            res += " ";
        }
    }
    else if(choose == 2)
    {
        stack<int> s1;
        s1 = stack_Ik;

        while(!s1.empty()){
            int tmp_num = s1.top();
            string tmp_str = "I" + to_string(tmp_num);
            ss1.push_back(tmp_str);
            s1.pop();
        }
        for(int i=ss1.size()-1; i>=0; i--){
            res += ss1[i];
            res += " ";
        }
    }
    
    return res;
}

void AnalysisSLR()
{
    inputIstr();
    //压入终止符号
    GAnalasis.push("$");
    //初始状态0压入栈
    stack_Ik.push(0);
    int i=0, steps=0;
    cout<<"输入串 '"<<istr<<"' 的分析过程如下:"<<endl;
    for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
    cout<<endl;
    cout<<setw(16)<<left<<"过程计数";
    cout<<setw(36)<<left<<"状态栈";
    cout<<setw(36)<<left<<"语法分析栈";
    cout<<setw(30)<<left<<"剩余未匹配的字串";

    cout<<setw(20)<<left<<"操作";
    cout<<setw(15)<<left<<"ACTION";
    cout<<setw(15)<<left<<"GOTO"<<endl;
    for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
    cout<<endl;

    while(i<istr.length())
    {
        steps++;
        cout<<setw(16)<<left<<steps;
        string tmp = getStackStr(2);
        // cout<<"状态栈:"<<tmp<<endl;
        cout<<setw(36)<<left<<tmp;
        tmp = getStackStr(1);
        // cout<<"语法分析栈:"<<tmp<<endl;
        cout<<setw(36)<<left<<tmp;
        string tmp2="";
        for(int j=i;j<istr.length();j++){
            tmp2+=istr[j];
        }
        cout<<setw(15)<<left<<tmp2;
        char cur_c = istr[i];   //当前指示字符
        //取栈顶元素
        if(GAnalasis.empty()){
            cout<<"栈为空!!!"<<endl;
            return;
        }
        //判断是否为id类型
        int new_i=-1;
        string str_id = "";
        if((VT.count("id")>0)&&(cur_c >= 'a' && cur_c <= 'z'))
        {
            str_id += cur_c;
            new_i = i+1;
            while(true)
            {
                if((istr[new_i] >= 'a' && istr[new_i] <= 'z')||(istr[new_i] >= '0' && istr[new_i] <= '9'))
                {
                    str_id += istr[new_i];
                }
                else{
                    break;
                }
                new_i ++;
            }
        }
        string str_vt="";
        if(new_i > -1)
        {
            // id类型
            str_vt = str_id;
            // i = new_i;            
        }
        else
        {
            // 其他终结符类型
           str_vt += cur_c;
            //    i++;
        }
        
        //查表 Action[状态栈顶Ik, str_vt]
        int topIk = stack_Ik.top();
        int ac=0;
        for(; ac<actionTables.size(); ac++)
        {
            if(topIk == actionTables[ac].stateK)
            {
                if((new_i > 0) && (actionTables[ac].vt == "id"))
                {
                    break;
                }
                if(actionTables[ac].vt == str_vt)
                {
                    break;
                }
            }
        }
        if(ac >= actionTables.size())
        {
            cout<<endl;
            cout<<"✖️ ✖️ ✖️ ERROR ✖️ ✖️ ✖️"<<endl;
            for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
            cout<<endl;
            return;
        }
        if(actionTables[ac].val == "error")
        {
            cout<<endl;
            cout<<"✖️ ✖️ ✖️ ERROR ✖️ ✖️ ✖️"<<endl;
            for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
            cout<<endl;
            return;
        }
        else
        {
            if(actionTables[ac].val[0] == 'S')
            {
                //移进 操作
                if(new_i > -1)
                {
                    i = new_i;
                }
                else
                {
                    i++;
                }
                cout<<setw(20)<<left<<"移进";
                cout<<setw(15)<<left<<actionTables[ac].val;
                cout<<setw(15)<<left<<"        "<<endl;
                int snum = stoi(actionTables[ac].val.substr(1));
                // 状态栈压栈
                stack_Ik.push(snum);
                // 语法分析栈压入str_vt
                GAnalasis.push(str_vt);

            }
            else if(actionTables[ac].val[0] == 'r')
            {
                //归约
                int rnum = stoi(actionTables[ac].val.substr(1));
                // 找到产生式编号为rnum
                int pro_index = getProI(rnum);
                string pro_str = "归约:";
                pro_str += productions[pro_index].left;
                pro_str += "->";
                for(int ps=0; ps<productions[pro_index].right.size(); ps++)
                {
                    pro_str += productions[pro_index].right[ps];
                    pro_str += " ";
                }
                cout<<setw(20)<<left<<pro_str;
                cout<<setw(15)<<left<<actionTables[ac].val;
                
                // 更新语法分析栈
                // cout<<"归约使用产生式:";
                // productions[pro_index].print();
                // 出栈 数量等同 产生式右部 符号个数
                for(int pnum=0; pnum<productions[pro_index].right.size(); pnum++)
                {
                    GAnalasis.pop();
                    stack_Ik.pop();
                }
                int top_back_num = stack_Ik.top();
                // 产生式左部入栈
                GAnalasis.push(productions[pro_index].left);
                // 找Goto[top_back_num, productions[pro_index].left]
                int goto_index=0;
                for(;goto_index<gotoTables.size();goto_index++)
                {
                    if((gotoTables[goto_index].vnt == productions[pro_index].left) 
                    && (gotoTables[goto_index].stateK == top_back_num))
                    {
                        // 新状态压入栈
                        // cout<<"新状态"<<gotoTables[goto_index].toK2<<"入栈"<<endl;
                        stack_Ik.push(gotoTables[goto_index].toK2);
                        string tmpgo = "I" + to_string(gotoTables[goto_index].toK2);
                        cout<<setw(15)<<left<<tmpgo<<endl;
                        break;
                    }
                }
            }
            else if(actionTables[ac].val == "acc")
            {
                //接受,完美结束
                cout<<setw(20)<<left<<"接受!😍!";
                cout<<setw(15)<<left<<"    ";
                cout<<setw(15)<<left<<"    "<<endl;
                for(int ppp=0; ppp<34;ppp++)cout<<"— — ";
                cout<<endl;
                return;
            }
        }
        
        // cout<<"step:"<<steps<<" done!"<<endl;
        // cout<<"cur_i:"<<i<<endl;
    }
}

void WholeBeautifulProcess()
{
    inputG();
    cout<<endl;
    cout<<"。。。增广文法处理。。。"<<endl<<endl;
    broadenG();
    printProductions();
    calVN();
    calVT();
    calProjectSet();
    printVNT();
    cout<<endl<<"➖  ➖  ➖  ➖  ➖  ➖ 项目表 ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖"<<endl;
    printProjectSet();
    cout<<"➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖  ➖"<<endl<<endl;
    initFcollections();
    calFIRST();
    calFOLLOW();

    cout<<endl<<" 🐲  🐲  🐲  🐲  🐲  🐲  输 出 非 终 结 符 的 FIRST 和 FOLLOW 集 合 计 算 结 果  🐲  🐲  🐲  🐲  🐲  🐲"<<endl;
    printFirstFollow();
    cout<<" 🐲  🐲  🐲  🐲  🐲  🐲 🐲  🐲  🐲  🐲  🐲  🐲  🐲  🐲  🐲  🐲  🐲  🐲"<<endl<<endl;

    calProjectsNormFamily();
    calActionTable();

    cout<<endl<<"🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 项 目 集 规 范 族 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁"<<endl;
    printProjectsNormFamily();
    cout<<"🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁 🍁"<<endl<<endl;

    printGotoTable();


    printSLRtable();


    if(isSLR())
    {
        AnalysisSLR();
    }
}
  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

路飞DoD

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

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

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

打赏作者

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

抵扣说明:

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

余额充值