c\c++ 编译原理实现消除(直接/间接)左递归,first集,follow集,预测分析表,主控程序

#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);
}
  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值