【編譯原理】LL(1)文法分析全過程(FIRST/FLLOW/SELECT集等)實現(c++語言)

注:本程序只能進行LL(1)文法的分析,非LL(1)文法請轉化爲LL(1)文法

變量聲明

string M[2000][2000];     //任務分析表
stack <char> cc;          //分析棧
queue <char> qq;          //輸入串
set <char> ww[200];       //first集
set <char> T;             //終結符集
set <char> N;             //非終結符集合
set <char> vv[200];       //中間過程記錄集
set <char> ff[200];       //fllow集合
set <char> select[200];   //select集合

int step = 0;             //步驟統計變量
int error_flag=0;         //錯誤標誌位
int nullflag[1000];       //是否推空標誌
int nullselect[1000];     //集合是否推空標誌
int ll=0;                 //文法行數
int T_flag[1000];         //右側是否含有終結符
int length_char[1000];    //每行文法的字符個數
char line[100][1024];     //文法記錄表

輸入&初步分析:文件輸入(每個文法一行,如A->B)

void raedFromFile()
{
    fstream infile("project.txt",ios::in);
    while(infile.getline(line[ll],sizeof(line[ll])))
    {
        for(int i=0;i<100;i++)
        {
            if(int(line[ll][i])==0)
                {
                    length_char[ll]=i;
                    break;
                }
            if(isT(line[ll][i]))
                T_flag[ll]=1;
                T.insert(line[ll][i]);
            if(isN(line[ll][i]))
                N.insert(line[ll][i]);
        }
        if(isT(line[ll][3]))
        {
            //first集合
            if(line[ll][3]=='^')
            {
                nullflag[int(line[ll][0])]=1;
            }
            ww[int(line[ll][0])].insert(line[ll][3]);
        }else
        {
            vv[int(line[ll][0])].insert(line[ll][3]);
        }
        ll++;
    }
}


求FIRST集

void firstSet()
{
    for(int i=0;i<ll;i++)
    {
        if(isN(line[i][3]))
        {
            int j=3;
            while(nullflag[int(line[i][j])]==1)
            {
                if(j+1==length_char[i])
                {
                    break;
                }
                if(isN(line[i][j+1]))
                {
                    vv[int(line[i][0])].insert(line[i][j+1]);
                    j++;
                }
            }
        }
    }
    while(!isEmpty())
    {
        for(set<char>::iterator ite1 = N.begin();ite1!=N.end();ite1++)
        {
            //對於所有非終結符
            //如果他的first已經完畢收集
            if(vv[int(*ite1)].empty())
            {
                //那麼就把他的first加入到含有他的vv中
                for(set<char>::iterator ite3 = N.begin();ite3!=N.end();ite3++)
                {
                    for(set<char>::iterator ite4 = vv[int(*ite3)].begin();ite4!=vv[int(*ite3)].end();ite4++)
                    {
                        if(*ite4==*ite1)
                        {
                            vv[int(*ite3)].erase(*ite4);
                            //ite1的first集
                            for(set<char>::iterator ite5 = ww[int(*ite1)].begin();ite5!=ww[int(*ite1)].end();ite5++)
                            {
                              ww[int(*ite3)].insert(*ite5);
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}

FLLOW集

void fllowSet()
{
    ff[int(line[0][0])].insert('#');
    for(int i=0;i<ll;i++)
    {
        int j=3;
        while(j!=length_char[i])
        {
            //依次考慮每個非終結符,分情況,情況就是我們平時的那幾個情況
            if(isN(line[i][j]))
            {
                if(j==length_char[i]-1)
                {
                    if(line[i][0]!=line[i][j])
                        vv[int(line[i][j])].insert(line[i][0]);
                }
                else if(isN(line[i][j+1])&&nullflag[int(line[i][j+1])]==1)
                {
                    if(line[i][0]!=line[i][j])
                        vv[int(line[i][j])].insert(line[i][0]);
                    for(set<char>::iterator ite2 = ww[int(line[i][j+1])].begin();ite2!=ww[int(line[i][j+1])].end();ite2++)
                    {
                        if(*ite2!='^')
                            ff[int(line[i][j])].insert(*ite2);
                    }
                }
                else if(isN(line[i][j+1])&&nullflag[int(line[i][j+1])]==0)
                {
                    for(set<char>::iterator ite2 = ww[int(line[i][j+1])].begin();ite2!=ww[int(line[i][j+1])].end();ite2++)
                    {
                        if(*ite2!='^')
                            ff[int(line[i][j])].insert(*ite2);
                    }
                }
                else if(isT(line[i][j+1]))
                {
                    ff[int(line[i][j])].insert(line[i][j+1]);
                }else{}
            }
            j++;
        }
    }


    while(!isEmpty())
    {
        for(set<char>::iterator ite1 = N.begin();ite1!=N.end();ite1++)
        {
            //對於所有非終結符
            //如果他的fllow已經完畢收集
            if(vv[int(*ite1)].empty())
            {
                //那麼就把他的first加入到含有他的vv中
                for(set<char>::iterator ite3 = N.begin();ite3!=N.end();ite3++)
                {
                    for(set<char>::iterator ite4 = vv[int(*ite3)].begin();ite4!=vv[int(*ite3)].end();ite4++)
                    {
                        if(*ite4==*ite1)
                        {
                            vv[int(*ite3)].erase(*ite4);
                            //ite1的first集
                            for(set<char>::iterator ite5 = ff[int(*ite1)].begin();ite5!=ff[int(*ite1)].end();ite5++)
                            {
                              ff[int(*ite3)].insert(*ite5);
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}

SELECT集

void selectSet()
{
    for(int i=0;i<ll;i++)
    {
        int j=3;
        if(isN(line[i][3]))
        {
            for(set<char>::iterator ite2 = ww[line[i][3]].begin();ite2!=ww[line[i][3]].end();ite2++)
            {
                if(*ite2!='^')
                    select[i].insert(*ite2);
            }
        }
        while(isN(line[i][j])&&nullflag[int(line[i][j])]==1)
        {
            if(j==length_char[i]-1)
                break;
            for(set<char>::iterator ite2 = ww[line[i][j+1]].begin();ite2!=ww[line[i][j+1]].end();ite2++)
            {
                if(*ite2!='^')
                    select[i].insert(*ite2);
            }
            j++;
        }
        if(isT(line[i][j]))
        {
            select[i].insert(line[i][j]);
        }
    }

    _null2();
    for(int i=0;i<ll;i++)
    {
        if(nullselect[i]==1)
        {
            select[i].erase('^');
            for(set<char>::iterator ite5 = ff[int(line[i][0])].begin();ite5!=ff[int(line[i][0])].end();ite5++)
            {
                select[i].insert(*ite5);
            }
        }
    }
}
建表

void LL_1Table()
{
    for(int i=0;i<ll;i++)
    {
        for(set<char>::iterator ite2 = select[i].begin();ite2!=select[i].end();ite2++)
        {
            for(int j=0;j<length_char[i];j++)
                M[int(line[i][0])][int(*ite2)]+=line[i][j];
        }
    }
}
表分析

void grammatical_analysis(string s)
{
    cout<<"步驟  "<<"符號棧 "<<"剩餘輸入串  "<<"產生式(空用^表示)"<<endl;
    for(int i=0 ; i<s.length();i++)
    {   //初始化輸入串隊列
        qq.push(s[i]);
    }
    //分析過程
    while((qq.front()=='#'&&cc.top()=='#')==0)
    {
        while(isN(cc.top()))
        {
            string str=M[cc.top()][qq.front()];
            //錯誤1號
            if(str=="")
            {
                cout<<step<<" "<<"輸入句不是文法的合法句型"<<endl;
                error_flag=1;
                break;
            }
            cout<<step<<"\t";
            step++;
            showCC();
            showPP();
            cout<<str<<endl;
            cc.pop();
            for(int i=str.size()-1;i>=0;i--)
            {
                if(str[i]=='>')
                    break;
                if(str[i]!='^')
                cc.push(str[i]);
            }
        }
        //接受
        if(error_flag==1)
        {
            break;
        }
        if(cc.top()=='#'&&qq.front()=='#')
        {
            cout<<step<<"\t";
            step++;
            showCC();
            showPP();
            cout<<"接受"<<endl;
        }
        else if(cc.top()==qq.front())
        {
            cout<<step<<"\t";
            step++;
            showCC();
            showPP();
            cout<<"\""<<cc.top()<<"\"匹配"<<endl;
            qq.pop();
            cc.pop();
        }else{
            //錯誤2號
            cout<<step<<" "<<"輸入句不是文法的合法句型"<<endl;
        }
    }
}
以上是整個的具體思路即核心代碼


完整代碼請見點擊打開鏈接

         



 
     
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章