#include<iostream>
#include<map>
#include<list>
#include<vector>
#include<stdio.h>
#include<set>
#include<string>
#include<stack>
using namespace std;
typedef struct {
string left;
string right[200];
int length;
bool flag = false;
bool followFlag = false;
}grammarElement;
vector<string> li;
grammarElement gramOldSet[200];//原始文法的产生式集
typedef struct {
string left;
set<string> firstOrFollow;
}SET;//set集
typedef struct {
string left;
string con[200];
}MAP;//set集
string terSymbol="i+*()#";//终结符号
string non_ter="ETFE'T'";//非终结符号
string allSymbol="ETFE'T'+*()";//所有符号
SET firstSET[200];//各产生式右部的FIRST集
SET followSET[200];//各产生式左部的FOLLOW集
MAP M[200];//分析表
int MAX;
bool flag3 = false;
//分割输入的
vector<string> split(string str,string separator){
vector<string> result;
int cutAt;
while((cutAt = str.find_first_of(separator))!=str.npos){
if(cutAt>0){
result.push_back(str.substr(0,cutAt));
}
str=str.substr(cutAt+1);
}
if(str.length()>0){
result.push_back(str);
}
return result;
}
void split(int max) {
vector<string>::iterator it = li.begin();
for (int i=0; it!=li.end(); it++,i++)
{
string str = *it;
vector<string> v;
gramOldSet[i].left =str.at(0);
str = str.substr(3);
v=split(str, "|");
for (int j = 0; j<int(v.size()); j++) {
gramOldSet[i].right[j] = v[j];
gramOldSet[i].length++;
}
}
}
//消除直接左递归
void elimunateCabinets(int i) {
int flag = 0, m=0, flag2=0;
for (int j = 0; j < gramOldSet[i].length; j++)
{
string strn = gramOldSet[i].right[j].substr(0, 1);
string str = "";
str = gramOldSet[i].right[j].substr(1);
string first = gramOldSet[i].left;
string first1 = "'";
if (gramOldSet[i].left == strn) {
flag = 1;
//向gramOldSet,最后添加新的一组产生式
gramOldSet[MAX].left = first + first1;//左边的 E'
gramOldSet[MAX].right[0] = str + first + first1;//右边的
gramOldSet[MAX].right[1] = "$";//伊普西龙
gramOldSet[MAX].length += 2;
MAX++;
gramOldSet[i].right[j] = "";
}
else {
if (flag2==0&&flag==1)
{
flag2 = 1;
m = 0;
//修改当前的没有左递归的候选式
for (; m< gramOldSet[i].length; m++)
{
if (gramOldSet[i].right[m].length() != 0)
{
gramOldSet[i].right[m] = gramOldSet[i].right[m] + first + first1;
}
}
}
}
}
}
//消除间接递归
void eliminateMakingCabinets(int len) {
int newstrlen = 0;
int glen = len;
for (int i = len -1; i >=0; i--)
{
int flag = 0;
for (int j = len -1; j>i; j--)
{
for (int k = 0; k < gramOldSet[i].length; k++)
{
vector<string> newstr;
if(gramOldSet[i].right[k].find(gramOldSet[j].left))//第i个候选式,包含之后的几个候选式的左部,则带入
{
//带入
flag++;
string str = gramOldSet[i].right[k].substr(1);//待带入的产生式从第二位开始截取
for (int m = 0; m < gramOldSet[j].length; m++)
{
string str1 = gramOldSet[j].right[m] + str;
newstr.push_back(str1);
}
}
if (flag!=0)
{
newstrlen = gramOldSet[i].length;
for(int s=0;s<gramOldSet[i].length;s++)
{
if (gramOldSet[i].right[s].find(gramOldSet[j].left))//如果是这个候选式被带入,则不做处理
{
continue;
}
else {//否则,将这个候选式加入newstrlen
newstr.push_back(gramOldSet[i].right[s]);
}
}
//清空这个产生式的右部,将newstr放在这个产生式右部
int s = 0;
vector<string>::iterator it= newstr.begin();
for (; it!=newstr.end();it++)
{
gramOldSet[i].right[s] = *it;//将这个产生式右部全部替换
}
}
}
}
elimunateCabinets(i);
glen++;
}
}
//求某个产生式的位置
int location(string str) {
for (int i = 0; i < MAX; i++)
{
if (str==gramOldSet[i].left)
{
return i;
}
}
return -1;
}
// 当前产生式右部符号可推出空字
int isToNUll(int i, int j,string *p) {
string* q = p;
string str = gramOldSet[i].right[j].at(0) + "";
if (gramOldSet[i].right[j].at(1) == '\'')
{
str += '\'';
p++;
}
int m = location(str);
for (int n = 0; n < gramOldSet[m].length; n++)
{
if (gramOldSet[m].right[n].at(0)=='$')
{
flag3 = true;
return 1;
}
else if(terSymbol.find(gramOldSet[m].right[n].at(0))){
continue;//看下一个候选式
}
else {
isToNUll(m, n,q);
}
}
return 0;
}
//first集
void firstList(int i) {
firstSET[i].left = gramOldSet[i].left;//firstset初始化
set<string>::iterator it = firstSET[i].firstOrFollow.begin();
if (non_ter.find(gramOldSet[i].left)!=-1) {// X为非终结符,这个产生式的左部
for (int j = 0; j < gramOldSet[i].length; j++)//查找这个产生式的所有候选式
{
if (gramOldSet[i].right[j].length() != 0) {
flag3 = false;//用于判断当前产生式的候选式右部符号可推出空字
if (terSymbol.find(gramOldSet[i].right[j].at(0))!=-1|| gramOldSet[i].right[j] == "$")//右部第一个字符是终结符,或者$
{
firstSET[i].firstOrFollow.insert(gramOldSet[i].right[j].substr(0,1));//添加终结符到firstset中
}
else {
string str = gramOldSet[i].right[j].substr(0, 1);
string* p = &gramOldSet[i].right[j];
if (gramOldSet[i].right[j].at(1) == '\'')
{
str += '\'';
}
if (str == gramOldSet[i].left)//产生式右部的第一个符号等于当前字符
{
// 跳到下一条产生式进行查找,递归
firstList(i + 1);
}
else if (!gramOldSet[location(str)].flag) {//当前非终结符还没有求其FIRST集
firstList(location(str));//查找它的FIRST集
gramOldSet[location(str)].flag = true;//标识此符号已求其FIRST集
set<string>::iterator it1 = firstSET[location(str)].firstOrFollow.begin();
for (; it1 != firstSET[location(str)].firstOrFollow.end(); it1++) {
firstSET[i].firstOrFollow.insert(*it1); //求得结果并入到X的FIRST集
}
}
//isToNUll(i,j,p)&&(p=p+1)!=NULL
else if (gramOldSet[i].right[j] == "$") {
firstSET[i].firstOrFollow.insert("$");
/*if (terSymbol.find(*p))//下一个字符终结符,直接加入
{
firstSET[i].firstOrFollow.insert(*p);
}
else {
int locate2 = location(*p);
if (!gramOldSet[locate2].flag)//当前非终结符还没有求其FIRST集
{
firstList(locate2);
gramOldSet[locate2].flag = true;
set<string>::iterator it1 = firstSET[locate2].firstOrFollow.begin();
for (; it1 != firstSET[location(str)].firstOrFollow.end(); it1++) {
firstSET[i].firstOrFollow.insert(*it); //求得结果并入到X的FIRST集
}
}
}*/
}
/*else if (flag3 && p == NULL)
{
firstSET[i].firstOrFollow.insert("$");//把空字加入到当前字符X的FIRST集
}*/
else {
continue;
}
}
}
}
gramOldSet[i].flag = true; //标识当前字符X已查找其FIRST集
}
}
//follow,对于A->1B2,2能否退出空字
bool judgeToNull(string s, string *p) {
string* q = p;
if (*p=="$")
{
return true;
}
if (non_ter.find(*q)!=-1)//*q是非终结符
{
int locate = location(*q);
for (int i = 0; i < gramOldSet[locate].length; i++)//遍历*q为左部的产生式的所有候选式
{
string str = gramOldSet[locate].right[i].substr(gramOldSet[locate].right[i].length() - 1, gramOldSet[locate].right[i].length());//截取最后一位
if (str == "\'")
{
str = gramOldSet[locate].right[i].substr(gramOldSet[locate].right[i].length() - 2, gramOldSet[locate].right[i].length());//截取最后两位位
}
if (gramOldSet[locate].right[i]=="$")
{
return true;
}
else if (non_ter.find(str) != -1) {
if (str == gramOldSet[locate].left) continue;//与左部相等则查找下一个候选式
string* r = &gramOldSet[locate].right[i];
judgeToNull(gramOldSet[locate].right[i], r);//递归求这个结尾为非终结符的候选式能不能退出空
}
}
return false;
}
else {//*q是终结符,不能退出空
return false;
}
}
//follow集
void followList(int i) {//i表示文法中是第几个非终结符
followSET[i].left = gramOldSet[i].left;//初始化左部
if (i==0)
{
followSET[i].firstOrFollow.insert("#");
}
for (int j = 0; j < MAX; j++)
{
for (int m = 0; m < gramOldSet[j].length; m++)//对全部的产生式找一个右部
{
string str4 = "\0";
int location1 = gramOldSet[j].right[m].find(followSET[i].left);//这个非终结符在候选式string的位置
if (location1!=-1)
{
//str4 = gramOldSet[i].left;
str4 = gramOldSet[j].right[m].substr(location1, location1);
string str0 = gramOldSet[j].right[m].substr(location1 + 1, location1 + 2);
if (str0 == "\'")
{
str4 += '\'';
}
}
if (str4== gramOldSet[j].left) {
continue;
}
if (str4==gramOldSet[i].left)
{
string str1= gramOldSet[j].right[m].substr(location1 + 1, gramOldSet[j].right[m].length());
string str = gramOldSet[j].right[m].substr(gramOldSet[j].right[m].length() - 1, gramOldSet[j].right[m].length());//截取最后一位
if (str == "\'")
{
str = gramOldSet[j].right[m].substr(gramOldSet[j].right[m].length() - 2, gramOldSet[j].right[m].length());//截取最后两位位
//str1 = gramOldSet[j].right[m].substr(location1 + 2, gramOldSet[j].right[m].length());
}
if (str == str4)//X在产生式右部的最后(形如产生式AX)
{
if (!gramOldSet[j].followFlag)//查找非终结符A是否已经求过其FOLLOW集
{
followList(j);
gramOldSet[j].followFlag = true;
}
set<string>::iterator it1 = followSET[j].firstOrFollow.begin();
for (; it1 != followSET[j].firstOrFollow.end(); it1++) {
followSET[i].firstOrFollow.insert(*it1); //把FOLLOW(A)中的元素加入FOLLOW(X)
}
continue;// 继续查下一条产生式是否含有X
}
else {
string str2= gramOldSet[j].right[m].substr(location1 + 1, location1 + 2);
if (gramOldSet[j].right[m].at(location1 + 1)=='\'') {
str2 += '\'';
}
if (terSymbol.find(str2)!=-1) {//X后面是终结符
followSET[i].firstOrFollow.insert(str2);
}
else {
if (judgeToNull(str1, &str1)) {//X不在产生式右部的最后(A->1B2)且2能退出空
if (!gramOldSet[j].followFlag)查找非终结符A是否已经求过其FOLLOW集
{
followList(j);
}
set<string>::iterator it1 = followSET[j].firstOrFollow.begin();
for (; it1 != followSET[j].firstOrFollow.end(); it1++) {
followSET[i].firstOrFollow.insert(*it1); //把FOLLOW(A)中的元素加入FOLLOW(X)
}
}
int lo = location(str1);
set<string>::iterator it1 = firstSET[lo].firstOrFollow.begin();//吧2的first加入
for (; it1 != firstSET[lo].firstOrFollow.end(); it1++) {
if (*it1 != "$")
{
followSET[i].firstOrFollow.insert(*it1); //把FIRST()中所有非空元素加入到FOLLOW(B)中
}
}
}
}
}
}
}
gramOldSet[i].followFlag = true;
}
//预测分析表
void forecastAnalysisTable() {
//预测分析表预处理
for (int i = 1; i <= terSymbol.length(); i++)
{
M[0].con[i] = terSymbol[i - 1];
}
for (int i = 1; i <= MAX; i++) {
M[i].left = gramOldSet[i-1].left;
}
for (int i = 0; i < MAX; i++)
{
for (int j = 0; j < gramOldSet[i].length; j++) {//对文法G的每个产生式 A->阿尔法
if (gramOldSet[i].right[j]=="\0")
{
continue;
}
string str = gramOldSet[i].right[j].substr(0,1);
if (gramOldSet[i].right[j].substr(1,2)=="\'")
{
str += "\'";
}
int locate = location(str);
if (non_ter.find(str)!=-1)
{
set<string>::iterator it = firstSET[locate].firstOrFollow.begin();
for (int m = 0; it != firstSET[locate].firstOrFollow.end(); it++, m++) {
if (*it != "$") {
M[i+1].con[terSymbol.find(*it) + 1] = gramOldSet[i].left + "->" + gramOldSet[i].right[j];//M[A,a]=‘A->阿尔法...’
}
}
}
if (terSymbol.find(str)!=-1)
{
M[i + 1].con[terSymbol.find(str) + 1]= gramOldSet[i].left + "->" + gramOldSet[i].right[j];
}
if (str=="$")
{
set<string>::iterator it = followSET[i].firstOrFollow.begin();
for (int m = 0; it != followSET[i].firstOrFollow.end(); it++, m++) {//M[A,a]=‘A->空’,若 空∈FIRST(阿尔法),则对任意b∈FOLLOW(A),把A->加入到M[A , b]中;
if (terSymbol.find(*it)!=-1) {
M[i+1].con[terSymbol.find(*it) + 1] = gramOldSet[i].left + "->" + "$";//
}
}
}
}
}
}
//错误程序
void ERROR() {
cout << "\n错误表达式!";
}
//获取栈内元素
string getStack(stack<string> s) {
string str0;
while (s.size())
{
str0.insert(0, s.top());
s.pop();
}
return str0;
}
//主控程序
void masterControlProgram(string str) {
stack<string> mid, fin;
char* q = &str[0];//首先把‘#’然后把文法开始符号推进STACK栈;
string X,a;
int step = 0;
fin.push("#");
fin.push(gramOldSet[0].left);
a = *q;//把第一个输入符号读进a;
bool flag = true;
cout << "步骤\t" << "栈中元素\t" << "待输入串\t" << "所用产生式\t\n";
while (flag)
{
cout << ++step << "\t";
cout << getStack(fin) << "\t";
cout << q << "\t";
X = fin.top();
fin.pop();//把STACK栈顶符号上托出去并放在X中;
if (X == "#")
{
if (X == a) {
cout << "\nsuccess!";
flag = false;
}
else {
ERROR();
break;
}
}
if (terSymbol.find(X)!=-1)
{
if (X==a)
{
q++;
a = *q;//把下一输入符号读进a
}
else {
ERROR();
break;
}
}
else if (M[location(X)+1].con[terSymbol.find(a)+1]!="")
{
char* p;
string str0 = M[location(X)+1].con[terSymbol.find(a)+1];
string str1;
cout << str0 << "\t";//所用产生式
int lo = str0.find(">");
str0 = str0.substr(lo + 1);
if (str0!="$")//若X1X2…Xk=$?,不推什么进栈
{
p = &str0[0];
for (; *p != '\0'; p++) {
str1 = *p;
if (*(p+1)=='\'')
{
str1 += "\'";
p++;
}
mid.push(str1);
}
while (!mid.empty())
{
fin.push(mid.top());//把Xk,Xk-1,…,X1一一推进STACK栈
string st = fin.top();
mid.pop();
}
}
}
else {
ERROR();
break;
}
cout << "\n";
}
}
int main() {
li.push_back("E->E+T|T");
li.push_back("T->T*F|F");
li.push_back("F->(E)|i");
MAX+=3;
split(MAX);
for (int i = 0; i < MAX; i++)
{
elimunateCabinets(i);
}
for (int i = 0; i < MAX; i++)
{
cout << gramOldSet[i].left << "->";
for (int j = 0; j < gramOldSet[i].length; j++)
{
cout << " " << gramOldSet[i].right[j];
}
printf("\n");
}
for (int i = 0; i < MAX; i++)
{
firstList(i);
}
cout << "firstList:\n";
for (int i = 0; i < MAX; i++)
{
cout << firstSET[i].left<<":";
set<string>::iterator it = firstSET[i].firstOrFollow.begin();
for (it; it != firstSET[i].firstOrFollow.end(); it++)
{
cout << *it << " ";
}
printf("\n");
}
for (int i = 0; i < MAX; i++)
{
followList(i);
}
cout << "followList:\n";
for (int i = 0; i < MAX; i++)
{
cout << followSET[i].left << ":";
set<string>::iterator it = followSET[i].firstOrFollow.begin();
for (it; it != followSET[i].firstOrFollow.end(); it++)
{
cout << *it << " ";
}
printf("\n");
}
forecastAnalysisTable();
for (int i = 0; i <= MAX; i++) {
cout << M[i].left<<+" ";
for (int j = 0; j <=terSymbol.length(); j++)
{
cout << M[i].con[j] << +"\t\t";
}
printf("\n");
}
string str = "(i+i)*i#";
//主控程序
masterControlProgram(str);
}
c\c++ 编译原理实现消除(直接/间接)左递归,first集,follow集,预测分析表,主控程序
最新推荐文章于 2023-06-24 20:28:06 发布