编译原理 SLR文法(算法原理和C++实现)
设计目标
给定一个上下文无关文法,编程完成以下功能:
- 计算非终结符的
FOLLOW
集✔️ - 求
LR(0)
项目集规范族✔️ - 构造
SLR
分析表✔️ - 判断该文法是否为
SLR
文法✔️ - 输入字符串,按照
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();
}
}