#include
using namespace std;
#include "definition.h"
#include "Check.h"
#include "Init.h"
#include "getFirst.h"
#include "getFollow.h"
#include "Display.h"
#include "getI.h"
#include "getTable.h"
#include "analyse.h"
int main()
{
ifstream file;
file.open("test/input3.txt");
string str;
while(getline(file, str)){ //输入一行,即一个非终结符的候选式
cout<
#ifndef DEFINITION_H_INCLUDED
#define DEFINITION_H_INCLUDED
#define SIZE 100
int idVt = 0; //终结符编号
int idVn = 1; //非终结符编号,0号为扩展文法开始符
int idPro = 1; //产生式编号,0号为扩展文法开始符
int JING; //# 号
int EMPTY = 5*SIZE; //空串
int startVt = -1; //判断是否处理了开始符,只处理一次
int ERROR = 4*SIZE; //出错标志
int ACC = 5*SIZE; //成功标志
mapmpVn,mpVt; //编号(字符,编号)
maprmpVn,rmpVt; //双向映射(编号,字符)
//存储分开编号的产生式,下标为编号
struct Pro {
int Vn; //产生式左部 1 <=> A
vectorcandy; //产生式右部{1,2,-1} 代表 A -> ABa
Pro(){
Vn =0 ;
candy.clear();
}
}pro[SIZE];
//项目集I
struct Ix{
set >pro; //记录项目集拥有的产生式编号以及对应的‘.’ 号的位置 {idPro,dot} 例如: { {0,0} , {1,1} } <=> { S`->.XX, E -> X.XX }
setv; //记录项目集的边的符号的编号如:a编号1。GOTO(a,I)、GOTO(b,I) 的a, b
set >go; //(idVt/idVn, numI) 对应的边以及其GOTO到的项目集
void Clear(){
pro.clear();
v.clear();
go.clear();
}
}I[SIZE];
//每个非终结符对应一个结构体
struct NoTml
{
vector > pro; //候选式:例如 {{1,2},{-1,2},{0} } => AB | aB | &
set FIRST, FOLLOW; //FIRST集,FOLLOW集
int proNum; //处理FIRST集时使用,判断以及完成的候选式
bool FirstFinish; //处理FIRST集时使用,判断是否全部候选式都完成
NoTml(){
FirstFinish = false;
int proNum = 0 ;
FIRST.clear();
FOLLOW.clear();
pro.clear();
}
}notml[SIZE]; //每个下标对应一个非终结符
#endif // DEFINITION_H_INCLUDED
#ifndef INIT_H_INCLUDED
#define INIT_H_INCLUDED
void init(string str){
int len = str.length();
int pos = 0;
int idLeft = 0;
string word="";
vectorvec;
//获取产生式左部
while(pos='A'&&str[pos]<='Z'){ //判断是否为大写字母开始,即是否为非终结符
word="";
word+=str[pos];
pos++;
while(pos') {
idLeft = mpVn[word];
pos+=2;
break;
}
else {
errorG(); //文法输入错误
return ;
}
}
//扩展文法开始符
if(startVt == -1){
rmpVt[EMPTY]="&"; //& 代表空串
mpVt["&"] = EMPTY;
JING = idVt++; //对 # 号进行编号
rmpVt[JING]="#";
mpVt["#"] = JING;
ERROR = SIZE+1;
startVt = idLeft;
mpVn["S`"] = 0;
rmpVn[0] = "S`";
pro[0].candy.push_back(idLeft);
pro[0].Vn = 0;
notml[0].pro.push_back({idLeft});
}
//获取产生式右部
while(pos='A'&&str[pos]<='Z') { //对非终结符编号
word="";
word+=str[pos];
pos++;
while(pos='A'&&str[pos]<='Z')){ //对终结符编号
word="";
word+=str[pos];
pos++;
while(pos=SIZE||idVn>=SIZE) { //终结符或,非终结符超出范围,错误
errorG();
return ;
}
}
#endif // INIT_H_INCLUDED
#ifndef GETFIRST_H_INCLUDED
#define GETFIRST_H_INCLUDED
//输出FIRST集合
void dispalyFirst(){
cout<<"---------------FIRST start---------------------"<::iterator it=notml[i].FIRST.begin();it!=notml[i].FIRST.end();it++){
cout< Y...的FIRST(Y)/{&}加入到FIRST(X)
for(int i=0;i0){ //判断首字符是否为非终结符
settmp;
int idk=notml[i].pro[j][0]; //获取首字符的编号
tmp.insert(notml[idk].FIRST.begin(),notml[idk].FIRST.end());
if(tmp.count(EMPTY)) tmp.erase(EMPTY);
notml[i].FIRST.insert(tmp.begin(),tmp.end());
}
}
}
//规则(2)第二步,每次有变化都要进行更新
bool hasChange = true;
int Empty=0;
while(hasChange){
hasChange = false;
for(int i=0;i0&&!notml[id].FirstFinish){ //必须是已经处理完成的非终结符才能更新现在的非终结符
ok=false;
break;
}
}
if(ok){ //对非终结符进行更新
for(int k=0;k0&¬ml[id].FirstFinish){
set tmp;
tmp.insert(notml[id].FIRST.begin(),notml[id].FIRST.end()); //将FIRST(Y)加入到FIRST(X)
if(notml[id].FIRST.count(EMPTY)){ //判断空串
Empty++;
tmp.erase(EMPTY);
notml[i].FIRST.insert(tmp.begin(),tmp.end());
hasChange = true;
}
else {
notml[i].FIRST.insert(tmp.begin(),tmp.end());
hasChange = true;
break; //没有空串则停止
}
}
}
if(Empty == notml[i].pro[j].size()){ //如果全部字符都有空串,则加入空串到FIRST(X)
notml[i].FIRST.insert(EMPTY);
}
notml[i].proNum++; //记录已经处理候选式
if(notml[i].proNum == notml[i].pro.size()) notml[i].FirstFinish = true; //全部候选式处理完则该非终结符处理完
}
}
}
}
}
}
#endif // GETFIRST_H_INCLUDED
#ifndef GETFOLLOW_H_INCLUDED
#define GETFOLLOW_H_INCLUDED
//输出FOLLOW集合
void dispalyFollow(){
cout<<"---------------FOLLOW start---------------------"<::iterator it=notml[i].FOLLOW.begin();it!=notml[i].FOLLOW.end();it++){
cout< aBP 将FIRST(P)/{&} 加入到FOLLOW(B)
for(int id=0;id0)){
settmp;
int idk = notml[i].pro[j][k+1];
tmp.insert(notml[idk].FIRST.begin(),notml[idk].FIRST.end());
if(tmp.count(EMPTY))
tmp.erase(EMPTY);
notml[id].FOLLOW.insert(tmp.begin(),tmp.end()); //FIRST(P)/{&}加入FOLLOW(A)
}
}
}
}
}
//规则(3)A -> aB 或 A-> aBP
queueque; //记录需要进行处理的非终结符
for(int i=1;i aB
if(notml[i].FOLLOW.size()==0) que.push(id);
else notml[id].FOLLOW.insert(notml[i].FOLLOW.begin(),notml[i].FOLLOW.end());
}
else if((notml[i].pro[j][k]==id)&&(k+10)&&(notml[notml[i].pro[j][k+1]].FIRST.count(0)>0)){
//候选式为 A -> aBP
if(notml[i].FOLLOW.size()==0) que.push(id);
else notml[id].FOLLOW.insert(notml[i].FOLLOW.begin(),notml[i].FOLLOW.end());
}
}
}
}
}
}
#endif // GETFOLLOW_H_INCLUDED
#ifndef GETI_H_INCLUDED
#define GETI_H_INCLUDED
//处理项目集
stackst; //记录需要增长的项目集
bool vis[SIZE]; //标志每次扩展一个项目集的产生式,判断是否重复
int numI = 0; //项目集的数量
Ix tmpI; //项目集的临时变量
//显示每个项目集
void displayByIdI(int id){
cout<<"-----------------start---------------------"< x : I[id].pro){
int idV = x.first;
int dot = x.second;
int idV2 = pro[idV].Vn;
flag = false;
cout<";
for(int j=0;j0){
cout< x:I[id].go){
cout<<"GOTO(";
if(x.first>0){
cout< p:I[i].pro){
// cout< p:I[i].go){
// cout<0){
Closure(pro[i].candy[0]); //根据第一个字符继续搜索
}
}
}
}
//求项目集
void GOTO(int idV,int dot){
memset(vis, false, sizeof(vis)); //每次处理一个项目集要将产生式标志清零
tmpI.pro.insert({idV, dot+1}); //存储产生式以及它的点‘.’位置
if(dot+1 x:I[0].pro){
int idV = x.first;
int dot = x.second;
int Vn = pro[idV].candy[dot];
I[0].v.insert(Vn);
}
//使用栈存储需要增长的项目集,从0号项目集开始
st.push(0);
while(!st.empty()){
int idI = st.top(); //获取项目集编号
st.pop();
for(int x:I[idI].v){ //遍历项目集的出度边
tmpI.Clear(); //初始化临时遍历,用来指定下一个扩展的节点
for(pair p:I[idI].pro){ //遍历项目集的产生式
int idV = p.first;
int dot = p.second;
int v = pro[idV].candy[dot];
if(x == v){ //产生式的点‘.’后面的字符是出度的边的字符则边指向另一个项目集
GOTO(idV, dot);
}
}
I[idI].go.insert({x,getNext()}); //增加一条边
}
}
//输出项目集
for(int i=0;i<=numI;i++){
displayByIdI(i);
cout<
#ifndef GETACTION_H_INCLUDED
#define GETACTION_H_INCLUDED
//求ACTION和GOTO表
int Action[SIZE][SIZE]; //第一维表示项目集编号,第二维表示终结符或非终结符
int Goto[SIZE][SIZE];
//显示表内容
void displayTable(){
cout<<"------------------------------LR Table-----------------------------"<=2*SIZE){
cout<<"r"<p:I[i].pro){ //遍历其全部产生式
idP = p.first;
dot = p.second;
if(pro[idP].candy.size()==dot&&idP==0){ //规则(3) 处理文法开始符,如S` -> S
Action[i][JING]=ACC;
}
else if(pro[idP].candy.size()==dot){ //规则(2) 处理点‘.’在产生式最右边 如A -> a .
for(int j=0;j x:I[i].go){ //遍历每条边
int idt = x.first; //边的字符 a
int idI = x.second; //边的指向项目集 I
if(idt>0){ //点‘.’后面是非终结符 如A -> a . Bp
Goto[i][idt] = idI;
}
else if(pro[idP].candy.size()>dot&&(pro[idP].candy[dot]==idt)){ //点‘.’后面是终结符 如A -> c . ap
Action[i][-idt] = idI;
}
}
}
}
}
displayTable();
}
#endif // GETACTION_H_INCLUDED
#ifndef ANALYSE_H_INCLUDED
#define ANALYSE_H_INCLUDED
//输出ACTION动作
void displayS(int inNum,int stzNum,int stfNum,int tableNum){
cout<<"ACTION["<";
for(int i=0;i0) cout<st){
vectorvec;
while(!st.empty()){
vec.push_back(st.top());
st.pop();
}
for(int i=vec.size()-1;i>=0;i--){
if(i==0) cout.width(20-2*vec.size());
cout<st){
vectorvec;
while(!st.empty()){
vec.push_back(st.top());
st.pop();
}
for(int i=vec.size()-1;i>=0;i--){
if(i==0) cout.width(20-2*vec.size());
if(vec[i]>0) cout< vec){
for(int i=pos;i0) cout<input;
for(int i=0;istz, stf; //状态栈和符号栈
stz.push(0);
stf.push(-JING);
int pos = 0;
int step = 1;
while(1){
cout.width(8);
cout<=2*SIZE){ //归约
int idP = tableNum - 2*SIZE;
for(int i=pro[idP].candy.size()-1;i>=0;i--){ //根据产生式右部进行出栈
if(pro[idP].candy[i]!=stf.top()) errorA();
if(stf.size()==0||stz.size()==0){
errorA();
return ;
}
stf.pop();
stz.pop();
}
stf.push(pro[idP].Vn); //将产生式左部加进符号栈
if(stf.size()==0||stz.size()==0){
errorA();
return ;
}
int stzT = stz.top();
int stznew = Goto[stzT][pro[idP].Vn]; //取得对应的GOTO表值
stz.push(stznew); //将GOTO表的值加入状态栈
displayR(stzT,tableNum,idP,stznew); //输出归约动作
}else{ //移进
stz.push(tableNum);
stf.push(inNum);
pos++;
displayS(inNum,stzNum,stfNum,tableNum);
}
cout<
#ifndef CHECK_H_INCLUDED
#define CHECK_H_INCLUDED
void errorG()
{
cout<<"输入的文法有误"<
#ifndef DISPLAY_H_INCLUDED
#define DISPLAY_H_INCLUDED
void displayPro2(){
for(int i=0;i ";
for(int j=0;j< notml[i].pro.size();j++){
for(int k=0;k0)
cout<";
for(int x : pro[i].candy){
if(x>0){
cout<