提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、正则表达式 -> DFA -> 最小化DFA
#include<iostream>
#include<cstring>
#include<string>
#include<stack>
#include<vector>
#include<set>
#include<queue>
#define MAX 128
using namespace std;
typedef set<int> IntSet;
typedef set<char> CharSet;
/********************表达式转NFA********************/
struct NfaState /*定义NFA状态*/
{
int index; /*NFA状态的状态号*/
char input; /*NFA状态弧上的值*/
int chTrans; /*NFA状态弧转移到的状态号*/
IntSet epTrans; /*当前状态通过ε转移到的状态号集合*/
};
struct NFA
{
NfaState *head; /*NFA的头指针*/
NfaState *tail; /*NFA的尾指针*/
};
NfaState NfaStates[MAX]; /*NFA状态数组*/
int nfaStateNum = 0; /*NFA状态总数*/
/*从状态n1到状态n2添加一条弧,弧上的值为ch*/
void add(NfaState *n1, NfaState *n2, char ch)
{
n1->input = ch;
n1->chTrans = n2->index;
}
/*从状态n1到状态n2添加一条弧,弧上的值为ε*/
void add(NfaState *n1, NfaState *n2)
{
n1->epTrans.insert(n2->index);
}
/*新建一个NFA(即从NFA状态数组中取出两个状态)*/
NFA creatNFA(int sum)
{
NFA n;
n.head = &NfaStates[sum];
n.tail = &NfaStates[sum + 1];
return n;
}
/*在字符串s第n位后面插入字符ch*/
void insert(string &s, int n, char ch)
{
s += '#';
for(int i = s.size() - 1; i > n; i--)
{
s[i] = s[i - 1];
}
s[n] = ch;
}
/*对字符串s进行预处理,在第一位是操作数、‘*’或‘)’且第二位是操作数或‘(’之间加入连接符‘&’*/
void preprocess(string &s)
{
int i = 0 , length = s.size();
while(i < length)
{
if((s[i] >= 'a' && s[i] <= 'z') || (s[i] == '*') || (s[i] == ')'))
{
if((s[i + 1] >= 'a' && s[i + 1] <= 'z') || s[i + 1] == '(')
{
insert(s, i+1 , '&');
length ++;
}
}
i++;
}
}
/*中缀转后缀时用到的优先级比较,即为每个操作符赋一个权重,通过权重大小比较优先级*/
int priority(char ch)
{
if(ch == '*')
{
return 3;
}
if(ch == '&')
{
return 2;
}
if(ch == '|')
{
return 1;
}
if(ch == '(')
{
return 0;
}
}
/*中缀表达式转后缀表达式*/
string infixToSuffix(string s)
{
preprocess(s); /*对字符串进行预处理*/
string str; /*要输出的后缀字符串*/
stack<char> oper; /*运算符栈*/
for(int i = 0; i < s.size(); i++)
{
if(s[i] >= 'a' && s[i] <= 'z') /*如果是操作数直接输出*/
{
str += s[i];
}
else /*遇到运算符时*/
{
if(s[i] == '(') /*遇到左括号压入栈中*/
{
oper.push(s[i]);
}
else if(s[i] == ')') /*遇到右括号时*/
{
char ch = oper.top();
while(ch != '(') /*将栈中元素出栈,直到栈顶为左括号*/
{
str += ch;
oper.pop();
ch = oper.top();
}
oper.pop(); /*最后将左括号出栈*/
}
else /*遇到其他操作符时*/
{
if(!oper.empty()) /*如果栈不为空*/
{
char ch = oper.top();
while(priority(ch) >= priority(s[i])) /*弹出栈中优先级大于等于当前运算符的运算符*/
{
str += ch;
oper.pop();
if(oper.empty()) /*如果栈为空则结束循环*/
{
break;
}
else ch = oper.top();
}
oper.push(s[i]); /*再将当前运算符入栈*/
}
else /*如果栈为空,直接将运算符入栈*/
{
oper.push(s[i]);
}
}
}
}
/*最后如果栈不为空,则出栈并输出到字符串*/
while(!oper.empty())
{
char ch = oper.top();
oper.pop();
str += ch;
}
cout<<"*******************************************"<<endl<<endl;
cout<<"中缀表达式为:"<<s<<endl<<endl;
cout<<"后缀表达式为:"<<str<<endl<<endl;
return str;
}
/*后缀表达式转nfa*/
NFA strToNfa(string s)
{
stack<NFA> NfaStack; /*定义一个NFA栈*/
for(int i = 0; i < s.size(); i++) /*读取后缀表达式,每次读一个字符*/
{
if(s[i] >= 'a' && s[i] <= 'z') /*遇到操作数*/
{
NFA n = creatNFA(nfaStateNum); /*新建一个NFA*/
nfaStateNum += 2; /*NFA状态总数加2*/
add(n.head, n.tail, s[i]); /*NFA的头指向尾,弧上的值为s[i]*/
NfaStack.push(n); /*将该NFA入栈*/
}
else if(s[i] == '*') /*遇到闭包运算符*/
{
NFA n1 = creatNFA(nfaStateNum); /*新建一个NFA*/
nfaStateNum += 2; /*NFA状态总数加2*/
NFA n2 = NfaStack.top(); /*从栈中弹出一个NFA*/
NfaStack.pop();
add(n2.tail, n1.head); /*n2的尾通过ε指向n1的头*/
add(n2.tail, n1.tail); /*n2的尾通过ε指向n1的尾*/
add(n1.head, n2.head); /*n1的头通过ε指向n2的头*/
add(n1.head, n1.tail); /*n1的头通过ε指向n1的尾*/
NfaStack.push(n1); /*最后将新生成的NFA入栈*/
}
else if(s[i] == '|') /*遇到或运算符*/
{
NFA n1, n2; /*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
n2 = NfaStack.top();
NfaStack.pop();
n1 = NfaStack.top();
NfaStack.pop();
NFA n = creatNFA(nfaStateNum); /*新建一个NFA*/
nfaStateNum +=2; /*NFA状态总数加2*/
add(n.head, n1.head); /*n的头通过ε指向n1的头*/
add(n.head, n2.head); /*n的头通过ε指向n2的头*/
add(n1.tail, n.tail); /*n1的尾通过ε指向n的尾*/
add(n2.tail, n.tail); /*n2的尾通过ε指向n的尾*/
NfaStack.push(n); /*最后将新生成的NFA入栈*/
}
else if(s[i] == '&') /*遇到连接运算符*/
{
NFA n1, n2, n; /*定义一个新的NFA n*/
n2 = NfaStack.top(); /*从栈中弹出两个NFA,栈顶为n2,次栈顶为n1*/
NfaStack.pop();
n1 = NfaStack.top();
NfaStack.pop();
add(n1.tail, n2.head); /*n1的尾通过ε指向n2的尾*/
n.head = n1.head; /*n的头为n1的头*/
n.tail = n2.tail; /*n的尾为n2的尾*/
NfaStack.push(n); /*最后将新生成的NFA入栈*/
}
}
return NfaStack.top(); /*最后的栈顶元素即为生成好的NFA*/
}
/*打印NFA函数*/
void printNFA(NFA nfa)
{
cout<<"*************** NFA ***************"<<endl<<endl;
cout<<"NFA总共有"<<nfaStateNum<<"个状态,"<<endl;
cout<<"初态为"<<nfa.head->index<<",终态为" <<nfa.tail->index<<"。"<<endl<<endl<<"转移函数为:"<<endl;
for(int i = 0; i < nfaStateNum; i++) /*遍历NFA状态数组*/
{
if(NfaStates[i].input != '#') /*如果弧上的值不是初始时的‘#’则输出*/
{
cout<<NfaStates[i].index<<"-->'"<<NfaStates[i].input<<"'-->"<<NfaStates[i].chTrans<<'\t';
}
IntSet::iterator it; /*输出该状态经过ε到达的状态*/
for(it = NfaStates[i].epTrans.begin(); it != NfaStates[i].epTrans.end(); it++)
{
cout<<NfaStates[i].index<<"-->'"<<' '<<"'-->"<<*it<<'\t';
}
cout<<endl;
}
}
/********************NFA转DFA********************/
struct Edge /*定义DFA的转换弧*/
{
char input; /*弧上的值*/
int Trans; /*弧所指向的状态号*/
};
struct DfaState /*定义DFA状态*/
{
bool isEnd; /*是否为终态,是为true,不是为false*/
int index; /*DFA状态的状态号*/
IntSet closure; /*NFA的ε-move()闭包*/
int edgeNum; /*DFA状态上的射出弧数*/
Edge Edges[10]; /*DFA状态上的射出弧*/
};
DfaState DfaStates[MAX]; /*DFA状态数组*/
int dfaStateNum = 0; /*DFA状态总数*/
struct DFA /*定义DFA结构*/
{
int startState; /*DFA的初态*/
set<int> endStates; /*DFA的终态集*/
set<char> terminator; /*DFA的终结符集*/
int trans[MAX][26]; /*DFA的转移矩阵*/
};
/*求一个状态集的ε-cloure*/
IntSet epcloure(IntSet s)
{
stack<int> epStack; /*(此处栈和队列均可)*/
IntSet::iterator it;
for(it = s.begin(); it != s.end(); it++)
{
epStack.push(*it); /*将该状态集中的每一个元素都压入栈中*/
}
while(!epStack.empty()) /*只要栈不为空*/
{
int temp = epStack.top(); /*从栈中弹出一个元素*/
epStack.pop();
IntSet::iterator iter;
for(iter = NfaStates[temp].epTrans.begin(); iter != NfaStates[temp].epTrans.end(); iter++)
{
if(!s.count(*iter)) /*遍历它通过ε能转换到的状态集*/
{ /*如果当前元素没有在集合中出现*/
s.insert(*iter); /*则把它加入集合中*/
epStack.push(*iter); /*同时压入栈中*/
}
}
}
return s; /*最后的s即为ε-cloure*/
}
/*求一个状态集s的ε-cloure(move(ch))*/
IntSet moveEpCloure(IntSet s, char ch)
{
IntSet temp;
IntSet::iterator it;
for(it = s.begin(); it != s.end(); it++) /*遍历当前集合s中的每个元素*/
{
if(NfaStates[*it].input == ch) /*如果对应转换弧上的值为ch*/
{
temp.insert(NfaStates[*it].chTrans); /*则把该弧通过ch转换到的状态加入到集合temp中*/
}
}
temp = epcloure(temp); /*最后求temp的ε闭包*/
return temp;
}
/*判断一个状态是否为终态*/
bool IsEnd(NFA n, IntSet s)
{
IntSet::iterator it;
for(it = s.begin(); it != s.end(); it++) /*遍历该状态所包含的nfa状态集*/
{
if(*it == n.tail->index) /*如果包含nfa的终态,则该状态为终态,返回true*/
{
return true;
}
}
return false; /*如果不包含,则不是终态,返回false*/
}
/*nfa转dfa主函数*/
DFA nfaToDfa(NFA n, string str) /*参数为nfa和后缀表达式*/
{
cout<<"*************** DFA ***************"<<endl<<endl;
int i;
DFA d;
set<IntSet> states; /*定义一个存储整数集合的集合,用于判断求出一个状态集s的ε-cloure(move(ch))后是否出现新状态*/
memset(d.trans, -1, sizeof(d.trans)); /*初始化dfa的转移矩阵*/
for(i = 0; i < str.size(); i++) /*遍历后缀表达式*/
{
if(str[i] >= 'a' && str[i] <= 'z') /*如果遇到操作数,则把它加入到dfa的终结符集中*/
{
d.terminator.insert(str[i]);
}
}
d.startState = 0; /*dfa的初态为0*/
IntSet tempSet;
tempSet.insert(n.head->index); /*将nfa的初态加入到集合中*/
DfaStates[0].closure = epcloure(tempSet); /*求dfa的初态*/
DfaStates[0].isEnd = IsEnd(n, DfaStates[0].closure); /*判断初态是否为终态*/
dfaStateNum++; /*dfa数量加一*/
queue<int> q;
q.push(d.startState); /*把dfa的初态存入队列中(此处栈和队列均可)*/
while(!q.empty()) /*只要队列不为空,就一直循环*/
{
int num = q.front(); /*出去队首元素*/
q.pop();
CharSet::iterator it;
for(it = d.terminator.begin(); it != d.terminator.end(); it++) /*遍历终结符集*/
{
IntSet temp = moveEpCloure(DfaStates[num].closure, *it); /*计算每个终结符的ε-cloure(move(ch))*/
/*IntSet::iterator t;
cout<<endl;
for(t = temp.begin(); t != temp.end(); t++) 打印每次划分
{
cout<<*t<<' ';
}
cout<<endl;*/
if(!states.count(temp) && !temp.empty()) /*如果求出来的状态集不为空且与之前求出来的状态集不同,则新建一个DFA状态*/
{
states.insert(temp); /*将新求出来的状态集加入到状态集合中*/
DfaStates[dfaStateNum].closure = temp;
DfaStates[num].Edges[DfaStates[num].edgeNum].input = *it; /*该状态弧的输入即为当前终结符*/
DfaStates[num].Edges[DfaStates[num].edgeNum].Trans = dfaStateNum; /*弧转移到的状态为最后一个DFA状态*/
DfaStates[num].edgeNum++; /*该状态弧的数目加一*/
d.trans[num][*it - 'a'] = dfaStateNum; /*更新转移矩阵*/
DfaStates[dfaStateNum].isEnd = IsEnd(n, DfaStates[dfaStateNum].closure); /*判断是否为终态*/
q.push(dfaStateNum); /*将新的状态号加入队列中*/
dfaStateNum++; /*DFA状态总数加一*/
}
else /*求出来的状态集在之前求出的某个状态集相同*/
{
for(i = 0; i < dfaStateNum; i++) /*遍历之前求出来的状态集合*/
{
if(temp == DfaStates[i].closure) /*找到与该集合相同的DFA状态*/
{
DfaStates[num].Edges[DfaStates[num].edgeNum].input = *it; /*该状态弧的输入即为当前终结符*/
DfaStates[num].Edges[DfaStates[num].edgeNum].Trans = i; /*该弧转移到的状态即为i*/
DfaStates[num].edgeNum++; /*该状态弧的数目加一*/
d.trans[num][*it - 'a'] = i; /*更新转移矩阵*/
break;
}
}
}
}
}
/*计算dfa的终态集*/
for(i = 0; i < dfaStateNum; i++) /*遍历dfa的所有状态*/
{
if(DfaStates[i].isEnd == true) /*如果该状态是终态*/
{
d.endStates.insert(i); /*则将该状态号加入到dfa的终态集中*/
}
}
return d;
}
/*打印dfa函数*/
void printDFA(DFA d)
{
int i, j;
cout<<"DFA总共有"<<dfaStateNum<<"个状态,"<<"初态为"<<d.startState<<endl<<endl;
cout<<"有穷字母表为{ ";
set<char>::iterator it;
for(it = d.terminator.begin(); it != d.terminator.end(); it++)
{
cout<<*it<<' ';
}
cout<<'}'<<endl<<endl;
cout<<"终态集为{ ";
IntSet::iterator iter;
for(iter = d.endStates.begin(); iter != d.endStates.end(); iter++)
{
cout<<*iter<<' ';
}
cout<<'}'<<endl<<endl;
cout<<"转移函数为:"<<endl;
for(i = 0; i < dfaStateNum; i++)
{
for(j = 0; j < DfaStates[i].edgeNum; j++)
{
if(DfaStates[DfaStates[i].Edges[j].Trans].isEnd == true)
{
cout<<DfaStates[i].index<<"-->'"<<DfaStates[i].Edges[j].input;
cout<<"'--><"<<DfaStates[i].Edges[j].Trans<<">\t";
}
else
{
cout<<DfaStates[i].index<<"-->'"<<DfaStates[i].Edges[j].input;
cout<<"'-->"<<DfaStates[i].Edges[j].Trans<<'\t';
}
}
cout<<endl;
}
cout<<endl<<"转移矩阵为:"<<endl<<" ";
CharSet::iterator t;
for(t = d.terminator.begin(); t != d.terminator.end(); t++)
{
cout<<*t<<" ";
}
cout<<endl;
for(i = 0; i < dfaStateNum; i++)
{
if(d.endStates.count(i))
{
cout<<'<'<<i<<"> ";
}
else
{
cout<<' '<<i<<" ";
}
for(j = 0; j < 26; j++)
{
if(d.terminator.count(j + 'a'))
{
if(d.trans[i][j] != -1)
{
cout<<d.trans[i][j]<<" ";
}
else
{
cout<<" ";
}
}
}
cout<<endl;
}
}
/******************DFA的最小化******************/
IntSet s[MAX]; /*划分出来的集合数组*/
DfaState minDfaStates[MAX]; /*minDfa状态数组*/
int minDfaStateNum = 0; /*minDfa的状态总数,同时也是划分出的集合数*/
struct stateSet /*划分状态集*/
{
int index; /*该状态集所能转换到的状态集标号*/
IntSet s; /*该状态集中的dfa状态号*/
};
/*当前划分总数为count,返回状态n所属的状态集标号i*/
int findSetNum(int count, int n)
{
for(int i = 0; i < count; i++)
{
if(s[i].count(n))
{
return i;
}
}
}
/*最小化DFA*/
DFA minDFA(DFA d)
{
int i, j;
cout<<endl<<"************* minDFA **************"<<endl<<endl;
DFA minDfa;
minDfa.terminator = d.terminator; /*把dfa的终结符集赋给minDfa*/
memset(minDfa.trans, -1, sizeof(minDfa.trans)); /*初始化minDfa转移矩阵*/
/*做第一次划分,即将终态与非终态分开*/
bool endFlag = true; /*判断dfa的所有状态是否全为终态的标志*/
for(i = 0; i < dfaStateNum; i++) /*遍历dfa状态数组*/
{
if(DfaStates[i].isEnd == false) /*如果该dfa状态不是终态*/
{
endFlag = false; /*标志应为false*/
minDfaStateNum = 2; /*第一次划分应该有两个集合*/
s[1].insert(DfaStates[i].index); /*把该状态的状态号加入s[1]集合中*/
}
else /*如果该dfa状态是终态*/
{
s[0].insert(DfaStates[i].index); /*把该状态的状态号加入s[0]集合中*/
}
}
if(endFlag) /*如果标志为真,则所有dfa状态都是终态*/
{
minDfaStateNum = 1; /*第一次划分结束应只有一个集合*/
}
bool cutFlag = true; /*上一次是否产生新的划分的标志*/
while(cutFlag) /*只要上一次产生新的划分就继续循环*/
{
int cutCount = 0; /*需要产生新的划分的数量*/
for(i = 0; i < minDfaStateNum; i++) /*遍历每个划分集合*/
{
CharSet::iterator it;
for(it = d.terminator.begin(); it != d.terminator.end(); it++) /*遍历dfa的终结符集*/
{
int setNum = 0; /*当前缓冲区中的状态集个数*/
stateSet temp[20]; /*划分状态集“缓冲区”*/
IntSet::iterator iter;
for(iter = s[i].begin(); iter != s[i].end(); iter++) /*遍历集合中的每个状态号*/
{
bool epFlag = true; /*判断该集合中是否存在没有该终结符对应的转换弧的状态*/
for(j = 0; j < DfaStates[*iter].edgeNum; j++) /*遍历该状态的所有边*/
{
if(DfaStates[*iter].Edges[j].input == *it) /*如果该边的输入为该终结符*/
{
epFlag = false; /*则标志为false*/
/*计算该状态转换到的状态集的标号*/
int transNum = findSetNum(minDfaStateNum, DfaStates[*iter].Edges[j].Trans);
int curSetNum = 0; /*遍历缓冲区,寻找是否存在到达这个标号的状态集*/
while((temp[curSetNum].index != transNum) && (curSetNum < setNum))
{
curSetNum++;
}
if(curSetNum == setNum) /*缓冲区中不存在到达这个标号的状态集*/
{
/*在缓冲区中新建一个状态集*/
temp[setNum].index = transNum; /*该状态集所能转换到的状态集标号为transNum*/
temp[setNum].s.insert(*iter); /*把当前状态添加到该状态集中*/
setNum++; /*缓冲区中的状态集个数加一*/
}
else /*缓冲区中存在到达这个标号的状态集*/
{
temp[curSetNum].s.insert(*iter); /*把当前状态加入到该状态集中*/
}
}
}
if(epFlag) /*如果该状态不存在与该终结符对应的转换弧*/
{
/*寻找缓冲区中是否存在转换到标号为-1的状态集
这里规定如果不存在转换弧,则它所到达的状态集标号为-1*/
int curSetNum = 0;
while((temp[curSetNum].index != -1) && (curSetNum < setNum))
{
curSetNum++;
}
if(curSetNum == setNum) /*如果不存在这样的状态集*/
{
/*在缓冲区中新建一个状态集*/
temp[setNum].index = -1; /*该状态集转移到的状态集标号为-1*/
temp[setNum].s.insert(*iter); /*把当前状态加入到该状态集中*/
setNum++; /*缓冲区中的状态集个数加一*/
}
else /*缓冲区中存在到达这个标号的状态集*/
{
temp[curSetNum].s.insert(*iter); /*把当前状态加入到该状态集中*/
}
}
}
if(setNum > 1) /*如果缓冲区中的状态集个数大于1,表示同一个状态集中的元素能转换到不同的状态集,则需要划分*/
{
cutCount++; /*划分次数加一*/
/*为每组划分创建新的dfa状态*/
for(j = 1; j < setNum; j++) /*遍历缓冲区,这里从1开始是将第0组划分留在原集合中*/
{
IntSet::iterator t;
for(t = temp[j].s.begin(); t != temp[j].s.end(); t++)
{
s[i].erase(*t); /*在原来的状态集中删除该状态*/
s[minDfaStateNum].insert(*t); /*在新的状态集中加入该状态*/
}
minDfaStateNum++; /*最小化DFA状态总数加一*/
}
}
}
}
if(cutCount == 0) /*如果需要划分的次数为0,表示本次不需要进行划分*/
{
cutFlag = false;
}
}
/*遍历每个划分好的状态集*/
for(i = 0; i < minDfaStateNum; i++)
{
IntSet::iterator y;
for(y = s[i].begin(); y != s[i].end(); y++) /*遍历集合中的每个元素*/
{
if(*y == d.startState) /*如果当前状态为dfa的初态,则该最小化DFA状态也为初态*/
{
minDfa.startState = i;
}
if(d.endStates.count(*y)) /*如果当前状态是终态,则该最小化DFA状态也为终态*/
{
minDfaStates[i].isEnd = true;
minDfa.endStates.insert(i); /*将该最小化DFA状态加入终态集中*/
}
for(j = 0; j < DfaStates[*y].edgeNum; j++) /*遍历该DFA状态的每条弧,为最小化DFA创建弧*/
{
/*遍历划分好的状态集合,找出该弧转移到的状态现在属于哪个集合*/
for(int t = 0; t < minDfaStateNum; t++)
{
if(s[t].count(DfaStates[*y].Edges[j].Trans))
{
bool haveEdge = false; /*判断该弧是否已经创建的标志*/
for(int l = 0; l < minDfaStates[i].edgeNum; l++) /*遍历已创建的弧*/
{ /*如果该弧已经存在*/
if((minDfaStates[i].Edges[l].input == DfaStates[*y].Edges[j].input) && (minDfaStates[i].Edges[l].Trans == t))
{
haveEdge = true; /*标志为真*/
}
}
if(!haveEdge) /*如果该弧不存在,则创建一条新的弧*/
{
minDfaStates[i].Edges[minDfaStates[i].edgeNum].input = DfaStates[*y].Edges[j].input; /*弧的值与DFA的相同*/
minDfaStates[i].Edges[minDfaStates[i].edgeNum].Trans = t; /*该弧转移到的状态为这个状态集的标号*/
minDfa.trans[i][DfaStates[*y].Edges[j].input - 'a'] = t; /*更新转移矩阵*/
minDfaStates[i].edgeNum++; /*该状态的弧的数目加一*/
}
break;
}
}
}
}
}
return minDfa;
}
void printMinDFA(DFA d)
{
int i, j;
cout<<"minDFA总共有"<<minDfaStateNum<<"个状态,"<<"初态为"<<d.startState<<endl<<endl;
cout<<"有穷字母表为{ ";
set<char>::iterator it;
for(it = d.terminator.begin(); it != d.terminator.end(); it++)
{
cout<<*it<<' ';
}
cout<<'}'<<endl<<endl;
cout<<"终态集为{ ";
IntSet::iterator iter;
for(iter = d.endStates.begin(); iter != d.endStates.end(); iter++)
{
cout<<*iter<<' ';
}
cout<<'}'<<endl<<endl;
cout<<"转移函数为:"<<endl;
for(i = 0; i < minDfaStateNum; i++)
{
for(j = 0; j < minDfaStates[i].edgeNum; j++)
{
if(minDfaStates[minDfaStates[i].Edges[j].Trans].isEnd == true)
{
cout<<minDfaStates[i].index<<"-->'"<<minDfaStates[i].Edges[j].input;
cout<<"'--><"<<minDfaStates[i].Edges[j].Trans<<">\t";
}
else
{
cout<<minDfaStates[i].index<<"-->'"<<minDfaStates[i].Edges[j].input;
cout<<"'-->"<<minDfaStates[i].Edges[j].Trans<<'\t';
}
}
cout<<endl;
}
cout<<endl<<"转移矩阵为:"<<endl<<" ";
CharSet::iterator t;
for(t = d.terminator.begin(); t != d.terminator.end(); t++)
{
cout<<*t<<" ";
}
cout<<endl;
for(i = 0; i < minDfaStateNum; i++)
{
if(d.endStates.count(i))
{
cout<<'<'<<i<<"> ";
}
else
{
cout<<' '<<i<<" ";
}
for(j = 0; j < 26; j++)
{
if(d.terminator.count(j + 'a'))
{
if(d.trans[i][j] != -1)
{
cout<<d.trans[i][j]<<" ";
}
else
{
cout<<" ";
}
}
}
cout<<endl;
}
cout<<endl<<"*******************************************";
}
int main()
{
/*测试样例1
string str = "(a|b)*abb";*/
/*测试样例2*/
string str = "(a|b*)c*";
str = infixToSuffix(str); /*将中缀表达式转换为后缀表达式*/
/***初始化所有的数组***/
int i, j;
for(i = 0; i < MAX; i++)
{
NfaStates[i].index = i;
NfaStates[i].input = '#';
NfaStates[i].chTrans = -1;
}
for(i = 0; i < MAX; i++)
{
DfaStates[i].index = i;
DfaStates[i].isEnd = false;
for(j = 0; j < 10; j++)
{
DfaStates[i].Edges[j].input = '#';
DfaStates[i].Edges[j].Trans = -1;
}
}
for(i = 0; i < MAX; i++)
{
minDfaStates[i].index = i;
minDfaStates[i].isEnd = false;
for(int j = 0; j < 10; j++)
{
minDfaStates[i].Edges[j].input = '#';
minDfaStates[i].Edges[j].Trans = -1;
}
}
NFA n = strToNfa(str);
printNFA(n);
DFA d = nfaToDfa(n, str);
printDFA(d);
DFA minDfa = minDFA(d);
printMinDFA(minDfa);
return 0;
}
二、LL(1)
#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <stack>
using namespace std;
// 未实现处理左递归 & 公共左因子 仅能处理LL(1)文法
// 用&符号代表一步赛龙e,且不充当表格行头的终结符。
/* 产生式结构体 */
struct Production {
char left; // 左部符号
vector<char> rigths; // 右部符号串
};
/* 文法结构体 */
struct Grammar {
int num; // 产生式数量
vector<char> T; // 终结符
vector<char> N; // 非终结符
vector<Production> prods; //产生式
} grammar;
/* FIRST集和FOLLOW集 */
map<char, set<char> > first;
map<char, set<char> > follow;
/* 分析栈 */
stack<char> ST;
/* 待分析串 */
string str;
/* 预测分析表 */
vector<char> M[50][50];
/* 判断ch是否是终结符 */
int isInT(char ch)
{
for (int i = 0; i < grammar.T.size(); i++) {
if (grammar.T[i] == ch) {
return i + 1;
}
}
return 0;
}
/* 判断ch是否是非终结符 */
int isInN(char ch)
{
for (int i = 0; i < grammar.N.size(); i++) {
if (grammar.N[i] == ch) {
return i + 1;
}
}
return 0;
}
/* 求(T U N)的FIRST集 */
void getFirstSet()
{
/* 终结符的FIRST集是其本身 */
for (int i = 0; i < grammar.T.size(); i++) {
char X = grammar.T[i];
set<char> tmp;
tmp.insert(X);
first[X] = tmp;
}
/* 当非终结符的FIRST集发生变化时循环 */
bool change = true;
while (change) {
change = false;
/* 枚举每个产生式 */
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
char X = P.left;
set<char> &FX = first[X];
/* 如果右部第一个符号是空或者是终结符,则加入到左部的FIRST集中 */
if (isInT(P.rigths[0]) || P.rigths[0] == '&') {
/* 查找是否FIRST集是否已经存在该符号 */
auto it = FX.find(P.rigths[0]);
/* 不存在 */
if (it == FX.end()) {
change = true; // 标注FIRST集发生变化,循环继续
FX.insert(P.rigths[0]);
}
} else {
/* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
bool next = true;
/* 待判断符号的下标 */
int idx = 0;
while (next && idx < P.rigths.size()) {
next = false;
char Y = P.rigths[idx];
set<char> &FY = first[Y];
for (auto it = FY.begin(); it != FY.end(); it++) {
/* 把当前符号的FIRST集中非空元素加入到左部符号的FIRST集中 */
if (*it != '&') {
auto itt = FX.find(*it);
if (itt == FX.end()) {
change = true;
FX.insert(*it);
}
}
}
/* 当前符号的FIRST集中有空, 标记next为真,idx下标+1 */
auto it = FY.find('&');
if (it != FY.end()) {
next = true;
idx = idx + 1;
}
}
}
}
}
printf("FIRST:\n");
for (int i = 0; i < grammar.N.size(); i++) {
char X = grammar.N[i];
printf("%c: ", X);
for (auto it = first[X].begin(); it != first[X].end(); it++) {
printf("%c ", *it);
}
printf("\n");
}
}
/* 产找alpha串的FIRST集, 保存到FS集合中 */
void getFirstByAlphaSet(vector<char> &alpha, set<char> &FS)
{
/* 当前符号是非终结符,若当前符号可以推出空,则还需判断下一个符号 */
bool next = true;
int idx = 0;
while (idx < alpha.size() && next) {
next = false;
/* 当前符号是终结符或空,加入到FIRST集中 */
if (isInT(alpha[idx]) || alpha[idx] == '&') {
/* 判断是否已经在FIRST集中 */
auto itt = FS.find(alpha[idx]);
if (itt == FS.end()) {
FS.insert(alpha[idx]);
}
} else {
char B = alpha[idx];
set<char> &FB = first[B];
for (auto it = first[B].begin(); it != first[B].end(); it++) {
/* 当前符号FIRST集包含空,标记next为真,并跳过当前循环 */
if (*it == '&') {
next = true;
continue;
}
/* 把非空元素加入到FIRST集中 */
auto itt = FS.find(*it);
if (itt == FS.end()) {
FS.insert(*it);
}
}
}
idx = idx + 1;
}
/* 如果到达产生式右部末尾next还为真,说明alpha可以推空,将空加入到FIRST集中 */
if (next) {
FS.insert('&');
}
}
/* 求非终结符的FOLLOW集 */
void getFollowSet()
{
/* 初始化终结符的FOLLOW集为空集 */
for (int i = 0; i < grammar.N.size(); i++) {
char B = grammar.N[i];
follow[B] = set<char>();
}
/* 将$加入到文法的开始符号的FOLLOW集中 */
char S = grammar.N[0];
follow[S].insert('$');
bool change = true;
while (change) {
change = false;
/* 枚举每个产生式 */
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
for (int j = 0; j < P.rigths.size(); j++) {
char B = P.rigths[j];
/* 当前符号是非终结符 */
if (isInN(B)) {
set<char> &FB = follow[B];
set<char> FS;
/* alpha是从当前符号下一个符号开始的符号串 */
vector<char> alpha(P.rigths.begin() + j + 1, P.rigths.end());
/* 求alpha的FIRST集,即FS */
getFirstByAlphaSet(alpha, FS);
/* 将alpha的FIRST集中所有非空元素加入到当前符号的FOLLOW集中 */
for (auto it = FS.begin(); it != FS.end(); it++) {
if (*it == '&') {
continue;
}
auto itt = FB.find(*it);
if (itt == FB.end()) {
change = true;
FB.insert(*it);
}
}
/* 如果alpha能推空,或者当前符号是产生式右部末尾,则将文法左部符号的FOLLOW集加入到当前符号的FOLLOW集中 */
auto itt = FS.find('&');
if (itt != FS.end() || (j + 1) >= P.rigths.size()) {
char A = P.left; // A为左部符号
for (auto it = follow[A].begin(); it != follow[A].end(); it++) {
auto itt = FB.find(*it);
if (itt == FB.end()) {
change = true;
FB.insert(*it);
}
}
}
}
}
}
}
printf("FOLLOW:\n");
for (int i = 0; i < grammar.N.size(); i++) {
char X = grammar.N[i];
printf("%c: ", X);
for (auto it = follow[X].begin(); it != follow[X].end(); it++) {
printf("%c ", *it);
}
printf("\n");
}
}
/* 把生成式插入到预测分析表对应的项中 */
void insertTOForecastAnalysisTable(char A, char a, Production &P)
{
/* 根据A和a找到对应表项 */
int i = isInN(A) - 1;
int j = isInT(a) - 1;
/* 把P.left->P.rights插入*/
M[i][j].push_back(P.left);
M[i][j].push_back('-');
M[i][j].push_back('>');
for (auto it = P.rigths.begin(); it != P.rigths.end(); it++) {
M[i][j].push_back(*it);
}
}
/* 取出预测分析表对应的项中的产生式 */
void getFromForecastAnalysisTable(char A, char a, vector<char> &s)
{
/* 根据A和a找到对应表项 */
int i = isInN(A) - 1;
int j = isInT(a) - 1;
/* 取出 */
s.assign(M[i][j].begin(), M[i][j].end());
}
/* 构建预测分析表 */
void productForecastAnalysisTable()
{
/* 枚举所有产生式 */
for (int i = 0; i < grammar.prods.size(); i++) {
/* 假设P为 A->alpha */
Production &P = grammar.prods[i];
set<char> FS;
/* 对每个 a in FIRST(alpha) 把 A->alpha放入M[A, a]中 */
getFirstByAlphaSet(P.rigths, FS);
for (auto it = FS.begin(); it != FS.end(); it++) {
insertTOForecastAnalysisTable(P.left, *it, P);
}
/* 如果alpha能推空,则把每个b in FOLLOW(A) 把 A->alpha放入M[A, b]中*/
auto itt = FS.find('&');
if (itt != FS.end()) {
for (auto it = follow[P.left].begin(); it != follow[P.left].end(); it++) {
insertTOForecastAnalysisTable(P.left, *it, P);
}
}
}
/* 输出预测分析表 */
printf("forecast analysis table:\n");
printf("\t");
for (int i = 0; i < grammar.T.size(); i++) {
printf("%c\t\t", grammar.T[i]);
}
printf("\n");
for (int i = 0; i < grammar.N.size(); i++) {
printf("%c\t", grammar.N[i]);
for (int j = 0; j < grammar.T.size(); j++) {
for(auto k = M[i][j].begin(); k != M[i][j].end(); k++) {
printf("%c", *k);
}
printf("\t\t");
}
printf("\n");
}
}
/* 读入并初始化语法 */
void initGrammar()
{
printf("Please enter the num of production:\n");
cin >> grammar.num;
string s;
printf("Please enter the production:\n");
for (int i = 0; i < grammar.num; i++) {
cin >> s;
Production tmp;
tmp.left = s[0];
for (int j = 3; j < s.size(); j++) {
tmp.rigths.push_back(s[j]);
}
grammar.prods.push_back(tmp);
}
printf("Please enter the non-terminators(end with #):\n");
char ch;
cin >> ch;
while (ch != '#') {
grammar.N.push_back(ch);
cin >> ch;
}
printf("Please enter the terminators(end with #):\n");
cin >> ch;
while (ch != '#') {
grammar.T.push_back(ch);
cin >> ch;
}
/* 把$当作终结符 */
grammar.T.push_back('$');
/* 求FIRST集和FOLLOW集 */
getFirstSet();
getFollowSet();
/* 生成预测分析表 */
productForecastAnalysisTable();
/* 读入待分析串并初始化分析栈 */
printf("Please enter the String to be analyzed:\n");
cin >> str;
str += '$';
ST.push('$');
ST.push(grammar.N[0]);
}
/* 分析程序 */
void process()
{
/* 指向当前字符 */
int ip = 0;
/* 栈顶符号X, 和当前输入符号a */
char X, a;
printf("The answer:\n");
do{
X = ST.top();
a = str[ip];
/* 如果是终结符或者$ */
if (isInT(X)) {
/* 如果栈顶符号和当前符号匹配,出栈,指针前移 */
if (X == a) {
ST.pop();
ip = ip + 1;
} else { /* 不匹配报错 */
printf("error1\n");
}
} else { //非终结符
vector<char> s;
/* 取出对应预测分析表的项 */
getFromForecastAnalysisTable(X, a, s);
/* 预测分析表项中有元素 */
if (!s.empty()) {
/* 弹栈并将右部符号串逆序入栈 */
ST.pop();
for (int i = s.size() - 1; i >= 3; i--) {
if (s[i] != '&') { // 为空时不入栈
ST.push(s[i]);
}
}
/* 输出产生式 */
for (int i = 0; i < s.size(); i++) {
printf("%c", s[i]);
}
printf("\n");
} else { // 空,报错
printf("error2\n");
}
}
} while (X != '$');
}
int main()
{
initGrammar();
process();
return 0;
}
三、LR(0)
#include<iostream>
#include<vector>
#include<set>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<iomanip>
#define maxn 100
using namespace std;
struct G{
char left;
int dot=0;
string right;
};
string Action[maxn][maxn];
int Goto[maxn][maxn];
vector<char> tmp_index[maxn];//第i个状态的全部首字母
string Terminal="";
string NotTerminal="";
set<char> First[maxn];
int book[maxn]={0};
G g[maxn];
int flag=0;
int total;
vector<G> NotTerminal_closure[maxn];
vector<G> I[maxn];
vector<char> stack;
vector<char> input;
int hadFirst[maxn]={0};
int haveNone[maxn]={0};
void getFirst(char X)
{
int index=NotTerminal.find(X);
if(hadFirst[index]>total)return;
else hadFirst[index]++;
for(int i=0;i<total;i++)
{
if(g[i].left==X)
{
if(haveNone[index]) {
First[index].insert('@');
if(g[i].right[0]=='@'){
continue;
}
}
//第一个为终结符
if(Terminal.find(g[i].right[0])!=string::npos)
{
First[index].insert(g[i].right[0]);
}
else{
//第一个为非终结符
for(int j=0;j<g[i].right.length();j++)
{
//直到找到终结符或者不能推出空串的非终结符才停止
if(Terminal.find(g[i].right[j])!=string::npos)
{
First[index].insert(g[i].right[j]);
break;
}else{
int index_temp = NotTerminal.find(g[i].right[j]);
getFirst(g[i].right[j]);
set<char>::iterator iter;
for(iter=First[index_temp].begin();iter!=First[index_temp].end();iter++)
{
First[index].insert(*iter);
}
if(!haveNone[index_temp])break;
}
}
}
}
}
}
string getsearchFirst(string str){
string temp_str="";
for(int i=0;i<str.length();i++)
{
if(Terminal.find(str[i])!=string::npos)
{
temp_str+=str[i];
break;
}else{
int index = NotTerminal.find(str[i]);
set<char>::iterator iter;
for(iter=First[index].begin();iter!=First[index].end();iter++)
{
temp_str+=(*iter);
}
if(!haveNone[index])break;
}
}
return temp_str;
}
void getAnalysis(string str)
{
stack.push_back('#');
stack.push_back(0);
input.push_back('#');
for(int i=str.length()-1;i>=0;i--) input.push_back(str[i]);
cout<<setw(20)<<"分析栈"<<setw(20)<<"输入串"<<setw(20)<<"动作"<<endl;
do{
string output_str="";
for(int i=0;i<stack.size();i++){
if(i%2==0)
output_str+=stack[i];
else
{
stringstream ss;
ss<<int(stack[i]);
output_str+=ss.str();
}
}
cout<<setw(20)<<output_str;
output_str="";
for(int i=input.size()-1;i>=0;i--) output_str+=input[i];
cout<<setw(20)<<output_str;
int stack_top = stack[stack.size()-1];
char in_top = input[input.size()-1];
int input_top = Terminal.find(in_top);
cout<<input_top;
string output = Action[stack_top][input_top];
cout<<setw(20)<<output<<endl;
if(output[0]=='S')
{
int move=0;
for(int i=1;i<output.length();i++)
move=move*10+(output[i]-'0');
stack.push_back(in_top);
stack.push_back(move);
input.pop_back();
}else if(output[0]=='r')
{
int num=0;
for(int i=1;i<output.length();i++)
num+=num*10+(output[i]-'0');
int p=g[num-1].right.length()-1;
while(p>=0&&stack.size()>=2&&stack[stack.size()-2]==g[num-1].right[p--]){
stack.pop_back();
stack.pop_back();
}
int go_to_2 = NotTerminal.find(g[num-1].left);
int go_to_1 = stack[(stack.size()-1)];
int go_to = Goto[go_to_1][go_to_2];
stack.push_back(g[num-1].left);
stack.push_back(go_to);
}else if(output=="acc"){
//cout<<setw(20)<<"配对成功!";
return;
}
}while(true);
}
void getTable(G item,char X,int num)
{
if(Terminal.find(X)!=string::npos){
int t=Terminal.find(X);
if(item.right.length()==item.dot){
if(item.left==g[0].left){
Action[num][(Terminal.length()-1)]="acc";
}else{
stringstream ss;
ss<<(flag+1);
Action[num][t]="S"+ss.str();
for(int j=0;j<total;j++){
if(item.left==g[j].left&&item.right==g[j].right){
stringstream ss;
ss<<(j+1);
for(int k=0;k<=Terminal.length();k++)
Action[(flag+1)][k]="r"+ss.str();;
break;
}
}
}
}else{
stringstream ss;
ss<<(flag+1);
Action[num][t]="S"+ss.str();
}
}else{
int t=NotTerminal.find(X);
Goto[num][t]=flag+1;
if(item.right.length()==item.dot){
if(item.left==g[0].left)
Action[(flag+1)][(Terminal.length()-1)]="acc";
else{
for(int j=0;j<total;j++)
if(item.left==g[j].left&&item.right==g[j].right){
stringstream ss;
ss<<(j+1);
for(int k=0;k<=Terminal.length();k++)
Action[(flag+1)][k]="r"+ss.str();;
break;
}
}
}
}
}
vector<G> go(vector<G> item,char X,int num)
{
vector<G> tmp;
for(int i=0;i<item.size();i++)
{
if(item[i].right.length()!=item[i].dot)
if(item[i].right[(item[i].dot)] == X){
//cout<<item[i].right<<"haha"<<endl;
item[i].dot++;
getTable(item[i],X,num);
tmp.push_back(item[i]);
}
}
// for(int i=0;i<tmp.size();i++)
// cout<<"tmpbegin "<<tmp[i].left<<"->"<<tmp[i].right<<" "<<tmp[i].dot<<" "<<X<<tmp.empty()<<endl;
int book[maxn]={0};
if(!tmp.empty()){
for(int i=0;i<tmp.size();i++)
{
if(NotTerminal.find(tmp[i].right[(tmp[i].dot)])!=string::npos)
{
int t=NotTerminal.find(tmp[i].right[(tmp[i].dot)]);
if(!book[t])
for(int j=0;j<NotTerminal_closure[t].size();j++)
{
G temp_g = NotTerminal_closure[t][j];
tmp.push_back(temp_g);
}
book[t]=1;
}
}
// for(int i=0;i<tmp.size();i++)
// cout<<"tmpend "<<tmp[i].left<<"->"<<tmp[i].right<<" "<<tmp[i].dot<<" "<<X<<tmp.empty()<<endl;
}
return tmp;
}
//求状态规范族
void get_I()
{
I[0].push_back(g[0]);
//非终结符
int book[maxn]={0};
for(int i=0;i<I[0].size();i++)
{
if(NotTerminal.find(I[0][i].right[(I[0][i].dot)])!=string::npos)
{
int t=NotTerminal.find(I[0][i].right[(I[0][i].dot)]);
if(!book[t])
for(int j=0;j<NotTerminal_closure[t].size();j++)
{
G temp_g = NotTerminal_closure[t][j];
I[0].push_back(temp_g);
}
book[t]=1;
}
}
tmp_index[0].push_back(g[0].right[0]);
for(int i=0;i<=flag;i++)
{
for(int j=0;j<I[i].size();j++)
{
//if(!tmp_index.empty())
if(I[i][j].dot<I[i][j].right.length()&&I[i][j].right[(I[i][j].dot)]!='@'&&find(tmp_index[i].begin(),tmp_index[i].end(),I[i][j].right[(I[i][j].dot)])==tmp_index[i].end())
tmp_index[i].push_back(I[i][j].right[(I[i][j].dot)]);
}
for(int it=0;it<tmp_index[i].size();it++)
{
vector<G> temp=go(I[i],tmp_index[i][it],i);
if(!temp.empty())
I[++flag]=temp;
}
}
for(int i=0;i<=flag;i++)
{
cout<<"I"<<i<<":"<<endl;
for(int j=0;j<I[i].size();j++){
cout<<I[i][j].left<<"->"<<I[i][j].right.substr(0,I[i][j].dot)<<"."<<I[i][j].right.substr(I[i][j].dot,I[i][j].right.length()-I[i][j].dot)<<" "<<I[i][j].dot<<endl;
}
}
}
int main()
{
ifstream read;
read.open("LR(0)input.txt",ios::app);
read>>total;
for(int i=0;i<total;i++)
{
//getchar();
read>>g[i].left>>g[i].right;
cout<<g[i].left<<"->"<<g[i].right<<endl;
g[i].dot=0;
if(NotTerminal.find(g[i].left)==string::npos)
{
NotTerminal+=g[i].left;
}
for(int j=0;j<g[i].right.length();j++)
{
if(g[i].right[j]=='@'){
int temp=NotTerminal.find(g[i].left);
book[temp]=1;
}
else if(g[i].right[j]>='A'&&g[i].right[j]<='Z')
{
if(NotTerminal.find(g[i].right[j])==string::npos)
{
NotTerminal+=g[i].right[j];
}
}
else if(Terminal.find(g[i].right[j])==string::npos)
{
Terminal+=g[i].right[j];
}
}
NotTerminal_closure[NotTerminal.find(g[i].left)].push_back(g[i]);
}
for(int i=0;i<NotTerminal.length();i++)
{
getFirst(NotTerminal[i]);
cout<<"First("<<NotTerminal[i]<<")={";
set<char>::iterator iter;
for(iter=First[i].begin();iter!=First[i].end();iter++)
{
cout<<(*iter)<<",";
}
cout<<"}"<<endl;
}
cout<<"终结符:"<<Terminal<<endl;
cout<<"非终结符:"<<NotTerminal<<endl;
for(int i=0;i<NotTerminal.length();i++)
{
cout<<NotTerminal_closure[i].size();
for(int j=0;j<NotTerminal_closure[i].size();j++)
cout<<NotTerminal_closure[i][j].left<<"->"<<NotTerminal_closure[i][j].right<<" ";
cout<<endl;
}
Terminal+="#";
get_I();
for(int i=0;i<=flag;i++)
{
for(int j=0;j<=Terminal.length();j++)
{
if(!Action[i][j].empty())cout<<"i="<<i<<",j="<<j<<","<<Action[i][j]<<endl;
}
}
for(int i=0;i<NotTerminal.length();i++)
cout<<NotTerminal[i]<<" ";
cout<<"#"<<endl;
for(int i=0;i<=flag;i++)
{
for(int j=0;j<=NotTerminal.length();j++)
cout<<Goto[i][j]<<" ";
cout<<endl;
}
//getAnalysis("aedaec") ;
getAnalysis("vi,i:r") ;
return 0;
}
四、LR(1)
#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <queue>
using namespace std;
/* 产生式结构体,左部符号和右部符号串 */
struct Production {
char left;
vector<char> rigths;
/* 重载== */
bool operator==(Production& rhs) const {
if (left != rhs.left)
return false;
for (int i = 0; i < rigths.size(); i++) {
if (i >= rhs.rigths.size())
return false;
if (rigths[i] != rhs.rigths[i])
return false;
}
return true;
}
};
/* LR1项目 */
struct LR1Item {
Production p;
/* 点的位置 */
int location;
/* 向前看符号 */
char next;
};
/* LR1项目集 */
struct LR1Items {
vector<LR1Item> items;
};
/* LR1项目集规范族 */
struct CanonicalCollection {
/* 项目集集合 */
vector<LR1Items> items;
/* 保存DFA的图,first为转移到的状态序号,second是经什么转移 */
vector< pair<int, char> > g[100];
}CC;
/* 文法结构体 */
struct Grammar {
int num; // 产生式数量
vector<char> T; // 终结符
vector<char> N; // 非终结符
vector<Production> prods; //产生式
}grammar;
/* FIRST集和FOLLOW集 */
map<char, set<char> > first;
map<char, set<char> > follow;
/* DFA队列, 用于存储待转移的有效项目集 */
queue< pair<LR1Items, int> > Q;
/* action表和goto表 */
pair<int, int> action[100][100]; // first表示分析动作,0->ACC 1->S 2->R second表示转移状态或者产生式序号
int goton[100][100];
/* 待分析串 */
string str;
/* 分析栈 */
stack< pair<int, char> > ST; // first是state,second 是symble
/* 判断ch是否是终结符 */
int isInT(char ch)
{
for (int i = 0; i < grammar.T.size(); i++) {
if (grammar.T[i] == ch) {
return i + 1;
}
}
return 0;
}
/* 判断ch是否是非终结符 */
int isInN(char ch)
{
for (int i = 0; i < grammar.N.size(); i++) {
if (grammar.N[i] == ch) {
return i + 1;
}
}
return 0;
}
/* 求(T U N)的FIRST集 */
void getFirstSet()
{
/* 终结符的FIRST集是其本身 */
for (int i = 0; i < grammar.T.size(); i++) {
char X = grammar.T[i];
set<char> tmp;
tmp.insert(X);
first[X] = tmp;
}
/* 当非终结符的FIRST集发生变化时循环 */
bool change = true;
while (change) {
change = false;
/* 枚举每个产生式 */
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
char X = P.left;
set<char> &FX = first[X];
/* 如果右部第一个符号是空或者是终结符,则加入到左部的FIRST集中 */
if (isInT(P.rigths[0]) || P.rigths[0] == '&') {
/* 查找是否FIRST集是否已经存在该符号 */
auto it = FX.find(P.rigths[0]);
/* 不存在 */
if (it == FX.end()) {
change = true; // 标注FIRST集发生变化,循环继续
FX.insert(P.rigths[0]);
}
} else {
/* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
bool next = true;
/* 待判断符号的下标 */
int idx = 0;
while (next && idx < P.rigths.size()) {
next = false;
char Y = P.rigths[idx];
set<char> &FY = first[Y];
for (auto it = FY.begin(); it != FY.end(); it++) {
/* 把当前符号的FIRST集中非空元素加入到左部符号的FIRST集中 */
if (*it != '&') {
auto itt = FX.find(*it);
if (itt == FX.end()) {
change = true;
FX.insert(*it);
}
}
}
/* 当前符号的FIRST集中有空, 标记next为真,idx下标+1 */
auto it = FY.find('&');
if (it != FY.end()) {
next = true;
idx = idx + 1;
}
}
}
}
}
printf("FIRST:\n");
for (int i = 0; i < grammar.N.size(); i++) {
char X = grammar.N[i];
printf("%c: ", X);
for (auto it = first[X].begin(); it != first[X].end(); it++) {
printf("%c ", *it);
}
printf("\n");
}
}
/* 产找alpha串的FIRST集, 保存到FS集合中 */
void getFirstByAlphaSet(vector<char> &alpha, set<char> &FS)
{
/* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
bool next = true;
int idx = 0;
while (idx < alpha.size() && next) {
next = false;
/* 当前符号是终结符或空,加入到FIRST集中 */
if (isInT(alpha[idx]) || alpha[idx] == '&') {
/* 判断是否已经在FIRST集中 */
auto itt = FS.find(alpha[idx]);
if (itt == FS.end()) {
FS.insert(alpha[idx]);
}
} else {
char B = alpha[idx];
set<char> &FB = first[B];
for (auto it = first[B].begin(); it != first[B].end(); it++) {
/* 当前符号FIRST集包含空,标记next为真,并跳过当前循环 */
if (*it == '&') {
next = true;
continue;
}
/* 把非空元素加入到FIRST集中 */
auto itt = FS.find(*it);
if (itt == FS.end()) {
FS.insert(*it);
}
}
}
idx = idx + 1;
}
/* 如果到达产生式右部末尾next还为真,说明alpha可以推空,将空加入到FIRST集中 */
if (next) {
FS.insert('&');
}
}
/* 判断是LR1项目t否在有效项目集I中 */
bool isInLR1Items(LR1Items &I, LR1Item &t)
{
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR1Item &item = *it;
if (item.p == t.p && item.location == t.location && item.next == t.next)
return true;
}
return false;
}
/* 打印某个项目集 */
void printLR1Items(LR1Items &I)
{
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR1Item &L = *it;
printf("%c->", L.p.left);
for (int i = 0; i < L.p.rigths.size(); i++) {
if (L.location == i)
printf(".");
printf("%c", L.p.rigths[i]);
}
if (L.location == L.p.rigths.size())
printf(".");
printf(",%c ", L.next);
}
printf("\n");
}
/* 求I的闭包 */
void closure(LR1Items &I)
{
bool change = true;
while (change) {
change = false;
LR1Items J;
/* 枚举每个项目 */
J.items.assign(I.items.begin(), I.items.end());
for (auto it = J.items.begin(); it != J.items.end(); it++) {
LR1Item &L = *it;
/* 非规约项目 */
if (L.location < L.p.rigths.size()) {
char B = L.p.rigths[L.location];
if (isInN(B)) {
/* 把符合条件的LR1项目加入闭包中 */
/* 先求出B后面的FIRST集 */
set<char> FS;
vector<char> alpha;
alpha.assign(L.p.rigths.begin() + L.location + 1, L.p.rigths.end());
alpha.push_back(L.next);
getFirstByAlphaSet(alpha, FS);
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
if (P.left == B) {
/* 枚举每个b in B后面的FIRST集 */
for (auto it = FS.begin(); it != FS.end(); it++) {
char b = *it;
LR1Item t;
t.location = 0;
t.next = b;
t.p.left = P.left;
t.p.rigths.assign(P.rigths.begin(), P.rigths.end());
if (!isInLR1Items(I, t)) {
/* 标记改变 */
change = true;
I.items.push_back(t);
}
}
}
}
}
}
}
}
}
/* 判断是否在项目集规范族中,若在返回序号 */
int isInCanonicalCollection(LR1Items &I)
{
for (int i = 0; i < CC.items.size(); i++) {
LR1Items &J = CC.items[i];
bool flag = true;
if (J.items.size() != I.items.size()) {
flag = false;
continue;
}
/* 每个项目都在该项目集中,则认为这个两个项目集相等 */
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR1Item &t = *it;
if (!isInLR1Items(J, t)) {
flag = false;
break;
}
}
if (flag) {
return i + 1;
}
}
return 0;
}
/* 转移函数,I为当前的项目集,J为转移后的项目集, 经X转移 */
void go(LR1Items &I, char X, LR1Items &J)
{
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR1Item &L = *it;
/* 非规约项目 */
if (L.location < L.p.rigths.size()) {
char B = L.p.rigths[L.location];
/* 如果点后面是非终结符,且非终结符为X,点位置加1, 加入到转移项目集中*/
if (B == X) {
LR1Item t;
t.location = L.location + 1;
t.next = L.next;
t.p.left = L.p.left;
t.p.rigths.assign(L.p.rigths.begin(), L.p.rigths.end());
J.items.push_back(t);
}
}
}
/* 若J中有项目,则求其闭包 */
if (J.items.size() > 0) {
closure(J);
}
}
/* 构建DFA和项目集规范族 */
void DFA()
{
/* 构建初始项目集 */
LR1Item t;
t.location = 0;
t.next = '$';
t.p.left = grammar.prods[0].left;
t.p.rigths.assign(grammar.prods[0].rigths.begin(), grammar.prods[0].rigths.end());
LR1Items I;
I.items.push_back(t);
closure(I);
/* 加入初始有效项目集 */
CC.items.push_back(I);
/* 把新加入的有效项目集加入待扩展队列中 */
Q.push(pair<LR1Items, int>(I, 0));
while (!Q.empty()) {
LR1Items &S = Q.front().first;
int sidx = Q.front().second;
/* 遍历每个终结符 */
for (int i = 0; i < grammar.T.size(); i++) {
LR1Items D;
go(S, grammar.T[i], D);
int idx;
/* 若不为空 */
if (D.items.size() > 0) {
/* 查找是否已经在有效项目集族里 */
idx = isInCanonicalCollection(D);
if (idx > 0) {
idx = idx - 1;
} else {
idx = CC.items.size();
CC.items.push_back(D);
/* 把新加入的有效项目集加入待扩展队列中 */
Q.push(pair<LR1Items, int>(D, idx));
}
/* 从原状态到转移状态加一条边,边上的值为转移符号 */
CC.g[sidx].push_back(pair<char, int>(grammar.T[i], idx));
}
}
/* 遍历每个非终结符 */
for (int i = 0; i < grammar.N.size(); i++) {
LR1Items D;
go(S, grammar.N[i], D);
int idx;
if (D.items.size() > 0) {
/* 查找是否已经在有效项目集族里 */
idx = isInCanonicalCollection(D);
if (idx != 0) {
idx = idx - 1;
} else {
idx = CC.items.size();
CC.items.push_back(D);
/* 把新加入的有效项目集加入待扩展队列中 */
Q.push(pair<LR1Items, int>(D, idx));
}
/* 从原状态到转移状态加一条边,边上的值为转移符号 */
CC.g[sidx].push_back(pair<char, int>(grammar.N[i], idx));
}
}
/* 当前状态扩展完毕,移除队列*/
Q.pop();
}
printf("CC size: %d\n", CC.items.size());
for (int i = 0; i < CC.items.size(); i++) {
printf("LR1Items %d:\n", i);
printLR1Items(CC.items[i]);
for (int j = 0; j < CC.g[i].size(); j++) {
pair<char, int> p= CC.g[i][j];
printf("to %d using %c\n", p.second, p.first);
}
}
}
/* 生成LR1分析表 */
void productLR1AnalysisTabel()
{
for (int i = 0; i < CC.items.size(); i++) {
LR1Items &LIt= CC.items[i];
/* 构建action表 */
for (auto it = LIt.items.begin(); it != LIt.items.end(); it++) {
LR1Item &L = *it;
/* 非规约项目 */
if (L.location < L.p.rigths.size()) {
char a = L.p.rigths[L.location];
int j = isInT(a);
/* a是终结符 */
if (j > 0) {
j = j - 1;
/* 找到对应a的出边,得到其转移到的状态 */
for (int k = 0; k < CC.g[i].size(); k++) {
pair<char, int> p = CC.g[i][k];
if (p.first == a) {
action[i][j].first = 1; // 1->S
action[i][j].second = p.second; //转移状态
break;
}
}
}
} else { // 规约项目
/* 接受项目 */
if (L.p.left == grammar.prods[0].left) {
if (L.next == '$')
action[i][grammar.T.size() - 1].first = 3;
} else {
/* 终结符 */
int j = isInT(L.next) - 1;
/* 找到产生式对应的序号 */
for (int k = 0; k < grammar.prods.size(); k++) {
if (L.p == grammar.prods[k]) {
action[i][j].first = 2;
action[i][j].second = k;
break;
}
}
}
}
}
/* 构建goto表 */
for (int k = 0; k < CC.g[i].size(); k++) {
pair<char, int> p = CC.g[i][k];
char A = p.first;
int j = isInN(A);
/* 终结符 */
if (j > 0) {
j = j - 1;
goton[i][j] = p.second; //转移状态
}
}
}
/* 打印LR1分析表 */
for (int i = 0; i < grammar.T.size() / 2; i++)
printf("\t");
printf("action");
for (int i = 0; i < grammar.N.size() / 2 + grammar.T.size() / 2 + 1; i++)
printf("\t");
printf("goto\n");
printf("\t");
for (int i = 0; i < grammar.T.size(); i++) {
printf("%c\t", grammar.T[i]);
}
printf("|\t");
for (int i = 1; i < grammar.N.size(); i++) {
printf("%c\t", grammar.N[i]);
}
printf("\n");
for (int i = 0; i < CC.items.size(); i++) {
printf("%d\t", i);
for (int j = 0; j < grammar.T.size(); j++) {
if (action[i][j].first == 1) {
printf("%c%d\t", 'S', action[i][j].second);
} else if (action[i][j].first == 2) {
printf("%c%d\t", 'R', action[i][j].second);
} else if (action[i][j].first == 3) {
printf("ACC\t");
} else {
printf("\t");
}
}
printf("|\t");
for (int j = 1; j < grammar.N.size(); j++) {
if (goton[i][j]) {
printf("%d\t", goton[i][j]);
} else {
printf("\t");
}
}
printf("\n");
}
}
void initGrammar()
{
printf("Please enter the num of production:\n");
cin >> grammar.num;
string s;
printf("Please enter the production:\n");
for (int i = 0; i < grammar.num; i++) {
cin >> s;
Production tmp;
tmp.left = s[0];
for (int j = 3; j < s.size(); j++) {
tmp.rigths.push_back(s[j]);
}
grammar.prods.push_back(tmp);
}
printf("Please enter the non-terminators(end with #):\n");
char ch;
cin >> ch;
while (ch != '#') {
grammar.N.push_back(ch);
cin >> ch;
}
printf("Please enter the terminators(end with #):\n");
cin >> ch;
while (ch != '#') {
grammar.T.push_back(ch);
cin >> ch;
}
/* 把$当作终结符 */
grammar.T.push_back('$');
/* 求FIRST集 */
getFirstSet();
/* 构建DFA和SLR1预测分析表 */
DFA();
productLR1AnalysisTabel();
/* 读入待分析串并初始化分析栈 */
printf("Please enter the String to be analyzed:\n");
cin >> str;
str += '$';
ST.push(pair<int, char>(0, '-'));
}
/* 分析程序 */
void process()
{
int ip = 0;
printf("The ans:\n");
do {
int s = ST.top().first;
char a = str[ip];
int j = isInT(a) - 1;
/* 移进 */
if (action[s][j].first == 1) {
ST.push(pair<int, char>(action[s][j].second, a));
ip = ip + 1;
} else if (action[s][j].first == 2) { // 规约
Production &P = grammar.prods[action[s][j].second];
/* 弹出并输出产生式 */
printf("%c->", P.left);
for (int i = 0; i < P.rigths.size(); i++) {
ST.pop();
printf("%c", P.rigths[i]);
}
printf("\n");
s = ST.top().first;
char A = P.left;
j = isInN(A) - 1;
ST.push(pair<int, char>(goton[s][j], A));
} else if (action[s][j].first == 3) { //接受
printf("ACC\n");
return;
} else {
printf("error\n");
}
} while(1);
}
int main()
{
initGrammar();
process();
return 0;
}
五、SLR(1)
#include <cstdio>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <queue>
using namespace std;
/* 产生式结构体,左部符号和右部符号串 */
struct Production {
char left;
vector<char> rigths;
/* 重载== */
bool operator==(Production& rhs) const {
if (left != rhs.left)
return false;
for (int i = 0; i < rigths.size(); i++) {
if (i >= rhs.rigths.size())
return false;
if (rigths[i] != rhs.rigths[i])
return false;
}
return true;
}
};
/* LR0项目 */
struct LR0Item {
Production p;
/* 点的位置 */
int location;
};
/* LR0项目集 */
struct LR0Items {
vector<LR0Item> items;
};
/* LR0项目集规范族 */
struct CanonicalCollection {
/* 项目集集合 */
vector<LR0Items> items;
/* 保存DFA的图,first为转移到的状态序号,second是经什么转移 */
vector< pair<int, char> > g[100];
}CC;
/* 文法结构体 */
struct Grammar {
int num; // 产生式数量
vector<char> T; // 终结符
vector<char> N; // 非终结符
vector<Production> prods; //产生式
}grammar;
/* FIRST集和FOLLOW集 */
map<char, set<char> > first;
map<char, set<char> > follow;
/* DFA队列, 用于存储待转移的有效项目集 */
queue< pair<LR0Items, int> > Q;
/* action表和goto表 */
pair<int, int> action[100][100]; // first表示分析动作,0->ACC 1->S 2->R second表示转移状态或者产生式序号
int goton[100][100];
/* 待分析串 */
string str;
/* 分析栈 */
stack< pair<int, char> > ST; // first是state,second 是symble
/* 判断ch是否是终结符 */
int isInT(char ch)
{
for (int i = 0; i < grammar.T.size(); i++) {
if (grammar.T[i] == ch) {
return i + 1;
}
}
return 0;
}
/* 判断ch是否是非终结符 */
int isInN(char ch)
{
for (int i = 0; i < grammar.N.size(); i++) {
if (grammar.N[i] == ch) {
return i + 1;
}
}
return 0;
}
/* 求(T U N)的FIRST集 */
void getFirstSet()
{
/* 终结符的FIRST集是其本身 */
for (int i = 0; i < grammar.T.size(); i++) {
char X = grammar.T[i];
set<char> tmp;
tmp.insert(X);
first[X] = tmp;
}
/* 当非终结符的FIRST集发生变化时循环 */
bool change = true;
while (change) {
change = false;
/* 枚举每个产生式 */
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
char X = P.left;
set<char> &FX = first[X];
/* 如果右部第一个符号是空或者是终结符,则加入到左部的FIRST集中 */
if (isInT(P.rigths[0]) || P.rigths[0] == '&') {
/* 查找是否FIRST集是否已经存在该符号 */
auto it = FX.find(P.rigths[0]);
/* 不存在 */
if (it == FX.end()) {
change = true; // 标注FIRST集发生变化,循环继续
FX.insert(P.rigths[0]);
}
} else {
/* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
bool next = true;
/* 待判断符号的下标 */
int idx = 0;
while (next && idx < P.rigths.size()) {
next = false;
char Y = P.rigths[idx];
set<char> &FY = first[Y];
for (auto it = FY.begin(); it != FY.end(); it++) {
/* 把当前符号的FIRST集中非空元素加入到左部符号的FIRST集中 */
if (*it != '&') {
auto itt = FX.find(*it);
if (itt == FX.end()) {
change = true;
FX.insert(*it);
}
}
}
/* 当前符号的FIRST集中有空, 标记next为真,idx下标+1 */
auto it = FY.find('&');
if (it != FY.end()) {
next = true;
idx = idx + 1;
}
}
}
}
}
printf("FIRST:\n");
for (int i = 0; i < grammar.N.size(); i++) {
char X = grammar.N[i];
printf("%c: ", X);
for (auto it = first[X].begin(); it != first[X].end(); it++) {
printf("%c ", *it);
}
printf("\n");
}
}
/* 产找alpha串的FIRST集, 保存到FS集合中 */
void getFirstByAlphaSet(vector<char> &alpha, set<char> &FS)
{
/* 当前符号是非终结符,且当前符号可以推出空,则还需判断下一个符号 */
bool next = true;
int idx = 0;
while (idx < alpha.size() && next) {
next = false;
/* 当前符号是终结符或空,加入到FIRST集中 */
if (isInT(alpha[idx]) || alpha[idx] == '&') {
/* 判断是否已经在FIRST集中 */
auto itt = FS.find(alpha[idx]);
if (itt == FS.end()) {
FS.insert(alpha[idx]);
}
} else {
char B = alpha[idx];
set<char> &FB = first[B];
for (auto it = first[B].begin(); it != first[B].end(); it++) {
/* 当前符号FIRST集包含空,标记next为真,并跳过当前循环 */
if (*it == '&') {
next = true;
continue;
}
/* 把非空元素加入到FIRST集中 */
auto itt = FS.find(*it);
if (itt == FS.end()) {
FS.insert(*it);
}
}
}
idx = idx + 1;
}
/* 如果到达产生式右部末尾next还为真,说明alpha可以推空,将空加入到FIRST集中 */
if (next) {
FS.insert('&');
}
}
/* 求非终结符的FOLLOW集 */
void getFollowSet()
{
/* 初始化终结符的FOLLOW集为空集 */
for (int i = 0; i < grammar.N.size(); i++) {
char B = grammar.N[i];
follow[B] = set<char>();
}
/* 将$加入到文法的开始符号的FOLLOW集中 */
char S = grammar.N[0];
follow[S].insert('$');
bool change = true;
while (change) {
change = false;
/* 枚举每个产生式 */
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
for (int j = 0; j < P.rigths.size(); j++) {
char B = P.rigths[j];
/* 当前符号是非终结符 */
if (isInN(B)) {
set<char> &FB = follow[B];
set<char> FS;
/* alpha是从当前符号下一个符号开始的符号串 */
vector<char> alpha(P.rigths.begin() + j + 1, P.rigths.end());
/* 求alpha的FIRST集,即FS */
getFirstByAlphaSet(alpha, FS);
// printf("%c:\n", B);
/* 将alpha的FIRST集中所有非空元素加入到当前符号的FOLLOW集中 */
for (auto it = FS.begin(); it != FS.end(); it++) {
// printf("%c ", *it);
if (*it == '&') {
continue;
}
auto itt = FB.find(*it);
if (itt == FB.end()) {
change = true;
FB.insert(*it);
}
}
// printf("\n");
/* 如果alpha能推空,或者当前符号是产生式右部末尾,则将文法左部符号的FOLLOW集加入到当前符号的FOLLOW集中 */
auto itt = FS.find('&');
if (itt != FS.end() || (j + 1) >= P.rigths.size()) {
char A = P.left;
for (auto it = follow[A].begin(); it != follow[A].end(); it++) {
auto itt = FB.find(*it);
if (itt == FB.end()) {
change = true;
FB.insert(*it);
}
}
}
}
}
}
}
printf("FOLLOW:\n");
for (int i = 0; i < grammar.N.size(); i++) {
char X = grammar.N[i];
printf("%c: ", X);
for (auto it = follow[X].begin(); it != follow[X].end(); it++) {
printf("%c ", *it);
}
printf("\n");
}
}
/* 判断是LR0项目t否在有效项目集I中 */
bool isInLR0Items(LR0Items &I, LR0Item &t)
{
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR0Item &item = *it;
if (item.p == t.p && item.location == t.location)
return true;
}
return false;
}
/* 打印某个项目集 */
void printLR0Items(LR0Items &I)
{
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR0Item &L = *it;
printf("%c->", L.p.left);
for (int i = 0; i < L.p.rigths.size(); i++) {
if (L.location == i)
printf(".");
printf("%c", L.p.rigths[i]);
}
if (L.location == L.p.rigths.size())
printf(".");
printf(" ");
}
printf("\n");
}
/* 求I的闭包 */
void closure(LR0Items &I)
{
bool change = true;
while (change) {
change = false;
LR0Items J;
/* 枚举每个项目 */
J.items.assign(I.items.begin(), I.items.end());
for (auto it = J.items.begin(); it != J.items.end(); it++) {
LR0Item &L = *it;
/* 非规约项目 */
if (L.location < L.p.rigths.size()) {
char B = L.p.rigths[L.location];
if (isInN(B)) {
/* 把符合条件的LR0项目加入闭包中 */
for (int i = 0; i < grammar.prods.size(); i++) {
Production &P = grammar.prods[i];
if (P.left == B) {
LR0Item t;
t.location = 0;
t.p.left = P.left;
t.p.rigths.assign(P.rigths.begin(), P.rigths.end());
if (!isInLR0Items(I, t)) {
/* 标记改变 */
change = true;
I.items.push_back(t);
}
}
}
}
}
}
}
}
/* 判断是否在项目集规范族中,若在返回序号 */
int isInCanonicalCollection(LR0Items &I)
{
for (int i = 0; i < CC.items.size(); i++) {
LR0Items &J = CC.items[i];
bool flag = true;
if (J.items.size() != I.items.size()) {
flag = false;
continue;
}
/* 每个项目都在该项目集中,则认为这个两个项目集相等 */
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR0Item &t = *it;
if (!isInLR0Items(J, t)) {
flag = false;
break;
}
}
if (flag) {
return i + 1;
}
}
return 0;
}
/* 转移函数,I为当前的项目集,J为转移后的项目集, 经X转移 */
void go(LR0Items &I, char X, LR0Items &J)
{
for (auto it = I.items.begin(); it != I.items.end(); it++) {
LR0Item &L = *it;
/* 非规约项目 */
if (L.location < L.p.rigths.size()) {
char B = L.p.rigths[L.location];
/* 如果点后面是非终结符,且非终结符为X,点位置加1, 加入到转移项目集中*/
if (B == X) {
LR0Item t;
t.location = L.location + 1;
t.p.left = L.p.left;
t.p.rigths.assign(L.p.rigths.begin(), L.p.rigths.end());
J.items.push_back(t);
}
}
}
/* 若J中有项目,则求其闭包 */
if (J.items.size() > 0) {
closure(J);
}
}
/* 构建DFA和项目集规范族 */
void DFA()
{
/* 构建初始项目集 */
LR0Item t;
t.location = 0;
t.p.left = grammar.prods[0].left;
t.p.rigths.assign(grammar.prods[0].rigths.begin(), grammar.prods[0].rigths.end());
LR0Items I;
I.items.push_back(t);
closure(I);
/* 加入初始有效项目集 */
CC.items.push_back(I);
/* 把新加入的有效项目集加入待扩展队列中 */
Q.push(pair<LR0Items, int>(I, 0));
while (!Q.empty()) {
LR0Items &S = Q.front().first;
int sidx = Q.front().second;
/* 遍历每个终结符 */
for (int i = 0; i < grammar.T.size(); i++) {
LR0Items D;
go(S, grammar.T[i], D);
int idx;
/* 若不为空 */
if (D.items.size() > 0) {
/* 查找是否已经在有效项目集族里 */
idx = isInCanonicalCollection(D);
if (idx > 0) {
idx = idx - 1;
} else {
idx = CC.items.size();
CC.items.push_back(D);
/* 把新加入的有效项目集加入待扩展队列中 */
Q.push(pair<LR0Items, int>(D, idx));
}
/* 从原状态到转移状态加一条边,边上的值为转移符号 */
CC.g[sidx].push_back(pair<char, int>(grammar.T[i], idx));
}
}
/* 遍历每个非终结符 */
for (int i = 0; i < grammar.N.size(); i++) {
LR0Items D;
go(S, grammar.N[i], D);
int idx;
if (D.items.size() > 0) {
/* 查找是否已经在有效项目集族里 */
idx = isInCanonicalCollection(D);
if (idx != 0) {
idx = idx - 1;
} else {
idx = CC.items.size();
CC.items.push_back(D);
/* 把新加入的有效项目集加入待扩展队列中 */
Q.push(pair<LR0Items, int>(D, idx));
}
/* 从原状态到转移状态加一条边,边上的值为转移符号 */
CC.g[sidx].push_back(pair<char, int>(grammar.N[i], idx));
}
}
/* 当前状态扩展完毕,移除队列*/
Q.pop();
}
printf("CC size: %d\n", CC.items.size());
for (int i = 0; i < CC.items.size(); i++) {
printf("LR0Items %d:\n", i);
printLR0Items(CC.items[i]);
for (int j = 0; j < CC.g[i].size(); j++) {
pair<char, int> p= CC.g[i][j];
printf("to %d using %c\n", p.second, p.first);
}
}
}
/* 生成SLR1分析表 */
void productSLR1AnalysisTabel()
{
for (int i = 0; i < CC.items.size(); i++) {
LR0Items &LIt= CC.items[i];
/* 构建action表 */
for (auto it = LIt.items.begin(); it != LIt.items.end(); it++) {
LR0Item &L = *it;
/* 非规约项目 */
if (L.location < L.p.rigths.size()) {
char a = L.p.rigths[L.location];
int j = isInT(a);
/* a是终结符 */
if (j > 0) {
j = j - 1;
/* 找到对应a的出边,得到其转移到的状态 */
for (int k = 0; k < CC.g[i].size(); k++) {
pair<char, int> p = CC.g[i][k];
if (p.first == a) {
action[i][j].first = 1; // 1->S
action[i][j].second = p.second; //转移状态
break;
}
}
}
} else { // 规约项目
/* 接受项目 */
if (L.p.left == grammar.prods[0].left) {
action[i][grammar.T.size() - 1].first = 3;
} else {
char A = L.p.left;
for (auto a = follow[A].begin(); a != follow[A].end(); a++) {
int j = isInT(*a);
/* 终结符 */
if (j > 0) {
j = j - 1;
/* 找到产生式对应的序号 */
for (int k = 0; k < grammar.prods.size(); k++) {
if (L.p == grammar.prods[k]) {
action[i][j].first = 2;
action[i][j].second = k;
break;
}
}
}
}
}
}
}
/* 构建goto表 */
for (int k = 0; k < CC.g[i].size(); k++) {
pair<char, int> p = CC.g[i][k];
char A = p.first;
int j = isInN(A);
/* 终结符 */
if (j > 0) {
j = j - 1;
goton[i][j] = p.second; //转移状态
}
}
}
/* 打印SLR1分析表 */
for (int i = 0; i < grammar.T.size() / 2; i++)
printf("\t");
printf("action");
for (int i = 0; i < grammar.N.size() / 2 + grammar.T.size() / 2 + 1; i++)
printf("\t");
printf("goto\n");
printf("\t");
for (int i = 0; i < grammar.T.size(); i++) {
printf("%c\t", grammar.T[i]);
}
printf("|\t");
for (int i = 1; i < grammar.N.size(); i++) {
printf("%c\t", grammar.N[i]);
}
printf("\n");
for (int i = 0; i < CC.items.size(); i++) {
printf("%d\t", i);
for (int j = 0; j < grammar.T.size(); j++) {
if (action[i][j].first == 1) {
printf("%c%d\t", 'S', action[i][j].second);
} else if (action[i][j].first == 2) {
printf("%c%d\t", 'R', action[i][j].second);
} else if (action[i][j].first == 3) {
printf("ACC\t");
} else {
printf("\t");
}
}
printf("|\t");
for (int j = 1; j < grammar.N.size(); j++) {
if (goton[i][j]) {
printf("%d\t", goton[i][j]);
} else {
printf("\t");
}
}
printf("\n");
}
}
void initGrammar()
{
printf("Please enter the num of production:\n");
cin >> grammar.num;
string s;
printf("Please enter the production:\n");
for (int i = 0; i < grammar.num; i++) {
cin >> s;
Production tmp;
tmp.left = s[0];
for (int j = 3; j < s.size(); j++) {
tmp.rigths.push_back(s[j]);
}
grammar.prods.push_back(tmp);
}
printf("Please enter the non-terminators(end with #):\n");
char ch;
cin >> ch;
while (ch != '#') {
grammar.N.push_back(ch);
cin >> ch;
}
printf("Please enter the terminators(end with #):\n");
cin >> ch;
while (ch != '#') {
grammar.T.push_back(ch);
cin >> ch;
}
/* 把$当作终结符 */
grammar.T.push_back('$');
/* 求FIRST集和FOLLOW集 */
getFirstSet();
getFollowSet();
/* 构建DFA和SLR1预测分析表 */
DFA();
productSLR1AnalysisTabel();
/* 读入待分析串并初始化分析栈 */
printf("Please enter the String to be analyzed:\n");
cin >> str;
str += '$';
ST.push(pair<int, char>(0, '-'));
}
/* 分析程序 */
void process()
{
int ip = 0;
printf("The ans:\n");
do {
int s = ST.top().first;
char a = str[ip];
int j = isInT(a) - 1;
/* 移进 */
if (action[s][j].first == 1) {
ST.push(pair<int, char>(action[s][j].second, a));
ip = ip + 1;
} else if (action[s][j].first == 2) { // 规约
Production &P = grammar.prods[action[s][j].second];
/* 弹出并输出产生式 */
printf("%c->", P.left);
for (int i = 0; i < P.rigths.size(); i++) {
ST.pop();
printf("%c", P.rigths[i]);
}
printf("\n");
s = ST.top().first;
char A = P.left;
j = isInN(A) - 1;
ST.push(pair<int, char>(goton[s][j], A));
} else if (action[s][j].first == 3) { //接受
printf("ACC\n");
return;
} else {
printf("error\n");
}
} while(1);
}
int main()
{
initGrammar();
process();
return 0;
}